Page MenuHomec4science

No OneTemporary

File Metadata

Created
Sat, Apr 27, 03:17
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.clang-tidy b/.clang-tidy
index b044a7204..a1c6f4e86 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,15 +1,30 @@
Checks: "
-*,
modernize-use-*,
-modernize-use-trailing-return-type*,
+ cppcoreguidelines-*,
+ -cppcoreguidelines-macro-usage,
+ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+
+ performance-*,
+
readability-*,
-readability-magic-numbers,
-readability-redundant-access-specifiers,
-readability-convert-member-functions-to-static,
-readability-isolate-declaration,
+ -readability-identifier-length,
"
+
AnalyzeTemporaryDtors: false
HeaderFilterRegex: 'src/.*'
FormatStyle: file
+UseColor: true
+
+CheckOptions:
+ - key: readability-identifier-length.IgnoreVariableNames
+ value: True
+ - key: readability-identifier-length.MinimumLoopCounterNameLength
+ value: 1
diff --git a/.codeclimate.yml b/.codeclimate.yml
index fc0df9490..16fa27d26 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -1,39 +1,51 @@
checks:
duplicate:
enabled: true
exclude_patterns:
- "test/"
- "examples/"
structure:
enabled: true
exclude_patterns:
+ - "cmake/"
- "test/"
+ - "examples/"
plugins:
editorconfig:
enabled: false
config:
editorconfig: .editorconfig
exclude_patterns:
- ".clangd/"
- ".cache/"
+ pylint:
+ enabled: false
+ exclude_patterns:
+ - "cmake"
+ - "doc"
+ - "test/test_fe_engine/py_engine/py_engine.py"
+ - "test/ci"
+ PYTHONPATH:
+ - python
+ - build/python
pep8:
enabled: true
exclude_patterns:
- "test/test_fe_engine/py_engine/py_engine.py"
cppcheck:
enabled: false
project: build/compile_commands.json
language: c++
check: warning, style, performance
- stds: [c++14]
+ stds: [c++17]
exclude_patterns:
- "python/"
fixme:
enabled: true
exclude_patterns:
- "doc/"
exclude_patterns:
-- "third-party/"
-- "build*/"
+ - "third-party/"
+ - "build*/"
diff --git a/.flake8 b/.flake8
index 76f42ce8a..de211914b 100644
--- a/.flake8
+++ b/.flake8
@@ -1,5 +1,5 @@
[flake8]
exclude = build*,__pycache__,third-party
-max-line-length = 99
+max-line-length = 79
per-file-ignores =
py_engine.py:E201,E202,E203,E501
diff --git a/.gitignore b/.gitignore
index 0b944748f..6b1ba8e19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,32 +1,34 @@
build*
.dir-locals.el
TAGS
third-party/*/
!third-party/cmake/*
-!third-party/akantu-iterators
+!third-party/akantu_iterators
!third-party/iohelper
*~
release
.*.swp
*.tar.gz
*.tgz
*.tbz
*.tar.bz2
.idea
__pycache__
.mailmap
paraview/*
*.vtu
*.pvd
*.pvtu
*.vtk
compile_commands.json
.clangd
.iwyu.imp
.cache
setup.cfg
.vscode
.auctex*
.clangd
+.ccls-cache
.ccls
VERSION
+
diff --git a/.gitlab-ci.d/code-quality.yaml b/.gitlab-ci.d/code-quality.yaml
index caf7d6035..837888511 100644
--- a/.gitlab-ci.d/code-quality.yaml
+++ b/.gitlab-ci.d/code-quality.yaml
@@ -1,63 +1,70 @@
.code_quality_common:
stage: code_quality
allow_failure: true
+ cache:
+ - key: ${CI_COMMIT_REF_SLUG}-third-party
+ policy: pull
+ paths:
+ - third-party/eigen3
+ - third-party/pybind11
+ - third-party/google-test
rules:
- if: "$CODE_QUALITY_DISABLED"
when: never
- if: "$CI_COMMIT_TAG || $CI_COMMIT_BRANCH"
.code_quality_gitlab_template:
extends:
- .code_quality_common
image: docker:20.10.21
allow_failure: true
services:
- docker:20.10.21-dind
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.87.0"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.89.0"
needs: []
script:
- export SOURCE_CODE=$PWD
- |
if ! docker info &>/dev/null; then
if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
export DOCKER_HOST='tcp://localhost:2375'
fi
fi
- | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
function propagate_env_vars() {
CURRENT_ENV=$(printenv)
for VAR_NAME; do
echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
done
}
- docker pull --quiet "$CODE_QUALITY_IMAGE"
- |
docker run --rm \
$(propagate_env_vars \
SOURCE_CODE \
TIMEOUT_SECONDS \
CODECLIMATE_DEBUG \
CODECLIMATE_DEV \
REPORT_STDOUT \
REPORT_FORMAT \
ENGINE_MEMORY_LIMIT_BYTES \
CODECLIMATE_PREFIX \
) \
--volume "$PWD":/code \
--volume /var/run/docker.sock:/var/run/docker.sock \
"$CODE_QUALITY_IMAGE" /code
.clang_tools:
extends:
- .code_quality_common
- .debian_bullseye_clang
before_script:
- if [ 'x${CI_MERGE_REQUEST_ID}' != 'x' ]; then
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- git diff --name-only $CI_COMMIT_SHA $CI_MERGE_REQUEST_TARGET_BRANCH_NAME > file_list
- FILE_LIST_ARG='-f file_list'
- fi
diff --git a/.gitlab-ci.d/images.yaml b/.gitlab-ci.d/images.yaml
index 503a80594..e960e3df6 100644
--- a/.gitlab-ci.d/images.yaml
+++ b/.gitlab-ci.d/images.yaml
@@ -1,109 +1,112 @@
+# yaml-language-server: $schema=gitlab-ci
+# yaml-language-server: $format.enable=false
+
.docker_build:
image: "docker:20.10.21"
stage: .pre
services:
- docker:20.10.21-dind
variables:
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- cd test/ci/${IMAGE_NAME}/
- docker build --no-cache -t registry.gitlab.com/akantu/akantu/${IMAGE_NAME} .
- docker push registry.gitlab.com/akantu/akantu/${IMAGE_NAME}
rules:
- changes:
- test/ci/${IMAGE_NAME}/*
# ------------------------------------------------------------------------------
.cache_build:
variables:
CCACHE_BASEDIR: ${CI_PROJECT_DIR}/
CCACHE_DIR: ${CI_PROJECT_DIR}/.ccache
CCACHE_MAXSIZE: 1Gi
- cache:
- key: ${output}_${BUILD_TYPE}
- policy: pull-push
- paths:
- - .ccache/
- - third-party/google-test
- - third-party/pybind11
before_script:
- ccache --zero-stats || true
after_script:
- ccache --show-stats || true
# ------------------------------------------------------------------------------
.image_debian_bullseye:
image: registry.gitlab.com/akantu/akantu/debian:bullseye
.image_ubuntu_lts:
image: registry.gitlab.com/akantu/akantu/ubuntu:lts
.image_manylinux:
image: registry.gitlab.com/akantu/akantu/manylinux:2014_x86_64
# ------------------------------------------------------------------------------
.compiler_gcc:
variables:
CC: /usr/lib/ccache/gcc
CXX: /usr/lib/ccache/g++
FC: gfortran
GCOV_EXECUTABLE: gcov
+.compiler_gcc_ubuntu:
+ variables:
+ CC: /usr/lib/ccache/gcc-8
+ CXX: /usr/lib/ccache/g++-8
+ FC: /usr/bin/gfortran-8
+ GCOV_EXECUTABLE: gcov
+
.compiler_clang:
variables:
CC: /usr/lib/ccache/clang
CXX: /usr/lib/ccache/clang++
FC: gfortran
GCOV_EXECUTABLE: llvm-cov gcov
.build_coverage:
variables:
TEST_EXAMPLES: "FALSE"
BUILD_TYPE: "Coverage"
.build_release:
variables:
TEST_EXAMPLES: "TRUE"
BUILD_TYPE: "Release"
.build_valgrind:
variables:
TEST_EXAMPLES: "FALSE"
BUILD_TYPE: "Valgrind"
# ------------------------------------------------------------------------------
.debian_bullseye_gcc:
variables:
output: debian_bullseye_gcc
extends:
- .compiler_gcc
- .image_debian_bullseye
- .cache_build
.debian_bullseye_clang:
variables:
output: debian_bullseye_clang
extends:
- .compiler_clang
- .image_debian_bullseye
- .cache_build
.ubuntu_lts_gcc:
variables:
output: ubuntu_lts_gcc
extends:
- - .compiler_gcc
+ - .compiler_gcc_ubuntu
- .image_ubuntu_lts
- .cache_build
.manylinux_2014_x64_gcc:
variables:
output: manylinux_2014_x64_gcc
extends:
- .compiler_gcc
- .image_manylinux
- .cache_build
diff --git a/.gitlab-ci.d/templates.yaml b/.gitlab-ci.d/templates.yaml
index 39a8b4506..902993507 100644
--- a/.gitlab-ci.d/templates.yaml
+++ b/.gitlab-ci.d/templates.yaml
@@ -1,140 +1,169 @@
-# yaml-language-server: $format.enable=false, $schemaStore.enable=true, $schemas=gitlab-ci
+# yaml-language-server: $schema=gitlab-ci
+# yaml-language-server: $format.enable=false
# Configuration template
.configure:
stage: configure
variables:
BLA_VENDOR: "Generic"
CMAKE_GENERATOR: "Unix Makefiles"
# CMAKE_GENERATOR: 'Ninja'
+ cache:
+ - key: ${CI_COMMIT_REF_SLUG}-third-party
+ policy: push
+ paths:
+ - third-party/eigen3
+ - third-party/pybind11
+ - third-party/google-test
+ - key: ${output}-${BUILD_TYPE}-ccache
+ policy: pull-push
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ policy: push
+ paths:
+ - build/
script:
# Create the build folder
- cmake -E make_directory build
- cd build
- echo BUILD_TYPE=${BUILD_TYPE}
# Configure the project
- cmake -DAKANTU_COHESIVE_ELEMENT:BOOL=TRUE
- -DAKANTU_IMPLICIT:BOOL=TRUE
- -DAKANTU_PARALLEL:BOOL=TRUE
- -DAKANTU_STRUCTURAL_MECHANICS:BOOL=TRUE
- -DAKANTU_HEAT_TRANSFER:BOOL=TRUE
- -DAKANTU_DAMAGE_NON_LOCAL:BOOL=TRUE
- -DAKANTU_PHASE_FIELD:BOOL=TRUE
- -DAKANTU_PYTHON_INTERFACE:BOOL=TRUE
- -DAKANTU_CONTACT_MECHANICS:BOOL=TRUE
- -DAKANTU_EXAMPLES:BOOL=TRUE
- -DAKANTU_BUILD_ALL_EXAMPLES:BOOL=TRUE
- -DAKANTU_TESTS:BOOL=TRUE
- -DAKANTU_RUN_IN_DOCKER:BOOL=TRUE
- -DAKANTU_TEST_EXAMPLES:BOOL=${TEST_EXAMPLES}
- -DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE}
- -G "${CMAKE_GENERATOR}" ..
+ -DAKANTU_IMPLICIT:BOOL=TRUE
+ -DAKANTU_IMPLICIT_SOLVER:STRING="Mumps"
+ -DAKANTU_PARALLEL:BOOL=TRUE
+ -DAKANTU_STRUCTURAL_MECHANICS:BOOL=TRUE
+ -DAKANTU_HEAT_TRANSFER:BOOL=TRUE
+ -DAKANTU_DAMAGE_NON_LOCAL:BOOL=TRUE
+ -DAKANTU_PHASE_FIELD:BOOL=TRUE
+ -DAKANTU_PYTHON_INTERFACE:BOOL=TRUE
+ -DAKANTU_CONTACT_MECHANICS:BOOL=TRUE
+ -DAKANTU_EXAMPLES:BOOL=TRUE
+ -DAKANTU_BUILD_ALL_EXAMPLES:BOOL=TRUE
+ -DAKANTU_TESTS:BOOL=TRUE
+ -DAKANTU_RUN_IN_DOCKER:BOOL=TRUE
+ -DAKANTU_TEST_EXAMPLES:BOOL=${TEST_EXAMPLES}
+ -DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE}
+ -G "${CMAKE_GENERATOR}" ..
# Copy the compile commands for the code quality
- if [ -e compile_commands.json ]; then
- cp compile_commands.json ..
- fi
artifacts:
when: on_success
paths:
- - build
+ - VERSION
- compile_commands.json
expire_in: 10h
# Build the libraries
.build_libs:
stage: build_libs
+ cache:
+ - key: ${CI_COMMIT_REF_SLUG}-third-party
+ policy: pull
+ paths:
+ - third-party/eigen3
+ - third-party/pybind11
+ - third-party/google-test
+ - key: ${output}-${BUILD_TYPE}-ccache
+ policy: pull-push
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ policy: pull-push
+ paths:
+ - build/
script:
- echo BUILD_TYPE=${BUILD_TYPE}
- - cmake --build build --target akantu -j1
- > >(tee -a build-${output}-out.log)
- 2> >(tee -a build-${output}-err.log >&2)
- - cmake --build build --target py11_akantu -j1
- > >(tee -a build-${output}-out.log)
- 2> >(tee -a build-${output}-err.log >&2)
+ - cmake --build build/src
+ > >(tee -a build-${output}-out.log)
+ 2> >(tee -a build-${output}-err.log >&2)
+ - cmake --build build/python
+ > >(tee -a build-${output}-out.log)
+ 2> >(tee -a build-${output}-err.log >&2)
+ - ls build/test
artifacts:
when: on_success
paths:
- - build/
+ - VERSION
- build-${output}-err.log
- compile_commands.json
expire_in: 10h
+ timeout: 5h
# build the tests
.build_tests:
stage: build_tests
+ cache:
+ - key: ${CI_COMMIT_REF_SLUG}-third-party
+ policy: pull
+ paths:
+ - third-party/eigen3
+ - third-party/pybind11
+ - third-party/google-test
+ - key: ${output}-${BUILD_TYPE}-ccache
+ policy: pull-push
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ policy: pull
+ paths:
+ - build/
script:
- - cmake --build build -j1
- > >(tee -a build-${output}-out.log)
- 2> >(tee -a build-${output}-err.log >&2)
- artifacts:
- when: on_success
- paths:
- - build/
- - build-${output}-err.log
- - compile_commands.json
- exclude:
- - build/**/*.o
- expire_in: 10h
-
-# Build all
-.build_all:
- stage: build_libs
- script:
- - cmake --build build/src
- > >(tee -a build-${output}-out.log)
- 2> >(tee -a build-${output}-err.log >&2)
- - cmake --build build/python
- > >(tee -a build-${output}-out.log)
- 2> >(tee -a build-${output}-err.log >&2)
- - cmake --build build/test/
- > >(tee -a build-${output}-out.log)
- 2> >(tee -a build-${output}-err.log >&2)
+ - ls
+ - ls build
+ - cmake --build build/test
+ > >(tee -a build-${output}-out.log)
+ 2> >(tee -a build-${output}-err.log >&2)
- cmake --build build/examples
- > >(tee -a build-${output}-out.log)
- 2> >(tee -a build-${output}-err.log >&2)
+ > >(tee -a build-${output}-out.log)
+ 2> >(tee -a build-${output}-err.log >&2)
artifacts:
when: on_success
paths:
- - build/
+ - VERSION
- build-${output}-err.log
- compile_commands.json
+ - build
exclude:
- build/**/*.o
expire_in: 10h
# Run the tests
.tests:
stage: test
script:
- cd build
- ctest -T test --output-on-failure --no-compress-output --timeout 1800
after_script:
- cd build
- tag=$(head -n 1 < Testing/TAG)
- if [ -e Testing/${tag}/Test.xml ]; then
- - xsltproc -o ./juint.xml ${CI_PROJECT_DIR}/test/ci/ctest2junit.xsl Testing/${tag}/Test.xml;
+ - xsltproc -o ./juint.xml ${CI_PROJECT_DIR}/test/ci/ctest2junit.xsl Testing/${tag}/Test.xml;
- fi
- if [ ${BUILD_TYPE} = "Coverage" ]; then
- - gcovr --xml
- --gcov-executable "${GCOV_EXECUTABLE}"
- --xml-pretty
- --exclude-unreachable-branches
- --print-summary
- --output coverage.xml
- --object-directory ${CI_PROJECT_DIR}/build
- --root ${CI_PROJECT_DIR} -s || true
+ - gcovr --xml
+ --gcov-executable "${GCOV_EXECUTABLE}"
+ --xml-pretty
+ --exclude-unreachable-branches
+ --print-summary
+ --output coverage.xml
+ --object-directory ${CI_PROJECT_DIR}/build
+ --root ${CI_PROJECT_DIR} -s || true
- fi
artifacts:
when: always
expire_in: 2 days
paths:
- build/juint.xml
- build/coverage.xml
reports:
junit:
- build/juint.xml
coverage_report:
coverage_format: cobertura
path: build/coverage.xml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fec923ec1..415f13ce3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,375 +1,432 @@
# yaml-language-server: $schema=gitlab-ci
# yaml-language-server: $format.enable=false
stages:
- version
- configure
- build_libs
- build_tests
- test
- code_quality
- deploy
include:
local: ".gitlab-ci.d/*.yaml"
#-------------------------------------------------------------------------------
# Rebuilding the docker images if needed
#-------------------------------------------------------------------------------
docker build:debian-bullseye:
variables:
IMAGE_NAME: debian:bullseye
extends: .docker_build
docker build:ubuntu-lts:
variables:
IMAGE_NAME: ubuntu:lts
extends: .docker_build
docker build:manylinux:
variables:
IMAGE_NAME: manylinux:2014_x86_64
extends: .docker_build
version_determination:
stage: version
image: python:latest
variables:
GIT_STRATEGY: fetch
GIT_DEPTH: 500
script:
- python3 cmake/semver.py > VERSION
- cat VERSION
artifacts:
when: on_success
paths:
- VERSION
expire_in: 1day
# ------------------------------------------------------------------------------
# Debian bullseye compiled with GCC
# ------------------------------------------------------------------------------
configure:debian_bullseye_gcc:
extends:
- .debian_bullseye_gcc
- - .build_coverage
+ - .build_release
- .configure
needs:
- version_determination
-build:debian_bullseye_gcc:
+build_libs:debian_bullseye_gcc:
extends:
- .debian_bullseye_gcc
- - .build_coverage
- - .build_all
+ - .build_release
+ - .build_libs
needs:
- job: configure:debian_bullseye_gcc
+build_tests:debian_bullseye_gcc:
+ extends:
+ - .debian_bullseye_gcc
+ - .build_release
+ - .build_tests
+ needs:
+ - job: build_libs:debian_bullseye_gcc
+
test:debian_bullseye_gcc:
extends:
- .debian_bullseye_gcc
- - .build_coverage
+ - .build_release
- .tests
coverage: '/^lines: (\d+\.\d+\%)/'
needs:
- - job: build:debian_bullseye_gcc
+ - job: build_tests:debian_bullseye_gcc
# ------------------------------------------------------------------------------
# Debian bullseye compiled with Clang
# ------------------------------------------------------------------------------
configure:debian_bullseye_clang:
extends:
- .debian_bullseye_clang
- - .build_coverage
+ - .build_release
- .configure
needs:
- version_determination
-build:debian_bullseye_clang:
+build_libs:debian_bullseye_clang:
extends:
- .debian_bullseye_clang
- - .build_coverage
- - .build_all
+ - .build_release
+ - .build_libs
needs:
- job: configure:debian_bullseye_clang
+build_tests:debian_bullseye_clang:
+ extends:
+ - .debian_bullseye_clang
+ - .build_release
+ - .build_tests
+ needs:
+ - job: build_libs:debian_bullseye_clang
+
test:debian_bullseye_clang:
extends:
- .debian_bullseye_clang
- - .build_coverage
+ - .build_release
- .tests
coverage: '/^lines: (\d+\.\d+\%)/'
needs:
- - job: build:debian_bullseye_clang
+ - job: build_tests:debian_bullseye_clang
# ------------------------------------------------------------------------------
# Ubuntu LTS compiled with GCC
# ------------------------------------------------------------------------------
configure:ubuntu_lts_gcc:
extends:
- .ubuntu_lts_gcc
- .build_release
- .configure
needs:
- version_determination
-build:ubuntu_lts_gcc:
+build_libs:ubuntu_lts_gcc:
extends:
- .ubuntu_lts_gcc
- .build_release
- - .build_all
+ - .build_libs
needs:
- job: configure:ubuntu_lts_gcc
+build_tests:ubuntu_lts_gcc:
+ extends:
+ - .ubuntu_lts_gcc
+ - .build_release
+ - .build_tests
+ needs:
+ - job: build_libs:ubuntu_lts_gcc
+
test:ubuntu_lts_gcc:
extends:
- .ubuntu_lts_gcc
- .build_release
- .tests
needs:
- - job: build:ubuntu_lts_gcc
+ - job: build_tests:ubuntu_lts_gcc
# ------------------------------------------------------------------------------
# Debian bullseye compiled with GCC tested with valgrind
# ------------------------------------------------------------------------------
configure:ubuntu_lts_gcc_valgrind:
extends:
- .ubuntu_lts_gcc
- .build_valgrind
- .configure
needs:
- version_determination
-build:ubuntu_lts_gcc_valgrind:
+build_libs:ubuntu_lts_gcc_valgrind:
extends:
- .ubuntu_lts_gcc
- .build_valgrind
- - .build_all
+ - .build_libs
needs:
- job: configure:ubuntu_lts_gcc_valgrind
+build_tests:ubuntu_lts_gcc_valgrind:
+ extends:
+ - .ubuntu_lts_gcc
+ - .build_valgrind
+ - .build_tests
+ needs:
+ - job: build_libs:ubuntu_lts_gcc_valgrind
+
test:ubuntu_lts_gcc_valgrind:
extends:
- .ubuntu_lts_gcc
- .build_valgrind
- .tests
needs:
- - job: build:ubuntu_lts_gcc_valgrind
+ - job: build_tests:ubuntu_lts_gcc_valgrind
# ------------------------------------------------------------------------------
# Manylinux to build python packages
# ------------------------------------------------------------------------------
configure:python_package:
stage: configure
extends:
- .manylinux_2014_x64_gcc
- .build_release
+ cache:
+ - key: ${CI_COMMIT_REF_SLUG}-third-party
+ paths:
+ - third-party/eigen3
+ - third-party/pybind11
+ - third-party/google-test
+ - key: ${output}-${BUILD_TYPE}-ccache
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ paths:
+ - build/
script:
# create the build folder
- cmake -E make_directory build
- cd build
# Variables for cmake
- export CMAKE_PREFIX_PATH=/softs/view
- export BOOST_ROOT=/softs/view
# Configure in sequential and without tests or examples
- cmake -DAKANTU_COHESIVE_ELEMENT:BOOL=TRUE
-DAKANTU_IMPLICIT:BOOL=TRUE
-DAKANTU_PARALLEL:BOOL=FALSE
-DAKANTU_STRUCTURAL_MECHANICS:BOOL=TRUE
-DAKANTU_HEAT_TRANSFER:BOOL=TRUE
-DAKANTU_DAMAGE_NON_LOCAL:BOOL=TRUE
-DAKANTU_PHASE_FIELD:BOOL=TRUE
-DAKANTU_PYTHON_INTERFACE:BOOL=FALSE
-DAKANTU_CONTACT_MECHANICS:BOOL=TRUE
-DAKANTU_EXAMPLES:BOOL=FALSE
-DAKANTU_TESTS:BOOL=FALSE
-DMUMPS_DETECT_DEBUG:BOOL=TRUE
-DCMAKE_INSTALL_PREFIX:PATH=${CI_PROJECT_DIR}/install
-DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE} ..
needs:
- version_determination
artifacts:
when: on_success
paths:
- - build/
- VERSION
expire_in: 10h
build_akantu:python_package:
extends:
- .build_libs
- .build_release
- .manylinux_2014_x64_gcc
script:
- cmake --build build --target akantu -j1
- cmake --install build
artifacts:
when: on_success
paths:
- install/
- VERSION
expire_in: 10h
needs:
- job: configure:python_package
build_pip:python_package:
stage: build_tests
extends:
- .build_release
- .manylinux_2014_x64_gcc
+ cache:
+ - key: ${CI_COMMIT_REF_SLUG}-third-party
+ paths:
+ - third-party/eigen3
+ - third-party/pybind11
+ - third-party/google-test
+ - key: ${output}-${BUILD_TYPE}-ccache
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ paths:
+ - build/
script:
- export CI_AKANTU_INSTALL_PREFIX=${CI_PROJECT_DIR}/install
- export CMAKE_PREFIX_PATH=/softs/view:${CI_AKANTU_INSTALL_PREFIX}
- test/ci/make-wheels.sh
needs:
- job: build_akantu:python_package
artifacts:
when: on_success
paths:
- wheelhouse
expire_in: 10h
test:python_package:
stage: test
image: python:3.8
needs:
- job: build_pip:python_package
script:
- pip install numpy scipy
- pip install akantu --no-index --find-links=${PWD}/wheelhouse
- python -c "import akantu"
- cd examples/python/dynamics/
- apt update && apt install -y gmsh
- gmsh -2 bar.geo
- python ./dynamics.py
package:python_gitlab:
stage: deploy
image: python:latest
script:
- pip install twine
- TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token
python3 -m twine upload
--repository-url https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi
wheelhouse/*
needs:
- job: build_pip:python_package
- job: test:python_package
only:
- master
package:python_pypi:
stage: deploy
image: python:latest
script:
- pip install twine
- TWINE_PASSWORD=${PYPI_TOKEN} TWINE_USERNAME=__token__
python3 -m twine upload --verbose wheelhouse/*
needs:
- job: build_pip:python_package
- job: test:python_package
only:
- tags
# ------------------------------------------------------------------------------
# Code Quality
# ------------------------------------------------------------------------------
cq:code_quality:
extends:
- .code_quality_gitlab_template
needs:
- - job: build:debian_bullseye_clang
+ - job: build_libs:debian_bullseye_clang
artifacts:
paths:
- gl-code-quality-report.json
cq:clang_tidy:
extends:
- .clang_tools
script:
- test/ci/scripts/cq
-x third-party
-x extra-packages
-x pybind11
-x test
-x build
${FILE_LIST_ARG}
clang-tidy
- -p ${CI_PROJECT_DIR}/build > gl-clang-tidy-report.json
+ -p ${CI_PROJECT_DIR} > gl-clang-tidy-report.json
needs:
- - job: build:debian_bullseye_clang
+ - job: configure:debian_bullseye_clang
artifacts:
paths:
- gl-clang-tidy-report.json
cq:clang_format:
extends:
- .clang_tools
script:
- test/ci/scripts/cq
-x third-party
-x extra-packages
-x build
clang-format
- -p ${CI_PROJECT_DIR}/build > gl-clang-format-report.json
+ -p ${CI_PROJECT_DIR} > gl-clang-format-report.json
needs:
- - job: build:debian_bullseye_clang
+ - job: configure:debian_bullseye_clang
artifacts:
paths:
- gl-clang-format-report.json
cq:compilation_warnings:
stage: code_quality
image: python:latest
script:
- pip install warning-parser termcolor Click
- ls build-*-err.log
- test/ci/scripts/cq
-x third-party
-x extra-packages
-x build
warnings
build-*-err.log > gl-warnings-report.json
needs:
- - job: build:debian_bullseye_clang
- - job: build:debian_bullseye_gcc
- - job: build:ubuntu_lts_gcc
+ - job: build_libs:debian_bullseye_clang
+ - job: build_libs:debian_bullseye_gcc
+ - job: build_libs:ubuntu_lts_gcc
artifacts:
paths:
- gl-warnings-report.json
cq:merge_code_quality:
stage: deploy
extends:
- .debian_bullseye_clang
script:
- jq -Ms '[.[][]]' gl-*-report.json | tee gl-codequality.json | jq -C
needs:
- job: cq:code_quality
- job: cq:clang_tidy
- job: cq:clang_format
- job: cq:compilation_warnings
artifacts:
reports:
codequality: [gl-codequality.json]
+ paths:
+ - gl-codequality.json
# ------------------------------------------------------------------------------
# Deploy pages
# ------------------------------------------------------------------------------
pages:
stage: deploy
extends:
- .debian_bullseye_gcc
script:
- cd build
- cmake -DAKANTU_DOCUMENTATION=ON ..
- cmake --build . -t sphinx-doc
- mv doc/dev-doc/html ../public
needs:
- - job: build:debian_bullseye_gcc
+ - job: configure:debian_bullseye_gcc
artifacts:
paths:
- public
only:
- master
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76c42c153..836d03d15 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,91 +1,91 @@
## Version 4.0 (09-21-2021)
### Added
- pybind11 binding
- contact mechanics model
- phase field model
- Added a Changelog
### Changed
- transferred CI from jenkinsfile to gitlab CI/CD
- API changes to make container mode STL compatible
- clear does not set to 0 anymore but empties containers
- empty does not empty containers but tells if the container is empty
- zero replace the old empty and set containers to 0
### Deprecated
- `getForce` in the `SolidMechanicsModel` becomes `getExternalForce`
- `firstType()`, `lastType()` replaced by `elementTypes()`
## Version 3.2 (not released)
### Added
- Activating PETSc solver back with the new solver interface
### Deprecated
- deprecating old C++ 03 code
## 3.0 (2018-03)
### Added
- Parallel cohesive elements
- Element groups created by default for “physical_names”
- Named arguments for functions (e.g. model.initFull(_analysis_method = _static))
### Changed
- Models using new interface for solvers
- Same configuration for all models
- Solver can be configured in input file
- Only one function to solve a step model.solveStep()
- Simplification of the parallel simulation with the mesh.distribute() function
- Switch from C++ standard 2003 to 2014 Example of changes implied by this:
- for (UInt g = _not_ghost; g <= _ghost; ++g) {
+ for (Int g = _not_ghost; g <= _ghost; ++g) {
GhostType gt = (GhostType)g;
Mesh::type_iterator it = this->mesh.firstType(spatial_dimension, gt);
Mesh::type_iterator end = this->mesh.lastType(spatial_dimension, gt);
for (; it != end; ++it) {
ElementType & type = *it;
...
}
}
becomes:
for (auto ghost_type : ghost_types) {
for (auto type : mesh.elementTypes(spatial_dimension,
ghost_type)) {
...
}
}
### Deleted
- PETSc interface temporary inactive
- Periodic boundary condition temporary inactive
## 2.3 (2016-03)
### Added
- swig python interface
## 2.2 (2014-09)
### Added
- Cohesive elements
## 1.0 (2012-06)
### Added
- Continuum damage local and non-local
- Models: solid mechanics, structural mechanics, heat transfer
diff --git a/CMakeLists.txt b/CMakeLists.txt
index afbecb4c4..99bde7d7b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,214 +1,216 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Mon Jun 14 2010
# @date last modification: Sat Mar 13 2021
#
# @brief main configuration file
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
# @section DESCRIPTION
#-------------------------------------------------------------------------------
# _ _
# | | | |
# __ _| | ____ _ _ __ | |_ _ _
# / _` | |/ / _` | '_ \| __| | | |
# | (_| | < (_| | | | | |_| |_| |
# \__,_|_|\_\__,_|_| |_|\__|\__,_|
#
#===============================================================================
#===============================================================================
# CMake Project
#===============================================================================
-cmake_minimum_required(VERSION 3.5.1)
+cmake_minimum_required(VERSION 3.9)
# add this options before PROJECT keyword
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
if(CMAKE_VERSION VERSION_GREATER 3.12)
cmake_policy(SET CMP0074 NEW)
endif()
set(AKANTU_COPYRIGHT "2010-2021, EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)")
set(AKANTU_MAINTAINER "Nicolas Richart")
set(AKANTU_HOMEPAGE_URL "https://akantu.ch")
if(CMAKE_VERSION VERSION_GREATER 3.12)
project(Akantu
HOMEPAGE_URL "https://akantu.ch")
else()
project(Akantu)
endif()
enable_language(CXX)
#===============================================================================
# Misc. config for cmake
#===============================================================================
set(AKANTU_CMAKE_DIR "${PROJECT_SOURCE_DIR}/cmake")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/Modules")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL
"Enable/Disable output of compile commands during generation" FORCE)
mark_as_advanced(BUILD_SHARED_LIBS)
+set(AKANTU_CXX_STANDARD 17 CACHE INTERNAL "")
+
if(NOT AKANTU_TARGETS_EXPORT)
set(AKANTU_TARGETS_EXPORT AkantuTargets)
endif()
include(CMakeVersionGenerator)
include(CMakePackagesSystem)
include(CMakeFlagsHandling)
include(AkantuPackagesSystem)
include(AkantuMacros)
include(AkantuCleaning)
#cmake_activate_debug_message()
include(GNUInstallDirs)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
#===============================================================================
# Version Number
#===============================================================================
# AKANTU version number.
define_project_version()
#===============================================================================
# Options
#===============================================================================
option(AKANTU_EXAMPLES "Activate examples" OFF)
option(AKANTU_TESTS "Activate tests" OFF)
option(AKANTU_SHARED "Build Akantu as a shared library" ON)
option(AKANTU_POSITION_INDEPENDENT "Build with -fPIC when static" ON)
option(AKANTU_RUN_IN_DOCKER "Set the approriate flage tu run in docker" OFF)
set(AKANTU_PREFERRED_PYTHON_VERSION 3
CACHE STRING "Preferred version for python related things")
mark_as_advanced(
AKANTU_PREFERRED_PYTHON_VERSION
AKANTU_RUN_IN_DOCKER
AKANTU_POSITION_INDEPENDENT
AKANTU_SHARED
)
if (AKANTU_SHARED)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries.")
else()
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries.")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
include(AkantuExtraCompilationProfiles)
#===============================================================================
# Dependencies
#===============================================================================
declare_akantu_types()
package_list_packages(${PROJECT_SOURCE_DIR}/packages
EXTRA_PACKAGES_FOLDER ${PROJECT_SOURCE_DIR}/extra_packages
NO_AUTO_COMPILE_FLAGS)
#===============================================================================
# Akantu library
#===============================================================================
if (NOT AKANTU_BYPASS_AKANTU_TARGET)
add_subdirectory(src)
else()
find_package(Akantu REQUIRED)
if (Akantu_FOUND)
get_target_property(_lib akantu INTERFACE_LINK_LIBRARIES)
message(STATUS "Found Akantu: ${_lib} (found version ${AKANTU_VERSION})")
endif()
endif()
#===============================================================================
# Documentation
#===============================================================================
if(AKANTU_DOCUMENTATION OR AKANTU_DOCUMENTATION_MANUAL)
add_subdirectory(doc)
else()
set(AKANTU_DOC_EXCLUDE_FILES "${PROJECT_SOURCE_DIR}/doc/manual" CACHE INTERNAL "")
endif()
#===============================================================================
# Python interface
#===============================================================================
package_is_activated(python_interface _python_act)
if(_python_act)
include(AkantuNeedPybind11)
if(IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}")
set(AKANTU_PYTHON_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
else()
set(AKANTU_PYTHON_INSTALL_PREFIX "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_PREFIX}")
endif()
add_subdirectory(python)
endif()
#===============================================================================
# Examples and tests
#===============================================================================
include(AkantuTestsMacros)
include(AkantuExampleMacros)
if(AKANTU_TESTS)
include(AkantuNeedPybind11)
option(AKANTU_BUILD_ALL_TESTS "Build all tests" ON)
find_package(GMSH REQUIRED)
endif()
# tests
add_test_tree(test)
if(AKANTU_EXAMPLES)
if(AKANTU_TESTS)
option(AKANTU_TEST_EXAMPLES "Run the examples" ON)
endif()
find_package(GMSH REQUIRED)
add_subdirectory(examples)
endif()
#===============================================================================
# Install and Packaging
#===============================================================================
if (NOT AKANTU_BYPASS_AKANTU_TARGET)
include(AkantuInstall)
option(AKANTU_DISABLE_CPACK
"This option commands the generation of extra info for the \"make package\" target" ON)
mark_as_advanced(AKANTU_DISABLE_CPACK)
if(NOT AKANTU_DISABLE_CPACK)
include(AkantuCPack)
endif()
endif()
diff --git a/cmake/AkantuExtraCompilationProfiles.cmake b/cmake/AkantuExtraCompilationProfiles.cmake
index d25cb5976..571c3f9f9 100644
--- a/cmake/AkantuExtraCompilationProfiles.cmake
+++ b/cmake/AkantuExtraCompilationProfiles.cmake
@@ -1,119 +1,123 @@
#===============================================================================
# @file AkantuExtraCompilationProfiles.cmake
#
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Fri Dec 02 2016
# @date last modification: Wed Feb 03 2021
#
# @brief Compilation profiles
#
#
# @section LICENSE
#
# Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
option (FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." FALSE)
mark_as_advanced(FORCE_COLORED_OUTPUT)
if(FORCE_COLORED_OUTPUT)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_flags(cxx "-fcolor-diagnostics")
else()
add_flags(cxx "-fdiagnostics-color=always")
endif()
endif()
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DAKANTU_NDEBUG"
CACHE STRING "Flags used by the compiler during release builds" FORCE)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} -ggdb3"
CACHE STRING "Flags used by the compiler during debug builds" FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT} -ggdb3"
CACHE STRING "Flags used by the compiler during debug builds" FORCE)
endif()
function(declare_compilation_profile name)
include(CMakeParseArguments)
cmake_parse_arguments(_args
"" "COMPILER;LINKER;DOC" "" ${ARGN})
string(TOUPPER "${name}" _u_name)
if(NOT _args_DOC)
string(TOLOWER "${name}" _args_DOC)
endif()
if(NOT _args_COMPILER)
message(FATAL_ERROR "declare_compilation_profile: you should at least give COMPILER flags")
endif()
if(NOT _args_LINKER)
set(_args_LINKER ${_args_COMPILER})
endif()
foreach(_flag CXX C Fortran SHARED_LINKER EXE_LINKER)
set(_stage "compiler")
set(_flags ${_args_COMPILER})
if(_stage MATCHES ".*LINKER")
set(_stage "linker")
set(_flags ${_args_LINKER})
endif()
set(CMAKE_${_flag}_FLAGS_${_u_name} ${_flags}
CACHE STRING "Flags used by the ${_stage} during coverage builds" FORCE)
mark_as_advanced(CMAKE_${_flag}_FLAGS_${_u_name})
endforeach()
endfunction()
# Profiling
declare_compilation_profile(PROFILING
COMPILER "-g -ggdb3 -pg -DNDEBUG -DAKANTU_NDEBUG -O3")
# Valgrind
declare_compilation_profile(VALGRIND
- COMPILER "-g -ggdb3 -O3")
+ COMPILER "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -O3")
# Coverage
declare_compilation_profile(COVERAGE
COMPILER "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -O2 --coverage")
# Sanitize the code
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.2") OR
CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(_blacklist " -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/cmake/sanitize-blacklist.txt")
endif()
declare_compilation_profile(SANITIZE
COMPILER "-g -ggdb3 -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer${_blacklist}")
+
+ declare_compilation_profile(SANITIZE_DEBUG
+ COMPILER "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer${_blacklist}")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
declare_compilation_profile(SANITIZEMEMORY
COMPILER "-g -ggdb3 -O2 -fPIE -fsanitize=memory -fsanitize-memory-track-origins -fsanitize-recover=all -fno-omit-frame-pointer -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/cmake/sanitize-blacklist.txt"
DOC "\"sanitize memory\"")
endif()
-if (CMAKE_BUILD_TYPE MATCHES "[Vv][Aa][Ll][Gg][Rr][Ii][Nn][Dd]")
+string(TOLOWER "${CMAKE_BUILD_TYPE}" _cmake_build_type_lower)
+if (_cmake_build_type_lower MATCHES "valgrind")
find_program(VALGRIND_EXECUTABLE valgrind)
endif()
diff --git a/cmake/AkantuMacros.cmake b/cmake/AkantuMacros.cmake
index 0615d7b41..c83535623 100644
--- a/cmake/AkantuMacros.cmake
+++ b/cmake/AkantuMacros.cmake
@@ -1,274 +1,302 @@
#===============================================================================
# @file AkantuMacros.cmake
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Fri Oct 22 2010
# @date last modification: Tue Mar 24 2020
#
# @brief Set of macros used by akantu cmake files
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
#===============================================================================
function(set_third_party_shared_libirary_name _var _lib)
set(${_var}
${PROJECT_BINARY_DIR}/third-party/lib/${CMAKE_SHARED_LIBRARY_PREFIX}${_lib}${CMAKE_SHARED_LIBRARY_SUFFIX}
CACHE FILEPATH "" FORCE)
endfunction()
# ==============================================================================
function(_add_file_to_copy target file)
get_filename_component(_file_name_we ${file} NAME_WE)
get_filename_component(_file_name_ext ${file} EXT)
get_filename_component(_file_name ${file} NAME)
get_filename_component(_file_path ${file}
ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
configure_file(
${_file_path}
${CMAKE_CURRENT_BINARY_DIR}/${_file_name}
COPYONLY)
# set(copy_target copy_${_file_name_we}_${_file_name_ext}_${target})
# add_custom_target(${copy_target}
# DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_file_name})
# add_custom_command(
# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_file_name}
# COMMAND ${CMAKE_COMMAND} -E copy_if_different
# ${file}
# ${CMAKE_CURRENT_BINARY_DIR}
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
# DEPENDS ${_file_path}
# COMMENT "Copying file ${_file_name} for the target ${target}"
# )
# add_dependencies(${target} ${copy_target})
endfunction()
# ==============================================================================
function(get_target_list_of_associated_files tgt files)
if(TARGET ${tgt})
get_target_property(_type ${tgt} TYPE)
else()
set(_type ${tgt}-NOTFOUND)
endif()
if(_type STREQUAL "SHARED_LIBRARY"
OR _type STREQUAL "STATIC_LIBRARY"
OR _type STREQUAL "MODULE_LIBRARY"
OR _type STREQUAL "EXECUTABLE")
get_target_property(_srcs ${tgt} SOURCES)
set(_dep_ressources)
foreach(_file ${_srcs})
list(APPEND _dep_ressources ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
endforeach()
elseif(_type)
get_target_property(_dep_ressources ${tgt} RESSOURCES)
endif()
set(${files} ${_dep_ressources} PARENT_SCOPE)
endfunction()
#===============================================================================
# Generate the list of currently loaded materials
function(generate_material_list)
message(STATUS "Determining the list of recognized materials...")
package_get_all_include_directories(
AKANTU_LIBRARY_INCLUDE_DIRS
)
package_get_all_external_informations(
PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR
INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR
LIBRARIES AKANTU_EXTERNAL_LIBRARIES
)
set(_include_dirs
${AKANTU_INCLUDE_DIRS}
${AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR}
${AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR}
)
try_run(_material_list_run _material_list_compile
${CMAKE_BINARY_DIR}
${PROJECT_SOURCE_DIR}/cmake/material_lister.cc
- CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${_include_dirs}" "-DCMAKE_CXX_STANDARD=14"
+ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${_include_dirs}" "-DCMAKE_CXX_STANDARD=${AKANTU_CXX_STANDARD}"
COMPILE_DEFINITIONS "-DAKANTU_CMAKE_LIST_MATERIALS"
COMPILE_OUTPUT_VARIABLE _compile_results
RUN_OUTPUT_VARIABLE _result_material_list)
if(_material_list_compile AND "${_material_list_run}" EQUAL 0)
message(STATUS "Materials included in Akantu:")
string(REPLACE "\n" ";" _material_list "${_result_material_list}")
foreach(_mat ${_material_list})
string(REPLACE ":" ";" _mat_key "${_mat}")
list(GET _mat_key 0 _key)
list(GET _mat_key 1 _class)
list(LENGTH _mat_key _l)
if("${_l}" GREATER 2)
list(REMOVE_AT _mat_key 0 1)
set(_opt " -- options: [")
foreach(_o ${_mat_key})
set(_opt "${_opt} ${_o}")
endforeach()
set(_opt "${_opt} ]")
else()
set(_opt "")
endif()
message(STATUS " ${_class} -- key: ${_key}${_opt}")
endforeach()
else()
message(STATUS "Could not determine the list of materials.")
message("${_compile_results}")
endif()
endfunction()
#===============================================================================
# Declare the options for the types and defines the approriate typedefs
function(declare_akantu_types)
set(AKANTU_TYPE_FLOAT "double (64bit)" CACHE STRING "Precision force floating point types")
mark_as_advanced(AKANTU_TYPE_FLOAT)
set_property(CACHE AKANTU_TYPE_FLOAT PROPERTY STRINGS
"quadruple (128bit)"
"double (64bit)"
"float (32bit)"
)
set(AKANTU_TYPE_INTEGER "int (32bit)" CACHE STRING "Size of the integer types")
mark_as_advanced(AKANTU_TYPE_INTEGER)
set_property(CACHE AKANTU_TYPE_INTEGER PROPERTY STRINGS
"int (32bit)"
"long int (64bit)"
)
include(CheckTypeSize)
# ----------------------------------------------------------------------------
# Floating point types
# ----------------------------------------------------------------------------
if(AKANTU_TYPE_FLOAT STREQUAL "float (32bit)")
set(AKANTU_FLOAT_TYPE "float" CACHE INTERNAL "")
set(AKANTU_FLOAT_SIZE 4 CACHE INTERNAL "")
elseif(AKANTU_TYPE_FLOAT STREQUAL "double (64bit)")
set(AKANTU_FLOAT_TYPE "double" CACHE INTERNAL "")
set(AKANTU_FLOAT_SIZE 8 CACHE INTERNAL "")
elseif(AKANTU_TYPE_FLOAT STREQUAL "quadruple (128bit)")
check_type_size("long double" LONG_DOUBLE)
if(HAVE_LONG_DOUBLE)
set(AKANTU_FLOAT_TYPE "long double" CACHE INTERNAL "")
set(AKANTU_FLOAT_SIZE 16 CACHE INTERNAL "")
message("This feature is not tested and will most probably not compile")
else()
message(FATAL_ERROR "The type long double is not defined on your system")
endif()
else()
message(FATAL_ERROR "The float type is not defined")
endif()
include(CheckIncludeFileCXX)
include(CheckCXXSourceCompiles)
# ----------------------------------------------------------------------------
# Integer types
# ----------------------------------------------------------------------------
check_include_file_cxx(cstdint HAVE_CSTDINT)
if(NOT HAVE_CSTDINT)
check_include_file_cxx(stdint.h HAVE_STDINT_H)
if(HAVE_STDINT_H)
list(APPEND _int_include stdint.h)
endif()
else()
list(APPEND _int_include cstdint)
endif()
check_include_file_cxx(cstddef HAVE_CSTDDEF)
if(NOT HAVE_CSTDINT)
check_include_file_cxx(stddef.h HAVE_STDDEF_H)
if(HAVE_STDINT_H)
list(APPEND _int_include stddef.h)
endif()
else()
list(APPEND _int_include cstddef)
endif()
if(AKANTU_TYPE_INTEGER STREQUAL "int (32bit)")
set(AKANTU_INTEGER_SIZE 4 CACHE INTERNAL "")
check_type_size("int" INT)
if(INT EQUAL 4)
set(AKANTU_SIGNED_INTEGER_TYPE "int" CACHE INTERNAL "")
set(AKANTU_UNSIGNED_INTEGER_TYPE "unsigned int" CACHE INTERNAL "")
else()
check_type_size("int32_t" INT32_T LANGUAGE CXX)
if(HAVE_INT32_T)
set(AKANTU_SIGNED_INTEGER_TYPE "int32_t" CACHE INTERNAL "")
set(AKANTU_UNSIGNED_INTEGER_TYPE "uint32_t" CACHE INTERNAL "")
list(APPEND _extra_includes ${_int_include})
endif()
endif()
elseif(AKANTU_TYPE_INTEGER STREQUAL "long int (64bit)")
set(AKANTU_INTEGER_SIZE 8 CACHE INTERNAL "")
check_type_size("long int" LONG_INT)
if(LONG_INT EQUAL 8)
set(AKANTU_SIGNED_INTEGER_TYPE "long int" CACHE INTERNAL "")
set(AKANTU_UNSIGNED_INTEGER_TYPE "unsigned long int" CACHE INTERNAL "")
else()
check_type_size("long long int" LONG_LONG_INT)
if(HAVE_LONG_LONG_INT AND LONG_LONG_INT EQUAL 8)
set(AKANTU_SIGNED_INTEGER_TYPE "long long int" CACHE INTERNAL "")
set(AKANTU_UNSIGNED_INTEGER_TYPE "unsigned long long int" CACHE INTERNAL "")
else()
check_type_size("int64_t" INT64_T)
if(HAVE_INT64_T)
set(AKANTU_SIGNED_INTEGER_TYPE "int64_t" CACHE INTERNAL "")
set(AKANTU_UNSIGNED_INTEGER_TYPE "uint64_t" CACHE INTERNAL "")
list(APPEND _extra_includes ${_int_include})
endif()
endif()
endif()
else()
message(FATAL_ERROR "The integer type is not defined")
endif()
# ----------------------------------------------------------------------------
# includes
# ----------------------------------------------------------------------------
foreach(_inc ${_extra_includes})
set(_incs "#include <${_inc}>\n${_incs}")
endforeach()
set(AKANTU_TYPES_EXTRA_INCLUDES ${_incs} CACHE INTERNAL "")
+
+ # ----------------------------------------------------------------------------
+ set(CMAKE_REQUIRED_FLAGS "-Werror -Wall -std=c++${AKANTU_CXX_STANDARD}")
+ set(CMAKE_REQUIRED_INCLUDES "${PROJECT_SOURCE_DIR}/src/common")
+ file(READ ${PROJECT_SOURCE_DIR}/cmake/check_constexpr_map.cc _check_constexpr_map_code)
+ check_cxx_source_compiles("${_check_constexpr_map_code}"
+ can_compile_constexpr_map)
+
+ if(can_compile_constexpr_map EQUAL 1)
+ set(AKANTU_CAN_COMPILE_CONSTEXPR_MAP TRUE CACHE INTERNAL "")
+ else()
+ set(AKANTU_CAN_COMPILE_CONSTEXPR_MAP FALSE CACHE INTERNAL "")
+ endif()
+
+
+ file(READ ${PROJECT_SOURCE_DIR}/cmake/check_gnu_unlikely.cc _has_gnu_unlikely_code)
+ check_cxx_source_compiles("${_has_unlikely_code}"
+ has_gnu_unlikely)
+ if(has_gnu_unlikely EQUAL 1)
+ set(AKANTU_HAS_GNU_UNLIKELY FALSE CACHE INTERNAL "")
+ else()
+ file(READ ${PROJECT_SOURCE_DIR}/cmake/check_builtin_expect.cc _has_builtin_expect_code)
+ check_cxx_source_compiles("${_has_builtin_expect_code}"
+ has_builtin_expect)
+ if(has_builtin_expect EQUAL 1)
+ set(AKANTU_HAS_BUILTIN_EXPECT FALSE CACHE INTERNAL "")
+ endif()
+ endif()
endfunction()
function(mask_package_options prefix)
get_property(_list DIRECTORY PROPERTY VARIABLES)
foreach(_var ${_list})
if("${_var}" MATCHES "^${prefix}.*")
mark_as_advanced(${_var})
endif()
endforeach()
endfunction()
diff --git a/cmake/AkantuNeedPybind11.cmake b/cmake/AkantuNeedPybind11.cmake
index e23bb6d94..d4e25de5d 100644
--- a/cmake/AkantuNeedPybind11.cmake
+++ b/cmake/AkantuNeedPybind11.cmake
@@ -1,16 +1,18 @@
if(DEFINED AKANTU_NEED_PYBIND11_LOADED)
return()
endif()
set(AKANTU_NEED_PYBIND11_LOADED TRUE)
set(PYBIND11_PYTHON_VERSION ${AKANTU_PREFERRED_PYTHON_VERSION} CACHE INTERNAL "")
find_package(pybind11 QUIET)
if (NOT pybind11_FOUND)
set(PYBIND11_VERSION "v2.4.2")
set(PYBIND11_GIT "https://github.com/pybind/pybind11.git")
include(${PROJECT_SOURCE_DIR}/third-party/cmake/pybind11.cmake)
+else()
+ message(STATUS "Found pybind11: ${pybind11_INCLUDE_DIRS} (${pybind11_VERSION})")
endif()
diff --git a/cmake/AkantuPackagesSystem.cmake b/cmake/AkantuPackagesSystem.cmake
index e26ebcda4..bb71c483a 100644
--- a/cmake/AkantuPackagesSystem.cmake
+++ b/cmake/AkantuPackagesSystem.cmake
@@ -1,354 +1,155 @@
#===============================================================================
# @file AkantuPackagesSystem.cmake
#
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Sat Jul 18 2015
# @date last modification: Fri Mar 16 2018
#
# @brief Addition to the PackageSystem specific for Akantu
#
#
# @section LICENSE
#
# Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
-#===============================================================================
-# Element Types
-#===============================================================================
-#-------------------------------------------------------------------------------
-function(package_declare_elements pkg)
- set(_options
- KIND
- ELEMENT_TYPES
- GEOMETRICAL_TYPES
- INTERPOLATION_TYPES
- GEOMETRICAL_SHAPES
- GAUSS_INTEGRATION_TYPES
- INTERPOLATION_KIND
- FE_ENGINE_LISTS
- )
-
- cmake_parse_arguments(_opt_pkg
- ""
- ""
- "${_options}"
- ${ARGN})
-
- foreach(_opt ${_options})
- if(_opt_pkg_${_opt})
- package_set_variable(ET_${_opt} ${pkg} ${_opt_pkg_${_opt}})
- endif()
- endforeach()
-endfunction()
-
-#-------------------------------------------------------------------------------
-function(_transfer_list_to_enum types enum)
- if(${enum})
- set(_enum_tmp ${${enum}})
- else()
- unset(_enum_tmp)
- endif()
-
- foreach(_type ${${types}})
- # defining the types for the enum
- if(DEFINED _enum_tmp)
- set(_enum_tmp "${_enum_tmp}
- ${_type},")
- else()
- set(_enum_tmp "${_type},")
- endif()
- endforeach()
-
- set(${enum} ${_enum_tmp} PARENT_SCOPE)
-endfunction()
-
-
-#-------------------------------------------------------------------------------
-function(_transfer_list_to_boost_seq types boost_seq)
- if(${boost_seq})
- set(_boost_seq_tmp ${${boost_seq}})
- endif()
-
- foreach(_type ${${types}})
- if(DEFINED _boost_seq_tmp)
- set(_boost_seq_tmp "${_boost_seq_tmp}${_tabs}\\
- (${_type})")
- else()
- set(_boost_seq_tmp " (${_type})")
- endif()
-
- string(LENGTH "${_type}" _length)
- if(_length LESS 13)
- set(_tabs "\t\t\t\t")
- elseif(_length LESS 28)
- set(_tabs "\t\t\t")
- else()
- set(_tabs "\t\t")
- endif()
- endforeach()
-
- set(${boost_seq} ${_boost_seq_tmp} PARENT_SCOPE)
-endfunction()
-
-#-------------------------------------------------------------------------------
-function(package_get_element_lists)
- package_get_all_activated_packages(_activated_list)
-
- set(_lists
- KIND
- ELEMENT_TYPES
- GEOMETRICAL_TYPES
- INTERPOLATION_TYPES
- GEOMETRICAL_SHAPES
- GAUSS_INTEGRATION_TYPES
- INTERPOLATION_TYPES
- INTERPOLATION_KIND
- FE_ENGINE_LISTS
- )
-
- set(_element_kind "#define AKANTU_ELEMENT_KIND")
- set(_all_element_types "#define AKANTU_ALL_ELEMENT_TYPE\t")
-
- set(_inter_types_boost_seq "#define AKANTU_INTERPOLATION_TYPES\t\t")
-
- foreach(_pkg_name ${_activated_list})
- foreach(_list ${_lists})
- string(TOLOWER "${_list}" _l_list)
- _package_get_variable(ET_${_list} ${_pkg_name} _${_l_list})
- _transfer_list_to_enum(_${_l_list} _${_l_list}_enum)
- endforeach()
-
- if(_interpolation_types)
- _transfer_list_to_boost_seq(_interpolation_types _inter_types_boost_seq)
- endif()
-
- if(_kind)
- string(TOUPPER "${_kind}" _u_kind)
- if(_element_types)
- set(_boosted_element_types "${_boosted_element_types}
-#define AKANTU_ek_${_kind}_ELEMENT_TYPE\t")
- _transfer_list_to_boost_seq(_element_types _boosted_element_types)
- set(_boosted_element_types "${_boosted_element_types}\n")
-
- # defininf the kinds variables
- set(_element_kinds "${_element_kinds}
-#define AKANTU_${_u_kind}_KIND\t(_ek_${_kind})")
-
- # defining the full list of element
- set(_all_element_types "${_all_element_types}\t\\
- AKANTU_ek_${_kind}_ELEMENT_TYPE")
- endif()
-
- # defining the full list of kinds
- set(_element_kind "${_element_kind}${_kind_tabs}\t\t\\
- AKANTU_${_u_kind}_KIND")
- set(_kind_tabs "\t")
-
- # defining the macros
- set(_boost_macros "${_boost_macros}
-#define AKANTU_BOOST_${_u_kind}_ELEMENT_SWITCH(macro) \\
- AKANTU_BOOST_ELEMENT_SWITCH(macro, \\
- AKANTU_ek_${_kind}_ELEMENT_TYPE)
-
-#define AKANTU_BOOST_${_u_kind}_ELEMENT_LIST(macro) \\
- AKANTU_BOOST_APPLY_ON_LIST(macro, \\
- AKANTU_ek_${_kind}_ELEMENT_TYPE)
-")
-
- list(APPEND _aka_fe_lists ${_fe_engine_lists})
- foreach(_fe_engine_list ${_fe_engine_lists})
- if(NOT DEFINED _fe_engine_list_${_fe_engine_list})
- string(TOUPPER "${_fe_engine_list}" _u_list)
- string(LENGTH "#define AKANTU_FE_ENGINE_LIST_${_u_list}" _length)
- math(EXPR _length "72 - ${_length}")
- set(_space "")
- while(_length GREATER 0)
- if(CMAKE_VERSION VERSION_GREATER 3.0)
- string(CONCAT _space "${_space}" " ")
- else()
- set(_space "${_space} ")
- endif()
- math(EXPR _length "${_length} - 1")
- endwhile()
-
- set(_fe_engine_list_${_fe_engine_list}
- "#define AKANTU_FE_ENGINE_LIST_${_u_list}${_space}\\
- AKANTU_GENERATE_KIND_LIST((_ek_${_kind})")
- else()
- set(_fe_engine_list_${_fe_engine_list}
- "${_fe_engine_list_${_fe_engine_list}}\t\t\t\t\\
- (_ek_${_kind})")
- endif()
- endforeach()
- endif()
- endforeach()
-
- if(_aka_fe_lists)
- list(REMOVE_DUPLICATES _aka_fe_lists)
- foreach(_fe_list ${_aka_fe_lists})
- set(_aka_fe_defines "${_fe_engine_list_${_fe_list}})\n${_aka_fe_defines}")
- endforeach()
- endif()
-
- foreach(_list ${_lists})
- string(TOLOWER "${_list}" _l_list)
- set(AKANTU_${_list}_ENUM ${_${_l_list}_enum} PARENT_SCOPE)
- endforeach()
-
- set(AKANTU_INTERPOLATION_TYPES_BOOST_SEQ ${_inter_types_boost_seq} PARENT_SCOPE)
- set(AKANTU_ELEMENT_TYPES_BOOST_SEQ ${_boosted_element_types} PARENT_SCOPE)
- set(AKANTU_ELEMENT_KINDS_BOOST_SEQ ${_element_kinds} PARENT_SCOPE)
- set(AKANTU_ELEMENT_KIND_BOOST_SEQ ${_element_kind} PARENT_SCOPE)
- set(AKANTU_ALL_ELEMENT_BOOST_SEQ ${_all_element_types} PARENT_SCOPE)
- set(AKANTU_ELEMENT_KINDS_BOOST_MACROS ${_boost_macros} PARENT_SCOPE)
- set(AKANTU_FE_ENGINE_LISTS ${_aka_fe_defines} PARENT_SCOPE)
-endfunction()
-
-#-------------------------------------------------------------------------------
-function(package_get_element_types pkg list)
- package_get_name(${pkg} _pkg_name)
- _package_get_variable(ET_ELEMENT_TYPES ${_pkg_name} _tmp_list)
- set(${list} ${_tmp_list} PARENT_SCOPE)
-endfunction()
-
#===============================================================================
# Material specific
#===============================================================================
#-------------------------------------------------------------------------------
function(package_declare_material_infos pkg)
cmake_parse_arguments(_opt_pkg
""
""
"LIST;INCLUDE"
${ARGN})
package_set_variable(MATERIAL_LIST ${pkg} ${_opt_pkg_LIST})
package_set_variable(MATERIAL_INCLUDE ${pkg} ${_opt_pkg_INCLUDE})
endfunction()
#-------------------------------------------------------------------------------
function(package_get_all_material_includes includes)
_package_get_variable_for_activated(MATERIAL_INCLUDE _includes)
foreach(_mat_inc ${_includes})
if(DEFINED _mat_includes)
set(_mat_includes "${_mat_includes}\n#include \"${_mat_inc}\"")
else()
set(_mat_includes "#include \"${_mat_inc}\"")
endif()
endforeach()
set(${includes} ${_mat_includes} PARENT_SCOPE)
endfunction()
#-------------------------------------------------------------------------------
function(package_get_all_material_lists lists)
_package_get_variable_for_activated(MATERIAL_LIST _lists)
foreach(_mat_list ${_lists})
if(DEFINED _mat_lists)
set(_mat_lists "${_mat_lists}\n ${_mat_list}\t\t\t\\")
else()
set(_mat_lists " ${_mat_list}\t\t\t\\")
endif()
endforeach()
set(${lists} ${_mat_lists} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Extra files to consider in source package generated by CPack
# ------------------------------------------------------------------------------
function(package_declare_extra_files_to_package pkg)
set(_types SOURCES MANUAL TESTS PROJECT)
cmake_parse_arguments(_extra_files
""
""
"${_types}"
${ARGN})
set(_files ${_extra_files_UNPARSED_ARGUMENTS})
package_get_sources_folder(${pkg} _folder_SOURCES)
package_get_manual_folder(${pkg} _folder_MANUAL)
package_get_tests_folder(${pkg} _folder_TESTS)
set(_folder_PROJECT ${PROJECT_SOURCE_DIR})
foreach(_type ${_types})
if(_extra_files_${_type})
foreach(_file ${_extra_files_${_type}})
list(APPEND _files ${_folder_${_type}}/${_file})
if(NOT EXISTS ${_folder_${_type}}/${_file})
message(SEND_ERROR "The package ${pkg} tries to register the file ${_file} (as a ${_type} file).
This file cannot be found.")
endif()
endforeach()
endif()
endforeach()
package_set_variable(EXTRA_FILES ${pkg} ${_files})
endfunction()
# ------------------------------------------------------------------------------
function(package_add_files_to_package)
set(_files)
foreach(_file ${ARGN})
list(APPEND _files ${PROJECT_SOURCE_DIR}/${_file})
endforeach()
package_add_to_project_variable(EXTRA_FILES ${_files})
endfunction()
function(package_get_files_for_package files)
package_get_project_variable(EXTRA_FILES _tmp)
set(${files} ${_tmp} PARENT_SCOPE)
endfunction()
package_add_files_to_package(
.clang-format
AUTHORS
README
VERSION
COPYING
COPYING.lesser
CTestConfig.cmake
cmake/akantu_environement.sh.in
cmake/akantu_environement.csh.in
cmake/akantu_install_environement.sh.in
cmake/akantu_install_environement.csh.in
cmake/Modules/CMakeFlagsHandling.cmake
cmake/Modules/CMakePackagesSystem.cmake
cmake/Modules/CMakePackagesSystemGlobalFunctions.cmake
cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake
cmake/Modules/CMakeVersionGenerator.cmake
cmake/Modules/PCHgcc.cmake
cmake/AkantuBuildTreeSettings.cmake.in
cmake/AkantuConfig.cmake.in
cmake/AkantuCPack.cmake
cmake/AkantuCPackMacros.cmake
cmake/AkantuInstall.cmake
cmake/AkantuMacros.cmake
cmake/AkantuPackagesSystem.cmake
cmake/AkantuUse.cmake
cmake/AkantuSimulationMacros.cmake
cmake/material_lister.cc
cmake/Modules/FindGMSH.cmake
)
diff --git a/cmake/AkantuTestsMacros.cmake b/cmake/AkantuTestsMacros.cmake
index 19e4134c9..f9c2c7b2d 100644
--- a/cmake/AkantuTestsMacros.cmake
+++ b/cmake/AkantuTestsMacros.cmake
@@ -1,656 +1,655 @@
#===============================================================================
# @file AkantuTestsMacros.cmake
#
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Fri Sep 03 2010
# @date last modification: Tue Jun 30 2020
#
# @brief macros for tests
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
#[=======================================================================[.rst:
AkantuTestsMacros
-----------------
This modules provides the functions to helper to declare tests and folders
containing tests in akantu
.. command:: add_test_tree
add_test_tree(<test_direcotry>)
``<test_directory>`` is the entry direcroty of the full structure of
subfolders containing tests
.. command:: add_akantu_test
add_akantu_test(<dir> <desc>)
This function add a subdirectory ``<dir>`` of tests that will be conditionnaly
activable and will be visible only if the parent folder as been activated An
option ``AKANTU_BUILD_TEST_<dir>`` will appear in ccmake with the description
``<desc>``. The compilation of all tests can be forced with the option
``AKANTU_BUILD_ALL_TESTS``
.. command:: register_test
register_test(<test_name>
SOURCES <sources>...
PACKAGE <akantu_packages>...
SCRIPT <scirpt>
[FILES_TO_COPY <filenames>...]
[DEPENDS <targets>...]
[DIRECTORIES_TO_CREATE <directories>...]
[COMPILE_OPTIONS <flags>...]
[EXTRA_FILES <filnames>...]
[LINK_LIBRARIES <libraries>...]
[INCLUDE_DIRECTORIES <include>...]
[UNSABLE]
[PARALLEL]
[PARALLEL_LEVEL <procs>...]
)
This function defines a test ``<test_name>_run`` this test could be of
different nature depending on the context. If Just sources are provided the
test consist of running the executable generated. If a file ``<test_name>.sh``
is present the test will execute the script. And if a ``<test_name>.verified``
exists the output of the test will be compared to this reference file
The options are:
``SOURCES <sources>...``
The list of source files to compile to generate the executable of the test
``PACKAGE <akantu_packages>...``
The list of package to which this test belongs. The test will be activable
only of all the packages listed are activated
``SCRIPT <script>``
The script to execute instead of the executable
``FILES_TO_COPY <filenames>...``
List of files to copy from the source directory to the build directory
``DEPENDS <targets>...``
List of targets the test depends on, for example if a mesh as to be generated
``DIRECTORIES_TO_CREATE <directories>...``
Obsolete. This specifies a list of directories that have to be created in
the build folder
``COMPILE_OPTIONS <flags>...``
List of extra compilations options to pass to the compiler
``EXTRA_FILES <filnames>...``
Files to consider when generating a package_source
``UNSABLE``
If this option is specified the test can be unacitivated by the glocal option
``AKANTU_BUILD_UNSTABLE_TESTS``, this is mainly intendeed to remove test
under developement from the continious integration
``PARALLEL``
This specifies that this test should be run in parallel. It will generate a
series of test for different number of processors. This automaticaly adds a
dependency to the package ``AKANTU_PARALLEL``
``PARALLEL_LEVEL``
This defines the different processor numbers to use, if not defined the
macro tries to determine it in a "clever" way
]=======================================================================]
set(AKANTU_DRIVER_SCRIPT ${AKANTU_CMAKE_DIR}/akantu_test_driver.sh)
# ==============================================================================
macro(add_test_tree dir)
if(AKANTU_TESTS)
enable_testing()
include(CTest)
mark_as_advanced(BUILD_TESTING)
set(_akantu_current_parent_test ${dir} CACHE INTERNAL "Current test folder" FORCE)
set(_akantu_${dir}_tests_count 0 CACHE INTERNAL "" FORCE)
string(TOUPPER ${dir} _u_dir)
set(AKANTU_BUILD_${_u_dir} ON CACHE INTERNAL "${desc}" FORCE)
package_get_all_test_folders(_test_dirs)
foreach(_dir ${_test_dirs})
add_subdirectory(${_dir})
endforeach()
endif()
endmacro()
set(_test_flags
UNSTABLE
PARALLEL
PYTHON
GTEST
HEADER_ONLY
)
set(_test_one_variables
POSTPROCESS
SCRIPT
)
set(_test_multi_variables
SOURCES
FILES_TO_COPY
DEPENDS
DIRECTORIES_TO_CREATE
COMPILE_OPTIONS
EXTRA_FILES
LINK_LIBRARIES
INCLUDE_DIRECTORIES
PACKAGE
PARALLEL_LEVEL
)
# ==============================================================================
function(add_akantu_test dir desc)
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
return()
endif()
set(_my_parent_dir ${_akantu_current_parent_test})
# initialize variables
set(_akantu_current_parent_test ${dir} CACHE INTERNAL "Current test folder" FORCE)
set(_akantu_${dir}_tests_count 0 CACHE INTERNAL "" FORCE)
# set the option for this directory
string(TOUPPER ${dir} _u_dir)
option(AKANTU_BUILD_${_u_dir} "${desc}")
mark_as_advanced(AKANTU_BUILD_${_u_dir})
# add the sub-directory
add_subdirectory(${dir})
# if no test can be activated make the option disappear
set(_force_deactivate_count FALSE)
if(${_akantu_${dir}_tests_count} EQUAL 0)
set(_force_deactivate_count TRUE)
endif()
# if parent off make the option disappear
set(_force_deactivate_parent FALSE)
string(TOUPPER ${_my_parent_dir} _u_parent_dir)
if(NOT AKANTU_BUILD_${_u_parent_dir})
set(_force_deactivate_parent TRUE)
endif()
if(_force_deactivate_parent OR _force_deactivate_count OR AKANTU_BUILD_ALL_TESTS)
if(NOT DEFINED _AKANTU_BUILD_${_u_dir}_SAVE)
set(_AKANTU_BUILD_${_u_dir}_SAVE ${AKANTU_BUILD_${_u_dir}} CACHE INTERNAL "" FORCE)
endif()
unset(AKANTU_BUILD_${_u_dir} CACHE)
if(AKANTU_BUILD_ALL_TESTS AND NOT _force_deactivate_count)
set(AKANTU_BUILD_${_u_dir} ON CACHE INTERNAL "${desc}" FORCE)
else()
set(AKANTU_BUILD_${_u_dir} OFF CACHE INTERNAL "${desc}" FORCE)
endif()
else()
if(DEFINED _AKANTU_BUILD_${_u_dir}_SAVE)
unset(AKANTU_BUILD_${_u_dir} CACHE)
set(AKANTU_BUILD_${_u_dir} ${_AKANTU_BUILD_${_u_dir}_SAVE} CACHE BOOL "${desc}")
unset(_AKANTU_BUILD_${_u_dir}_SAVE CACHE)
endif()
endif()
# adding up to the parent count
math(EXPR _tmp_parent_count "${_akantu_${dir}_tests_count} + ${_akantu_${_my_parent_dir}_tests_count}")
set(_akantu_${_my_parent_dir}_tests_count ${_tmp_parent_count} CACHE INTERNAL "" FORCE)
# restoring the parent current dir
set(_akantu_current_parent_test ${_my_parent_dir} CACHE INTERNAL "Current test folder" FORCE)
endfunction()
function(is_test_active is_active)
cmake_parse_arguments(_register_test
"${_test_flags}"
"${_test_one_variables}"
"${_test_multi_variables}"
${ARGN}
)
if(NOT _register_test_PACKAGE)
message(FATAL_ERROR "No reference package was defined for the test"
" ${test_name} in folder ${CMAKE_CURRENT_SOURCE_DIR}")
endif()
if(_register_test_PYTHON)
list(APPEND _register_test_PACKAGE python_interface)
endif()
set(_test_act TRUE)
# Activate the test anly if all packages associated to the test are activated
foreach(_package ${_register_test_PACKAGE})
package_is_activated(${_package} _act)
if(NOT _act)
set(_test_act FALSE)
endif()
endforeach()
# check if the test is marked unstable and if the unstable test should be run
if(_register_test_UNSTABLE AND NOT AKANTU_BUILD_UNSTABLE_TESTS)
set(_test_act FALSE)
endif()
if(_test_act)
# todo this should be checked for the build package_sources since the file will not be listed.
math(EXPR _tmp_parent_count "${_akantu_${_akantu_current_parent_test}_tests_count} + 1")
set(_akantu_${_akantu_current_parent_test}_tests_count ${_tmp_parent_count} CACHE INTERNAL "" FORCE)
endif()
string(TOUPPER ${_akantu_current_parent_test} _u_parent)
if(NOT (AKANTU_BUILD_${_u_parent} OR AKANTU_BUILD_ALL_TESTS))
set(_test_act FALSE)
endif()
set(${is_active} ${_test_act} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
function(register_gtest_sources)
cmake_parse_arguments(_register_test
"${_test_flags}"
"${_test_one_variables}"
"${_test_multi_variables}"
${ARGN}
)
is_test_active(_is_active ${ARGN})
register_test_files_to_package(${ARGN})
if(NOT _is_active)
return()
endif()
if(_register_test_PACKAGE)
set(_list ${_gtest_PACKAGE})
list(APPEND _list ${_register_test_PACKAGE})
list(REMOVE_DUPLICATES _list)
set(_gtest_PACKAGE ${_list} PARENT_SCOPE)
endif()
foreach (_var ${_test_flags})
if(_var STREQUAL "HEADER_ONLY")
if(NOT DEFINED_register_test_${_var})
set(_gtest_${_var} OFF PARENT_SCOPE)
elseif(NOT DEFINED _gtest_${_var})
set(_gtest_${_var} ON PARENT_SCOPE)
endif()
continue()
endif()
if(_register_test_${_var})
set(_gtest_${_var} ON PARENT_SCOPE)
else()
if(_gtest_${_var})
message("Another gtest file required ${_var} to be ON it will be globally set for this folder...")
endif()
endif()
endforeach()
if(_register_test_UNPARSED_ARGUMENTS)
list(APPEND _register_test_SOURCES ${_register_test_UNPARSED_ARGUMENTS})
endif()
foreach (_var ${_test_multi_variables})
if(_register_test_${_var})
set(_list ${_gtest_${_var}})
list(APPEND _list ${_register_test_${_var}})
list(REMOVE_DUPLICATES _list)
set(_gtest_${_var} ${_list} PARENT_SCOPE)
endif()
endforeach()
endfunction()
# ==============================================================================
function(akantu_pybind11_add_module target)
if(pybind11_FOUND)
package_get_all_external_informations(
INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR
)
pybind11_add_module(${target} ${ARGN})
target_link_libraries(${target} PRIVATE akantu)
target_include_directories(${target} SYSTEM PRIVATE ${PYBIND11_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/python)
set_property(TARGET ${target} PROPERTY DEBUG_POSTFIX "")
endif()
endfunction()
# ==============================================================================
function(register_gtest_test test_name)
if(NOT _gtest_PACKAGE)
return()
endif()
set(_argn ${test_name}_gtest)
set(_link_libraries GTest::GTest GTest::Main)
list(FIND _gtest_PACKAGE python_interface _pos)
package_is_activated(python_interface _python_interface_act)
if(_python_interface_act AND (NOT _pos EQUAL -1))
list(APPEND _link_libraries pybind11::embed)
set(_compile_flags COMPILE_OPTIONS "AKANTU_TEST_USE_PYBIND11")
endif()
is_test_active(_is_active ${ARGN} PACKAGE ${_gtest_PACKAGE})
if(NOT _is_active)
return()
endif()
register_gtest_sources(${ARGN}
SOURCES ${PROJECT_SOURCE_DIR}/test/test_gtest_main.cc
LINK_LIBRARIES ${_link_libraries}
PACKAGE ${_gtest_PACKAGE}
${_compile_flags}
)
foreach (_var ${_test_flags})
if(_gtest_${_var})
list(APPEND _argn ${_var})
unset(_gtest_${_var})
endif()
endforeach()
foreach (_var ${_test_multi_variables})
if(_gtest_${_var})
list(APPEND _argn ${_var} ${_gtest_${_var}})
unset(_gtest_${_var})
endif()
endforeach()
register_test(${_argn} GTEST)
target_include_directories(${test_name}_gtest PRIVATE ${PROJECT_SOURCE_DIR}/test)
endfunction()
# ==============================================================================
function(register_test test_name)
cmake_parse_arguments(_register_test
"${_test_flags}"
"${_test_one_variables}"
"${_test_multi_variables}"
${ARGN}
)
register_test_files_to_package(${ARGN})
is_test_active(_test_act ${ARGN})
if(NOT _test_act)
return()
endif()
set(_extra_args)
# check that the sources are files that need to be compiled
if(_register_test_SOURCES} OR _register_test_UNPARSED_ARGUMENTS)
set(_need_to_compile TRUE)
else()
set(_need_to_compile FALSE)
endif()
set(_compile_source)
foreach(_file ${_register_test_SOURCES} ${_register_test_UNPARSED_ARGUMENTS})
if(_file MATCHES "\\.cc$" OR _file MATCHES "\\.hh$")
list(APPEND _compile_source ${_file})
endif()
endforeach()
if(_compile_source)
# get the include directories for sources in activated directories
package_get_all_include_directories(
AKANTU_LIBRARY_INCLUDE_DIRS
)
# get the external packages compilation and linking informations
package_get_all_external_informations(
INTERFACE_INCLUDE AKANTU_EXTERNAL_INCLUDE_DIR
)
foreach(_pkg ${_register_test_PACKAGE})
package_get_nature(${_pkg} _nature)
if(_nature MATCHES "^external.*")
package_get_include_dir(${_pkg} _incl)
package_get_libraries(${_pkg} _libs)
list(APPEND _register_test_INCLUDE_DIRECTORIES ${_incl})
list(APPEND _register_test_LINK_LIBRARIES ${_libs})
endif()
endforeach()
# Register the executable to compile
add_executable(${test_name} ${_compile_source})
# set the proper includes to build most of the tests
target_include_directories(${test_name}
PRIVATE ${AKANTU_LIBRARY_INCLUDE_DIRS}
${AKANTU_EXTERNAL_INCLUDE_DIR}
${PROJECT_BINARY_DIR}/src
${_register_test_INCLUDE_DIRECTORIES})
if(NOT _register_test_HEADER_ONLY)
target_link_libraries(${test_name} PRIVATE akantu ${_register_test_LINK_LIBRARIES})
else()
get_target_property(_features akantu INTERFACE_COMPILE_FEATURES)
target_link_libraries(${test_name} ${_register_test_LINK_LIBRARIES})
target_compile_features(${test_name} PRIVATE ${_features})
endif()
# add the extra compilation options
if(_register_test_COMPILE_OPTIONS)
set_target_properties(${test_name}
PROPERTIES COMPILE_DEFINITIONS "${_register_test_COMPILE_OPTIONS}")
endif()
if(AKANTU_EXTRA_CXX_FLAGS)
set_target_properties(${test_name}
PROPERTIES COMPILE_FLAGS "${AKANTU_EXTRA_CXX_FLAGS}")
endif()
else()
add_custom_target(${test_name} ALL)
if(_register_test_UNPARSED_ARGUMENTS AND NOT _register_test_SCRIPT)
set(_register_test_SCRIPT ${_register_test_UNPARSED_ARGUMENTS})
endif()
endif()
if(_register_test_DEPENDS)
add_dependencies(${test_name} ${_register_test_DEPENDS})
endif()
# copy the needed files to the build folder
if(_register_test_FILES_TO_COPY)
foreach(_file ${_register_test_FILES_TO_COPY})
_add_file_to_copy(${test_name} "${_file}")
endforeach()
endif()
# create the needed folders in the build folder
if(_register_test_DIRECTORIES_TO_CREATE)
foreach(_dir ${_register_test_DIRECTORIES_TO_CREATE})
if(IS_ABSOLUTE ${dir})
file(MAKE_DIRECTORY "${_dir}")
else()
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_dir}")
endif()
endforeach()
endif()
# register the test for ctest
set(_arguments -n "${test_name}")
if(_register_test_SCRIPT)
_add_file_to_copy(${test_name} ${_register_test_SCRIPT})
if(_register_test_PYTHON)
if(NOT PYTHONINTERP_FOUND)
find_package(PythonInterp ${AKANTU_PREFERRED_PYTHON_VERSION} REQUIRED)
endif()
list(APPEND _arguments -e "${PYTHON_EXECUTABLE}")
list(APPEND _extra_args "${_register_test_SCRIPT}")
add_dependencies(${test_name} py11_akantu)
else()
list(APPEND _arguments -e "./${_register_test_SCRIPT}")
endif()
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.sh")
_add_file_to_copy(${test_name} ${test_name}.sh)
list(APPEND _arguments -e "./${test_name}.sh")
else()
list(APPEND _arguments -e "./${test_name}")
endif()
if(_register_test_GTEST)
list(APPEND _extra_args "--" "--gtest_output=xml:${PROJECT_BINARY_DIR}/gtest_reports/${test_name}.xml")
endif()
list(APPEND _arguments -E "${PROJECT_BINARY_DIR}/akantu_environement.sh")
package_is_activated(parallel _is_parallel)
if(_is_parallel AND AKANTU_TESTS_ALWAYS_USE_MPI AND NOT _register_test_PARALLEL)
set(_register_test_PARALLEL TRUE)
set(_register_test_PARALLEL_LEVEL 1)
endif()
if(_register_test_PARALLEL AND _is_parallel)
set(_exe ${MPIEXEC})
if(NOT _exe)
set(_exe ${MPIEXEC_EXECUTABLE})
endif()
list(APPEND _arguments -p "${_exe} ${MPIEXEC_PREFLAGS} ${MPIEXEC_NUMPROC_FLAG}")
if(_register_test_PARALLEL_LEVEL)
set(_procs "${_register_test_PARALLEL_LEVEL}")
elseif(CMAKE_VERSION VERSION_GREATER "3.0")
set(_procs)
if(MPIEXEC_MAX_NUMPROCS)
set(N MPIEXEC_MAX_NUMPROCS)
else()
include(ProcessorCount)
ProcessorCount(N)
endif()
while(N GREATER 1)
list(APPEND _procs ${N})
math(EXPR N "${N} / 2")
endwhile()
list(APPEND _procs 1)
endif()
if(NOT _procs)
set(_procs 2)
endif()
endif()
if(_register_test_POSTPROCESS)
list(APPEND _arguments -s "${_register_test_POSTPROCESS}")
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${_register_test_POSTPROCESS}
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
endif()
list(APPEND _arguments -w "${CMAKE_CURRENT_BINARY_DIR}")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified")
list(APPEND _arguments -r "${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified")
- endif()
+ endif()
if(CMAKE_BUILD_TYPE MATCHES "[Vv][Aa][Ll][Gg][Rr][Ii][Nn][Dd]" AND VALGRINDXECUTABLE)
list(APPEND _arguments -v "${VALGRIND_EXECUTABLE} --error-exitcode=111 --leak-check=full --suppressions=${PROJECT_SOURCE_DIR}/test/ci/ompi_init.supp")
endif()
- string(REPLACE ";" " " _command "${_arguments}")
+ #string(REPLACE ";" " " _command "${_arguments}")
# register them test
if(_procs)
foreach(p ${_procs})
add_test(NAME ${test_name}_${p} COMMAND ${AKANTU_DRIVER_SCRIPT} ${_arguments} -N ${p} ${_extra_args})
set_property(TEST ${test_name}_${p} PROPERTY PROCESSORS ${p})
endforeach()
else()
add_test(NAME ${test_name} COMMAND ${AKANTU_DRIVER_SCRIPT} ${_arguments} ${_extra_args})
set_property(TEST ${test_name} PROPERTY PROCESSORS 1)
endif()
endfunction()
-
function(register_test_files_to_package)
cmake_parse_arguments(_register_test
"${_test_flags}"
"${_test_one_variables}"
"${_test_multi_variables}"
${ARGN}
)
if(_register_test_PYTHON)
list(APPEND _register_test_PACKAGE python_interface)
endif()
set(_test_all_files)
# add the source files in the list of all files
foreach(_file ${_register_test_SOURCES} ${_register_test_UNPARSED_ARGUMENTS}
${_register_test_EXTRA_FILES} ${_register_test_SOURCES} ${_register_test_SCRIPT}
${_register_test_POSTPROCESS} ${_register_test_FILES_TO_COPY})
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_file} OR EXISTS ${_file})
list(APPEND _test_all_files "${_file}")
else()
message("The file \"${_file}\" registred by the test \"${test_name}\" does not exists")
endif()
endforeach()
# add the different dependencies files (meshes, local libraries, ...)
foreach(_dep ${_register_test_DEPENDS})
get_target_list_of_associated_files(${_dep} _dep_ressources)
if(_dep_ressources)
list(APPEND _test_all_files "${_dep_ressources}")
endif()
endforeach()
# add extra files to the list of files referenced by a given test
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.sh")
list(APPEND _test_all_files "${test_name}.sh")
endif()
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified")
list(APPEND _test_all_files "${test_name}.verified")
endif()
if(_register_test_SCRIPT)
list(APPEND _test_all_files "${_register_test_SCRIPT}")
endif()
# clean the list of all files for this test and add them in the total list
foreach(_file ${_test_all_files})
get_filename_component(_full ${_file} ABSOLUTE)
file(RELATIVE_PATH __file ${PROJECT_SOURCE_DIR} ${_full})
list(APPEND _tmp "${__file}")
endforeach()
foreach(_pkg ${_register_test_PACKAGE})
package_get_name(${_pkg} _pkg_name)
_package_add_to_variable(TESTS_FILES ${_pkg_name} ${_tmp})
endforeach()
endfunction()
diff --git a/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake b/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake
index 42eca6811..d2a5d35d7 100644
--- a/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake
+++ b/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake
@@ -1,984 +1,1005 @@
#===============================================================================
# @file CMakePackagesSystemPrivateFunctions.cmake
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Sat Jul 18 2015
# @date last modification: Mon Mar 08 2021
#
# @brief Set of macros used by the package system, internal functions
#
#
# @section LICENSE
#
# Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
if (DEFINED CMAKE_PACKAGES_SYSTEM_PRIVATE_FUNCTIONS_LOADED)
return()
endif()
set(CMAKE_PACKAGES_SYSTEM_PRIVATE_FUNCTIONS_LOADED TRUE)
# ==============================================================================
# "Private" Accessors
# ==============================================================================
# ------------------------------------------------------------------------------
# Real name
# ------------------------------------------------------------------------------
function(_package_get_real_name pkg_name real_name)
set(${real_name} ${${pkg_name}} PARENT_SCOPE)
endfunction()
function(_package_set_real_name pkg_name real_name)
set(${pkg_name} ${real_name} CACHE INTERNAL "" FORCE)
endfunction()
# ------------------------------------------------------------------------------
# Option name
# ------------------------------------------------------------------------------
function(_package_declare_option pkg_name)
string(TOUPPER "${PROJECT_NAME}" _project)
_package_get_real_name(${pkg_name} _real_name)
string(TOUPPER "${_real_name}" _u_package)
_package_get_nature(${pkg_name} _nature)
if(${_nature} MATCHES "internal" OR ${_nature} MATCHES "meta")
set(_opt_name ${_project}_${_u_package})
elseif(${_nature} MATCHES "external")
set(_opt_name ${_project}_USE_${_u_package})
else()
set(_opt_name UNKNOWN_NATURE_${_project}_${_u_package})
endif()
_package_set_variable(OPTION_NAME ${pkg_name} ${_opt_name})
endfunction()
function(_package_get_option_name pkg_name opt_name)
_package_get_variable(OPTION_NAME ${pkg_name} _opt_name)
set(${opt_name} ${_opt_name} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Set if system package or compile external lib
# ------------------------------------------------------------------------------
function(_package_set_system_option pkg_name default)
string(TOUPPER "${PROJECT_NAME}" _project)
_package_get_real_name(${pkg_name} _real_name)
string(TOUPPER "${_real_name}" _u_package)
set(${_project}_USE_SYSTEM_${_u_package} ${default} CACHE STRING
"Should akantu compile the third-party: \"${_real_name}\"")
mark_as_advanced(${_project}_USE_SYSTEM_${_u_package})
set_property(CACHE ${_project}_USE_SYSTEM_${_u_package} PROPERTY STRINGS ON OFF AUTO)
endfunction()
function(_package_use_system pkg_name use)
string(TOUPPER "${PROJECT_NAME}" _project)
_package_get_real_name(${pkg_name} _real_name)
string(TOUPPER "${_real_name}" _u_package)
if(DEFINED ${_project}_USE_SYSTEM_${_u_package})
if(${${_project}_USE_SYSTEM_${_u_package}} MATCHES "(ON|AUTO)")
set(${use} TRUE PARENT_SCOPE)
else()
set(${use} FALSE PARENT_SCOPE)
endif()
else()
set(${use} TRUE PARENT_SCOPE)
endif()
endfunction()
function(_package_has_system_fallback pkg_name fallback)
string(TOUPPER "${PROJECT_NAME}" _project)
_package_get_real_name(${pkg_name} _real_name)
string(TOUPPER "${_real_name}" _u_package)
if(DEFINED ${_project}_USE_SYSTEM_${_u_package})
if(${${_project}_USE_SYSTEM_${_u_package}} MATCHES "AUTO")
set(${fallback} TRUE PARENT_SCOPE)
else()
set(${fallback} FALSE PARENT_SCOPE)
endif()
else()
set(${fallback} FALSE PARENT_SCOPE)
endif()
endfunction()
function(_package_set_system_script pkg_name script)
_package_set_variable(COMPILE_SCRIPT ${pkg_name} "${script}")
endfunction()
function(_package_add_third_party_script_variable pkg_name var)
_package_set_variable(VARIABLE_${var} ${pkg_name} "${ARGN}")
set(${var} ${ARGN} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
function(_package_load_third_party_script pkg_name)
if(${pkg_name}_COMPILE_SCRIPT)
# set the stored variable
get_cmake_property(_all_vars VARIABLES)
foreach(_var ${_all_vars})
if(_var MATCHES "^${pkg_name}_VARIABLE_.*")
string(REPLACE "${pkg_name}_VARIABLE_" "" _orig_var "${_var}")
set(${_orig_var} ${${_var}})
endif()
endforeach()
_package_get_real_name(${pkg_name} _name)
string(TOUPPER "${_name}" _u_name)
_package_get_option_name(${pkg_name} _opt_name)
if(${_opt_name}_VERSION)
set(_version "${${_opt_name}_VERSION}")
set(${_u_name}_VERSION "${_version}" CACHE INTERNAL "" FORCE)
elseif(${_u_name}_VERSION)
set(_version "${${_u_name}_VERSION}")
endif()
# load the script
include(ExternalProject)
include(${${pkg_name}_COMPILE_SCRIPT})
if(${_u_name}_LIBRARIES)
_package_set_libraries(${pkg_name} ${${_u_name}_LIBRARIES})
list(APPEND _required_vars ${_u_name}_LIBRARIES)
endif()
if(${_u_name}_INCLUDE_DIR)
_package_set_include_dir(${pkg_name} ${${_u_name}_INCLUDE_DIR})
list(APPEND _required_vars ${_u_name}_INCLUDE_DIR)
endif()
include(FindPackageHandleStandardArgs)
if (NOT _required_vars)
message(FATAL_ERROR "The package ${_name} does not define any of the variables ${_u_name}_INCLUDE_DIR nor ${_u_name}_LIBRARIES")
endif()
if(CMAKE_VERSION VERSION_GREATER 2.8.12)
find_package_handle_standard_args(${_name}
REQUIRED_VARS ${_required_vars}
VERSION_VAR _version
FAIL_MESSAGE "Something was not configured by a the third-party script for ${_name}"
)
else()
find_package_handle_standard_args(${_name}
"Something was not configured by a the third-party script for ${_name}"
${_required_vars}
)
endif()
endif()
set(${pkg_name}_USE_SYSTEM_PREVIOUS FALSE CACHE INTERNAL "" FORCE)
endfunction()
# ------------------------------------------------------------------------------
# Nature
# ------------------------------------------------------------------------------
function(_package_set_nature pkg_name nature)
_package_set_variable(NATURE ${pkg_name} ${nature})
endfunction()
function(_package_get_nature pkg_name nature)
_package_get_variable(NATURE ${pkg_name} _nature "unknown")
set(${nature} ${_nature} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Description
# ------------------------------------------------------------------------------
function(_package_set_description pkg_name desc)
_package_set_variable(DESC ${pkg_name} ${desc})
endfunction()
function(_package_get_description pkg_name desc)
_package_get_variable(DESC ${pkg_name} _desc "No description set for the package ${${pkg_name}} (${pkg_name})")
set(${desc} ${_desc} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Package file name
# ------------------------------------------------------------------------------
function(_package_set_filename pkg_name file)
_package_set_variable(FILE ${pkg_name} ${file})
endfunction()
function(_package_get_filename pkg_name file)
_package_get_variable(FILE ${pkg_name} _file "No filename set for the package ${${pkg_name}}")
set(${file} ${_file} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Source folder
# ------------------------------------------------------------------------------
function(_package_set_sources_folder pkg_name src_folder)
_package_set_variable(SRC_FOLDER ${pkg_name} ${src_folder})
endfunction()
function(_package_get_sources_folder pkg_name src_folder)
_package_get_variable(SRC_FOLDER ${pkg_name} _src_folder)
set(${src_folder} ${_src_folder} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Test folder
# ------------------------------------------------------------------------------
function(_package_set_tests_folder pkg_name test_folder)
_package_set_variable(TEST_FOLDER ${pkg_name} ${test_folder})
endfunction()
function(_package_get_tests_folder pkg_name test_folder)
_package_get_variable(TEST_FOLDER ${pkg_name} _test_folder)
set(${test_folder} ${_test_folder} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Manual folder
# ------------------------------------------------------------------------------
function(_package_set_manual_folder pkg_name manual_folder)
_package_set_variable(MANUAL_FOLDER ${pkg_name} ${manual_folder})
endfunction()
function(_package_get_manual_folder pkg_name manual_folder)
_package_get_variable(MANUAL_FOLDER ${pkg_name} _manual_folder)
set(${manual_folder} ${_manual_folder} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Extra option for the find_package
# ------------------------------------------------------------------------------
function(_package_set_find_package_extra_options pkg_name)
_package_set_variable(FIND_PKG_OPTIONS ${pkg_name} ${ARGN})
endfunction()
function(_package_get_find_package_extra_options pkg_name options)
_package_get_variable(FIND_PKG_OPTIONS ${pkg_name} _options)
set(${options} ${_options} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Compilation flags
# ------------------------------------------------------------------------------
function(_package_set_compile_flags pkg_name lang)
_package_set_variable(COMPILE_${lang}_FLAGS ${pkg_name} ${ARGN})
endfunction()
function(_package_unset_compile_flags pkg_name lang)
_package_variable_unset(COMPILE_${lang}_FLAGS ${pkg_name})
endfunction()
function(_package_get_compile_flags pkg_name lang flags)
_package_get_variable(COMPILE_${lang}_FLAGS ${pkg_name} _tmp_flags)
string(REPLACE ";" " " _flags "${_tmp_flags}")
set(${flags} "${_flags}" PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Include dir
# ------------------------------------------------------------------------------
function(_package_set_include_dir pkg_name)
_package_set_variable(INCLUDE_DIR ${pkg_name} ${ARGN})
endfunction()
function(_package_get_include_dir pkg_name include_dir)
_package_get_variable(INCLUDE_DIR ${pkg_name} _include_dir "")
set(${include_dir} ${_include_dir} PARENT_SCOPE)
endfunction()
function(_package_add_include_dir pkg_name)
_package_add_to_variable(INCLUDE_DIR ${pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Libraries
# ------------------------------------------------------------------------------
function(_package_set_libraries pkg_name)
_package_set_variable(LIBRARIES ${pkg_name} ${ARGN})
endfunction()
function(_package_get_libraries pkg_name libraries)
_package_get_variable(LIBRARIES ${pkg_name} _libraries "")
set(${libraries} ${_libraries} PARENT_SCOPE)
endfunction()
function(_package_add_libraries pkg_name)
_package_add_to_variable(LIBRARIES ${pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Extra dependencies like custom commands of ExternalProject
# ------------------------------------------------------------------------------
function(_package_add_extra_dependency pkg_name)
_package_add_to_variable(EXTRA_DEPENDENCY ${pkg_name} ${ARGN})
endfunction()
function(_package_rm_extra_dependency pkg_name dep)
_package_remove_from_variable(EXTRA_DEPENDENCY ${pkg_name} ${dep})
endfunction()
function(_package_set_extra_dependencies pkg)
_package_set_variable(EXTRA_DEPENDENCY ${pkg_name} ${ARGN})
endfunction()
function(_package_get_extra_dependencies pkg deps)
_package_get_variable(EXTRA_DEPENDENCY ${pkg_name} _deps "")
set(${deps} ${_deps} PARENT_SCOPE)
endfunction()
function(_package_unset_extra_dependencies pkg_name)
_package_variable_unset(EXTRA_DEPENDENCY ${pkg_name})
endfunction()
# ------------------------------------------------------------------------------
# Activate/deactivate
# ------------------------------------------------------------------------------
function(_package_activate pkg_name)
_package_set_variable(STATE ${pkg_name} ON)
endfunction()
function(_package_deactivate pkg_name)
_package_set_variable(STATE ${pkg_name} OFF)
endfunction()
function(_package_is_activated pkg_name act)
_package_get_variable(STATE ${pkg_name} _state OFF)
if(_state)
set(${act} TRUE PARENT_SCOPE)
else()
set(${act} FALSE PARENT_SCOPE)
endif()
endfunction()
function(_package_is_deactivated pkg_name act)
_package_get_variable(STATE ${pkg_name} _state OFF)
if(NOT _state)
set(${act} TRUE PARENT_SCOPE)
else()
set(${act} FALSE PARENT_SCOPE)
endif()
endfunction()
function(_package_unset_activated pkg_name)
_package_variable_unset(STATE ${pkg_name})
endfunction()
# ------------------------------------------------------------------------------
# Callbacks
# ------------------------------------------------------------------------------
function(_package_on_enable_script pkg_name script)
string(TOLOWER "${pkg_name}" _l_pkg_name)
set(_output_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_l_pkg_name}.cmake")
file(WRITE "${_output_file}"
"${script}")
_package_set_variable(CALLBACK_SCRIPT ${pkg_name} "${_output_file}")
endfunction()
function(_package_get_callback_script pkg_name filename)
_package_get_variable(CALLBACK_SCRIPT ${pkg_name} _filename NOTFOUND)
set(${filename} ${_filename} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Export list
# ------------------------------------------------------------------------------
function(_package_add_to_export_list pkg_name)
_package_add_to_variable(EXPORT_LIST ${pkg_name} ${ARGN})
endfunction()
function(_package_remove_from_export_list pkg_name)
_package_remove_from_variable(EXPORT_LIST ${pkg_name} ${ARGN})
endfunction()
function(_package_get_export_list pkg_name export_list)
_package_get_variable(EXPORT_LIST ${pkg_name} _export_list)
set(${export_list} ${_export_list} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Direct dependencies
# ------------------------------------------------------------------------------
function(_package_add_dependencies pkg_name type)
_package_add_to_variable(DEPENDENCIES_${type} ${pkg_name} ${ARGN})
endfunction()
function(_package_get_dependencies pkg_name type dependencies)
_package_get_variable(DEPENDENCIES_${type} ${pkg_name} _dependencies)
set(${dependencies} ${_dependencies} PARENT_SCOPE)
endfunction()
function(_package_unset_dependencies pkg_name type)
_package_variable_unset(DEPENDENCIES_${type} ${pkg_name})
endfunction()
function(_package_remove_dependency pkg_name type dep)
set(_deps ${${pkg_name}_DEPENDENCIES_${type}})
_package_get_fdependencies(${dep} _fdeps)
# check if this is the last reverse dependency
list(LENGTH _fdeps len)
list(FIND _fdeps ${pkg_name} pos)
if((len EQUAL 1) AND (NOT pos EQUAL -1))
_package_get_description(${dep} _dep_desc)
_package_get_option_name(${dep} _dep_option_name)
set(${_dep_option_name} ${${dep}_OLD} CACHE BOOL "${_dep_desc}" FORCE)
unset(${dep}_OLD CACHE)
endif()
# remove the pkg_name form the reverse dependency
_package_remove_fdependency(${dep} ${pkg_name})
list(FIND _deps ${dep} pos)
if(NOT pos EQUAL -1)
list(REMOVE_AT _deps ${pos})
_package_set_variable(DEPENDENCIES_${type} ${pkg_name} ${_deps})
endif()
endfunction()
# ------------------------------------------------------------------------------
# Functions to handle reverse dependencies
# ------------------------------------------------------------------------------
function(_package_set_rdependencies pkg_name)
_package_set_variable(RDEPENDENCIES ${pkg_name} ${ARGN})
endfunction()
function(_package_get_rdependencies pkg_name rdependencies)
_package_get_variable(RDEPENDENCIES ${pkg_name} _rdependencies)
set(${rdependencies} ${_rdependencies} PARENT_SCOPE)
endfunction()
function(_package_add_rdependency pkg_name rdep)
# store the reverse dependency
_package_add_to_variable(RDEPENDENCIES ${pkg_name} ${rdep})
endfunction()
function(_package_remove_rdependency pkg_name rdep)
_package_remove_from_variable(RDEPENDENCIES ${pkg_name} ${rdep})
endfunction()
# ------------------------------------------------------------------------------
# Function to handle forcing dependencies (Package turn ON that enforce their
# dependencies ON)
# ------------------------------------------------------------------------------
function(_package_set_fdependencies pkg_name)
_package_set_variable(FDEPENDENCIES ${pkg_name} ${ARGN})
endfunction()
function(_package_get_fdependencies pkg_name fdependencies)
_package_get_variable(FDEPENDENCIES ${pkg_name} _fdependencies)
set(${fdependencies} ${_fdependencies} PARENT_SCOPE)
endfunction()
function(_package_add_fdependency pkg_name fdep)
# store the reverse dependency
_package_add_to_variable(FDEPENDENCIES ${pkg_name} ${fdep})
endfunction()
function(_package_remove_fdependency pkg_name fdep)
_package_remove_from_variable(FDEPENDENCIES ${pkg_name} ${fdep})
endfunction()
# ------------------------------------------------------------------------------
# Exteral package system as apt rpm dependencies
# ------------------------------------------------------------------------------
function(_package_set_package_system_dependency pkg system)
string(TOUPPER "${_system}" _u_system)
_package_set_variable(PACKAGE_SYSTEM_${_u_system} ${_pkg_name} ${ARGN})
endfunction()
function(_package_get_package_system_dependency pkg system var)
string(TOUPPER "${_system}" _u_system)
_package_get_variable(PACKAGE_SYSTEM_${_u_system} ${_pkg_name} ${_deps})
set(${var} ${_deps} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Documentation related functions
# ------------------------------------------------------------------------------
function(_package_set_documentation_files pkg_name)
_package_set_variable(DOCUMENTATION_FILES ${pkg_name} ${ARGN})
endfunction()
function(_package_get_documentation_files pkg_name doc_files)
_package_get_variable(DOCUMENTATION_FILES ${pkg_name} _doc_files "")
set(${doc_files} ${_doc_files} PARENT_SCOPE)
endfunction()
function(_package_set_documentation pkg_name)
# \n replaced by && and \\ by ££ to avoid cache problems
set(_doc_str "")
foreach(_str ${ARGN})
set(_doc_str "${_doc_str}&&${_str}")
endforeach()
string(REPLACE "\\" "££" _doc_escaped "${_doc_str}")
_package_set_variable(DOCUMENTATION ${pkg_name} "${_doc_str}")
endfunction()
function(_package_get_documentation pkg_name _doc)
# \n replaced by && and \\ by ££ to avoid cache problems
_package_get_variable(DOCUMENTATION ${pkg_name} _doc_tmp "")
string(REPLACE "££" "\\" _doc_escaped "${_doc_tmp}")
string(REPLACE "&&" "\n" _doc_newlines "${_doc_escaped}")
set(${_doc} "${_doc_newlines}" PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Special boost thingy
# ------------------------------------------------------------------------------
function(_package_set_boost_component_needed pkg_name)
_package_add_to_variable(BOOST_COMPONENTS_NEEDED ${pkg_name} ${ARGN})
package_get_name(Boost _boost_pkg_name)
_package_add_dependencies(${pkg_name} PRIVATE ${_boost_pkg_name})
endfunction()
function(_package_get_boost_component_needed pkg_name needed)
_package_get_variable(BOOST_COMPONENTS_NEEDED ${pkg_name} _needed)
set(${needed} ${_needed} PARENT_SCOPE)
endfunction()
function(_package_load_boost_components)
string(TOUPPER ${PROJECT_NAME} _project)
_package_get_variable_for_activated(BOOST_COMPONENTS_NEEDED _boost_needed_components)
package_get_name(Boost _pkg_name)
if(_boost_needed_components)
message(STATUS "Looking for Boost liraries: ${_boost_needed_components}")
foreach(_comp ${_boost_needed_components})
find_package(Boost COMPONENTS ${_comp} QUIET)
string(TOUPPER ${_comp} _u_comp)
if(Boost_${_u_comp}_FOUND)
message(STATUS " ${_comp}: FOUND")
package_set_project_variable(BOOST_${_u_comp} TRUE)
# Generate the libraries for the package
_package_add_libraries(${_pkg_name} ${Boost_${_u_comp}_LIBRARY})
else()
message(STATUS " ${_comp}: NOT FOUND")
endif()
endforeach()
endif()
endfunction()
# ------------------------------------------------------------------------------
# get the list of source files for a given package
# ------------------------------------------------------------------------------
function(_package_get_source_files pkg_name SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
string(TOUPPER ${PROJECT_NAME} _project)
set(tmp_SRCS)
set(tmp_PUBLIC_HEADERS)
set(tmp_PRIVATE_HEADERS)
foreach(_type SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
foreach(_file ${${pkg_name}_${_type}})
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" _rel_file "${_file}")
list(APPEND tmp_${_type} "${_rel_file}")
endforeach()
endforeach()
set(${SRCS} ${tmp_SRCS} PARENT_SCOPE)
set(${PUBLIC_HEADERS} ${tmp_PUBLIC_HEADERS} PARENT_SCOPE)
set(${PRIVATE_HEADERS} ${tmp_PRIVATE_HEADERS} PARENT_SCOPE)
endfunction()
# ==============================================================================
# Internal functions
# ==============================================================================
# ------------------------------------------------------------------------------
# Build the reverse dependencies from the dependencies
# ------------------------------------------------------------------------------
function(_package_build_rdependencies)
package_get_all_packages(_pkg_list)
# set empty lists
foreach(_pkg_name ${_pkg_list})
set(${_pkg_name}_rdeps)
endforeach()
# fill the dependencies list
foreach(_pkg_name ${_pkg_list})
_package_get_dependencies(${_pkg_name} PRIVATE _deps_priv)
_package_get_dependencies(${_pkg_name} INTERFACE _deps_interface)
foreach(_dep_name ${_deps_priv} ${_deps_interface})
list(APPEND ${_dep_name}_rdeps ${_pkg_name})
endforeach()
endforeach()
# clean and set the reverse dependencies
foreach(_pkg_name ${_pkg_list})
if(${_pkg_name}_rdeps)
list(REMOVE_DUPLICATES ${_pkg_name}_rdeps)
_package_set_rdependencies(${_pkg_name} ${${_pkg_name}_rdeps})
endif()
endforeach()
endfunction()
# ------------------------------------------------------------------------------
# This function resolve the dependance order run the needed find_packages
# ------------------------------------------------------------------------------
function(_package_load_packages)
package_get_all_packages(_pkg_list)
# Activate the dependencies of activated package and generate an ordered list
# of dependencies
set(ordered_loading_list)
foreach(_pkg_name ${_pkg_list})
_package_load_dependencies_package(${_pkg_name} ordered_loading_list)
endforeach()
# Load the packages in the propoer order
foreach(_pkg_name ${ordered_loading_list})
_package_get_option_name(${_pkg_name} _option_name)
if(${_option_name})
_package_load_package(${_pkg_name})
else()
# deactivate the packages than can already be deactivated
_package_deactivate(${_pkg_name})
endif()
endforeach()
# generates the activated and unactivated lists of packages
set(_packages_activated)
set(_packages_deactivated)
foreach(_pkg_name ${_pkg_list})
_package_is_activated(${_pkg_name} _active)
set(_exclude FALSE)
_package_get_variable(EXCLUDE_FROM_ALL ${_pkg_name} _exclude)
if(_active AND NOT _exclude)
list(APPEND _packages_activated ${_pkg_name})
else()
list(APPEND _packages_deactivated ${_pkg_name})
endif()
endforeach()
# generate the list usable by the calling code
package_set_project_variable(ACTIVATED_PACKAGE_LIST "${_packages_activated}")
package_set_project_variable(DEACTIVATED_PACKAGE_LIST "${_packages_deactivated}")
endfunction()
# ------------------------------------------------------------------------------
# This load an external package and recursively all its dependencies
# ------------------------------------------------------------------------------
function(_package_load_dependencies_package pkg_name loading_list)
# Get packages informations
_package_get_option_name(${pkg_name} _pkg_option_name)
_package_get_dependencies(${pkg_name} PRIVATE _deps_private)
_package_get_dependencies(${pkg_name} INTERFACE _deps_interface)
set(_dependencies ${_deps_private} ${_deps_interface})
# handle the dependencies
foreach(_dep_name ${_dependencies})
_package_get_description(${_dep_name} _dep_desc)
_package_get_option_name(${_dep_name} _dep_option_name)
_package_get_fdependencies(${_dep_name} _fdeps)
if(${_pkg_option_name})
if("${_fdeps}" STREQUAL "")
set(${_dep_name}_OLD ${${_dep_option_name}} CACHE INTERNAL "" FORCE)
endif()
# set the option to on
set(_type BOOL)
_package_get_nature(${_dep_name} _nature)
if(_nature MATCHES ".*not_optional$")
set(_type INTERNAL)
endif()
set(${_dep_option_name} ON CACHE BOOL "${_dep_desc}" FORCE)
# store the reverse dependency
_package_add_fdependency(${_dep_name} ${pkg_name})
else()
# check if this is the last reverse dependency
list(LENGTH _fdeps len)
list(FIND _fdeps ${pkg_name} pos)
if((len EQUAL 1) AND (NOT pos EQUAL -1))
set(${_dep_option_name} ${${_dep_name}_OLD} CACHE BOOL "${_dep_desc}" FORCE)
unset(${_dep_name}_OLD CACHE)
endif()
# remove the pkg_name form the reverse dependency
_package_remove_fdependency(${_dep_name} ${pkg_name})
endif()
# recusively load the dependencies
_package_load_dependencies_package(${_dep_name} ${loading_list})
endforeach()
# get the compile flags
_package_get_compile_flags(${pkg_name} CXX _pkg_compile_flags)
package_get_project_variable(NO_AUTO_COMPILE_FLAGS _no_auto_compile_flags)
# if package option is on add it in the list
if(${_pkg_option_name})
list(FIND ${loading_list} ${pkg_name} _pos)
if(_pos EQUAL -1)
set(_tmp_loading_list ${${loading_list}})
list(APPEND _tmp_loading_list ${pkg_name})
set(${loading_list} "${_tmp_loading_list}" PARENT_SCOPE)
endif()
#add the comilation flags if needed
if(_pkg_compile_flags AND NOT _no_auto_compile_flags)
add_flags(cxx ${_pkg_compile_flags})
endif()
else()
#remove the comilation flags if needed
if(_pkg_comile_flags AND NOT _no_auto_compile_flags)
remove_flags(cxx ${_pkg_compile_flags})
endif()
endif()
endfunction()
# ------------------------------------------------------------------------------
# Load the package if it is an external one
# ------------------------------------------------------------------------------
function(_package_load_package pkg_name)
# load the package if it is an external
_package_get_nature(${pkg_name} _nature)
if(${_nature} MATCHES "external")
_package_use_system(${pkg_name} _use_system)
set(_activated TRUE)
if(_use_system)
_package_load_external_package(${pkg_name} _activated)
endif()
_package_has_system_fallback(${pkg_name} _fallback)
if((NOT _use_system) OR (_fallback AND (NOT _activated)))
_package_load_third_party_script(${pkg_name})
set(_activated TRUE)
endif()
if(_activated)
_package_activate(${pkg_name})
elseif()
_package_deactivate(${pkg_name})
endif()
else()
_package_activate(${pkg_name})
endif()
endfunction()
# ------------------------------------------------------------------------------
# Load external packages
# ------------------------------------------------------------------------------
function(_package_load_external_package pkg_name activate)
_package_get_real_name(${pkg_name} _real_name)
string(TOUPPER ${_real_name} _u_package)
if(NOT ${pkg_name}_USE_SYSTEM_PREVIOUS)
#if system was off before clear the cache of preset variables
get_cmake_property(_all_vars VARIABLES)
foreach(_var ${_all_vars})
if(_var MATCHES "^${_u_package}_.*")
unset(${_var} CACHE)
endif()
endforeach()
set(${pkg_name}_USE_SYSTEM_PREVIOUS TRUE CACHE INTERNAL "" FORCE)
endif()
_package_get_find_package_extra_options(${pkg_name} _options)
if(_options)
cmake_parse_arguments(_opt_pkg "" "LANGUAGE" "LINK_LIBRARIES;PREFIX;FOUND;ARGS" ${_options})
if(_opt_pkg_UNPARSED_ARGUMENTS)
message("You passed too many options for the find_package related to ${${pkg_name}} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"")
endif()
endif()
if(_opt_pkg_LANGUAGE)
foreach(_language ${_opt_pkg_LANGUAGE})
enable_language(${_language})
endforeach()
endif()
# find the package
set(_required REQUIRED)
_package_has_system_fallback(${pkg_name} _fallback)
if(_fallback)
set(_required QUIET)
endif()
find_package(${_real_name} ${_required} ${_opt_pkg_ARGS})
# check if the package is found
if(_opt_pkg_PREFIX)
set(_package_prefix ${_opt_pkg_PREFIX})
else()
set(_package_prefix ${_u_package})
endif()
set(_act FALSE)
set(_prefix_to_consider)
if(DEFINED _opt_pkg_FOUND)
if(${_opt_pkg_FOUND})
set(_act TRUE)
set(_prefix_to_consider ${_package_prefix})
endif()
else()
foreach(_prefix ${_package_prefix})
if(${_prefix}_FOUND)
set(_act TRUE)
list(APPEND _prefix_to_consider ${_prefix})
endif()
endforeach()
endif()
if(_act)
+ set(_include_dirs)
+ set(_libraries)
foreach(_prefix ${_prefix_to_consider})
# Generate the include dir for the package
if(DEFINED ${_prefix}_INCLUDE_DIRS)
_package_set_include_dir(${pkg_name} ${${_prefix}_INCLUDE_DIRS})
+ list(APPEND _include_dirs ${${_prefix}_INCLUDE_DIRS})
elseif(DEFINED ${_prefix}_INCLUDE_DIR)
_package_set_include_dir(${pkg_name} ${${_prefix}_INCLUDE_DIR})
+ list(APPEND _include_dirs ${${_prefix}_INCLUDE_DIR})
elseif(DEFINED ${_prefix}_INCLUDE_PATH)
_package_set_include_dir(${pkg_name} ${${_prefix}_INCLUDE_PATH})
+ list(APPEND _include_dirs ${${_prefix}_INCLUDE_PATH})
endif()
# Generate the libraries for the package
if(_opt_pkg_LINK_LIBRARIES)
_package_set_libraries(${pkg_name} ${_opt_pkg_LINK_LIBRARIES})
+ list(APPEND _libraries ${${_prefix}_LINK_LIBRARIES})
elseif(DEFINED ${_prefix}_LIBRARIES)
_package_set_libraries(${pkg_name} ${${_prefix}_LIBRARIES})
+ list(APPEND _libraries ${${_prefix}_LIBRARIES})
elseif(DEFINED ${_prefix}_LIBRARY)
_package_set_libraries(${pkg_name} ${${_prefix}_LIBRARY})
+ list(APPEND _libraries ${${_prefix}_LIBRARY})
endif()
endforeach()
+ if(_required STREQUAL "QUIET")
+ if(_library)
+ set(_msg ${_library})
+ else()
+ set(_msg ${_include_dirs})
+ endif()
+
+ set(_version "")
+ if(${_real_name}_VERSION)
+ set(_version " (${${_real_name}_VERSION})")
+ endif()
+ message(STATUS "Found ${_real_name}: ${_msg}${_version}")
+ endif()
_package_get_callback_script(${pkg_name} _script_file)
if(_script_file)
include("${_script_file}")
endif()
endif()
set(${activate} ${_act} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Sanity check functions
# ------------------------------------------------------------------------------
function(_package_check_files_exists)
set(_message FALSE)
package_get_all_packages(_pkg_list)
foreach(_pkg_name ${_pkg_list})
set(_pkg_files
${${_pkg_name}_SRCS}
${${_pkg_name}_PUBLIC_HEADERS}
${${_pkg_name}_PRIVATE_HEADERS}
)
_package_get_real_name(${_pkg_name} _real_name)
foreach(_file ${_pkg_files})
if(NOT EXISTS "${_file}")
if(NOT _message)
set(_message TRUE)
message("This file(s) is(are) present in a package but are not present on disk.")
endif()
message(" PACKAGE ${_real_name} FILE ${_file}")
endif()
endforeach()
endforeach()
if(_message)
message(SEND_ERROR "Please check the content of your packages to correct this warnings")
endif()
endfunction()
# ------------------------------------------------------------------------------
function(_package_check_files_registered)
set(_pkg_files)
package_get_all_packages(_pkg_list)
# generates a file list of registered files
foreach(_pkg_name ${_pkg_list})
list(APPEND _pkg_files
${${_pkg_name}_SRCS}
${${_pkg_name}_PUBLIC_HEADERS}
${${_pkg_name}_PRIVATE_HEADERS}
)
endforeach()
# generates the list of files in the source folders
set(_all_src_files)
foreach(_src_folder ${ARGN})
foreach(_ext "cc" "hh" "c" "h" "hpp")
file(GLOB_RECURSE _src_files "${_src_folder}/*.${_ext}")
list(APPEND _all_src_files ${_src_files})
endforeach()
endforeach()
if(_all_src_files)
list(REMOVE_DUPLICATES _all_src_files)
endif()
set(_not_registerd_files)
# check only sources files in the source folders
foreach(_src_folder ${ARGN})
foreach(_file ${_all_src_files})
if("${_file}" MATCHES "${_src_folder}")
list(FIND _pkg_files "${_file}" _index)
if (_index EQUAL -1)
list(APPEND _not_registerd_files ${_file})
endif()
endif()
endforeach()
endforeach()
if(AUTO_MOVE_UNKNOWN_FILES)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/unknown_files)
endif()
# warn the user and move the files if needed
if(_not_registerd_files)
if(EXISTS ${PROJECT_BINARY_DIR}/missing_files_in_packages)
file(REMOVE ${PROJECT_BINARY_DIR}/missing_files_in_packages)
endif()
message("This files are present in the source folders but are not registered in any package")
foreach(_file ${_not_registerd_files})
message(" ${_file}")
if(AUTO_MOVE_UNKNOWN_FILES)
get_filename_component(_file_name ${_file} NAME)
file(RENAME ${_file} ${PROJECT_BINARY_DIR}/unknown_files/${_file_name})
endif()
file(APPEND ${PROJECT_BINARY_DIR}/missing_files_in_packages "${_file}
")
endforeach()
if(AUTO_MOVE_UNKNOWN_FILES)
message(SEND_ERROR "The files where moved in the followinf folder ${PROJECT_BINARY_DIR}/unknown_files\n
Please register them in the good package or clean the sources")
else()
message(SEND_ERROR "Please register them in the good package or clean the sources")
endif()
endif()
endfunction()
# ------------------------------------------------------------------------------
diff --git a/cmake/Modules/CMakeVersionGenerator.cmake b/cmake/Modules/CMakeVersionGenerator.cmake
index 91d616fc4..08926dd4e 100644
--- a/cmake/Modules/CMakeVersionGenerator.cmake
+++ b/cmake/Modules/CMakeVersionGenerator.cmake
@@ -1,278 +1,278 @@
#===============================================================================
# @file CMakeVersionGenerator.cmake
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Sun Oct 19 2014
# @date last modification: Mon Jan 18 2016
#
# @brief Set of macros used by akantu to handle the package system
#
#
# @section LICENSE
#
# Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
if(__DEFINE_PROJECT_VERSION__)
return()
endif()
set(__DEFINE_PROJECT_VERSION__ TRUE)
function(_match_semver _input_semver prefix)
set(_semver_regexp
"^([0-9]+(\\.[0-9]+)?(\\.[0-9]+)?)(-([a-zA-Z0-9\-]*))?(\\+(.*))?")
if(_input_semver MATCHES "^([0-9]+(\\.[0-9]+)?(\\.[0-9]+)?)(-([a-zA-Z0-9-]*))?(\\+(.*))?")
set(${prefix}_version ${CMAKE_MATCH_1} PARENT_SCOPE)
if(CMAKE_MATCH_4)
set(${prefix}_version_prerelease "${CMAKE_MATCH_5}" PARENT_SCOPE)
endif()
if(CMAKE_MATCH_6)
set(${prefix}_version_metadata "${CMAKE_MATCH_7}" PARENT_SCOPE)
endif()
endif()
endfunction()
function(_get_version_from_git)
if(NOT CMAKE_VERSION_GENERATOR_TAG_PREFIX)
set(CMAKE_VERSION_GENERATOR_TAG_PREFIX "v")
endif()
find_package(Git)
set(is_git FALSE)
if(Git_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --git-dir
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE _res
OUTPUT_QUIET
ERROR_QUIET)
if(_res EQUAL 0)
set(is_git TRUE)
endif()
endif()
if(is_git)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe
--tags
--abbrev=0
--match ${CMAKE_VERSION_GENERATOR_TAG_PREFIX}*
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE _res
OUTPUT_VARIABLE _out_tag
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE _err_tag)
if(NOT _res EQUAL 0)
return()
endif()
string(REGEX REPLACE "^${CMAKE_VERSION_GENERATOR_TAG_PREFIX}(.*)" "\\1" _tag "${_out_tag}")
execute_process(
COMMAND ${GIT_EXECUTABLE} describe
--tags
--dirty
--always
--long
--match ${CMAKE_VERSION_GENERATOR_TAG_PREFIX}*
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE _res
OUTPUT_VARIABLE _out
OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/git_info lines)
foreach(line ${lines})
if(line MATCHES
"describe: (${CMAKE_VERSION_GENERATOR_TAG_PREFIX}((0|[1-9][0-9]*)(.(0|[1-9][0-9]*))?(.(0|[1-9][0-9]*))?)-(.*))?")
set(_tag ${CMAKE_MATCH_2})
set(_out ${CMAKE_MATCH_1})
break()
endif()
endforeach()
endif()
_match_semver("${_tag}" _tag)
set(_git_version ${_tag_version} PARENT_SCOPE)
if(_tag_version_prerelease)
set(_git_version_prerelease ${_tag_version_prerelease} PARENT_SCOPE)
endif()
# git describe to PEP404 version
set(_version_regex
"^${CMAKE_VERSION_GENERATOR_TAG_PREFIX}${_tag}(-([0-9]+)-(g[0-9a-f]+)(-dirty)?)?$")
if(_out MATCHES ${_version_regex})
if(CMAKE_MATCH_1)
if(_tag_version_metadata)
set(_metadata "${_tag_version_metadata}.")
endif()
set(_metadata "${_metadata}${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
endif()
if(CMAKE_MATCH_4)
set(_metadata "${_metadata}.dirty")
endif()
elseif(is_git)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-list HEAD --count
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE _res
OUTPUT_VARIABLE _out_count
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(_out MATCHES "^([0-9a-f]+)(-dirty)?$")
set(_metadata "${CMAKE_MATCH_1}")
if(_res EQUAL 0)
set(_metadata "${_out_count}.${_metadata}")
endif()
if(CMAKE_MATCH_2)
set(_metadata "${_metadata}.dirty")
endif()
endif()
endif()
set(_git_version_metadata ${_metadata} PARENT_SCOPE)
endfunction()
function(_get_version_from_file)
if(EXISTS ${PROJECT_SOURCE_DIR}/VERSION)
file(STRINGS ${PROJECT_SOURCE_DIR}/VERSION _file_version)
_match_semver("${_file_version}" "_file")
set(_file_version ${_file_version} PARENT_SCOPE)
if(_file_version_metadata)
set(_file_version_metadata ${_file_version_metadata} PARENT_SCOPE)
endif()
if(_file_version_prerelease)
set(_file_version_prerelease ${_file_version_prerelease} PARENT_SCOPE)
endif()
endif()
endfunction()
function(_get_metadata_from_ci)
if(NOT DEFINED ENV{CI})
return()
endif()
if(DEFINED ENV{CI_MERGE_REQUEST_ID})
set(_ci_version_metadata ".mr$ENV{CI_MERGE_REQUEST_ID}" PARENT_SCOPE)
endif()
endfunction()
function(define_project_version)
string(TOUPPER ${PROJECT_NAME} _project)
if(${_project}_VERSION)
return()
endif()
_get_version_from_git()
if(_git_version)
set(_version "${_git_version}")
if(_git_version_metadata)
set(_version_metadata "${_git_version_metadata}")
endif()
if (_git_version_prerelease)
set(_version_prerelease "${_git_version_prerelease}")
endif()
else()
# we can get metadata if and no version if not tag is properly defined
if(_git_version_metadata)
set(git_version_metadata ".${_git_version_metadata}")
endif()
_get_version_from_file()
if(_file_version_metadata)
set(_version_metadata "${_file_version_metadata}${_git_version_metadata}")
endif()
if (_file_version)
set(_version "${_file_version}")
endif()
if (_file_version_prerelease)
set(_version_prerelease "${_file_version_prerelease}")
endif()
endif()
_get_metadata_from_ci()
if(_ci_version_metadata)
set(_version_metadata "${_version_metadata}${_ci_version_metadata}")
endif()
if(_version)
if(_version_prerelease)
set(_version_prerelease "-${_version_prerelease}")
endif()
if(_version_metadata)
set(_version_metadata "+${_version_metadata}")
if(_ci_version_metadata)
set(_version_metadata "${_version_metadata}.${_ci_version_metadata}")
endif()
endif()
set(${_project}_VERSION ${_version} PARENT_SCOPE)
set(_semver "${_version}${_version_prerelease}${_version_metadata}")
set(${_project}_SEMVER "${_semver}" PARENT_SCOPE)
message(STATUS "${PROJECT_NAME} version: ${_semver}")
if(_version MATCHES "^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?")
set(_major_version ${CMAKE_MATCH_1})
set(${_project}_MAJOR_VERSION ${_major_version} PARENT_SCOPE)
if(CMAKE_MATCH_2)
set(_minor_version ${CMAKE_MATCH_3})
set(${_project}_MINOR_VERSION ${_minor_version} PARENT_SCOPE)
endif()
if(CMAKE_MATCH_4)
set(_patch_version ${CMAKE_MATCH_5})
set(${_project}_PATCH_VERSION ${_patch_version} PARENT_SCOPE)
endif()
if(_version_prerelease)
set(${_project}_PRERELEASE_VERSION ${_version_prerelease} PARENT_SCOPE)
endif()
if(_version_metadata)
set(${_project}_LOCAL_VERSION ${_version_metadata} PARENT_SCOPE)
endif()
if(_version_metadata MATCHES "(\\+([0-9]+))(\\..*)*")
set(${_project}_TWEAK ${CMAKE_MATCH_1} PARENT_SCOPE)
endif()
endif()
else()
message(FATAL_ERROR "Could not determine the VERSION for ${PROJECT_NAME}")
endif()
if(NOT ${_project}_NO_LIBRARY_VERSION)
set(${_project}_LIBRARY_PROPERTIES ${${_project}_LIBRARY_PROPERTIES}
VERSION "${_version}"
SOVERSION "${_major_version}.${_minor_version}"
- )
+ PARENT_SCOPE)
endif()
endfunction()
diff --git a/cmake/Modules/FindMumps.cmake b/cmake/Modules/FindMumps.cmake
index a7f2218bf..bee680b00 100644
--- a/cmake/Modules/FindMumps.cmake
+++ b/cmake/Modules/FindMumps.cmake
@@ -1,393 +1,392 @@
#===============================================================================
# @file FindMumps.cmake
#
# @author Mathias Lebihain <mathias.lebihain@enpc.fr>
# @author Philip Mueller <philip.mueller@math.ethz.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Sun Oct 19 2014
# @date last modification: Fri Jan 22 2021
#
# @brief The find_package file for the Mumps solver
#
#
# @section LICENSE
#
# Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
set(_MUMPS_COMPONENTS "sequential" "parallel" "double" "float" "complex_double" "complex_float")
if(NOT Mumps_FIND_COMPONENTS)
set(Mumps_FIND_COMPONENTS "parallel" "double" "float" "complex_double" "complex_float")
endif()
#===============================================================================
enable_language(Fortran)
option(MUMPS_DETECT_DEBUG "Helps to debug mumps detection problems" OFF)
mark_as_advanced(MUMPS_DETECT_DEBUG)
set(MUMPS_PRECISIONS)
set(MUMPS_PLAT)
foreach(_comp ${Mumps_FIND_COMPONENTS})
if("${_comp}" STREQUAL "sequential")
set(MUMPS_PLAT _seq) #default plat on debian based distribution
endif()
if("${_comp}" STREQUAL "float")
list(APPEND MUMPS_PRECISIONS s)
endif()
if("${_comp}" STREQUAL "double")
list(APPEND MUMPS_PRECISIONS d)
endif()
if("${_comp}" STREQUAL "complex_float")
list(APPEND MUMPS_PRECISIONS c)
endif()
if("${_comp}" STREQUAL "complex_double")
list(APPEND MUMPS_PRECISIONS z)
endif()
endforeach()
if(NOT MUMPS_PRECISIONS)
set(MUMPS_PRECISIONS s d c z)
endif()
list(GET MUMPS_PRECISIONS 0 _first_precision)
string(TOUPPER "${_first_precision}" _u_first_precision)
find_path(MUMPS_INCLUDE_DIR ${_first_precision}mumps_c.h
PATHS "${MUMPS_DIR}" ENV MUMPS_DIR
PATH_SUFFIXES include
)
mark_as_advanced(MUMPS_INCLUDE_DIR)
set(_mumps_required_vars)
foreach(_precision ${MUMPS_PRECISIONS})
string(TOUPPER "${_precision}" _u_precision)
if(DEFINED MUMPS_LIBRARY_${_u_precision}MUMPS AND
(NOT "${Mumps_FIND_COMPONENTS}" STREQUAL "${Mumps_FIND_COMPONENTS_SAVE}"))
set(MUMPS_LIBRARY_${_u_precision}MUMPS NOTFOUND CACHE PATH "" FORCE)
endif()
find_library(MUMPS_LIBRARY_${_u_precision}MUMPS
NAMES ${_precision}mumps${MUMPS_PLAT} ${_precision}mumps
PATHS "${MUMPS_DIR}" ENV MUMPS_DIR
PATH_SUFFIXES lib
)
mark_as_advanced(MUMPS_LIBRARY_${_u_precision}MUMPS)
list(APPEND _mumps_required_vars MUMPS_LIBRARY_${_u_precision}MUMPS)
list(APPEND MUMPS_LIBRARIES_ALL ${MUMPS_LIBRARY_${_u_precision}MUMPS})
endforeach()
if(MUMPS_LIBRARY_${_u_first_precision}MUMPS MATCHES ".*${_first_precision}mumps.*${CMAKE_STATIC_LIBRARY_SUFFIX}")
# Assuming mumps was compiled as a static library
set(MUMPS_LIBRARY_TYPE STATIC CACHE INTERNAL "" FORCE)
else()
set(MUMPS_LIBRARY_TYPE SHARED CACHE INTERNAL "" FORCE)
endif()
macro(find_mpiseq)
find_library(MUMPS_LIBRARY_MPISEQ mpiseq${MUMPS_PLAT} mpiseq
PATHS "${MUMPS_DIR}" ENV MUMPS_DIR
PATH_SUFFIXES lib
)
if (NOT MUMPS_LIBRARY_MPISEQ)
message("Could not find libmpiseq for sequential version of MUMPS, was "
"MUMPS compiled in sequential ?")
endif()
set(${_libs} ${MUMPS_LIBRARY_MPISEQ} PARENT_SCOPE)
mark_as_advanced(MUMPS_LIBRARY_MPISEQ)
endmacro()
macro(debug_message)
if(MUMPS_DETECT_DEBUG)
message(${ARGN})
endif()
endmacro()
function(mumps_add_dependency _pdep _libs _incs)
string(TOUPPER ${_pdep} _u_pdep)
if(_pdep STREQUAL "mumps_common")
find_library(MUMPS_LIBRARY_COMMON
NAMES mumps_common${MUMPS_PLAT} mumps_common
PATHS "${MUMPS_DIR}" ENV MUMPS_DIR
PATH_SUFFIXES lib
)
set(${_libs} ${MUMPS_LIBRARY_COMMON} PARENT_SCOPE)
mark_as_advanced(MUMPS_LIBRARY_COMMON)
elseif(_pdep STREQUAL "pord")
find_library(MUMPS_LIBRARY_PORD
NAMES pord${MUMPS_PLAT} pord
PATHS "${MUMPS_DIR}" ENV MUMPS_DIR
PATH_SUFFIXES lib
)
set(${_libs} ${MUMPS_LIBRARY_PORD} PARENT_SCOPE)
mark_as_advanced(MUMPS_LIBRARY_PORD)
elseif(_pdep MATCHES "Scotch")
find_package(Scotch REQUIRED ${ARGN} QUIET)
if(ARGN)
list(GET ARGN 1 _comp)
string(TOUPPER ${_comp} _u_comp)
set(${_libs} ${SCOTCH_LIBRARY_${_u_comp}} PARENT_SCOPE)
else()
set(${_libs} ${${_u_pdep}_LIBRARIES} PARENT_SCOPE)
endif()
elseif(_pdep MATCHES "MPI")
if(MUMPS_PLAT STREQUAL "_seq")
find_mpiseq()
else()
if(NOT CMAKE_Fortran_COMPILER_LOADED)
enable_language(Fortran)
endif()
find_package(MPI REQUIRED QUIET
COMPONENTS C Fortran)
set(${_libs} ${MPI_C_LIBRARIES} ${MPI_Fortran_LIBRARIES} PARENT_SCOPE)
set(${_incs}
${MPI_C_INCLUDE_PATH} # deprecated
${MPI_C_INCLUDE_DIRS}
${MPI_Fortran_INCLUDE_PATH} # deprecated
${MPI_Fortran_INCLUDE_DIRS}
PARENT_SCOPE)
endif()
elseif(_pdep MATCHES "Threads")
find_package(Threads REQUIRED QUIET)
set(${_libs} Threads::Threads PARENT_SCOPE)
elseif(_pdep MATCHES "OpenMP")
find_package(OpenMP REQUIRED QUIET)
set(${_libs} OpenMP::OpenMP_C PARENT_SCOPE)
elseif(_pdep MATCHES "Math")
set(${_libs} m PARENT_SCOPE)
elseif(_pdep MATCHES "ScaLAPACK")
if(MUMPS_PLAT STREQUAL "_seq")
# ScaLAPACK symbols are in mpiseq form 5.20+
find_mpiseq()
else()
find_package(ScaLAPACK REQUIRED QUIET)
set(${_libs} ${SCALAPACK_LIBRARIES} PARENT_SCOPE)
endif()
elseif(_pdep MATCHES "gfortran")
if(NOT CMAKE_Fortran_COMPILER_LOADED)
enable_language(Fortran)
endif()
set(${_libs} gfortran PARENT_SCOPE)
else()
find_package(${_pdep} REQUIRED QUIET)
set(${_libs} ${${_u_pdep}_LIBRARIES} ${${_u_pdep}_LIBRARY} PARENT_SCOPE)
endif()
endfunction()
function(mumps_find_dependencies)
set(_libraries_all m ${MUMPS_LIBRARIES_ALL})
set(_include_dirs ${MUMPS_INCLUDE_DIR})
set(_mumps_test_dir "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}")
file(READ ${CMAKE_CURRENT_LIST_DIR}/CheckFindMumps.c _output)
file(WRITE "${_mumps_test_dir}/mumps_test_code.c"
"#include <${_first_precision}mumps_c.h>
${_u_first_precision}MUMPS_STRUC_C id;
#define mumps_c ${_first_precision}mumps_c
#define Real ${_u_first_precision}MUMPS_REAL
")
if(MUMPS_PLAT STREQUAL _seq)
file(APPEND "${_mumps_test_dir}/mumps_test_code.c"
"#define MUMPS_SEQ
")
else()
file(APPEND "${_mumps_test_dir}/mumps_test_code.c"
"// #undef MUMPS_SEQ
")
endif()
file(APPEND "${_mumps_test_dir}/mumps_test_code.c" "${_output}")
#===============================================================================
# ADD here the symbols needed to compile
set(_mumps_dep_compile_MPI mpi.h)
# ADD here the symbols needed to link
- set(_mumps_dep_link_MPI mpi_send mpi_type_free mpi_allreduce)
+ set(_mumps_dep_link_MPI mpi_send mpi_type_free mpi_allreduce MPI_)
set(_mumps_dep_link_BLAS ${_first_precision}gemm)
set(_mumps_dep_link_ScaLAPACK numroc)
set(_mumps_dep_link_LAPACK ilaenv)
set(_mumps_dep_link_Scotch SCOTCH_graphInit scotchfstratexit)
set(_mumps_dep_link_Scotch_ptscotch scotchfdgraphexit)
set(_mumps_dep_link_Scotch_esmumps esmumps)
set(_mumps_dep_link_mumps_common mumps_abort mumps_get_perlu)
set(_mumps_dep_link_pord SPACE_ordering)
set(_mumps_dep_link_METIS metis_nodend)
set(_mumps_dep_link_Threads pthread_create)
- set(_mumps_dep_link_OpenMP GOMP_loop_end_nowait)
+ set(_mumps_dep_link_OpenMP omp_ GOMP_loop_end_nowait)
set(_mumps_dep_link_gfortran gfortran)
- # TODO find missing symbols for IOMP
set(_mumps_dep_link_Math lround)
set(_mumps_dep_link_ParMETIS ParMETIS_V3_NodeND)
# ADD here the symbols needed to run
set(_mumps_dep_run_mumps_common mumps_fac_descband)
set(_mumps_dep_run_MPI mpi_bcast)
set(_mumps_dep_run_ScaLAPACK idamax numroc)
set(_mumps_dep_run_Scotch_ptscotch scotchfdgraphbuild)
set(_mumps_dep_comp_Scotch_ptscotch COMPONENTS ptscotch)
set(_mumps_dep_comp_Scotch_esmumps COMPONENTS esmumps)
set(_mumps_potential_dependencies
mumps_common pord
MPI Threads OpenMP
BLAS LAPACK ScaLAPACK
Scotch Scotch_ptscotch Scotch_esmumps
METIS ParMETIS
gfortran Math)
#===============================================================================
set(_retry_try_run TRUE)
set(_retry_count 0)
# trying only as long as we add dependencies to avoid infinite loop in case of
# an unknown dependency
while (_retry_try_run AND _retry_count LESS 100)
try_run(_mumps_run _mumps_compiles
"${_mumps_test_dir}"
"${_mumps_test_dir}/mumps_test_code.c"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${_include_dirs}"
LINK_LIBRARIES ${_libraries_all} ${_libraries_all}
RUN_OUTPUT_VARIABLE _run
COMPILE_OUTPUT_VARIABLE _out)
set(_retry_compile FALSE)
debug_message("COMPILATION outputs: \n${_out} \n RUN OUTPUT \n${_run}")
if(_mumps_compiles AND NOT (_mumps_run STREQUAL "FAILED_TO_RUN"))
break()
endif()
if(_retry_count EQUAL 0 AND
(NOT _mumps_compiles OR _mumps_run STREQUAL "FAILED_TO_RUN"))
message(STATUS "Searching for MUMPS link dependencies")
endif()
foreach(_pdep ${_mumps_potential_dependencies})
set(_libs)
set(_incs)
set(_add_pdep FALSE)
debug_message("Trying to add: ${_pdep} as a dependency")
if (NOT _mumps_compiles)
if(DEFINED _mumps_dep_link_${_pdep})
foreach (_link_dep ${_mumps_dep_link_${_pdep}})
debug_message(" - test ${_link_dep}")
if(_out MATCHES "undefined reference to.*${_link_dep}" OR
_out MATCHES "${_link_dep}.*referenced from")
set(_add_pdep TRUE)
debug_message(" - ${_pdep} is a link dependency")
endif()
endforeach()
endif()
if (DEFINED _mumps_dep_compile_${_pdep})
foreach (_compile_dep ${_mumps_dep_compile_${_pdep}})
if(_out MATCHES "${_compile_dep}.*(No such file|file not found)")
set(_add_pdep TRUE)
debug_message(" - ${_pdep} is a compile dependency")
endif()
endforeach()
endif()
elseif(_mumps_run STREQUAL "FAILED_TO_RUN" AND
DEFINED _mumps_dep_run_${_pdep})
foreach(_run_dep ${_mumps_dep_run_${_pdep}})
if(_run MATCHES "${_run_dep}")
set(_add_pdep TRUE)
debug_message(" - ${_pdep} is a run dependency")
endif()
endforeach()
endif()
if(_add_pdep)
mumps_add_dependency(${_pdep} _libs _incs ${_mumps_dep_comp_${_pdep}})
debug_message(" - Found: ${_pdep} (${_libs})")
if(NOT _libs)
message(FATAL_ERROR "MUMPS depends on ${_pdep} but no libraries where found")
else()
message(STATUS " Found MUMPS dependency ${_pdep} (${_libs})")
endif()
list(APPEND _libraries_all ${_libs})
if(_incs)
list(APPEND _include_dirs ${_incs})
endif()
set(_retry_try_run TRUE)
endif()
endforeach()
math(EXPR _retry_count "${_retry_count} + 1")
endwhile()
if(_retry_count GREATER 10)
message(FATAL_ERROR "Do not know what to do to link with mumps on your system, I give up!"
"Last compilation outputs: \n${_out} \n And last run output \n${_run}")
endif()
if(APPLE)
# in doubt add some stuff because mumps was perhaps badly compiled
mumps_add_dependency(pord _libs _incs)
list(APPEND _libraries_all ${_libs})
endif()
set(MUMPS_LIBRARIES_ALL ${_libraries_all} PARENT_SCOPE)
endfunction()
mumps_find_dependencies()
set(MUMPS_LIBRARIES ${MUMPS_LIBRARIES_ALL} CACHE INTERNAL "" FORCE)
#===============================================================================
include(FindPackageHandleStandardArgs)
if(CMAKE_VERSION VERSION_GREATER 2.8.12)
if(MUMPS_INCLUDE_DIR)
file(STRINGS ${MUMPS_INCLUDE_DIR}/dmumps_c.h _versions
REGEX "^#define MUMPS_VERSION .*")
foreach(_ver ${_versions})
string(REGEX MATCH "MUMPS_VERSION *\"([0-9.]+)\"" _tmp "${_ver}")
set(_mumps_VERSION ${CMAKE_MATCH_1})
endforeach()
set(MUMPS_VERSION "${_mumps_VERSION}" CACHE INTERNAL "")
endif()
find_package_handle_standard_args(Mumps
REQUIRED_VARS ${_mumps_required_vars}
MUMPS_INCLUDE_DIR
VERSION_VAR MUMPS_VERSION
)
else()
find_package_handle_standard_args(Mumps DEFAULT_MSG
${_mumps_required_vars} MUMPS_INCLUDE_DIR)
endif()
if(Mumps_FOUND)
set(Mumps_FIND_COMPONENTS_SAVE "${Mumps_FIND_COMPONENTS}" CACHE INTERNAL "")
endif()
diff --git a/cmake/Modules/FindPythonLibsNew.cmake b/cmake/Modules/FindPythonLibsNew.cmake
deleted file mode 100644
index b29b287de..000000000
--- a/cmake/Modules/FindPythonLibsNew.cmake
+++ /dev/null
@@ -1,195 +0,0 @@
-# - Find python libraries
-# This module finds the libraries corresponding to the Python interpreter
-# FindPythonInterp provides.
-# This code sets the following variables:
-#
-# PYTHONLIBS_FOUND - have the Python libs been found
-# PYTHON_PREFIX - path to the Python installation
-# PYTHON_LIBRARIES - path to the python library
-# PYTHON_INCLUDE_DIRS - path to where Python.h is found
-# PYTHON_MODULE_EXTENSION - lib extension, e.g. '.so' or '.pyd'
-# PYTHON_MODULE_PREFIX - lib name prefix: usually an empty string
-# PYTHON_SITE_PACKAGES - path to installation site-packages
-# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build
-#
-# Thanks to talljimbo for the patch adding the 'LDVERSION' config
-# variable usage.
-
-#=============================================================================
-# Copyright 2001-2009 Kitware, Inc.
-# Copyright 2012 Continuum Analytics, Inc.
-#
-# 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.
-#
-# * Neither the names of Kitware, Inc., the Insight Software Consortium,
-# nor the names of their 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 AND CONTRIBUTORS
-# "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
-# HOLDER OR CONTRIBUTORS 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.
-#=============================================================================
-
-# Checking for the extension makes sure that `LibsNew` was found and not just `Libs`.
-if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION)
- return()
-endif()
-
-# Use the Python interpreter to find the libs.
-if(PythonLibsNew_FIND_REQUIRED)
- find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} REQUIRED)
-else()
- find_package(PythonInterp ${PythonLibsNew_FIND_VERSION})
-endif()
-
-if(NOT PYTHONINTERP_FOUND)
- set(PYTHONLIBS_FOUND FALSE)
- return()
-endif()
-
-# According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
-# testing whether sys has the gettotalrefcount function is a reliable, cross-platform
-# way to detect a CPython debug interpreter.
-#
-# The library suffix is from the config var LDVERSION sometimes, otherwise
-# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows.
-execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
- "from distutils import sysconfig as s;import sys;import struct;
-print('.'.join(str(v) for v in sys.version_info));
-print(sys.prefix);
-print(s.get_python_inc(plat_specific=True));
-print(s.get_python_lib(plat_specific=True));
-print(s.get_config_var('SO'));
-print(hasattr(sys, 'gettotalrefcount')+0);
-print(struct.calcsize('@P'));
-print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION'));
-print(s.get_config_var('LIBDIR') or '');
-print(s.get_config_var('MULTIARCH') or '');
-"
- RESULT_VARIABLE _PYTHON_SUCCESS
- OUTPUT_VARIABLE _PYTHON_VALUES
- ERROR_VARIABLE _PYTHON_ERROR_VALUE)
-
-if(NOT _PYTHON_SUCCESS MATCHES 0)
- if(PythonLibsNew_FIND_REQUIRED)
- message(FATAL_ERROR
- "Python config failure:\n${_PYTHON_ERROR_VALUE}")
- endif()
- set(PYTHONLIBS_FOUND FALSE)
- return()
-endif()
-
-# Convert the process output into a list
-string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES})
-string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES})
-list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST)
-list(GET _PYTHON_VALUES 1 PYTHON_PREFIX)
-list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR)
-list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES)
-list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION)
-list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG)
-list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P)
-list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX)
-list(GET _PYTHON_VALUES 8 PYTHON_LIBDIR)
-list(GET _PYTHON_VALUES 9 PYTHON_MULTIARCH)
-
-# Make sure the Python has the same pointer-size as the chosen compiler
-# Skip if CMAKE_SIZEOF_VOID_P is not defined
-if(CMAKE_SIZEOF_VOID_P AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}"))
- if(PythonLibsNew_FIND_REQUIRED)
- math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8")
- math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8")
- message(FATAL_ERROR
- "Python config failure: Python is ${_PYTHON_BITS}-bit, "
- "chosen compiler is ${_CMAKE_BITS}-bit")
- endif()
- set(PYTHONLIBS_FOUND FALSE)
- return()
-endif()
-
-# The built-in FindPython didn't always give the version numbers
-string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST})
-list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
-list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
-list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH)
-
-# Make sure all directory separators are '/'
-string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX})
-string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR})
-string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES})
-
-if(CMAKE_HOST_WIN32)
- set(PYTHON_LIBRARY
- "${PYTHON_PREFIX}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
-
- # when run in a venv, PYTHON_PREFIX points to it. But the libraries remain in the
- # original python installation. They may be found relative to PYTHON_INCLUDE_DIR.
- if(NOT EXISTS "${PYTHON_LIBRARY}")
- get_filename_component(_PYTHON_ROOT ${PYTHON_INCLUDE_DIR} DIRECTORY)
- set(PYTHON_LIBRARY
- "${_PYTHON_ROOT}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
- endif()
-
- # raise an error if the python libs are still not found.
- if(NOT EXISTS "${PYTHON_LIBRARY}")
- message(FATAL_ERROR "Python libraries not found")
- endif()
-
-else()
- if(PYTHON_MULTIARCH)
- set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}")
- else()
- set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}")
- endif()
- #message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}")
- # Probably this needs to be more involved. It would be nice if the config
- # information the python interpreter itself gave us were more complete.
- find_library(PYTHON_LIBRARY
- NAMES "python${PYTHON_LIBRARY_SUFFIX}"
- PATHS ${_PYTHON_LIBS_SEARCH}
- NO_DEFAULT_PATH)
-
- # If all else fails, just set the name/version and let the linker figure out the path.
- if(NOT PYTHON_LIBRARY)
- set(PYTHON_LIBRARY python${PYTHON_LIBRARY_SUFFIX})
- endif()
-endif()
-
-MARK_AS_ADVANCED(
- PYTHON_LIBRARY
- PYTHON_INCLUDE_DIR
-)
-
-# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the
-# cache entries because they are meant to specify the location of a single
-# library. We now set the variables listed by the documentation for this
-# module.
-SET(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
-SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
-SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}")
-
-find_package_message(PYTHON
- "Found PythonLibs: ${PYTHON_LIBRARY}"
- "${PYTHON_EXECUTABLE}${PYTHON_VERSION}")
-
-set(PYTHONLIBS_FOUND TRUE)
diff --git a/cmake/akantu_environement.sh.in b/cmake/akantu_environement.sh.in
index 87b66a461..0660b4318 100644
--- a/cmake/akantu_environement.sh.in
+++ b/cmake/akantu_environement.sh.in
@@ -1,6 +1,15 @@
PYTHONPATH=$PYTHONPATH:@PROJECT_BINARY_DIR@/python/
PYTHONPATH=$PYTHONPATH:@PROJECT_SOURCE_DIR@/test:@PROJECT_SOURCE_DIR@/test/test_fe_engine
export PYTHONPATH
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:@PROJECT_BINARY_DIR@/src
export LD_LIBRARY_PATH
+
+# For cases run under sanitizers
+ASAN_OPTIONS=suppressions=@PROJECT_SOURCE_DIR@/cmake/asan_akantu.supp
+#ASAN_OPTIONS=${ASAN_OPTIONS}:abort_on_error=1
+export ASAN_OPTIONS
+
+LSAN_OPTIONS=suppressions=@PROJECT_SOURCE_DIR@/cmake/lsan_akantu.supp
+LSAN_OPTIONS=print_suppressions=0:${LSAN_OPTIONS}
+export LSAN_OPTIONS
diff --git a/cmake/akantu_test_driver.sh b/cmake/akantu_test_driver.sh
index eb675c9da..309b85787 100755
--- a/cmake/akantu_test_driver.sh
+++ b/cmake/akantu_test_driver.sh
@@ -1,150 +1,150 @@
#!/bin/bash
set -o errexit
set -o pipefail
show_help() {
cat << EOF
Usage: ${0##*/} -n NAME -e EXECUTABLE [-p MPI_WRAPPER] [-s SCRIPT_FILE]
[-r REFERENCE_FILE] [-w WORKING_DIR] [ARGS]
Execute the test in the good configuration according to the options given
-e EXECUTABLE Main executable of the test
-n NAME Name of the test
-p MPI_WRAPPER Executes the test for multiple parallel configuration
-s SCRIPT_FILE Script to execute after the execution of the test to
postprocess the results
-v VALGRIND_PATH Running the test using valgrind
-r REFERENCE_FILE Reference file to compare with if the name of the file
contains a <nb_proc> this will be used for the different
configuration when -p is given
-w WORKING_DIR The directory in which to execute the test
-E ENVIRONMENT_FILE File to source before running tests
-h Print this helps
EOF
}
full_redirect() {
local nproc=$1
shift
local name=$1
shift
local sout=".lastout"
local serr=".lasterr"
if [ "${nproc}" -ne 0 ]; then
sout="-${nproc}${sout}"
serr="-${nproc}${serr}"
fi
echo "Run $*"
( ($* | tee "${name}${sout}") 3>&1 1>&2 2>&3 | tee "${name}${serr}") 3>&1 1>&2 2>&3
lastout="${name}${sout}"
}
name=
executable=
parallel=
postprocess_script=
reference=
working_dir=
envi=
parallel_processes="2"
valgrind=""
while :
do
case "$1" in
-e)
executable=$2
shift 2
;;
-E)
envi="$2"
shift 2
;;
-h | --help)
show_help
exit 0
;;
-n)
name="$2"
shift 2
;;
-N)
parallel_processes="$2"
shift 2
;;
-p)
parallel="$2"
shift 2
;;
-r)
reference="$2"
shift 2
;;
-s)
postprocess_script="$2"
shift 2
;;
-w)
working_dir="$2"
shift 2
;;
-v)
valgrind="$2"
shift 2
;;
--) # End of all options
shift
break
;;
-*)
echo "Error: Unknown option: $1" >&2
show_help
exit 1
;;
*) #No more options
break
;;
esac
done
_args=$*
if [ -n "${envi}" ]; then
source "${envi}"
fi
if [ -z "${name}" ] || [ -z "${executable}" ]; then
echo "Missing executable or name"
show_help
exit 1
fi
if [ -n "${working_dir}" ]; then
# current_directory=$PWD
echo "Entering directory ${working_dir}"
cd "${working_dir}"
fi
if [ -z "${parallel}" ]; then
echo "Executing the test ${name}"
full_redirect 0 "${name}" "${valgrind} ${executable} ${_args}"
else
#for i in ${parallel_processes}; do
i=${parallel_processes}
echo "Executing the test ${name} for ${i} procs"
full_redirect "$i" "${name}"_"$i" "${parallel} ${i} ${valgrind} ${executable} ${_args}"
#done
fi
if [ -n "${postprocess_script}" ]; then
echo "Executing the test ${name} post-processing"
full_redirect 0 "${name}_pp" "./${postprocess_script}"
fi
if [ -n "${reference}" ]; then
echo "Comparing last generated output to the reference file"
- diff -w "${lastout}" "${reference}"
+ diff -biwI "([0-9]\+ ms\( total\)\?)" "${lastout}" "${reference}"
fi
diff --git a/cmake/asan_akantu.supp b/cmake/asan_akantu.supp
new file mode 100644
index 000000000..bb5c222df
--- /dev/null
+++ b/cmake/asan_akantu.supp
@@ -0,0 +1,7 @@
+interceptor_via_fun:MPI_*
+interceptor_via_fun:_ZN7testing8internal12UnitTestImpl12GetTestSuiteEPKcS3_PFvvES5_
+interceptor_via_fun:_ZN7testing8internal20StringStreamToStringEPNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE
+interceptor_via_fun:_ZN7testing8internal16BoolFromGTestEnvEPKcb
+interceptor_via_fun:_ZN7testing8internalL12FlagToEnvVarB5cxx11EPKc
+interceptor_via_fun:testing::internal::*
+interceptor_via_fun:_ZN7testing8internal*
diff --git a/cmake/check_builtin_expect.cc b/cmake/check_builtin_expect.cc
new file mode 100644
index 000000000..fe60d375a
--- /dev/null
+++ b/cmake/check_builtin_expect.cc
@@ -0,0 +1,6 @@
+#include <iostream>
+int main() {
+ if (__builtin_expect(true, 1)) {
+ std::cout << "has __builtin_expect" << std::endl;
+ }
+}
diff --git a/cmake/check_constexpr_map.cc b/cmake/check_constexpr_map.cc
new file mode 100644
index 000000000..89ca35a15
--- /dev/null
+++ b/cmake/check_constexpr_map.cc
@@ -0,0 +1,15 @@
+#include <iostream>
+
+#include "aka_constexpr_map.hh"
+
+int main() {
+ akantu::details::static_switch_dispatch(
+ std::tuple<std::integral_constant<int, 1>,
+ std::integral_constant<int, 2>>{},
+
+ [](auto && type) {
+ std::cout << std::decay_t<decltype(type)>::value << std::endl;
+ },
+ 2, [](auto && /*type*/) { std::cout << "Default" << std::endl; },
+ std::make_index_sequence<2>{});
+}
diff --git a/cmake/check_gnu_unlikely.cc b/cmake/check_gnu_unlikely.cc
new file mode 100644
index 000000000..2b93d58ab
--- /dev/null
+++ b/cmake/check_gnu_unlikely.cc
@@ -0,0 +1,6 @@
+#include <iostream>
+int main() {
+ if (true) [[gnu::likely]] {
+ std::cout << "has __builtin_expect" << std::endl;
+ }
+}
diff --git a/cmake/libakantu/v3/printers.py b/cmake/libakantu/v3/printers.py
index 960b86e3d..d704b04e8 100755
--- a/cmake/libakantu/v3/printers.py
+++ b/cmake/libakantu/v3/printers.py
@@ -1,341 +1,364 @@
#!/usr/bin/env python3
-""" printers.py: gdb pretty printers"""
+"""printers.py: gdb pretty printers."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
-__copyright__ = "Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale" \
- " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
- " en Mécanique des Solides)"
+__copyright__ = (
+ "Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale"
+ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation"
+ " en Mécanique des Solides)"
+)
__license__ = "LGPLv3"
#
# Inspired from boost's pretty printers from
# Rüdiger Sonderfeld <ruediger@c-plusplus.de>
# and from Pretty-printers for libstc++ from Free Software Foundation, Inc.
#
import gdb
import re
-import sys
import itertools
try:
import gdb.printing
except ImportError:
raise RuntimeError("Your GDB is too old")
+
class AkantuPrinter(object):
regex = None
@classmethod
def supports(cls, typename):
# print('{0} ~= {1}'.format(typename, cls.regex), file=sys.stderr)
return cls.regex.search(typename)
@classmethod
def get_basic_type(cls, value):
- """ Determines the type associated to a value"""
-
+ """Determines the type associated to a value"""
_type = value.type
# If it points to a reference, get the reference.
if _type.code == gdb.TYPE_CODE_REF:
_type = _type.target()
# Get the unqualified type, stripped of typedefs.
_type = _type.unqualified().strip_typedefs()
return _type.tag
-__akantu_pretty_printers__ = gdb.printing.RegexpCollectionPrettyPrinter("libakantu-v3")
+__akantu_pretty_printers__ = \
+ gdb.printing.RegexpCollectionPrettyPrinter("libakantu-v3")
def register_pretty_printer(pretty_printer):
- "Registers a Pretty Printer"
-
- __akantu_pretty_printers__.add_printer(pretty_printer.name,
- pretty_printer.regex,
- pretty_printer)
+ """Registers a Pretty Printer"""
+ __akantu_pretty_printers__.add_printer(
+ pretty_printer.name, pretty_printer.regex, pretty_printer
+ )
return pretty_printer
+
@register_pretty_printer
class AkaArrayPrinter(AkantuPrinter):
"""Pretty printer for akantu::Array<T>"""
- regex = re.compile('^akantu::Array<(.*?), (true|false)>$|^akantu::ArrayDataLayer<(.*?), \(akantu::ArrayAllocationType\)1>$')
- name = 'akantu::Array'
+
+ regex = re.compile(
+ "^akantu::Array<(.*?), (true|false)>$|^akantu::ArrayDataLayer<(.*?), \(akantu::ArrayAllocationType\)1>$" # noqa
+ )
+ name = "akantu::Array"
def __init__(self, value):
self.typename = self.get_basic_type(value)
self.value = value
- self.ptr = self.value['values']
- self.size = int(self.value['size_'])
- self.nb_component = int(self.value['nb_component'])
+ self.ptr = self.value["values"]
+ self.size = int(self.value["size_"])
+ self.nb_component = int(self.value["nb_component"])
def to_string(self):
m = self.regex.search(self.typename)
- return 'Array<{0}>({1}, {2}) stored at {3}'.format(
- m.group(1), self.size, self.nb_component, self.ptr)
-
+ return "Array<{0}>({1}, {2}) stored at {3}".format(
+ m.group(1), self.size, self.nb_component, self.ptr
+ )
+
def display_hint(self):
- return 'array'
+ return "array"
def children(self):
_ptr = self.ptr
for i in range(self.size):
for j in range(self.nb_component):
- yield ('[{0}, {1}]'.format(i, j), (_ptr + j).dereference())
+ yield ("[{0}, {1}]".format(i, j), (_ptr + j).dereference())
_ptr = _ptr + self.nb_component
class RbtreeIterator(object):
"""
Turn an RB-tree-based container (std::map, std::set etc.) into
a Python iterable object.
"""
+
def __init__(self, rbtree):
- self.size = rbtree['_M_t']['_M_impl']['_M_node_count']
- self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left']
+ self.size = rbtree["_M_t"]["_M_impl"]["_M_node_count"]
+ self.node = rbtree["_M_t"]["_M_impl"]["_M_header"]["_M_left"]
self.count = 0
def __iter__(self):
return self
def __len__(self):
return int(self.size)
def __next__(self):
if self.count == self.size:
raise StopIteration
result = self.node
self.count = self.count + 1
if self.count < self.size:
# Compute the next node.
node = self.node
- if node.dereference()['_M_right']:
- node = node.dereference()['_M_right']
- while node.dereference()['_M_left']:
- node = node.dereference()['_M_left']
+ if node.dereference()["_M_right"]:
+ node = node.dereference()["_M_right"]
+ while node.dereference()["_M_left"]:
+ node = node.dereference()["_M_left"]
else:
- parent = node.dereference()['_M_parent']
- while node == parent.dereference()['_M_right']:
+ parent = node.dereference()["_M_parent"]
+ while node == parent.dereference()["_M_right"]:
node = parent
- parent = parent.dereference()['_M_parent']
- if node.dereference()['_M_right'] != parent:
+ parent = parent.dereference()["_M_parent"]
+ if node.dereference()["_M_right"] != parent:
node = parent
self.node = node
return result
+
def get_value_from_aligned_membuf(buf, valtype):
"""Returns the value held in a __gnu_cxx::__aligned_membuf."""
- return buf['_M_storage'].address.cast(valtype.pointer()).dereference()
+ return buf["_M_storage"].address.cast(valtype.pointer()).dereference()
def get_value_from_Rb_tree_node(node):
"""Returns the value held in an _Rb_tree_node<_Val>"""
try:
member = node.type.fields()[1].name
- if member == '_M_value_field':
+ if member == "_M_value_field":
# C++03 implementation, node contains the value as a member
- return node['_M_value_field']
- elif member == '_M_storage':
+ return node["_M_value_field"]
+ elif member == "_M_storage":
# C++11 implementation, node stores value in __aligned_membuf
valtype = node.type.template_argument(0)
- return get_value_from_aligned_membuf(node['_M_storage'], valtype)
+ return get_value_from_aligned_membuf(node["_M_storage"], valtype)
except: # noqa: E722
pass
raise ValueError("Unsupported implementation for %s" % str(node.type))
def find_type(orig, name):
typ = orig.strip_typedefs()
while True:
# Strip cv-qualifiers. PR 67440.
- search = '%s::%s' % (typ.unqualified(), name)
+ search = "%s::%s" % (typ.unqualified(), name)
try:
return gdb.lookup_type(search)
except RuntimeError:
pass
# The type was not found, so try the superclass. We only need
# to check the first superclass, so we don't bother with
# anything fancier here.
field = typ.fields()[0]
if not field.is_base_class:
raise ValueError("Cannot find type %s::%s" % (str(orig), name))
typ = field.type
@register_pretty_printer
class AkaElementTypeMapArrayPrinter(AkantuPrinter):
"""Pretty printer for akantu::ElementTypeMap<Array<T>>"""
- regex = re.compile('^akantu::ElementTypeMap<akantu::Array<(.*?), (true|false)>\*, akantu::(.*?)>$') # noqa: E501,W605
- name = 'akantu::ElementTypeMapArray'
+
+ regex = re.compile(
+ "^akantu::ElementTypeMap<akantu::Array<(.*?), (true|false)>\*, akantu::(.*?)>$" # noqa
+ ) # noqa: E501,W605
+ name = "akantu::ElementTypeMapArray"
# Turn an RbtreeIterator into a pretty-print iterator.
class _rb_iter(object):
def __init__(self, rbiter, type, ghost_type):
self.rbiter = rbiter
self.count = 0
self.type = type
self.ghost_type = ghost_type
def __iter__(self):
return self
def __next__(self):
if self.count % 2 == 0:
n = next(self.rbiter)
n = n.cast(self.type).dereference()
n = get_value_from_Rb_tree_node(n)
self.pair = n
- item = "{0}:{1}".format(n['first'], self.ghost_type)
+ item = "{0}:{1}".format(n["first"], self.ghost_type)
else:
- item = self.pair['second'].dereference()
- result = ('[{0}]'.format(self.count), item)
+ item = self.pair["second"].dereference()
+ result = ("[{0}]".format(self.count), item)
self.count = self.count + 1
return result
def _iter(self, not_ghost, ghost, type):
iter_size = (len(not_ghost), len(ghost))
- it = self._rb_iter(not_ghost, type, '_not_ghost')
+ it = self._rb_iter(not_ghost, type, "_not_ghost")
for _ in range(iter_size[0] * 2):
yield next(it)
- it = self._rb_iter(ghost, type, '_ghost')
+ it = self._rb_iter(ghost, type, "_ghost")
for _ in range(iter_size[1] * 2):
yield next(it)
raise StopIteration
def __init__(self, value):
self.typename = self.get_basic_type(value)
self.value = value
- self.data = self.value['data']
- self.ghost_data = self.value['ghost_data']
+ self.data = self.value["data"]
+ self.ghost_data = self.value["ghost_data"]
def to_string(self):
m = self.regex.search(self.typename)
- return 'ElementTypMapArray<{0}> with '\
- '{1} _not_ghost and {2} _ghost'.format(
- m.group(1), len(RbtreeIterator(self.data)),
+ return "ElementTypMapArray<{0}> with " "{1} _not_ghost and {2} _ghost".format( # noqa
+ m.group(1),
+ len(RbtreeIterator(self.data)),
len(RbtreeIterator(self.ghost_data)))
def children(self):
# m = self.regex.search(self.typename)
- rep_type = find_type(self.data.type, '_Rep_type')
- node = find_type(rep_type, '_Link_type')
+ rep_type = find_type(self.data.type, "_Rep_type")
+ node = find_type(rep_type, "_Link_type")
node = node.strip_typedefs()
return itertools.chain(
self._rb_iter(RbtreeIterator(self.data), node, "_not_ghost"),
- self._rb_iter(RbtreeIterator(self.ghost_data), node, "_ghost"))
+ self._rb_iter(RbtreeIterator(self.ghost_data), node, "_ghost"),
+ )
def display_hint(self):
- return 'map'
+ return "map"
# @register_pretty_printer
class AkaTensorPrinter(AkantuPrinter):
"""Pretty printer for akantu::Tensor<T>"""
- regex = re.compile('^akantu::Tensor<(.*), +(.*), +(.*)>$')
- name = 'akantu::Tensor'
+
+ regex = re.compile("^akantu::Tensor<(.*), +(.*), +(.*)>$")
+ name = "akantu::Tensor"
value = None
typename = ""
ptr = None
dims = []
ndims = 0
def pretty_print(self):
def ij2str(i, j, m):
- return "{0}".format((self.ptr+m*j + i).dereference())
+ return "{0}".format((self.ptr + m * j + i).dereference())
def line(i, m, n):
- return "[{0}]".format(", ".join((ij2str(i, j, m) for j in
- range(n))))
+ return "[{0}]".format(
+ ", ".join((ij2str(i, j, m) for j in range(n))))
m = int(self.dims[0])
- if (self.ndims == 1):
+ if self.ndims == 1:
n = 1
else:
n = int(self.dims[1])
return "[{0}]".format(", ".join(line(i, m, n) for i in range(m)))
def __init__(self, value):
self.typename = self.get_basic_type(value)
self.value = value
- self.ptr = self.value['values']
- self.dims = self.value['n']
+ self.ptr = self.value["values"]
+ self.dims = self.value["n"]
def children(self):
- yield ('values', self.pretty_print())
- yield ('wrapped', self.value['wrapped'])
+ yield ("values", self.pretty_print())
+ yield ("wrapped", self.value["wrapped"])
@register_pretty_printer
class AkaVectorPrinter(AkaTensorPrinter):
"""Pretty printer for akantu::Vector<T>"""
- regex = re.compile('^akantu::Vector<(.*)>$')
- name = 'akantu::Vector'
+
+ regex = re.compile("^akantu::Vector<(.*)>$")
+ name = "akantu::Vector"
n = 0
ptr = 0x0
def __init__(self, value):
super(AkaVectorPrinter, self).__init__(value)
self.ndims = 1
def to_string(self):
m = self.regex.search(self.typename)
- return 'Vector<{0}>({1}) [{2}]'.format(m.group(1), int(self.dims[0]),
- str(self.ptr))
+ return "Vector<{0}>({1}) [{2}]".format(
+ m.group(1), int(self.dims[0]), str(self.ptr)
+ )
@register_pretty_printer
class AkaMatrixPrinter(AkaTensorPrinter):
- """Pretty printer for akantu::Matrix<T>"""
- regex = re.compile('^akantu::Matrix<(.*)>$')
- name = 'akantu::Matrix'
+ """Pretty printer for akantu::Matrix<T>."""
+
+ regex = re.compile("^akantu::Matrix<(.*)>$")
+ name = "akantu::Matrix"
def __init__(self, value):
super(AkaMatrixPrinter, self).__init__(value)
self.ndims = 2
def to_string(self):
m = self.regex.search(self.typename)
- return 'Matrix<%s>(%d, %d) [%s]' % (m.group(1), int(self.dims[0]),
- int(self.dims[1]),
- str(self.ptr))
+ return "Matrix<%s>(%d, %d) [%s]" % (
+ m.group(1),
+ int(self.dims[0]),
+ int(self.dims[1]),
+ str(self.ptr),
+ )
@register_pretty_printer
class AkaElementPrinter(AkantuPrinter):
- """Pretty printer for akantu::Element"""
- regex = re.compile('^akantu::Element$')
- name = 'akantu::Element'
+ """Pretty printer for akantu::Element."""
+
+ regex = re.compile("^akantu::Element$")
+ name = "akantu::Element"
def __init__(self, value):
self.typename = self.get_basic_type(value)
self.value = value
- self.element = self.value['element']
- self.eltype = self.value['type']
- self.ghost_type = self.value['ghost_type']
- self._ek_not_defined = gdb.parse_and_eval('akantu::_not_defined')
- self._casper = gdb.parse_and_eval('akantu::_casper')
- self._max_uint = gdb.parse_and_eval('(akantu::UInt) -1')
+ self.element = self.value["element"]
+ self.eltype = self.value["type"]
+ self.ghost_type = self.value["ghost_type"]
+ self._ek_not_defined = gdb.parse_and_eval("akantu::_not_defined")
+ self._casper = gdb.parse_and_eval("akantu::_casper")
+ self._max_uint = gdb.parse_and_eval("(akantu::Int) -1")
def to_string(self):
- if (self.element == self._max_uint) and \
- (self.eltype == self._ek_not_defined) and \
- (self.ghost_type == self._casper):
- return 'ElementNull'
+ if (
+ (self.element == self._max_uint)
+ and (self.eltype == self._ek_not_defined)
+ and (self.ghost_type == self._casper)
+ ):
+ return "ElementNull"
- return 'Element({0}, {1}, {2})'.format(self.element, self.eltype,
- self.ghost_type)
+ return "Element({0}, {1}, {2})".format(
+ self.element, self.eltype, self.ghost_type
+ )
def register_akantu_printers(obj):
- "Register Akantu Pretty Printers."
- gdb.printing.register_pretty_printer(obj, __akantu_pretty_printers__)
\ No newline at end of file
+ """Register Akantu Pretty Printers."""
+ gdb.printing.register_pretty_printer(obj, __akantu_pretty_printers__)
diff --git a/cmake/lsan_akantu.supp b/cmake/lsan_akantu.supp
new file mode 100644
index 000000000..d4c2f2cf3
--- /dev/null
+++ b/cmake/lsan_akantu.supp
@@ -0,0 +1,17 @@
+leak:libmpi
+leak:libpmix
+leak:libopen-pal
+leak:mca_mpool_hugepage
+leak:mca_coll_libnbc
+leak:mca_op_avx
+leak:mca_coll_han
+leak:hwloc
+leak:_multiarray_umath
+leak:PyObject_Malloc
+leak:PyThread_allocate_lock
+leak:_PyObject_GC_Resize
+leak:resize_compact
+leak:vasprintf_internal
+leak:interceptor_strdup
+leak:interceptor_malloc
+leak:_imp_create_dynamic
diff --git a/cmake/sanitize-blacklist.txt b/cmake/sanitize-blacklist.txt
index a5fc71fb5..bb5c222df 100644
--- a/cmake/sanitize-blacklist.txt
+++ b/cmake/sanitize-blacklist.txt
@@ -1,8 +1,7 @@
-src:/home/richart/dev/lsms/akantu-master/third-party/*
-fun:MPI_*
-fun:_ZN7testing8internal12UnitTestImpl12GetTestSuiteEPKcS3_PFvvES5_
-fun:_ZN7testing8internal20StringStreamToStringEPNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE
-fun:_ZN7testing8internal16BoolFromGTestEnvEPKcb
-fun:_ZN7testing8internalL12FlagToEnvVarB5cxx11EPKc
-fun:testing::internal::*
-fun:_ZN7testing8internal*
+interceptor_via_fun:MPI_*
+interceptor_via_fun:_ZN7testing8internal12UnitTestImpl12GetTestSuiteEPKcS3_PFvvES5_
+interceptor_via_fun:_ZN7testing8internal20StringStreamToStringEPNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE
+interceptor_via_fun:_ZN7testing8internal16BoolFromGTestEnvEPKcb
+interceptor_via_fun:_ZN7testing8internalL12FlagToEnvVarB5cxx11EPKc
+interceptor_via_fun:testing::internal::*
+interceptor_via_fun:_ZN7testing8internal*
diff --git a/cmake/semver.py b/cmake/semver.py
index fa0b2d808..b6b384620 100644
--- a/cmake/semver.py
+++ b/cmake/semver.py
@@ -1,208 +1,236 @@
#!/usr/bin/env python3
+
+"""module to get the VERSION from a git repository."""
+
import os
import re
+import sys
import subprocess
def run_git_command(args):
- git_dir = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))
+ """Run git commands and capture outputs."""
+ git_dir = os.path.realpath(
+ os.path.join(os.path.dirname(__file__),
+ os.pardir))
cmd = ["git"] + args
p = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=git_dir
)
stdout = p.communicate()[0].strip().decode()
if p.returncode != 0:
return None, p.returncode
return stdout, p.returncode
def _split_git_describe(describe):
describe_mo = re.search(
r"^(?P<tag>.+)"
r"-(?P<distance>\d+)"
r"-g(?P<short>[0-9a-f]+)"
r"(-(?P<dirty>dirty))?$",
describe,
)
if describe_mo:
pieces = {}
pieces["tag"] = describe_mo.group("tag")
# distance: number of commits since tag
pieces["distance"] = int(describe_mo.group("distance"))
# commit: short hex revision ID
pieces["short"] = describe_mo.group("short")
if describe_mo.group("dirty"):
pieces["dirty"] = describe_mo.group("dirty")
return pieces
return None
+def _eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+
semver_re = re.compile(
r"^(?P<major>0|[1-9]\d*)"
r"(\.(?P<minor>0|[1-9]\d*))?"
r"(\.(?P<patch>0|[1-9]\d*))?"
- r"(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"
+ r"(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"
+ r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"
r"(?:\+(?P<build>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
)
def _parse_semver(version):
- pieces = {}
semver_mo = semver_re.search(version)
- if semver_mo:
- for p in ["major", "minor", "patch", "prerelease", "build"]:
- if semver_mo.group(p):
- pieces[p] = semver_mo.group(p)
+ if not semver_mo:
+ return {}
+
+ pieces = {}
+ for p in ["major", "minor", "patch", "prerelease", "build"]:
+ if semver_mo.group(p):
+ pieces[p] = semver_mo.group(p)
return pieces
def get_git_version():
+ """Get the version from the git repository."""
out, rc = run_git_command(["rev-parse", "--git-dir"])
if rc != 0:
return None
git_describe, rc = run_git_command(
["describe", "--tags", "--dirty", "--always", "--match", "v*"]
)
- if '-g' in git_describe:
+ _eprint(f"git describe {git_describe}")
+ if "-g" in git_describe:
# TAG-DISTANCE-gHEX
pieces = _split_git_describe(git_describe)
else:
# tag only or no tag and hash
pieces = {"tag": git_describe}
# major.minor.patch-prerelease+build
if not pieces or ("tag" not in pieces):
return None
semver_mo = semver_re.search(pieces["tag"][1:])
- if semver_mo:
- for p in ["major", "minor", "patch", "prerelease", "build"]:
- if semver_mo.group(p):
- pieces[p] = semver_mo.group(p)
+ if not semver_mo:
+ return pieces
+
+ for p in ["major", "minor", "patch", "prerelease", "build"]:
+ if semver_mo.group(p):
+ pieces[p] = semver_mo.group(p)
return pieces
def get_git_attributes_version():
+ """Get the version from the attributes set a `git archive`."""
file_dir = os.path.dirname(os.path.realpath(os.path.abspath(__file__)))
attributes = None
pieces = None
with open(os.path.join(file_dir, "git_info")) as fh:
describe_re = re.compile(r"describe: ([^$].*[^$])")
for line in fh:
mo = describe_re.search(line)
if mo:
attributes = mo.group(1)
break
if attributes:
pieces = _split_git_describe(attributes)
return pieces
def get_ci_version():
+ """Get extra information from CI context."""
pieces = None
if "CI_AKANTU_INSTALL_PREFIX" not in os.environ:
return None
ci_akantu_install_prefix = os.environ["CI_AKANTU_INSTALL_PREFIX"]
- akantu_dir = os.path.join(ci_akantu_install_prefix, "lib", "cmake", "Akantu")
+ akantu_dir = os.path.join(ci_akantu_install_prefix,
+ "lib", "cmake", "Akantu")
cmake_config = os.path.join(akantu_dir, "AkantuConfig.cmake")
if not os.path.exists(cmake_config):
return None
version = None
with open(cmake_config, "r") as fh:
version_re = re.compile(r"^set\(AKANTU_VERSION (.*)\)$")
for line in fh:
version_mo = version_re.search(line)
if version_mo:
version = version_mo.group(1)
break
if not version:
return None
pieces = _parse_semver(version)
return pieces
def get_version_file():
+ """Get the version directly from the VERSION file."""
version_path = os.path.join(
os.path.realpath(
- os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
+ os.path.abspath(os.path.join(os.path.dirname(__file__),
+ os.path.pardir))
),
"VERSION",
)
if not os.path.exists(version_path):
return None
version = None
with open(version_path, "r") as fh:
version = fh.readline()
if not version:
return None
pieces = _parse_semver(version)
return pieces
def get_version():
+ """Combine all the version determination functions."""
pieces = None
if not pieces:
pieces = get_ci_version()
+ _eprint(f"pieces from ci_version: {pieces}")
if not pieces:
pieces = get_git_version()
+ _eprint(f"pieces from git_version: {pieces}")
if not pieces:
pieces = get_git_attributes_version()
+ _eprint(f"pieces from git attributes: {pieces}")
if not pieces:
pieces = get_version_file()
+ _eprint(f"pieces from version file: {pieces}")
if not pieces:
raise Exception("No version could be determined")
semver_build = []
if "build" in pieces:
semver_build = [pieces["build"]]
if "distance" in pieces:
semver_build.extend([str(pieces["distance"]), "g" + pieces["short"]])
if "dirty" in pieces and pieces["dirty"]:
semver_build.append(pieces["dirty"])
if semver_build:
pieces["build_part"] = "+" + ".".join(semver_build)
else:
pieces["build_part"] = ""
if "prerelease" in pieces:
pieces["prerelease"] = "-" + pieces["prerelease"]
else:
pieces["prerelease"] = ""
semver = "{major}.{minor}.{patch}{prerelease}{build_part}".format(**pieces)
if "CI_MERGE_REQUEST_ID" in os.environ:
semver = "{}.mr{}".format(semver, os.environ["CI_MERGE_REQUEST_ID"])
return semver
if __name__ == "__main__":
print(get_version())
diff --git a/doc/coding_convention/snippet/for b/doc/coding_convention/snippet/for
index 8bd190800..4973bc15a 100644
--- a/doc/coding_convention/snippet/for
+++ b/doc/coding_convention/snippet/for
@@ -1,5 +1,5 @@
#name : for (...; ...; ...) { ... }
# --
-for (${1:UInt ${2:i} = 0}; ${3:$2 < N}; ${4:++$2}) {
+for (${1:Int ${2:i} = 0}; ${3:$2 < N}; ${4:++$2}) {
$0
}
diff --git a/doc/dev-doc/changelog.rst b/doc/dev-doc/changelog.rst
index 03879c6fd..540e1c93d 100644
--- a/doc/dev-doc/changelog.rst
+++ b/doc/dev-doc/changelog.rst
@@ -1,63 +1,63 @@
Version 4.0
-------------
features
* transferred the CI from jenkins to Gitlab CI/CD
api
* breaking api changes to match the stl containers
* ``clear`` does not set to ``0`` anymore but empties containers
* ``empty`` does not empty containers but tells if the container is empty
* ``zero`` replace the old empty and set containers to ``0``
Version 3.2
-------------
features
Activating PETSc solver back with the new solver interface
api
deprecating old C++ 03 code
Version 3.0
-------------
c++14
switch from C++ standard ``2003`` to ``2014``
Example of changes implied by this::
- for (UInt g = _not_ghost; g <= _ghost; ++g) {
+ for (Int g = _not_ghost; g <= _ghost; ++g) {
GhostType gt = (GhostType)g;
Mesh::type_iterator it = this->mesh.firstType(spatial_dimension, gt);
Mesh::type_iterator end = this->mesh.lastType(spatial_dimension, gt);
for (; it != end; ++it) {
ElementType & type = *it;
...
}
}
becomes::
for (auto ghost_type : ghost_types) {
for (auto type : mesh.elementTypes(spatial_dimension,
ghost_type)) {
...
}
}
features
* Parallel cohesive elements
* Models using new interface for solvers
* Same configuration for all models
* Solver can be configured in input file
* PETSc interface temporary inactive
* Periodic boundary condition temporary inactive
* Element groups created by default for ``“physical_names”``
api
* Named arguments for functions (e.g. ``model.initFull(_analysis_method = _static)``)
* Only one function to solve a step :cpp:func:`model.solveStep() <akantu::ModelSolver::solveStep>`
* Simplification of the parallel simulation with the :cpp:func:`mesh.distribute() <akantu::Mesh::distribute>` function
diff --git a/doc/dev-doc/conf.py b/doc/dev-doc/conf.py
index de67c6d53..35471484d 100644
--- a/doc/dev-doc/conf.py
+++ b/doc/dev-doc/conf.py
@@ -1,333 +1,335 @@
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import shutil
import jinja2
# import git
# import re
import subprocess
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Number figures
numfig = True
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.coverage",
"sphinx.ext.mathjax",
"sphinx.ext.ifconfig",
"sphinx.ext.viewcode",
"sphinxcontrib.bibtex",
"breathe",
]
read_the_docs_build = os.environ.get("READTHEDOCS", None) == "True"
if read_the_docs_build:
akantu_path = "."
akantu_source_path = "../../"
else:
akantu_path = "@CMAKE_CURRENT_BINARY_DIR@"
akantu_source_path = "@CMAKE_SOURCE_DIR@"
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"
# The master toctree document.
master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = [
"CMakeLists.txt",
"manual/appendix/elements.rst",
"manual/appendix/material-parameters.rst",
"manual/constitutive-laws.rst",
"manual/new-constitutive-laws.rst",
]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
primary_domain = "cpp"
highlight_language = "cpp"
bibtex_bibfiles = ["manual/manual-bibliography.bib"]
# -- Project information -----------------------------------------------------
project = "Akantu"
copyright = (
"2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)"
+ " Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)"
)
author = "Nicolas Richart"
# try:
# tag_prefix = 'v'
# git_repo = git.Repo(akantu_source_path)
# git_describe = git_repo.git.describe('--tags', '--dirty', '--always',
# '--long',
# '--match', '{}*'.format(tag_prefix))
# print("GIT Describe: {}".format(git_describe))
# # git describe to PEP404 version
# describe_matches = re.search(
# (r'^{}(?P<version>.+?)' +
# r'(?:-(?P<distance>\d+)-g(?P<sha>[0-9a-f]+)' +
# r'(?:-(?P<dirty>dirty))?)?$').format(tag_prefix),
# git_describe)
# if describe_matches:
# describe_matches = describe_matches.groupdict()
# release = describe_matches['version']
# if describe_matches['distance']:
# release += '.' if '+' in release else '+'
# release += '{distance}.{sha}'.format(**describe_matches)
# if describe_matches['dirty']:
# release += '.dirty'
# else:
# count = git_repo.git.rev_list('HEAD', '--count')
# describe_matches = re.search(
# (r'^(?P<sha>[0-9a-f]+)' +
# r'(?:-(?P<dirty>dirty))?$').format(tag_prefix),
# git_describe).groupdict()
# release = '{}.{}+{}'.format(file_release, count,
# describe_matches['sha'])
# except git.InvalidGitRepositoryError:
# with open(os.path.join(akantu_source_path, 'VERSION'), 'r') as fh:
# version_file = fh.readlines()
# file_release = version_file[0].strip()
# release = file_release
# print("Release: {} - Version: {}".format(release, version))
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
if read_the_docs_build:
html_theme = "default"
else:
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
html_logo = "_static/logo_only_akantu.svg"
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
html_sidebars = {
"**": [
"relations.html", # needs 'show_related': True theme option to display
"searchbox.html",
]
}
math_eqref_format = "Eq. {number}"
# MathJax configuration
# if not read_the_docs_build:
mathjax2_config = {
"extensions": ["tex2jax.js", "siunitx.js"],
"TeX": {
"Macros": {
"st": [r"\mathrm{#1}", 1],
"mat": [r"\mathbf{#1}", 1],
"half": [r"\frac{1}{2}", 0],
},
"extensions": ["AMSmath.js", "AMSsymbols.js", "sinuitx.js"],
},
}
-#for old versions
+
+# for old versions
mathjax_config = mathjax2_config
mathjax3_config = {
"tex": {
"macros": {
"st": [r"\mathrm{#1}", 1],
"mat": [r"\mathbf{#1}", 1],
"half": [r"\frac{1}{2}", 0],
},
"packages": ["base", "ams"],
},
"loader": {"load": ["[tex]/ams"]},
}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = "Akantudoc"
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
"preamble": r"""\usepackage{amsmath}""",
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, "Akantu.tex", "Akantu Documentation", "Nicolas Richart", "manual"),
+ (master_doc, "Akantu.tex", "Akantu Documentation",
+ "Nicolas Richart", "manual"),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, "akantu", "Akantu Documentation", [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(
master_doc,
"Akantu",
"Akantu Documentation",
author,
"Akantu",
"One line description of project.",
"Miscellaneous",
),
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
epub_author = author
epub_publisher = author
epub_copyright = copyright
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
epub_identifier = ""
# A unique identification for the text.
#
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ["search.html"]
# -- Extension configuration -------------------------------------------------
j2_args = {}
if read_the_docs_build:
j2_template_path = "."
else:
j2_template_path = "@CMAKE_CURRENT_SOURCE_DIR@"
os.makedirs(os.path.join(akantu_path, "_static"), exist_ok=True)
shutil.copyfile(
os.path.join("@CMAKE_CURRENT_SOURCE_DIR@", html_logo),
os.path.join(akantu_path, html_logo),
)
j2_args = {
"akantu_source_path": akantu_source_path,
- #'akantu_version': version.replace('v', ''),
}
print(akantu_path)
j2_env = jinja2.Environment(
- loader=jinja2.FileSystemLoader(j2_template_path), undefined=jinja2.DebugUndefined
+ loader=jinja2.FileSystemLoader(j2_template_path),
+ undefined=jinja2.DebugUndefined
)
j2_template = j2_env.get_template("akantu.dox.j2")
with open(os.path.join(akantu_path, "akantu.dox"), "w") as fh:
fh.write(j2_template.render(j2_args))
subprocess.run(["doxygen", "akantu.dox"], cwd=akantu_path)
# print("akantu_path = '{}'".format(akantu_path))
breathe_projects = {"Akantu": os.path.join(akantu_path, "xml")}
breathe_default_project = "Akantu"
breathe_default_members = ("members", "undoc-members")
breathe_implementation_filename_extensions = [".c", ".cc", ".cpp"]
breathe_show_enumvalue_initializer = True
breathe_debug_trace_directives = True
# -- Options for intersphinx extension ---------------------------------------
intersphinx_mapping = {
"numpy": ("https://docs.scipy.org/doc/numpy/", None),
"scipy": ("https://docs.scipy.org/doc/scipy/reference", None),
}
diff --git a/doc/dev-doc/manual/getting_started.rst b/doc/dev-doc/manual/getting_started.rst
index 90ac8abd7..bc50a483b 100644
--- a/doc/dev-doc/manual/getting_started.rst
+++ b/doc/dev-doc/manual/getting_started.rst
@@ -1,496 +1,496 @@
Getting Started
===============
Building ``Akantu``
--------------------
Dependencies
````````````
In order to compile ``Akantu`` any compiler supporting fully C++14 should work.
In addition some libraries are required:
- CMake (>= 3.5.1)
- Boost (preprocessor and Spirit)
- zlib
- blas/lapack
For the python interface:
- Python (>=3 is recommended)
- pybind11 (if not present the build system will try to download it)
To run parallel simulations:
- MPI
- Scotch
To use the static or implicit dynamic solvers at least one of the following libraries is needed:
- MUMPS (since this is usually compiled in static you also need MUMPS dependencies)
- PETSc
To compile the tests and examples:
- Gmsh
- google-test (if not present the build system will try to download it)
Configuring and compilation
```````````````````````````
``Akantu`` is a `CMake <https://cmake.org/>`_ project, so to configure it, you can either
follow the usual way::
> cd akantu
> mkdir build
> cd build
> ccmake ..
[ Set the options that you need ]
> make
> make install
Using the python interface
--------------------------
You can install ``Akantu`` using pip::
> pip install akantu
You can then import the package in a python script as::
import akantu
The python API is similar to the C++ one, see :ref:`reference` . If you encouter any problem with the python interface, you are welcome to do a merge request or post an issue on `GitLab <https://gitlab.com/akantu/akantu/-/issues>`_ .
Tutorials with the python interface
```````````````````````````````````
To help getting started, several tutorials using the python interface
are available as notebooks with pre-installed version of ``Akantu`` on Binder.
The following tutorials are currently available:
`Plate whith a hole loaded <https://mybinder.org/v2/git/https%3A%2F%2Fgitlab.com%2Fakantu%2Ftutorials.git/HEAD?filepath=plate-hole/plate-hole.ipynb>`_
`Loaded cohesive crack <https://mybinder.org/v2/git/https%3A%2F%2Fgitlab.com%2Fakantu%2Ftutorials.git/HEAD?filepath=cohesive-fracture/cohesive-fracture.ipynb>`_
`Making your constitutive law in python <https://mybinder.org/v2/git/https%3A%2F%2Fgitlab.com%2Fakantu%2Ftutorials.git/HEAD?filepath=constitutive-laws/python_constitutive_law.ipynb>`_
Writing a ``main`` function
---------------------------
``Akantu`` first needs to be initialized. The memory management included in the
core library handles the correct allocation and de-allocation of vectors,
structures and/or objects. Moreover, in parallel computations, the
initialization procedure performs the communication setup. This is achieved by
the function :cpp:func:`initialize <akantu::initialize>` that is used as
follows::
#include "aka_common.hh"
#include "..."
using namespace akantu;
int main(int argc, char *argv[]) {
initialize("input_file.dat", argc, argv);
// your code ...
}
The :cpp:func:`initialize <akantu::initialize>` function takes the text inpute
file and the program parameters which can be parsed by ``Akantu`` in due form
(see sect:parser). Obviously it is necessary to include all files needed in
main. In this manual all provided code implies the usage of ``akantu`` as
namespace.
Compiling your simulation
-------------------------
The easiest way to compile your simulation is to create a ``cmake`` project by
putting all your code in some directory of your choosing. Then, make sure that
you have ``cmake`` installed and create a ``CMakeLists.txt`` file. An example of
a minimal ``CMakeLists.txt`` file would look like this:
.. code-block:: cmake
project(my_simu)
cmake_minimum_required(VERSION 3.0.0)
find_package(Akantu REQUIRED)
add_akantu_simulation(my_simu my_simu.cc)
Then create a directory called ``build`` and inside it execute ``cmake
-DAkantu_DIR=<path_to_akantu> -DCMAKE_BUILD_TYPE=RelWithDebInfo ..``. If you
installed ``Akantu`` in a standard directory such as ``/usr/local`` (using
``make install``), you can omit the ``-DAkantu_DIR=<path_to_akantu>`` option.
Other why ``path_to_akantu`` is either the folder where you built ``Akantu`` if
you did not do a ``make install``, or if you installed ``Akantu`` in
``CMAKE_INSTALL_PREFIX`` it is ``<CMAKE_INSTALL_PREFIX>/share/cmake/Akantu``.
Once ``cmake`` managed to configure and generate a ``makefile`` you can just do
``make``
.. _loading_mesh:
Creating and Loading a Mesh
---------------------------
In its current state, ``Akantu`` supports three types of meshes: Gmsh, Abaqus and
Diana. Once a :cpp:class:`akantu::Mesh` object is created with a given spatial
dimension, it can be filled by reading a mesh input file. The method
:cpp:func:`read <akantu::Mesh::read>` of the class :cpp:class:`Mesh
<akantu::Mesh>` infers the mesh type from the file extension. If a non-standard
file extension is used, the mesh type has to be specified. ::
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
// Reading Gmsh files
mesh.read("my_gmsh_mesh.msh");
mesh.read("my_gmsh_mesh", _miot_gmsh);
The Gmsh reader adds the geometrical and physical tags as mesh data. The
-physical values are stored as a :cpp:type:`UInt <akantu::UInt>` data called
+physical values are stored as a :cpp:type:`Int <akantu::Int>` data called
``tag_0``, if a string name is provided it is stored as a ``std::string`` data
-named ``physical_names``. The geometrical tag is stored as a :cpp:type:`UInt
-<akantu::UInt>` data named ``tag_1``.
+named ``physical_names``. The geometrical tag is stored as a :cpp:type:`Int
+<akantu::Int>` data named ``tag_1``.
Using Arrays
------------
Data in ``Akantu`` can be stored in data containers implemented by the
:cpp:class:`akantu::Array` class. In its most basic usage, the :cpp:class:`Array
<akantu::Array>` class implemented in \akantu is similar to the ``std::vector``
class of the Standard Template Library (STL) for C++. A simple :cpp:class:`Array
<akantu::Array>` containing a sequence of ``nb_element`` values (of a given
type) can be generated with::
Array<type> example_array(nb_element);
where ``type`` usually is :cpp:type:`Real <akantu::Real>`, :cpp:type:`Int
<akantu::Int>`, :cpp:type:`UInt <akantu::UInt>` or ``bool``. Each value is
associated to an index, so that data can be accessed by typing::
auto & val = example_array(index);
``Arrays`` can also contain tuples of values for each index. In that case, the
number of components per tuple must be specified at the :cpp:class:`Array
<akantu::Array>` creation. For example, if we want to create an
:cpp:class:`Array <akantu::Array>` to store the coordinates (sequences of three
values) of ten nodes, the appropriate code is the following::
UInt nb_nodes = 10;
- UInt spatial_dimension = 3;
+ Int spatial_dimension = 3;
Array<Real> position(nb_nodes, spatial_dimension);
In this case the :math:`x` position of the eighth node number will be given
by ``position(7, 0)`` (in C++, numbering starts at 0 and not 1). If
the number of components for the sequences is not specified, the
default value of 1 is used. Here is a list of some basic operations
that can be performed on :cpp:class:`Array <akantu::Array>`:
- :cpp:func:`resize(size) <akantu::ArrayDataLayer::resize>` change the size of
the :cpp:class:`Array <akantu::Array>`.
- :cpp:func:`clear <akantu::Array::clear>` reset the size of the
:cpp:class:`Array <akantu::Array>` to zero. (*warning* this changed in >
v4.0)
- :cpp:func:`set(t) <akantu::Array::set>` set all entries of the
:cpp:class:`Array <akantu::Array>` to ``t``.
- :cpp:func:`copy(const Array & other) <akantu::Array::copy>` copy another
:cpp:class:`Array <akantu::Array>` into the current one. The two
:cpp:class:`Arrays <akantu::Array>` should have the same number of
components.
- :cpp:func:`push_back(tuple) <akantu::Array::push_back>` append a tuple with
the correct number of components at the end of the :cpp:class:`Array <akantu::Array>`.
- :cpp:func:`erase(i) <akantu::Array::erase>` erase the value at the i-th position.
- :cpp:func:`find(value) <akantu::Array::find>` search ``value`` in the
current :cpp:class:`Array <akantu::Array>`. Return position index of the
first occurence or -1 if not found.
- :cpp:func:`storage() <akantu::Array::storage>` Return the address of the
allocated memory of the :cpp:class:`Array <akantu::Array>`.
Array iterators
---------------
It is very common in ``Akantu`` to loop over arrays to perform a specific treatment.
This ranges from geometric calculation on nodal quantities to tensor algebra (in
constitutive laws for example). The :cpp:class:`Array <akantu::Array>` object
has the possibility to request iterators in order to make the writing of loops
easier and enhance readability. For instance, a loop over the nodal coordinates
can be performed like::
// accessing the nodal coordinates Array
// with spatial_dimension components
const auto & nodes = mesh.getNodes();
for (const auto & coords : make_view(nodes, spatial_dimension)) {
// do what you need ....
}
In that example, each ``coords`` is a :cpp:class:`Vector\<Real\> <akantu::Vector>`
containing geometrical array of size ``spatial_dimension`` and the iteration is
conveniently performed by the :cpp:class:`Array <akantu::Array>` iterator.
The :cpp:class:`Array <akantu::Array>` object is intensively used to store
second order tensor values. In that case, it should be specified that the
returned object type is a matrix when constructing the iterator. This is done
when calling the :cpp:func:`make_view <akantu::make_view>`. For instance,
assuming that we have a :cpp:class:`Array <akantu::Array>` storing stresses, we
can loop over the stored tensors by::
for (const auto & stress :
make_view(stresses, spatial_dimension, spatial_dimension)) {
// stress is of type `const Matrix<Real>&`
}
In that last example, the :cpp:class:`Matrix\<Real\> <akantu::Matrix>` objects are
``spatial_dimension`` :math:`\times` ``spatial_dimension`` matrices. The light
objects :cpp:class:`Matrix\<T\> <akantu::Matrix>` and
:cpp:class:`Vector\<T\> <akantu::Vector>` can be used and combined to do most
common linear algebra. If the number of component is 1, it is possible to use
:cpp:func:`make_view <akantu::make_view>` to this effect.
In general, a mesh consists of several kinds of elements. Consequently, the
amount of data to be stored can differ for each element type. The
straightforward example is the connectivity array, namely the sequences of nodes
belonging to each element (linear triangular elements have fewer nodes than,
say, rectangular quadratic elements etc.). A particular data structure called
:cpp:class:`ElementTypeMapArray\<T\> <akantu::ElementTypeMapArray>` is provided
to easily manage this kind of data. It consists of a group of ``Arrays``, each
associated to an element type. The following code can retrieve the
:cpp:class:`ElementTypeMapArray\<UInt\> <akantu::ElementTypeMapArray>` which
stores the connectivity arrays for a mesh::
const ElementTypeMapArray<UInt> & connectivities =
mesh.getConnectivities();
Then, the specific array associated to a given element type can be obtained by::
const Array<UInt> & connectivity_triangle =
connectivities(_triangle_3);
where the first order 3-node triangular element was used in the presented piece
of code.
Vector & Matrix
```````````````
The :cpp:class:`Array\<T\> <akantu::Array>` iterators as presented in the previous
section can be shaped as :cpp:class:`Vector\<T\> <akantu::Vector>` or
:cpp:class:`Matrix\<T\> <akantu::Matrix>`. This objects represent 1st and 2nd order
tensors. As such they come with some functionalities that we will present a bit
more into detail in this here.
``Vector<T>``
'''''''''''''
- Accessors:
- :cpp:func:`v(i) <akantu::Vector::operator()>` gives the ``i`` -th
component of the vector ``v``
- :cpp:func:`v[i] <akantu::Vector::operator[]>` gives the ``i`` -th
component of the vector ``v``
- :cpp:func:`v.size() <akantu::Vector::size>` gives the number of component
- Level 1: (results are scalars)
- :cpp:func:`v.norm() <akantu::Vector::norm>` returns the geometrical norm
(:math:`L_2`)
- :cpp:func:`v.norm\<N\>() <akantu::Vector::norm<>>` returns the :math:`L_N`
norm defined as :math:`\left(\sum_i |v(i)|^N\right)^{1/N}`. N can take any
positive integer value. There are also some particular values for the most
commonly used norms, ``L_1`` for the Manhattan norm, ``L_2`` for the
geometrical norm and ``L_inf`` for the norm infinity.
- :cpp:func:`v.dot(x) <akantu::Vector::dot>` return the dot product of
``v`` and ``x``
- :cpp:func:`v.distance(x) <akantu::Vector::distance>` return the
geometrical norm of :math:`v - x`
- Level 2: (results are vectors)
- :cpp:func:`v += s <akantu::Vector::operator+=>`,
:cpp:func:`v -= s <akantu::Vector::operator-=>`,
:cpp:func:`v *= s <akantu::Vector::operator*=>`,
:cpp:func:`v /= s <akantu::Vector::operator/=>` those are element-wise
operators that sum, substract, multiply or divide all the component of ``v``
by the scalar ``s``
- :cpp:func:`v += x <akantu::Vector::operator+=>`, :cpp:func:`v -= x
<akantu::Vector::operator-=>` sums or substracts the vector ``x`` to/from
``v``
- :cpp:func:`v.mul(A, x, alpha) <akantu::Vector::mul>` stores the result of
:math:`\alpha \boldsymbol{A} \vec{x}` in ``v``, :math:`\alpha` is equal to 1
by default
- :cpp:func:`v.solve(A, b) <akantu::Vector::solve>` stores the result of
the resolution of the system :math:`\boldsymbol{A} \vec{x} = \vec{b}` in ``v``
- :cpp:func:`v.crossProduct(v1, v2) <akantu::Vector::crossProduct>`
computes the cross product of ``v1`` and ``v2`` and stores the result in
``v``
``Matrix<T>``
'''''''''''''
- Accessors:
- :cpp:func:`A(i, j) <akantu::Matrix::operator()>` gives the component
:math:`A_{ij}` of the matrix ``A``
- :cpp:func:`A(i) <akantu::Matrix::operator()>` gives the :math:`i^{th}`
column of the matrix as a ``Vector``
- :cpp:func:`A[k] <akantu::Matrix::operator[]>` gives the :math:`k^{th}`
component of the matrix, matrices are stored in a column major way, which
means that to access :math:`A_{ij}`, :math:`k = i + j M`
- :cpp:func:`A.rows() <akantu::Matrix::rows>` gives the number of rows of
``A`` (:math:`M`)
- :cpp:func:`A.cols() <akantu::Matrix::cols>` gives the number of columns
of ``A`` (:math:`N`)
- :cpp:func:`A.size() <akantu::Matrix::size>` gives the number of component
in the matrix (:math:`M \times N`)
- Level 1: (results are scalars)
- :cpp:func:`A.norm() <akantu::Matrix::norm>` is equivalent to
``A.norm<L_2>()``
- :cpp:func:`A.norm\<N\>() <akantu::Matrix::norm<>>` returns the :math:`L_N`
norm defined as :math:`\left(\sum_i\sum_j |A(i,j)|^N\right)^{1/N}`. N can take
any positive integer value. There are also some particular values for the most
commonly used norms, ``L_1`` for the Manhattan norm, ``L_2`` for the
geometrical norm and ``L_inf`` for the norm infinity.
- :cpp:func:`A.trace() <akantu::Matrix::trace>` return the trace of ``A``
- :cpp:func:`A.det() <akantu::Matrix::det>` return the determinant of ``A``
- :cpp:func:`A.doubleDot(B) <akantu::Matrix::doubleDot>` return the double
dot product of ``A`` and ``B``, :math:`\mat{A}:\mat{B}`
- Level 3: (results are matrices)
- :cpp:func:`A.eye(s) <akantu::Matrix::eye>`, ``Matrix<T>::eye(s)``
fills/creates a matrix with the :math:`s\mat{I}` with :math:`\mat{I}` the
identity matrix
- :cpp:func:`A.inverse(B) <akantu::Matrix::inverse>` stores
:math:`\mat{B}^{-1}` in ``A``
- :cpp:func:`A.transpose() <akantu::Matrix::transpose>` returns
:math:`\mat{A}^{t}`
- :cpp:func:`A.outerProduct(v1, v2) <akantu::Matrix::outerProduct>` stores
:math:`\vec{v_1} \vec{v_2}^{t}` in ``A``
- :cpp:func:`C.mul\<t_A, t_B\>(A, B, alpha) <akantu::Matrix::mul>`: stores
the result of the product of ``A`` and code{B} time the scalar ``alpha`` in
``C``. ``t_A`` and ``t_B`` are boolean defining if ``A`` and ``B`` should be
transposed or not.
+----------+----------+--------------+
|``t_A`` |``t_B`` |result |
| | | |
+----------+----------+--------------+
|false |false |:math:`\mat{C}|
| | |= \alpha |
| | |\mat{A} |
| | |\mat{B}` |
| | | |
+----------+----------+--------------+
|false |true |:math:`\mat{C}|
| | |= \alpha |
| | |\mat{A} |
| | |\mat{B}^t` |
| | | |
+----------+----------+--------------+
|true |false |:math:`\mat{C}|
| | |= \alpha |
| | |\mat{A}^t |
| | |\mat{B}` |
| | | |
+----------+----------+--------------+
|true |true |:math:`\mat{C}|
| | |= \alpha |
| | |\mat{A}^t |
| | |\mat{B}^t` |
+----------+----------+--------------+
- :cpp:func:`A.eigs(d, V) <akantu::Matrix::eigs>` this method computes the
eigenvalues and eigenvectors of ``A`` and store the results in ``d`` and
``V`` such that :math:`d(i) = \lambda_i` and :math:`V(i) = \vec{v_i}` with
:math:`\mat{A}\vec{v_i} = \lambda_i\vec{v_i}` and :math:`\lambda_1 > ... >
\lambda_i > ... > \lambda_N`
.. _sect-common-groups:
Mesh
----
Manipulating group of nodes and/or elements
```````````````````````````````````````````
``Akantu`` provides the possibility to manipulate subgroups of elements and
nodes. Any :cpp:class:`ElementGroup <akantu::ElementGroup>` and/or
:cpp:class:`NodeGroup <akantu::NodeGroup>` must be managed by a
:cpp:class:`GroupManager <akantu::GroupManager>`. Such a manager has the role to
associate group objects to names. This is a useful feature, in particular for
the application of the boundary conditions, as will be demonstrated in section
:ref:`sect-smm-boundary`. To most general group manager is the :cpp:class:`Mesh
<akantu::Mesh>` class which inherits from :cpp:class:`GroupManager
<akantu::GroupManager>`.
For instance, the following code shows how to request an element group
to a mesh:
.. code-block:: c++
// request creation of a group of nodes
NodeGroup & my_node_group = mesh.createNodeGroup("my_node_group");
// request creation of a group of elements
ElementGroup & my_element_group = mesh.createElementGroup("my_element_group");
/* fill and use the groups */
The ``NodeGroup`` object
''''''''''''''''''''''''
A group of nodes is stored in :cpp:class:`NodeGroup <akantu::NodeGroup>`
objects. They are quite simple objects which store the indexes of the selected
nodes in a :cpp:class:`Array\<UInt\> <akantu::Array>`. Nodes are selected by
adding them when calling :cpp:func:`add <akantu::NodeGroup::add>`. For instance
you can select nodes having a positive :math:`X` coordinate with the following
code:
.. code-block:: c++
const auto & nodes = mesh.getNodes();
auto & group = mesh.createNodeGroup("XpositiveNode");
for (auto && data : enumerate(make_view(nodes, spatial_dimension))){
auto node = std::get<0>(data);
const auto & position = std::get<1>(data);
if (position(0) > 0) group.add(node);
}
The ``ElementGroup`` object
'''''''''''''''''''''''''''
A group of elements is stored in :cpp:class:`ElementGroup
<akantu::ElementGroup>` objects. Since a group can contain elements of various
types the :cpp:class:`ElementGroup <akantu::ElementGroup>` object stores indexes
in a :cpp:class:`ElementTypeMapArray\<UInt\> <akantu::ElementTypeMapArray>`
object. Then elements can be added to the group by calling :cpp:func:`add
<akantu::ElementGroup::add>`.
For instance, selecting the elements for which the barycenter of the
nodes has a positive :math:`X` coordinate can be made with:
.. code-block:: c++
auto & group = mesh.createElementGroup("XpositiveElement");
Vector<Real> barycenter(spatial_dimension);
for_each_element(mesh, [&](auto && element) {
mesh.getBarycenter(element, barycenter);
if (barycenter(_x) > 0.) { group.add(element); }
});
diff --git a/doc/dev-doc/manual/heattransfermodel.rst b/doc/dev-doc/manual/heattransfermodel.rst
index ec4fba797..9f6eefb89 100644
--- a/doc/dev-doc/manual/heattransfermodel.rst
+++ b/doc/dev-doc/manual/heattransfermodel.rst
@@ -1,169 +1,169 @@
Heat Transfer Model
===================
The heat transfer model is a specific implementation of the :cpp:class:`Model
<akantu::Model>` interface dedicated to handle the dynamic heat equation.
Theory
------
The strong form of the dynamic heat equation
can be expressed as
.. math::
\rho c_v \dot{T} + \nabla \cdot \vec{\kappa} \nabla T = b
with :math:`T` the scalar temperature field, :math:`c_v` the specific heat capacity, :math:`\rho`
the mass density, :math:`\mat{\kappa}` the conductivity tensor, and :math:`b` the heat
generation per unit of volume. The discretized weak form with a finite number of
elements is
.. math::
\forall i \quad
\sum_j \left( \int_\Omega \rho c_v N_j N_i d\Omega \right) \dot{T}_j
- \sum_j \left( \int_\Omega \vec{\kappa} \nabla N_j \nabla N_i d\Omega \right) T_j =
- \int_{\Gamma} N_i \vec{q} \cdot \vec{n} d\Gamma + \int_\Omega b N_i d\Omega
with :math:`i` and :math:`j` the node indices, :math:`\vec{n}` the normal field to the surface
:math:`\Gamma = \partial \Omega`.
To simplify, we can define the capacity and the conductivity matrices as
.. math::
C_{ij} = \int_\Omega \rho c_v N_j N_i d\Omega \qquad \textrm{and} \qquad
K_{ij} = - \int_\Omega \vec{\kappa} \nabla N_j \nabla N_i d\Omega
and the system to solve can be written
.. math::
\mat{C} \cdot \vec{\dot{T}} = \vec{Q}^{\text{ext}} -\mat{K} \cdot \vec{T}~,
with :math:`\vec{Q}^{\text{ext}}` the consistent heat generated.
Using the Heat Transfer Model
-----------------------------
A material file name has to be provided during initialization.
Currently, the :cpp:class:`HeatTransferModel <akantu::HeatTransferModel>` object uses dynamic analysis
with an explicit time integration scheme. It can simply be created
like this
.. code-block:: c++
HeatTransferModel model(mesh, spatial_dimension);
while an existing mesh has been used (see \ref{sect:common:mesh}).
Then the model object can be initialized with:
.. code-block:: c++
model.initFull()
This function will load the material properties, and allocate / initialize the nodes and element :cpp:class:`Arrays <akantu::Array>`
More precisely, the heat transfer model contains 4 :cpp:class:`Arrays <akantu::Array>`:
- **temperature** contains the nodal temperature :math:`T` (zero by default after the initialization).
- **temperature_rate** contains the variations of temperature :math:`\dot{T}` (zero by default after the initialization).
- **blocked_dofs** contains a Boolean value for each degree of freedom specifying whether the degree is blocked or not. A Dirichlet boundary condition (:math:`T_d`) can be prescribed by setting the **blocked_dofs** value of a degree of freedom to ``true``. The **temperature** and the **temperature_rate** are computed for all degrees of freedom where the **blocked_dofs** value is set to ``false``. For the remaining degrees of freedom, the imposed values (zero by default after initialization) are kept.
- **external_heat_rate** contains the external heat generations. :math:`\vec{Q^{ext}}` on the nodes.
- **internal_heat_rate** contains the internal heat generations. :math:`\vec{Q^{int}} = -\mat{K} \cdot \vec{T}` on the nodes.
Only a single material can be specified on the domain. A material text file (*e.g.* material.dat) provides the material properties as follows:
.. code-block:: python
model heat_transfer_model [
capacity = %\emph{XXX}%
density = %\emph{XXX}%
conductivity = [%\emph{XXX}% ... %\emph{XXX}%]
]
where the ``capacity`` and ``density`` are scalars, and the ``conductivity`` is specified as a :math:`3\times 3` tensor.
Explicit Dynamic
----------------
The explicit time integration scheme in ``Akantu`` uses a lumped capacity
matrix :math:`\mat{C}` (reducing the computational cost, see Chapter :ref:`sect-smm`).
This matrix is assembled by distributing the capacity of each element onto its nodes. Therefore, the resulting :math:`\mat{C}` is a diagonal matrix stored in the ``capacity`` :cpp:class:`Array <akantu::Array>` of the model.
.. code-block:: c++
model.assembleCapacityLumped();
.. note::
Currently, only the explicit time integration with lumped capacity
matrix is implemented within ``Akantu``.
The explicit integration scheme is *Forward Euler* :cite:`curnier92a`.
- Predictor: :math:`\vec{T}_{n+1} = \vec{T}_{n} + \Delta t \dot{\vec{T}}_{n}`
- Update residual: :math:`\vec{R}_{n+1} = \left( \vec{Q^{ext}_{n+1}} - \vec{K}\vec{T}_{n+1} \right)`
- Corrector : :math:`\dot{\vec{T}}_{n+1} = \mat{C}^{-1} \vec{R}_{n+1}`
The explicit integration scheme is conditionally stable. The time step has to be
smaller than the stable time step, and it can be obtained in ``Akantu`` as
follows:
.. code-block:: c++
time_step = model.getStableTimeStep();
The stable time step is defined as:
.. math::
\Delta t_{\st{crit}} = 2 \Delta x^2 \frac{\rho c_v}{\mid\mid \mat{\kappa} \mid\mid^\infty}
:label: eqn:htm:explicit:stabletime
where :math:`\Delta x` is the characteristic length (*e.g* the in-radius in the
case of linear triangle element), :math:`\rho` is the density,
:math:`\mat{\kappa}` is the conductivity tensor, and :math:`c_v` is the specific
heat capacity. It is necessary to impose a time step which is smaller than the
stable time step, for instance, by multiplying the stable time step by a safety
factor smaller than one.
.. code-block:: c++
const Real safety_time_factor = 0.1;
Real applied_time_step = time_step * safety_time_factor;
model.setTimeStep(applied_time_step);
The following loop allows, for each time step, to update the ``temperature``,
``residual`` and ``temperature_rate`` fields following the previously described
integration scheme.
.. code-block:: c++
- for (UInt s = 1; (s-1)*applied_time_step < total_time; ++s) {
+ for (Int s = 1; (s-1)*applied_time_step < total_time; ++s) {
model.solveStep();
}
An example of explicit dynamic heat propagation is presented in
``examples/heat_transfer/explicit_heat_transfer.cc``. This example consists
of a square 2D plate of :math:`1 \text{m}^2` having an initial temperature of
:math:`100 \text{K}` everywhere but a none centered hot point maintained at
:math:`300 \text{K}`. :numref:`fig:htm:explicit:dynamic-1` presents the geometry
of this case. The material used is a linear fictitious elastic material with a
density of :math:`8940 \text{kg}/\text{m}^3`, a conductivity of
:math:`401 \text{W}/\text{m}/\text{K}` and a specific heat capacity of
:math:`385 \text{J}/\text{K}/\text{kg}`. The time step used is
:math:`0.12 \text{s}`.
.. _fig:htm:explicit:dynamic-1:
.. figure:: figures/hot-point-1.png
:align: center
Initial temperature field
.. _fig:htm:explicit:dynamic-2:
.. figure:: figures/hot-point-2.png
:align: center
Temperature field after 15000 time steps = 30 minutes. The lines represent iso-surfaces.
diff --git a/doc/dev-doc/manual/new-constitutive-laws.rst b/doc/dev-doc/manual/new-constitutive-laws.rst
index f8925e0fe..300b9f4e3 100644
--- a/doc/dev-doc/manual/new-constitutive-laws.rst
+++ b/doc/dev-doc/manual/new-constitutive-laws.rst
@@ -1,373 +1,373 @@
Adding a New Constitutive Law
-----------------------------
There are several constitutive laws in ``Akantu`` as described in the previous
Section :ref:`sect-smm-cl`. It is also possible to use a user-defined material
for the simulation. These materials are referred to as local materials since
they are local to the example of the user and not part of the ``Akantu``
library. To define a new local material, two files (``material_XXX.hh`` and
``material_XXX.cc``) have to be provided where ``XXX`` is the name of the new
material. The header file ``material_XXX.hh`` defines the interface of your
custom material. Its implementation is provided in the ``material_XXX.cc``. The
new law must inherit from the :cpp:class:`Material <akantu::Material>` class or
any other existing material class. It is therefore necessary to include the
interface of the parent material in the header file of your local material and
indicate the inheritance in the declaration of the class::
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 1);
solver.set("threshold", 1e-4);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
model.solveStep();
/* ---------------------------------------------------------------------- */
#include "material.hh"
/* ---------------------------------------------------------------------- */
#ifndef __AKANTU_MATERIAL_XXX_HH__
#define __AKANTU_MATERIAL_XXX_HH__
namespace akantu {
class MaterialXXX : public Material {
/// declare here the interface of your material
};
In the header file the user also needs to declare all the members of the new
material. These include the parameters that a read from the
material input file, as well as any other material parameters that will be
computed during the simulation and internal variables.
In the following the example of adding a new damage material will be
presented. In this case the parameters in the material will consist of the
Young's modulus, the Poisson coefficient, the resistance to damage and the
damage threshold. The material will then from these values compute its Lamé
coefficients and its bulk modulus. Furthermore, the user has to add a new
internal variable ``damage`` in order to store the amount of damage at each
quadrature point in each step of the simulation. For this specific material the
member declaration inside the class will look as follows::
class LocalMaterialDamage : public Material {
/// declare constructors/destructors here
/// declare methods and accessors here
/* -------------------------------------------------------------------- */
/* Class Members */
/* -------------------------------------------------------------------- */
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real);
private:
/// the young modulus
Real E;
/// Poisson coefficient
Real nu;
/// First Lame coefficient
Real lambda;
/// Second Lame coefficient (shear modulus)
Real mu;
/// resistance to damage
Real Yd;
/// damage threshold
Real Sd;
/// Bulk modulus
Real kpa;
/// damage internal variable
InternalField<Real> damage;
};
In order to enable to print the material parameters at any point in
the user's example file using the standard output stream by typing::
- for (UInt m = 0; m < model.getNbMaterials(); ++m)
+ for (Int m = 0; m < model.getNbMaterials(); ++m)
std::cout << model.getMaterial(m) << std::endl;
the standard output stream operator has to be redefined. This should be done at the end of the header file::
class LocalMaterialDamage : public Material {
/// declare here the interace of your material
}:
/* ---------------------------------------------------------------------- */
/* inline functions */
/* ---------------------------------------------------------------------- */
/// standard output stream operator
inline std::ostream & operator <<(std::ostream & stream, const LocalMaterialDamage & _this)
{
_this.printself(stream);
return stream;
}
However, the user still needs to register the material parameters that
should be printed out. The registration is done during the call of the
constructor. Like all definitions the implementation of the
constructor has to be written in the ``material_XXX.cc``
file. However, the declaration has to be provided in the
``material_XXX.hh`` file::
class LocalMaterialDamage : public Material {
/* -------------------------------------------------------------------- */
/* Constructors/Destructors */
/* -------------------------------------------------------------------- */
public:
LocalMaterialDamage(SolidMechanicsModel & model, const ID & id = "");
};
The user can now define the implementation of the constructor in the
``material_XXX.cc`` file::
/* ---------------------------------------------------------------------- */
#include "local_material_damage.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* ---------------------------------------------------------------------- */
LocalMaterialDamage::LocalMaterialDamage(SolidMechanicsModel & model,
const ID & id) :
Material(model, id),
damage("damage", *this) {
AKANTU_DEBUG_IN();
this->registerParam("E", E, 0., _pat_parsable, "Young's modulus");
this->registerParam("nu", nu, 0.5, _pat_parsable, "Poisson's ratio");
this->registerParam("lambda", lambda, _pat_readable, "First Lame coefficient");
this->registerParam("mu", mu, _pat_readable, "Second Lame coefficient");
this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
this->registerParam("Yd", Yd, 50., _pat_parsmod);
this->registerParam("Sd", Sd, 5000., _pat_parsmod);
damage.initialize(1);
AKANTU_DEBUG_OUT();
}
During the intializer list the reference to the model and the material id are
assigned and the constructor of the internal field is called. Inside the scope
of the constructor the internal values have to be initialized and the
parameters, that should be printed out, are registered with the function:
``registerParam``::
void registerParam(name of the parameter (key in the material file),
member variable,
default value (optional parameter),
access permissions,
description);
The available access permissions are as follows:
- ``_pat_internal``: Parameter can only be output when the material is printed.
- ``_pat_writable``: User can write into the parameter. The parameter is output when the material is printed.
- ``_pat_readable``: User can read the parameter. The parameter is output when the material is printed.
- ``_pat_modifiable``: Parameter is writable and readable.
- ``_pat_parsable``: Parameter can be parsed, *i.e.* read from the input file.
- ``_pat_parsmod``: Parameter is modifiable and parsable.
In order to implement the new constitutive law the user needs to
specify how the additional material parameters, that are not
defined in the input material file, should be calculated. Furthermore,
it has to be defined how stresses and the stable time step should be
computed for the new local material. In the case of implicit
simulations, in addition, the computation of the tangent stiffness needs
to be defined. Therefore, the user needs to redefine the following
functions of the parent material::
void initMaterial();
// for explicit and implicit simulations void
computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
// for implicit simulations
- void computeTangentStiffness(const ElementType & el_type,
+ void computeTangentStiffness(ElementType el_type,
Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost);
// for explicit and implicit simulations
Real getStableTimeStep(Real h, const Element & element);
In the following a detailed description of these functions is provided:
- ``initMaterial``: This method is called after the material file is fully read
and the elements corresponding to each material are assigned. Some of the
frequently used constant parameters are calculated in this method. For
example, the Lam\'{e} constants of elastic materials can be considered as such
parameters.
- ``computeStress``: In this method, the stresses are computed based on the
constitutive law as a function of the strains of the quadrature points. For
example, the stresses for the elastic material are calculated based on the
following formula:
.. math::
\mat{\sigma } =\lambda\mathrm{tr}(\mat{\varepsilon})\mat{I}+2 \mu \mat{\varepsilon}
Therefore, this method contains a loop on all quadrature points assigned to
the material using the two macros:
``MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN`` and
``MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END``
.. code::
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(element_type);
// sigma <- f(grad_u)
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
The strain vector in Akantu contains the values of :math:`\nabla \vec{u}`,
i.e. it is really the *displacement gradient*,
- ``computeTangentStiffness``: This method is called when the tangent to the
stress-strain curve is desired (see Fig \ref {fig:smm:AL:K}). For example,
it is called in the implicit solver when the stiffness matrix for the
regular elements is assembled based on the following formula:
.. math::
\label{eqn:smm:constitutive_elasc} \mat{K }
=\int{\mat{B^T}\mat{D(\varepsilon)}\mat{B}}
Therefore, in this method, the ``tangent`` matrix (\mat{D}) is
computed for a given strain.
The ``tangent`` matrix is a :math:`4^{th}` order tensor which is stored as
a matrix in Voigt notation.
.. _fig:smm:AL:K:
.. figure:: figures/tangent.svg
:align: center
:width: 60%
Tangent to the stress-strain curve.
..
\begin{figure}[!htb]
\begin{center}
\includegraphics[width=0.4\textwidth,keepaspectratio=true]{figures/tangent.pdf}
\caption{Tangent to the stress-strain curve.}
\label{fig:smm:AL:K}
\end{center}
\end{figure}
- ``getCelerity``: The stability criterion of the explicit integration scheme
depend on the fastest wave celerity~\eqref{eqn:smm:explicit:stabletime}. This
celerity depend on the material, and therefore the value of this velocity
should be defined in this method for each new material. By default, the
fastest wave speed is the compressive wave whose celerity can be defined in ``getPushWaveSpeed``.
Once the declaration and implementation of the new material has been
completed, this material can be used in the user's example by including the header file::
#include "material_XXX.hh"
For existing materials, as mentioned in Section~\ref{sect:smm:CL}, by
default, the materials are initialized inside the method
``initFull``. If a local material should be used instead, the
initialization of the material has to be postponed until the local
material is registered in the model. Therefore, the model is
initialized with the boolean for skipping the material initialization
equal to true::
/// model initialization
model.initFull(_analysis_method = _explicit_lumped_mass);
Once the model has been initialized, the local material needs
to be registered in the model::
model.registerNewCustomMaterials<XXX>("name_of_local_material");
Only at this point the material can be initialized::
model.initMaterials();
A full example for adding a new damage law can be found in
``examples/new_material``.
Adding a New Non-Local Constitutive Law
```````````````````````````````````````
In order to add a new non-local material we first have to add the local
constitutive law in Akantu (see above). We can then add the non-local version
of the constitutive law by adding the two files (``material_XXX_non_local.hh``
and ``material_XXX_non_local.cc``) where ``XXX`` is the name of the
corresponding local material. The new law must inherit from the two classes,
non-local parent class, such as the ``MaterialNonLocal`` class, and from the
local version of the constitutive law, *i.e.* ``MaterialXXX``. It is therefore
necessary to include the interface of those classes in the header file of your
custom material and indicate the inheritance in the declaration of the class::
/* ---------------------------------------------------------------------- */
#include "material_non_local.hh" // the non-local parent
#include "material_XXX.hh"
/* ---------------------------------------------------------------------- */
#ifndef __AKANTU_MATERIAL_XXX_HH__
#define __AKANTU_MATERIAL_XXX_HH__
namespace akantu {
class MaterialXXXNonLocal : public MaterialXXX,
public MaterialNonLocal {
/// declare here the interface of your material
};
As members of the class we only need to add the internal fields to store the
non-local quantities, which are obtained from the averaging process::
/* -------------------------------------------------------------------------- */
/* Class members */
/* -------------------------------------------------------------------------- */
protected:
InternalField<Real> grad_u_nl;
The following four functions need to be implemented in the non-local material::
/// initialization of the material
void initMaterial();
/// loop over all element and invoke stress computation
virtual void computeNonLocalStresses(GhostType ghost_type);
/// compute stresses after local quantities have been averaged
virtual void computeNonLocalStress(ElementType el_type, GhostType ghost_type)
/// compute all local quantities
void computeStress(ElementType el_type, GhostType ghost_type);
In the intialization of the non-local material we need to register the local
quantity for the averaging process. In our example the internal field
*grad_u_nl* is the non-local counterpart of the gradient of the displacement
field (*grad_u_nl*)::
void MaterialXXXNonLocal::initMaterial() {
MaterialXXX::initMaterial();
MaterialNonLocal::initMaterial();
/// register the non-local variable in the manager
this->model->getNonLocalManager().registerNonLocalVariable(
this->grad_u.getName(),
this->grad_u_nl.getName(),
spatial_dimension * spatial_dimension);
}
The function to register the non-local variable takes as parameters the name of
the local internal field, the name of the non-local counterpart and the number
of components of the field we want to average. In the *computeStress* we now
need to compute all the quantities we want to average. We can then write a loop
for the stress computation in the function *computeNonLocalStresses* and then
provide the constitutive law on each integration point in the function
*computeNonLocalStress*.
diff --git a/doc/dev-doc/manual/solidmechanicsmodel.rst b/doc/dev-doc/manual/solidmechanicsmodel.rst
index 63022b19c..236216a69 100644
--- a/doc/dev-doc/manual/solidmechanicsmodel.rst
+++ b/doc/dev-doc/manual/solidmechanicsmodel.rst
@@ -1,883 +1,883 @@
.. _sect-smm:
Solid Mechanics Model
=====================
The solid mechanics model is a specific implementation of the :cpp:class:`Model
<akantu::Model>` interface dedicated to handle the equations of motion or
equations of equilibrium. The model is created for a given mesh. It will create
its own :cpp:class:`FEEngine <akantu::FEEngine>` object to compute the
interpolation, gradient, integration and assembly operations. A
:cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>` object can simply
be created like this::
SolidMechanicsModel model(mesh);
where ``mesh`` is the mesh for which the equations are to be
solved. A second parameter called ``spatial_dimension`` can be
added after ``mesh`` if the spatial dimension of the problem is
different than that of the mesh.
This model contains at least the following six ``Arrays``:
:cpp:func:`blocked_dofs <akantu::SolidMechanicsModel::getBlockedDOFs>`
contains a Boolean value for each degree of freedom specifying whether that
degree is blocked or not. A Dirichlet boundary condition can be prescribed
by setting the **blocked_dofs** value of a degree of freedom to
``true``. A Neumann boundary condition can be applied by setting the
**blocked_dofs** value of a degree of freedom to ``false``. The
**displacement**, **velocity** and **acceleration** are
computed for all degrees of freedom for which the **blocked_dofs**
value is set to ``false``. For the remaining degrees of freedom, the imposed
values (zero by default after initialization) are kept.
:cpp:func:`displacement <akantu::SolidMechanicsModel::getDisplacement>`
contains the displacements of all degrees of freedom. It can be either a
computed displacement for free degrees of freedom or an imposed displacement
in case of blocked ones (:math:`\vec{u}` in the following).
:cpp:func:`velocity <akantu::SolidMechanicsModel::getVelocity>`
contains the velocities of all degrees of freedom. As **displacement**,
it contains computed or imposed velocities depending on the nature of the
degrees of freedom (:math:`\dot{\vec{u}}` in the following).
:cpp:func:`acceleration <akantu::SolidMechanicsModel::getAcceleration>`
contains the accelerations of all degrees of freedom. As **displacement**,
it contains computed or imposed accelerations depending on the nature of the
degrees of freedom (:math:`\ddot{\vec{u}}` in the following).
:cpp:func:`external_force <akantu::SolidMechanicsModel::getExternalForce>`
contains the external forces applied on the nodes
(:math:`\vec{f}_{\st{ext}}` in the following).
:cpp:func:`internal_force <akantu::SolidMechanicsModel::getInternalForce>`
contains the internal forces on the nodes (:math:`\vec{f}_{\mathrm{int}}` in
the following).
Some examples to help to understand how to use this model will be
presented in the next sections. In addition to vector quantities, the solid
mechanics model can be queried for energies with the :cpp:func:`getEnergy
<akantu::SolidMechanicsModel::getEnergy>` which accepts an energy type as an
arguement (e.g. ``kinetic`` or ``potential``).
Model Setup
-----------
Setting Initial Conditions
``````````````````````````
For a unique solution of the equations of motion, initial
displacements and velocities for all degrees of freedom must be
specified:
.. math::
\vec{u}(t=0) & = \vec{u}_0\\
\dot{\vec u}(t=0) & = \vec{v}_0
The solid mechanics model can be initialized as
follows::
model.initFull()
This function initializes the internal arrays and sets them to zero. Initial
displacements and velocities that are not equal to zero can be prescribed by
running a loop over the total number of nodes. Here, the initial displacement in
:math:`x`-direction and the initial velocity in :math:`y`-direction for all
nodes is set to :math:`0.1` and :math:`1`, respectively::
auto & disp = model.getDisplacement();
auto & velo = model.getVelocity();
- for (UInt node = 0; node < mesh.getNbNodes(); ++node) {
+ for (Int node = 0; node < mesh.getNbNodes(); ++node) {
disp(node, 0) = 0.1;
velo(node, 1) = 1.;
}
.. _sect-smm-boundary:
Setting Boundary Conditions
```````````````````````````
This section explains how to impose Dirichlet or Neumann boundary
conditions. A Dirichlet boundary condition specifies the values that
the displacement needs to take for every point :math:`x` at the boundary
(:math:`\Gamma_u`) of the problem domain (:numref:`fig-smm-boundaries`):
.. math::
\vec{u} = \bar{\vec u} \quad \forall \vec{x}\in \Gamma_{u}
A Neumann boundary condition imposes the value of the gradient of the
solution at the boundary :math:`\Gamma_t` of the problem domain
(:numref:`fig-smm-boundaries`):
.. math::
\vec{t} = \mat{\sigma} \vec{n} = \bar{\vec t} \quad
\forall \vec{x}\in \Gamma_{t}
.. _fig-smm-boundaries:
.. figure:: figures/problem_domain.svg
:align: center
Problem domain :math:`\Omega` with boundary in three dimensions. The
Dirchelet and the Neumann regions of the boundary are denoted with
:math:`\Gamma_u` and :math:`\Gamma_t`, respecitvely.
Different ways of imposing these boundary conditions exist. A basic
way is to loop over nodes or elements at the boundary and apply local
values. A more advanced method consists of using the notion of the
boundary of the mesh. In the following both ways are presented.
Starting with the basic approach, as mentioned, the Dirichlet boundary
conditions can be applied by looping over the nodes and assigning the
required values. :numref:`fig-smm-dirichlet_bc` shows a beam with a
fixed support on the left side. On the right end of the beam, a load
is applied. At the fixed support, the displacement has a given
value. For this example, the displacements in both the :math:`x` and the
:math:`y`-direction are set to zero. Implementing this displacement boundary
condition is similar to the implementation of initial displacement
conditions described above. However, in order to impose a displacement
boundary condition for all time steps, the corresponding nodes need to
be marked as boundary nodes using the function ``blocked``. While,
in order to impose a load on the right side, the nodes are not marked.
The detail codes are shown as follows
.. code-block:: c++
auto & blocked = model.getBlockedDOFs();
const auto & pos = mesh.getNodes();
UInt nb_nodes = mesh.getNbNodes();
- for (UInt node = 0; node < nb_nodes; ++node) {
+ for (Int node = 0; node < nb_nodes; ++node) {
if(Math::are_float_equal(pos(node, _x), 0)) {
blocked(node, _x) = true; // block dof in x-direction
blocked(node, _y) = true; // block dof in y-direction
disp(node, _x) = 0.; // fixed displacement in x-direction
disp(node, _y) = 0.; // fixed displacement in y-direction
} else if (Math::are_float_equal(pos(node, _y), 0)) {
blocked(node, _x) = false; // unblock dof in x-direction
forces(node, _x) = 10.; // force in x-direction
}
}
.. _fig-smm-dirichlet_bc:
.. figure:: figures/dirichlet.svg
:align: center
Beam with fixed support and load.
For the more advanced approach, one needs the notion of a boundary in
the mesh. Therefore, the boundary should be created before boundary
condition functors can be applied. Generally the boundary can be
specified from the mesh file or the geometry. For the first case, the
function ``createGroupsFromMeshData`` is called. This function
can read any types of mesh data which are provided in the mesh
file. If the mesh file is created with Gmsh, the function takes one
input strings which is either ``tag_0``, ``tag_1`` or
``physical_names``. The first two tags are assigned by Gmsh to
each element which shows the physical group that they belong to. In
Gmsh, it is also possible to consider strings for different groups of
elements. These elements can be separated by giving a string
``physical_names`` to the function
``createGroupsFromMeshData``
.. code-block:: c++
mesh.createGroupsFromMeshData<std::string>("physical_names").
Boundary conditions support can also be created from the geometry by calling
``createBoundaryGroupFromGeometry``. This function gathers all the elements on
the boundary of the geometry.
To apply the required boundary conditions, the function :cpp:func:`applyBC
<akantu::BoundaryCondition::applyBC>` needs to be called on a
:cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>`. This function
gets a Dirichlet or Neumann functor and a string which specifies the desired
boundary on which the boundary conditions is to be applied. The functors specify
the type of conditions to apply. Three built-in functors for Dirichlet exist:
:cpp:class:`FlagOnly <akantu::BC::Dirichlet::FlagOnly>`, :cpp:class:`FixedValue
<akantu::BC::Dirichlet::FixedValue>` and :cpp:class:`IncrementValue
<akantu::BC::Dirichlet::IncrementValue>`. The functor ``FlagOnly`` is used if a
point is fixed in a given direction. Therefore, the input parameter to this
functor is only the fixed direction. The ``FixedValue`` functor is used when a
displacement value is applied in a fixed direction. The ``IncrementValue``
applies an increment to the displacement in a given direction. The following
code shows the utilization of three functors for the top, bottom and side
surface of the mesh which were already defined in the Gmsh
.. code-block:: c++
model.applyBC(BC::Dirichlet::FixedValue(13.0, _y), "Top");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "Bottom");
model.applyBC(BC::Dirichlet::IncrementValue(13.0, _x), "Side");
To apply a Neumann boundary condition, the applied traction or stress should be
specified before. In case of specifying the traction on the surface, the functor
:cpp:class:`FromTraction <akantu::BC::Neumann::FromTraction>` of Neumann
boundary conditions is called. Otherwise, the functor :cpp:class:`FromStress
<akantu::BC::Neumann::FromStress>` should be called which gets the stress tensor
as an input parameter
.. code-block:: c++
Vector<Real> surface_traction{0., 0., 1.};
auto surface_stress(3, 3) = Matrix<Real>::eye(3);
model.applyBC(BC::Neumann::FromTraction(surface_traction), "Bottom");
model.applyBC(BC::Neumann::FromStress(surface_stress), "Top");
If the boundary conditions need to be removed during the simulation, a
functor is called from the Neumann boundary condition to free those
boundary conditions from the desired boundary
.. code-block:: c++
model.applyBC(BC::Neumann::FreeBoundary(), "Side");
User specified functors can also be implemented. A full example for
setting both initial and boundary conditions can be found in
``examples/boundary_conditions.cc``. The problem solved
in this example is shown in :numref:`fig-smm-bc_and_ic`. It consists
of a plate that is fixed with movable supports on the left and bottom
side. On the right side, a traction, which increases linearly with the
number of time steps, is applied. The initial displacement and
velocity in :math:`x`-direction at all free nodes is zero and two
respectively.
.. _fig-smm-bc_and_ic:
.. figure:: figures/bc_and_ic_example.svg
:align: center
:width: 75%
Plate on movable supports.
..
\begin{figure}[!htb]
\centering
\includegraphics[scale=0.8]{figures/bc_and_ic_example}
\caption{Plate on movable supports.\label{fig-smm-bc_and_ic}}
\end{figure}
As it is mentioned in Section \ref{sect:common:groups}, node and
element groups can be used to assign the boundary conditions. A
generic example is given below with a Dirichlet boundary condition::
// create a node group
NodeGroup & node_group = mesh.createNodeGroup("nodes_fix");
/* fill the node group with the nodes you want */
// create an element group using the existing node group
mesh.createElementGroupFromNodeGroup("el_fix",
"nodes_fix",
spatial_dimension-1);
// boundary condition can be applied using the element group name
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "el_fix");
Material Selector
`````````````````
If the user wants to assign different materials to different
finite elements groups in ``Akantu``, a material selector has to be
used. By default, ``Akantu`` assigns the first valid material in the
material file to all elements present in the model (regular continuum
materials are assigned to the regular elements and cohesive materials
are assigned to cohesive elements or element facets).
To assign different materials to specific elements, mesh data information such
as tag information or specified physical names can be used.
:cpp:class:`MeshDataMaterialSelector <akantu::MeshDataMaterialSelector>` class
uses this information to assign different materials. With the proper physical
name or tag name and index, different materials can be assigned as demonstrated
in the examples below::
auto mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
In this example the physical names specified in a GMSH geometry file will by
used to match the material names in the input file.
Another example would be to use the first (``tag_0``) or the second
(``tag_1``) tag associated to each elements in the mesh::
auto mat_selector = std::make_shared<MeshDataMaterialSelector<UInt>>(
"tag_1", model, first_index);
model.setMaterialSelector(*mat_selector);
where ``first_index`` (default is 1) is the value of ``tag_1`` that will
be associated to the first material in the material input file. The following
values of the tag will be associated with the following materials.
There are four different material selectors pre-defined in ``Akantu``.
:cpp:class:`MaterialSelector <akantu::MaterialSelector>` and
:cpp:class:`DefaultMaterialSelector <akantu::DefaultMaterialSelector>` is used
to assign a material to regular elements by default. For the regular elements,
as in the example above, :cpp:class:`MeshDataMaterialSelector
<akantu::MeshDataMaterialSelector>` can be used to assign different materials to
different elements.
Apart from the ``Akantu``'s default material selectors, users can always
develop their own classes in the main code to tackle various
multi-material assignment situations.
For cohesive material, ``Akantu`` has a pre-defined material selector to assign
the first cohesive material by default to the cohesive elements which is called
:cpp:class:`DefaultMaterialCohesiveSelector
<akantu::DefaultMaterialCohesiveSelector>` and it inherits its properties from
:cpp:class:`DefaultMaterialSelector <akantu::DefaultMaterialSelector>`. Multiple
cohesive materials can be assigned using mesh data information (for more
details, see :ref:`sect-smm-intrinsic-insertion`).
Insertion of Cohesive Elements
``````````````````````````````
Cohesive elements are currently compatible only with static simulation
and dynamic simulation with an explicit time integration scheme (see
section :ref:`ssect-smm-expl-time-integration`). They do not have to be
inserted when the mesh is generated (intrinsic) but can be added
during the simulation (extrinsic). At any time during the simulation,
it is possible to access the following energies with the relative
function:
.. code-block:: c++
Real Ed = model.getEnergy("dissipated");
Real Er = model.getEnergy("reversible");
Real Ec = model.getEnergy("contact");
A new model have to be call in a very similar way that the solid
mechanics model:
.. code-block:: c++
SolidMechanicsModelCohesive model(mesh);
model.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = true);
Cohesive element insertion can be either realized at the beginning of
the simulation or it can be carried out dynamically during the
simulation. The first approach is called ``intrinsic``, the second
one ``extrinsic``. When an element is present from the beginning, a
bi-linear or exponential cohesive law should be used instead of a
linear one. A bi-linear law works exactly like a linear one except for
an additional parameter :math:`\delta_0` separating an initial linear
elastic part from the linear irreversible one. For additional details
concerning cohesive laws see Section~\ref{sec:cohesive-laws}.
.. _fig-smm-coh-insertion:
.. figure:: figures/insertion.svg
:align: center
Insertion of a cohesive element.
Extrinsic cohesive elements are dynamically inserted between two
standard elements when
.. math::
\sigma_\mathrm{eff} > \sigma_\mathrm{c} \quad\text {with} \quad \sigma_\mathrm{eff} = \sqrt{\sigma_\mathrm{n} ^ 2 + \frac{\tau ^ 2} {\beta ^ 2 }}
in which :math:`\sigma_\mathrm { n }
` is the tensile normal traction and $\tau$ the resulting tangential one( :numref:`fig-smm-coh-insertion`).
Extrinsic approach
''''''''''''''''''
During the simulation, stress has to be checked along each facet in order to
insert cohesive elements where the stress criterion is reached. This check is
performed by calling the method :cpp:func:`checkCohesiveStress
<akantu::SolidMechanicsModelCohesive::checkCohesiveStress>`, as example before
each step resolution:
.. code-block:: c++
model.checkCohesiveStress();
model.solveStep();
The area where stresses are checked and cohesive elements inserted can be
limited using the method :cpp:func:`setLimit
<akantu::CohesiveInserter::setLimit>` on the :cpp:class:`CohesiveInserter
<akantu::CohesiveInserter>` during initialization. As example, to limit
insertion in the range :math:`[-1.5, 1.5]` in the $x$ direction:
.. code-block:: c++
auto & inserter = model.getElementInserter();
inserter.setLimit(_x, -1.5, 1.5);
Additional restrictions with respect to :math:`_y` and :math:`_z` directions can
be added as well.
.. _sect-smm-intrinsic-insertion:
Intrinsic approach
''''''''''''''''''
Intrinsic cohesive elements are inserted in the mesh with the method
:cpp:func:`initFull <akantu::SolidMechanicsModelCohesive::initFull>`.
Similarly, the range of insertion can be limited with :cpp:func:`setLimit
<akantu::CohesiveInserter::setLimit>` before the :cpp:func:`initFull
<akantu::SolidMechanicsModelCohesive::initFull>` call.
In both cases extrinsic and intrinsic the insertion can be restricted to
surfaces or element groups. To do so the list of groups should be specified in
the input file.
.. code-block::
model solid_mechanics_model_cohesive [
cohesive_inserter [
cohesive_surfaces = [surface1, surface2, ...]
cohesive_zones = [group1, group2, ...]
]
material cohesive_linear [
name = insertion
beta = 1
G_c = 10
sigma_c = 1e6
]
]
Static Analysis
---------------
The :cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>` class can
handle different analysis methods, the first one being presented is the static
case. In this case, the equation to solve is
.. math::
\mat{K} \vec{u} = \vec{f}_{\mathrm{ext}}
:label: eqn-smm-static
where :math:`\mat{K}` is the global stiffness matrix, :math:`\vec{u}` the
displacement vector and :math:`\vec{f}_{\st{ext}}` the vector of external
forces applied to the system.
To solve such a problem, the static solver of the
:cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>` object is used.
First, a model has to be created and initialized. To create the model, a mesh
(which can be read from a file) is needed, as explained in
Section~\ref{sect:common:mesh}. Once an instance of a
:cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>` is obtained, the
easiest way to initialize it is to use the :cpp:func:`initFull
<akantu::SolidMechanicsModel::initFull>` method by giving the
:cpp:class:`SolidMechanicsModelOptions <akantu::SolidMechanicsModelOptions>`.
These options specify the type of analysis to be performed and whether the
materials should be initialized with :cpp:func:`initMaterials
<akantu::SolidMechanicsModel::initMaterials>` or not
.. code-block:: c++
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _static);
Here, a static analysis is chosen by passing the argument
:cpp:enumerator:`_static <akantu::_static>` to the method. By default, the
Boolean for no initialization of the materials is set to false, so that they are
initialized during the ``initFull``. The method ``initFull`` also initializes
all appropriate vectors to zero. Once the model is created and initialized, the
boundary conditions can be set as explained in Section :ref:`sect-smm-boundary`.
Boundary conditions will prescribe the external forces for some free degrees of
freedom :math:`\vec{f}_{\st{ext}}` and displacements for some others. At this
point of the analysis, the function
:cpp:func:`solveStep <akantu::SolidMechanicsModel::solveStep>` can be called
.. code-block:: c++
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 1);
solver.set("threshold", 1e-4);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
model.solveStep();
This function is templated by the solving method and the convergence criterion
and takes two arguments: the tolerance and the maximum number of iterations (100
by default), which are :math:`10^{-4}` and :math:`1` for this example. The
modified Newton-Raphson method is chosen to solve the system. In this method,
the equilibrium equation (:eq:`eqn-smm-static`) is modified in order to apply a
Newton-Raphson convergence algorithm:
.. math::
\mat{K}^{i+1}\delta\vec{u}^{i+1} &= \vec{r} \\
&= \vec{f}_{\st{ext}} -\vec{f}_{\st{int}}\\
&= \vec{f}_{\st{ext}} - \mat{K}^{i} \vec{u}^{i}\\
\vec{u}^{i+1} &= \vec{u}^{i} + \delta\vec{u}^{i+1}~,
where :math:`\delta\vec{u}` is the increment of displacement to be added from
one iteration to the other, and :math:`i` is the Newton-Raphson iteration
counter. By invoking the ``solveStep`` method in the first step, the global
stiffness matrix :math:`\mat{K}` from (:eq:`eqn-smm-static`) is automatically
assembled. A Newton-Raphson iteration is subsequently started, :math:`\mat{K}`
is updated according to the displacement computed at the previous iteration and
one loops until the forces are balanced
(:cpp:enumerator:`SolveConvergenceCriteria::_residual
<akantu::SolveConvergenceCriteria::_residual>`), i.e. :math:`||\vec{r}|| <`
:cpp:member:`threshold
<akantu::NonLinearSolverNewtonRaphson::convergence_criteria>`. One can also
iterate until the increment of displacement is zero
(:cpp:enumerator:`SolveConvergenceCriteria::_solution
<akantu::SolveConvergenceCriteria::_solution>`) which also means that the
equilibrium is found. For a linear elastic problem, the solution is obtained in
one iteration and therefore the maximum number of iterations can be set to one.
But for a non-linear case, one needs to iterate as long as the norm of the
residual exceeds the tolerance threshold and therefore the maximum number of
iterations has to be higher, e.g. :math:`100`
.. code-block:: c++
solver.set("max_iterations", 100);
model.solveStep();
At the end of the analysis, the final solution is stored in the
**displacement** vector. A full example of how to solve a static
problem is presented in the code ``examples/static/static.cc``.
This example is composed of a 2D plate of steel, blocked with rollers
on the left and bottom sides as shown in :numref:`fig-smm-static`.
The nodes from the right side of the sample are displaced by :math:`0.01\%`
of the length of the plate.
.. _fig-smm-static:
.. figure:: figures/static.svg
:align: center
:width: 75%
Numerical setup.
The results of this analysis is depicted in
:numref:`fig-smm-implicit:static_solution`.
.. _fig-smm-implicit:static_solution:
.. figure:: figures/static_analysis.png
:align: center
:width: 75%
Solution of the static analysis. Left: the initial condition, right:
the solution (deformation magnified 50 times).
Dynamic Methods
---------------
Different ways to solve the equations of motion are implemented in the
solid mechanics model. The complete equations that should be solved
are:
.. math:: \mat{M}\ddot{\vec{u}} + \mat{C}\dot{\vec{u}} + \mat{K}\vec{u} = \vec{f}_{\mathrm{ext}}
:label: eqn-equation-motion
where :math:`\mat{M}`, :math:`\mat{C}` and :math:`\mat{K}` are the mass,
damping and stiffness matrices, respectively.
In the previous section, it has already been discussed how to solve this
equation in the static case, where :math:`\ddot{\vec{u}} = \dot{\vec{u}} = 0`.
Here the method to solve this equation in the general case will be presented.
For this purpose, a time discretization has to be specified. The most common
discretization method in solid mechanics is the Newmark-:math:`\beta` method,
which is also the default in ``Akantu``.
For the Newmark-:math:`\beta` method, (:eq:`eqn-equation-motion`) becomes a
system of three equations (see :cite:`curnier92a,hughes-83a` for more details):
.. math::
\begin{eqnarray}
\mat{M} \ddot{\vec{u}}_{n+1} + \mat{C}\dot{\vec{u}}_{n+1} + \mat{K} \vec{u}_{n+1} &={\vec{f}_{\st{ext}}}_{\, n+1}\\
\vec{u}_{n+1} &= \vec{u}_{n}
+ \left(1 - \alpha\right) \Delta t \dot{\vec{u}}_{n}
+ \alpha \Delta t \dot{\vec{u}}_{n+1}
+ \left(\frac{1}{2} - \alpha\right) \Delta t^2 \ddot{\vec{u}}_{n}\\
\dot{\vec{u}}_{n+1} &= \dot{\vec{u}}_{n}
+ \left(1 - \beta\right) \Delta t \ddot{\vec{u}}_{n}
+ \beta \Delta t \ddot{\vec{u}}_{n+1}
\end{eqnarray}
:label: eqn-equation-motion-discret
In these new equations, :math:`\ddot{\vec{u}}_{n}`, :math:`\dot{\vec{u}}_{n}`
and :math:`\vec{u}_{n}` are the approximations of :math:`\ddot{\vec{u}}(t_n)`,
:math:`\dot{\vec{u}}(t_n)` and :math:`\vec{u}(t_n)`.
Equation~(:eq:`eqn-equation-motion-discret`) is the equation of motion
discretized in space (finite-element discretization), and the equations above
are discretized in both space and time (Newmark discretization). The
:math:`\alpha` and :math:`\beta` parameters determine the stability and the
accuracy of the algorithm. Classical values for :math:`\alpha` and :math:`\beta`
are usually :math:`\beta = 1/2` for no numerical damping and :math:`0 < \alpha <
1/2`.
.. csv-table::
:header: ":math:`\\alpha`", "Method (:math:`\\beta = 1/2`)", "Type"
":math:`0`", "central difference", "explicit"
":math:`\frac{1}{6}`", "Fox-Goodwin(royal road)", "implicit"
":math:`\frac{1}{3}`", "Linear acceleration", "implicit"
":math:`\frac{1}{2}`", "Average acceleration (trapeziodal rule)", "implicit"
The solution of this system of equations,
(:eq:`eqn-equation-motion-discret`) is
split into a predictor and a corrector system of equations. Moreover,
in the case of a non-linear equations, an iterative algorithm such as
the Newton-Raphson method is applied. The system of equations can be
written as:
- *Predictor*:
.. math:: \vec{u}_{n+1}^{0} &= \vec{u}_{n} + \Delta t \dot{\vec{u}}_{n} + \frac{\Delta t^2}{2} \ddot{\vec{u}}_{n} \\
\dot{\vec{u}}_{n+1}^{0} &= \dot{\vec{u}}_{n} + \Delta t \ddot{\vec{u}}_{n} \\
\ddot{\vec{u}}_{n+1}^{0} &= \ddot{\vec{u}}_{n}
- *Solve*:
.. math:: \left(c \mat{M} + d \mat{C} + e \mat{K}_{n+1}^i\right)
\vec{w} &= {\vec{f}_{\st{ext}}}_{\,n+1} - {\vec{f}_{\st{int}}}_{\,n+1}^i -
\mat{C} \dot{\vec{u}}_{n+1}^i - \mat{M} \ddot{\vec{u}}_{n+1}^i\\
&= \vec{r}_{n+1}^i
- *Corrector*:
.. math:: \ddot{\vec{u}}_{n+1}^{i+1} &= \ddot{\vec{u}}_{n+1}^{i} +c \vec{w} \\
\dot{\vec{u}}_{n+1}^{i+1} &= \dot{\vec{u}}_{n+1}^{i} + d\vec{w} \\
\vec{u}_{n+1}^{i+1} &= \vec{u}_{n+1}^{i} + e \vec{w}
where :math:`i` is the Newton-Raphson iteration counter and :math:`c`, :math:`d` and :math:`e`
are parameters depending on the method used to solve the equations
.. csv-table::
:header: "", ":math:`\\vec{w}`", ":math:`e`", ":math:`d`", ":math:`c`"
"in acceleration", ":math:`\delta\ddot{\vec{u}}`", ":math:`\alpha\beta\Delta t^2`", ":math:`\beta\Delta t`", ":math:`1`"
"in velocity", ":math:`\delta\dot{\vec{u}}`", ":math:`\alpha\Delta t`", ":math:`1`", ":math:`\frac{1}{\beta\Delta t}`"
"in displacement", ":math:`\delta\vec{u}`", ":math:`1`", ":math:`\frac{1}{\alpha\Delta t}`", ":math:`\frac{1}{\alpha\beta \Delta t^2}`"
.. note:: If you want to use the implicit solver ``Akantu`` should be compiled at
least with one sparse matrix solver such as `Mumps
<http://mumps.enseeiht.fr/>`_ :cite:`mumps`.
Implicit Time Integration
`````````````````````````
To solve a problem with an implicit time integration scheme, first a
:cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>` object has to be
created and initialized. Then the initial and boundary conditions have to be
set. Everything is similar to the example in the static case
(Section~\ref{sect:smm:static}), however, in this case the implicit dynamic
scheme is selected at the initialization of the model::
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _implicit_dynamic);
Because a dynamic simulation is conducted, an integration time step
:math:`\Delta t` has to be specified. In the case of implicit simulations,
``Akantu`` implements a trapezoidal rule by default. That is to say
:math:`\alpha = 1/2` and :math:`\beta = 1/2` which is unconditionally
stable. Therefore the value of the time step can be chosen arbitrarily
within reason::
model.setTimeStep(time_step);
Since the system has to be solved for a given amount of time steps, the
method ``solveStep()``, (which has already been used in the static
example in Section~\ref{sect:smm:static}), is called inside a time
loop::
/// time loop
Real time = 0.;
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 100);
solver.set("threshold", 1e-12);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
- for (UInt s = 1; time <max_time; ++s, time += time_step) {
+ for (Int s = 1; time <max_time; ++s, time += time_step) {
model.solveStep();
}
An example of solid mechanics with an implicit time integration scheme is
presented in ``examples/implicit/implicit_dynamic.cc``. This example consists of
a 3D beam of
:math:`10\mathrm{m}\times1\mathrm{m}\times1\mathrm{m}` blocked
on one side and is on a roller on the other side. A constant force of
:math:`5\mathrm{kN}` is applied in its middle.
:numref:`fig-smm-implicit-dynamic` presents the geometry of this case. The
material used is a fictitious linear elastic material with a density of
:math:`1000 \mathrm{kg/m}^3`, a Young's Modulus of
:math:`120 \mathrm{MPa}` and Poisson's ratio of :math:`0.3`. These values
were chosen to simplify the analytical solution.
An approximation of the dynamic response of the middle point of the
beam is given by:
.. math::
u\left(\frac{L}{2}, t\right)
= \frac{1}{\pi^4} \left(1 - cos\left(\pi^2 t\right) +
\frac{1}{81}\left(1 - cos\left(3^2 \pi^2 t\right)\right) +
\frac{1}{625}\left(1 - cos\left(5^2 \pi^2 t\right)\right)\right)
.. _fig-smm-implicit-dynamic:
.. figure:: figures/implicit_dynamic.svg
:align: center
:width: 75%
Numerical setup.
..
\begin{figure}[!htb]
\centering
\includegraphics[scale=.6]{figures/implicit_dynamic}
\caption{Numerical setup}
\label{fig-smm-implicit:dynamic}
\end{figure}
:numref:`fig-smm-implicit-dynamic_solution` presents the deformed
beam at 3 different times during the simulation: time steps 0, 1000 and
2000.
.. _fig-smm-implicit-dynamic_solution:
.. figure:: figures/dynamic_analysis.png
:align: center
:width: 60%
Deformed beam at three different times (displacement :math:`\times
10`).
.. _ssect-smm-expl-time-integration:
Explicit Time Integration
`````````````````````````
The explicit dynamic time integration scheme is based on the
Newmark-:math:`\beta` scheme with :math:`\alpha=0` (see equations
\ref{eqn:equation-motion-discret}-\ref{eqn:finite-difference-2}). In
``Akantu``, :math:`\beta` is defaults to :math:`\beta=1/2`, see section
\ref{sect:smm:Dynamic_methods}.
The initialization of the simulation is similar to the static and implicit
dynamic version. The model is created from the :cpp:class:`SolidMechanicsModel
<akantu::SolidMechanicsModel>` class. In the initialization, the explicit scheme
is selected using the ``_explicit_lumped_mass`` constant::
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _explicit_lumped_mass);
.. note::
Writing ``model.initFull()`` or ``model.initFull();`` is
equivalent to use the ``_explicit_lumped_mass`` keyword, as this
is the default case.
The explicit time integration scheme implemented in ``Akantu`` uses a
lumped mass matrix :math:`\mat{M}` (reducing the computational cost). This
matrix is assembled by distributing the mass of each element onto its
nodes. The resulting :math:`\mat{M}` is therefore a diagonal matrix stored
in the **mass** vector of the model.
The explicit integration scheme is conditionally stable. The time step
has to be smaller than the stable time step which is obtained in
Akantu as follows::
critical_time_step = model.getStableTimeStep();
The stable time step corresponds to the time the fastest wave (the compressive
wave) needs to travel the characteristic length of the mesh:
.. math::
\Delta t_{\st{crit}} = \frac{\Delta x}{c}
where :math:`\Delta x` is a characteristic length (\eg the inradius in the case
of linear triangle element) and :math:`c` is the celerity of the fastest wave in
the material. It is generally the compressive wave of celerity :math:`c =
\sqrt{\frac{2 \mu + \lambda}{\rho}}`, :math:`\mu` and :math:`\lambda` are the
first and second Lame's coefficients and :math:`\rho` is the density. However,
it is recommended to impose a time step that is smaller than the stable time
step, for instance, by multiplying the stable time step by a safety factor
smaller than one::
const Real safety_time_factor = 0.8;
Real applied_time_step = critical_time_step * safety_time_factor;
model.setTimeStep(applied_time_step);
The initial displacement and velocity fields are, by default, equal to zero if
not given specifically by the user (see \ref{sect:smm:initial_condition}).
Like in implicit dynamics, a time loop is used in which the
displacement, velocity and acceleration fields are updated at each
time step. The values of these fields are obtained from the
Newmark:math:`-\beta` equations with :math:`\beta=1/2` and :math:`\alpha=0`. In ``Akantu``
these computations at each time step are invoked by calling the
function ``solveStep``::
- for (UInt s = 1; (s-1)*applied_time_step < total_time; ++s) {
+ for (Int s = 1; (s-1)*applied_time_step < total_time; ++s) {
model.solveStep();
}
The method ``solveStep`` wraps the four following functions:
- ``model.explicitPred()`` allows to compute the displacement
field at :math:`t+1` and a part of the velocity field at :math:`t+1`, denoted by
:math:`\vec{\dot{u}^{\st{p}}}_{n+1}`, which will be used later in the method
``model.explicitCorr()``. The equations are:
.. math::
\vec{u}_{n+1} &= \vec{u}_{n} + \Delta t
\vec{\dot{u}}_{n} + \frac{\Delta t^2}{2} \vec{\ddot{u}}_{n}\\
\vec{\dot{u}^{\st{p}}}_{n+1} &= \vec{\dot{u}}_{n} + \Delta t
\vec{\ddot{u}}_{n}
- ``model.updateResidual()`` and ``model.updateAcceleration()`` compute the acceleration increment
:math:`\delta \vec{\ddot{u}}`:
.. math::
\left(\mat{M} + \frac{1}{2} \Delta t \mat{C}\right)
\delta \vec{\ddot{u}} = \vec{f_{\st{ext}}} - \vec{f}_{\st{int}\, n+1}
- \mat{C} \vec{\dot{u}^{\st{p}}}_{n+1} - \mat{M} \vec{\ddot{u}}_{n}
The internal force :math:`\vec{f}_{\st{int}\, n+1}` is computed from the
displacement :math:`\vec{u}_{n+1}` based on the constitutive law.
- ``model.explicitCorr()`` computes the velocity and
acceleration fields at :math:`t+1`:
.. math::
\vec{\dot{u}}_{n+1} &= \vec{\dot{u}^{\st{p}}}_{n+1} + \frac{\Delta t}{2}
\delta \vec{\ddot{u}} \\ \vec{\ddot{u}}_{n+1} &=
\vec{\ddot{u}}_{n} + \delta \vec{\ddot{u}}
The use of an explicit time integration scheme is illustrated by the example:
``examples/explicit/explicit_dynamic.cc``. This example models the propagation
of a wave in a steel beam. The beam and the applied displacement in the
:math:`x` direction are shown in :numref:`fig-smm-explicit`.
.. _fig-smm-explicit:
.. figure:: figures/explicit.svg
:align: center
:width: 90%
Numerical setup.
The length and height of the beam are :math:`L={10}\textrm{m}` and :math:`h =
{1}\textrm{m}`, respectively. The material is linear elastic, homogeneous and
isotropic (density: :math:`7800\mathrm{kg/m}^3`, Young's modulus:
:math:`210\mathrm{GPa}` and Poisson's ratio: :math:`0.3`). The imposed
displacement follow a Gaussian function with a maximum amplitude of :math:`A =
{0.01}\textrm{m}`. The potential, kinetic and total energies are computed. The
safety factor is equal to :math:`0.8`.
.. include:: ./constitutive-laws.rst
.. include:: ./new-constitutive-laws.rst
diff --git a/doc/dev-doc/manual/structuralmechanicsmodel.rst b/doc/dev-doc/manual/structuralmechanicsmodel.rst
index 516d72fdd..1da5dd206 100644
--- a/doc/dev-doc/manual/structuralmechanicsmodel.rst
+++ b/doc/dev-doc/manual/structuralmechanicsmodel.rst
@@ -1,214 +1,214 @@
Structural Mechanics Model
==========================
Static structural mechanics problems can be handled using the class
:cpp:class:`StructuralMechanicsModel <akantu::StructuralMechanicsModel>`. So
far, ``Akantu`` provides 2D and 3D Bernoulli beam elements :cite:`frey2009`.
This model is instantiated for a given :cpp:class:`Mesh <akantu::Mesh>`, as for
the :cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>`. The model
will create its own :cpp:class:`FEEngine <akantu::FEEngine>` object to compute
the interpolation, gradient, integration and assembly operations. The
:cpp:class:`StructuralMechanicsModel <akantu::StructuralMechanicsModel>`
constructor is called in the following way:
.. code-block:: c++
StructuralMechanicsModel model(mesh, spatial_dimension);
where ``mesh`` is a :cpp:class:`Mesh <akantu::Mesh>` object defining the structure for
which the equations of statics are to be solved, and
``spatial_dimension`` is the dimensionality of the problem. If
``spatial_dimension`` is omitted, the problem is assumed to have
the same dimensionality as the one specified by the mesh.
.. warning::
Dynamic computations are not supported to date.
.. note::
Structural meshes are created and loaded
with ``_miot_gmsh_struct`` instead of ``_miot_gmsh`` (cf. :ref:`loading_mesh`)
.. code-block:: c++
Mesh mesh;
mesh.read("structural_mesh.msh", _miot_gmsh_struct);
This model contains at least the following :cpp:class:`Arrays <akantu::Arrays>`:
- **blocked_dofs** contains a Boolean value for each degree of
freedom specifying whether that degree is blocked or not. A
Dirichlet boundary condition can be prescribed by setting the
**blocked_dofs** value of a degree of freedom to
``true``. The **displacement** is computed for all degrees
of freedom for which the **blocked_dofs** value is set to
``false``. For the remaining degrees of freedom, the imposed
values (zero by default after initialization) are kept.
- **displacement_rotation** contains the generalized displacements (*i.e.* displacements and rotations) of all degrees of freedom. It can be either a computed displacement for free degrees of freedom or an imposed displacement in case of blocked ones (:math:`\vec{u}` in the following).
- **external_force** contains the generalized external forces (forces and moments) applied to the nodes (:math:`\vec{f_{\st{ext}}}` in the following).
- **internal_force** contains the generalized internal forces (forces and moments) applied to the nodes (:math:`\vec{f_{\st{int}}}` in the following).
An example to help understand how to use this model will be presented in the
next section.
.. _sec:structMechMod:setup:
Model Setup
-----------
Initialization
``````````````
The easiest way to initialize the structural mechanics model is:
.. code-block:: c++
model.initFull();
The method :cpp:class:`initFull <akantu::StructuralMechanicsModel::initFull>` computes the shape
functions, initializes the internal vectors mentioned above and allocates the
memory for the stiffness matrix, unlike the solid mechanics model, its default
argument is ``_static``.
Material properties are defined using the :cpp:class:`StructuralMaterial
<akantu::StructuralMaterial>` structure described in
:numref:`tab-structmechmod-strucmaterial`. Such a definition could, for
instance, look like
.. code-block:: c++
StructuralMaterial mat1;
mat.E=3e10;
mat.I=0.0025;
mat.A=0.01;
.. _tab-structmechmod-strucmaterial:
.. table:: Material properties for structural elements defined in the class :cpp:class:`StructuralMaterial <akantu::StructuralMaterial>`.
:align: center
====== ======
Field Description
====== ======
``E`` Young's modulus
``A`` Cross section area
``I`` Second cross sectional moment of inertia (for 2D elements)
``Iy`` ``I`` around beam :math:`y`--axis (for 3D elements)
``Iz`` ``I`` around beam :math:`z`--axis (for 3D elements)
``GJ`` Polar moment of inertia of beam cross section (for 3D elements)
====== ======
Materials can be added to the model's ``element_material`` vector using
.. code-block:: c++
model.addMaterial(mat1);
They are successively numbered and then assigned to specific elements.
.. code-block:: c++
- for (UInt i = 0; i < nb_element_mat_1; ++i) {
+ for (Int i = 0; i < nb_element_mat_1; ++i) {
model.getElementMaterial(_bernoulli_beam_2)(i,0) = 1;
}
.. _sect:structMechMod:boundary:
Setting Boundary Conditions
```````````````````````````
As explained before, the Dirichlet boundary conditions are applied through the
array **blocked_dofs**. Two options exist to define Neumann conditions.
If a nodal force is applied, it has to be directly set in the array
**force_momentum**. For loads distributed along the beam length, the
method :cpp:class:`computeForcesFromFunction <akantu::computeForcesFromFunction>` integrates them into nodal forces. The
method takes as input a function describing the distribution of loads along the
beam and a functor :cpp:class:`BoundaryFunctionType <akantu::BoundaryFunctionType>` specifing if the function is expressed in the local coordinates (``_bft_traction_local``) or in the
global system of coordinates (``_bft_traction``).
.. code-block:: c++
static void lin_load(double * position, double * load,
Real * normal, UInt surface_id){
memset(load,0,sizeof(Real)*3);
load[1] = position[0]*position[0]-250;
}
int main(){
...
model.computeForcesFromFunction<_bernoulli_beam_2>(lin_load,
_bft_traction_local);
...
}
.. _sect:structMechMod:static:
Static Analysis
---------------
The :cpp:class:`StructuralMechanicsModel <akantu::StructuralMechanicsModel>` class can perform static analyses of structures. In this case, the equation to solve is the same as for the :cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>` used for static analyses
.. math:: \mat{K} \vec{u} = \vec{f_{\st{ext}}}~,
:label: eqn-structmechmod-static
where :math:`\mat{K}` is the global stiffness matrix, :math:`\vec{u}` the
generalized displacement vector and :math:`\vec{f_{\st{ext}}}` the vector of
generalized external forces applied to the system.
To solve such a problem, the static solver of the
:cpp:class:`StructuralMechanicsModel <akantu::StructuralMechanicsModel>` object
is used. First a model has to be created and initialized.
.. code-block:: c++
StructuralMechanicsModel model(mesh);
model.initFull();
- :cpp:func:`model.initFull <akantu::StructuralMechanicsModel::initFull>` initializes all
internal vectors to zero.
Once the model is created and initialized, the boundary conditions can be set as explained in Section :ref:`sect:structMechMod:boundary`. Boundary conditions will prescribe the external forces or moments for the free degrees of freedom :math:`\vec{f_{\st{ext}}}` and displacements or rotations for the others. To completely define the system represented by equation (:eq:`eqn-structmechmod-static`), the global stiffness matrix :math:`\mat{K}` must be assembled.
.. code-block:: c++
model.assembleStiffnessMatrix();
The computation of the static equilibrium is performed using the same
Newton-Raphson algorithm as described in
Section~\ref{sect:smm:static}.
\note{To date, :cpp:class:`StructuralMechanicsModel
<akantu::StructuralMechanicsModel>` handles only constitutively and
geometrically linear problems, the algorithm is therefore guaranteed to converge
in two iterations.}
.. code-block:: c++
model.solveStep();
- :cpp:func:`model.solveStep <akantu::StructuralMechanicsModel::solveStep>` solves the :eq:`eqn-structmechmod-static`.
The **increment** vector of the model will contain the new
increment of displacements, and the **displacement_rotation**
vector is also updated to the new displacements.
At the end of the analysis, the final solution is stored in the
**displacement_rotation** vector. A full example of how to solve a structural
mechanics problem is presented in the code
``example/structural_mechanics/bernoulli_beam_2_example.cc``. This example is
composed of a 2D beam, clamped at the left end and supported by two rollers as
shown in :numref:`fig-structmechmod-exam1-1`. The problem is defined by the
applied load :math:`q=6 \text{\kN/m}`, moment :math:`\bar{M} = 3.6 \text{kN m}`,
moments of inertia :math:`I_1 = 250\,000 \text{cm}^4` and :math:`I_2 = 128\,000
\text{cm}^4` and lengths :math:`L_1 = 10\text{m}` and :math:`L_2 = 8\text{m}`.
The resulting rotations at node two and three are :math:`\varphi_2 = 0.001\,167`
and :math:`\varphi_3 = -0.000\,771`.
.. _fig-structmechmod-exam1-1:
.. figure:: figures/beam_example.svg
:align: center
2D beam example
diff --git a/doc/manual/manual-changelog.tex b/doc/manual/manual-changelog.tex
index 8e7b937f1..5a752203f 100644
--- a/doc/manual/manual-changelog.tex
+++ b/doc/manual/manual-changelog.tex
@@ -1,47 +1,47 @@
\chapter*{Changes, New Features, and Fixes}
\section*{Version 3.0.0}
\begin{itemize}
\item[\textbf{\texttt{c++14}}] Switch from C++ standard \code{2003} to \code{2014}\\
Example of changes implied by this:
\begin{cpp}
- for (UInt g = _not_ghost; g <= _ghost; ++g) {
+ for (Int g = _not_ghost; g <= _ghost; ++g) {
GhostType gt = (GhostType)g;
Mesh::type_iterator it = this->mesh.firstType(spatial_dimension, gt);
Mesh::type_iterator end = this->mesh.lastType(spatial_dimension, gt);
for (; it != end; ++it) {
ElementType & type = *it;
...
}
}
\end{cpp}
becomes
\begin{cpp}
for (auto ghost_type : ghost_types) {
for (auto type : mesh.elementTypes(spatial_dimension,
ghost_type)) {
...
}
}
\end{cpp}
\item[\textbf{\texttt{feature}}] Parallel cohesive elements
\item[\textbf{\texttt{feature}}] Models using new interface for solvers
\begin{itemize}
\item Same configuration for all models
\item Solver can be configured in input file
\item PETSc interface temporary inactive
\item Periodic boundary condition temporary inactive
\end{itemize}
\item[\textbf{\texttt{feature}}] Element groups created by default for \code{``physical\_names''}
\item[\textbf{\texttt{feature}}] Named arguments for functions (e.g. \code{model.initFull(\_analysis\_method = \_static)})
\item[\textbf{\texttt{api}}] Only one function to solve a step \code{model.solveStep()}
\item[\textbf{\texttt{api}}] Simplification of the parallel simulation with the
\code{mesh.distribute()} function
\end{itemize}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "manual"
%%% End:
diff --git a/doc/manual/manual-feengine.tex b/doc/manual/manual-feengine.tex
index 415b15d1e..4e5d2649c 100644
--- a/doc/manual/manual-feengine.tex
+++ b/doc/manual/manual-feengine.tex
@@ -1,75 +1,75 @@
\chapter{FEEngine\index{FEEngine}}
\label{chap:feengine}
The \code{FEEngine} interface is dedicated to handle the
finite-element approximations and the numerical integration of the
weak form. As we will see in Chapter \ref{sect:smm}, \code{Model}
creates its own \code{FEEngine} object so the explicit creation of the
object is not required.
\section{Mathematical Operations\label{sect:fe:mathop}}
Using the \code{FEEngine} object, one can compute a interpolation, an
integration or a gradient. A simple example is given below.
\begin{cpp}
// having a FEEngine object
FEEngine *fem = new FEEngineTemplate<IntegratorGauss,ShapeLagrange>(my_mesh,
dim,
"my_fem");
// instead of this, a FEEngine object can be get using the model:
// model.getFEEngine()
//compute the gradient
Array<Real> u; //append the values you want
Array<Real> nablauq; //gradient array to be computed
// compute the gradient
fem->gradientOnIntegrationPoints(const Array<Real> &u,
Array<Real> &nablauq,
- const UInt nb_degree_of_freedom,
+ const Int nb_degree_of_freedom,
ElementType type);
// interpolate
Array<Real> uq; //interpolated array to be computed
// compute the interpolation
fem->interpolateOnIntegrationPoints(const Array<Real> &u,
Array<Real> &uq,
- UInt nb_degree_of_freedom,
+ Int nb_degree_of_freedom,
ElementType type);
// interpolated function can be integrated over the elements
Array<Real> int_val_on_elem;
// integrate
fem->integrate(const Array<Real> &uq,
Array<Real> &int_uq,
- UInt nb_degree_of_freedom,
+ Int nb_degree_of_freedom,
ElementType type);
\end{cpp}
Another example below shows how to integrate stress and strain fields
over elements assigned to a particular material.
\begin{cpp}
-UInt sp_dim = 3; //spatial dimension
-UInt m = 1; //material index of interest
+Int sp_dim = 3; //spatial dimension
+Int m = 1; //material index of interest
const ElementType type = _tetrahedron_4; //element type
// get the stress and strain arrays associated to the material index m
const Array<Real> & strain_vec = model.getMaterial(m).getGradU(type);
const Array<Real> & stress_vec = model.getMaterial(m).getStress(type);
// get the element filter for the material index
-const Array<UInt> & elem_filter = model.getMaterial(m).getElementFilter(type);
+const Array<Idx> & elem_filter = model.getMaterial(m).getElementFilter(type);
// initialize the integrated stress and strain arrays
Array<Real> int_strain_vec(elem_filter.getSize(),
sp_dim*sp_dim, "int_of_strain");
Array<Real> int_stress_vec(elem_filter.getSize(),
sp_dim*sp_dim, "int_of_stress");
// integrate the fields
model.getFEEngine().integrate(strain_vec, int_strain_vec,
sp_dim*sp_dim, type, _not_ghost, elem_filter);
model.getFEEngine().integrate(stress_vec, int_stress_vec,
sp_dim*sp_dim, type, _not_ghost, elem_filter);
\end{cpp}
\input{manual-elements}
diff --git a/doc/manual/manual-gettingstarted.tex b/doc/manual/manual-gettingstarted.tex
index 383b48e38..8d7d873d4 100644
--- a/doc/manual/manual-gettingstarted.tex
+++ b/doc/manual/manual-gettingstarted.tex
@@ -1,466 +1,466 @@
\chapter{Getting Started}
\section{Downloading the Code}
The \akantu source code can be requested using the form accessible at the URL
\url{http://lsms.epfl.ch/akantu}. There, you will be asked to accept the LGPL
license terms.
\section{Compiling \akantu}
\akantu is a \code{cmake} project, so to configure it, you can either
follow the usual way:
\begin{command}
> cd akantu
> mkdir build
> cd build
> ccmake ..
[ Set the options that you need ]
> make
> make install
\end{command}
\noindent Or, use the \code{Makefile} we added for your convenience to
handle the \code{cmake} configuration
\begin{command}
> cd akantu
> make config
> make
> make install
\end{command}
\noindent All the \akantu options are documented in Appendix
\ref{app:package-dependencies}.
\section{Writing a \texttt{main} Function\label{sect:common:main}}
\label{sec:writing_main}
First of all, \akantu needs to be initialized. The memory management
included in the core library handles the correct allocation and
de-allocation of vectors, structures and/or objects. Moreover, in
parallel computations, the initialization procedure performs the
communication setup. This is achieved by a pair of functions
(\code{initialize} and \code{finalize}) that are used as follows:
\begin{cpp}
#include "aka_common.hh"
#include "..."
using namespace akantu;
int main(int argc, char *argv[]) {
initialize("input_file.dat", argc, argv);
// your code
...
finalize();
}
\end{cpp}
The \code{initialize} function takes the text inpute file and the program
parameters which can be parsed by \akantu in due form (see \ref{sect:parser}).
Obviously it is necessary to include all files needed in main. In this manual
all provided code implies the usage of \code{akantu} as namespace.
\section{Creating and Loading a Mesh\label{sect:common:mesh}}
In its current state, \akantu supports three types of meshes: Gmsh~\cite{gmsh},
Abaqus~\cite{abaqus} and Diana~\cite{diana}. Once a \code{Mesh} object is
created with a given spatial dimension, it can be filled by reading a mesh input file.
The method \code{read} of the class \code{Mesh} infers the mesh type from the file extension. If a non-standard file extension is used, the mesh type has to be specified.
\begin{cpp}
-UInt spatial_dimension = 2;
+Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
// Reading Gmsh files
mesh.read("my_gmsh_mesh.msh");
mesh.read("my_gmsh_mesh", _miot_gmsh);
// Reading Abaqus files
mesh.read("my_abaqus_mesh.inp");
mesh.read("my_abaqus_mesh", _miot_abaqus);
// Reading Diana files
mesh.read("my_diana_mesh.dat");
mesh.read("my_diana_mesh", _miot_diana);
\end{cpp}
The Gmsh reader adds the geometrical and physical tags as mesh data. The physical
-values are stored as a \code{UInt} data called \code{tag\_0}, if a string
+values are stored as a \code{Int} data called \code{tag\_0}, if a string
name is provided it is stored as a \code{std::string} data named
-\code{physical\_names}. The geometrical tag is stored as a \code{UInt} data named
+\code{physical\_names}. The geometrical tag is stored as a \code{Int} data named
\code{tag\_1}.
The Abaqus reader stores the \code{ELSET} in ElementGroups and the \code{NSET}
in NodeGroups. The material assignment can be retrieved from the
\code{std::string} mesh data named \code{abaqus\_material}.
% \akantu supports meshes generated with Gmsh~\cite{gmsh}, a free
% software available at \url{http://geuz.org/gmsh/} where a detailed
% documentation can be found. Consequently, this manual will not provide
% Gmsh usage directions. Gmsh outputs meshes in \code{.msh} format that can be read
% by \akantu. In order to import a mesh, it is necessary to create
% a \code{Mesh} object through the following function calls:
% \begin{cpp}
-% UInt spatial_dimension = 2;
+% Int spatial_dimension = 2;
% Mesh mesh(spatial_dimension);
% \end{cpp}
% The only parameter that has to be specified by the user is the spatial
% dimension of the problem. Now it is possible to read a \code{.msh} file with
% a \code{MeshIOMSH} object that takes care of loading a mesh to memory.
% This step is carried out by:
% \begin{cpp}
% mesh.read("square.msh");
% \end{cpp}
% where the \code{MeshIOMSH} object is first created before being
% used to read the \code{.msh} file. The mesh file name as well as the \code{Mesh}
% object must be specified by the user.
% The \code{MeshIOMSH} object can also write mesh files. This feature
% is useful to save a mesh that has been modified during a
% simulation. The \code{write} method takes care of it:
% \begin{cpp}
% mesh_io.write("square_modified.msh", mesh);
% \end{cpp}
% which works exactly like the \code{read} method.
% \akantu supports also meshes generated by
% DIANA (\url{http://tnodiana.com}), but only in reading mode. A similar
% procedure applies where the only
% difference is that the \code{MeshIODiana} object should be used
% instead of the \code{MeshIOMSH} one. Additional mesh readers can be
% introduced into \akantu by coding new \code{MeshIO} classes.
\section{Using \texttt{Arrays}}
Data in \akantu can be stored in data containers implemented by
the \code{Array} class. In its most basic usage, the \code{Array} class
implemented in \akantu is similar to the \code{vector} class of
the Standard Template Library (STL) for C++. A simple \code{Array}
containing a sequence of \code{nb\_element} values (of a given type) can be generated with:
\begin{cpp}
Array<type> example_array(nb_element);
\end{cpp}
where \code{type} usually is \code{Real}, \code{Int}, \code{UInt} or
\code{bool}. Each value is associated to an index, so that data can be
accessed by typing:
\begin{cpp}
auto & val = example_array(index)
\end{cpp}
\code{Arrays} can also contain tuples of values for each index. In
that case, the number of components per tuple must be specified at the
\code{Array} creation. For example, if we want to create an
\code{Array} to store the coordinates (sequences of three values) of
ten nodes, the appropriate code is the following:
\begin{cpp}
- UInt nb_nodes = 10;
- UInt spatial_dimension = 3;
+ Int nb_nodes = 10;
+ Int spatial_dimension = 3;
Array<Real> position(nb_nodes, spatial_dimension);
\end{cpp}
In this case the $x$ position of the eighth node number will be given by
\code{position(7, 0)} (in C++, numbering starts at 0 and not
1). If the number of components for the sequences is not specified, the
default value of 1 is used.
Here is a list of some basic operations that can be performed on \code{Array}:
\begin{itemize}
\item \code{resize(size)} change the size of the \code{Array}.
\item \code{clear()} set all entries of the \code{Array} to zero.
\item \code{set(t)} set all entries of the \code{Array} to \code{t}.
\item \code{copy(const Array<T> $\&$ other)} copy another \code{Array} into the current one. The two \code{Array} should have the same number of components.
\item \code{push$\_$back(tuple)} append a tuple with the correct number of components at the end of the \code{Array}.
\item \code{erase(i) erase the value at the i-th position.}
\item \code{find(value)} search \code{value} in the current \code{Array}. Return position index of the first occurence or $-1$ if not found.
\item \code{storage()} Return the address of the allocated memory of the \code{Array}.
\end{itemize}
\subsection{\texttt{Arrays} iterators}
It is very common in \akantu to loop over arrays to perform a specific
treatment. This ranges from geometric calculation on nodal quantities
to tensor algebra (in constitutive laws for example).
The \code{Array} object has the possibility to request iterators
in order to make the writing of loops easier and enhance readability.
For instance, a loop over the nodal coordinates can be performed like:
\begin{cpp}
//accessing the nodal coordinates Array (spatial_dimension components)
const auto & nodes = mesh.getNodes();
//creating the iterators
auto it = nodes.begin(spatial_dimension);
auto end = nodes.end(spatial_dimension);
for (; it != end; ++it){
const auto & coords = (*it);
//do what you need
....
}
\end{cpp}
In that example, each \code{coords} is a \code{Vector<Real>} containing
geometrical array of size \code{spatial\_dimension} and the iteration is
conveniently performed by the \code{Array} iterator.
With the switch to \code{c++14} this can be also written as
\begin{cpp}
//accessing the nodal coordinates Array (spatial_dimension components)
const auto & nodes = mesh.getNodes();
for (const auto & coords : make_view(nodes, spatial_dimension) {
//do what you need
....
}
\end{cpp}
The \code{Array} object is intensively used to store second order
tensor values. In that case, it should be specified that the returned
object type is a matrix when constructing the iterator. This is done
when calling the \code{begin} function. For instance, assuming that we
have a \code{Array} storing stresses, we can loop over the stored
tensors by:
\begin{cpp}
//creating the iterators
auto it = stresses.begin(spatial_dimension, spatial_dimension);
auto end = stresses.end(spatial_dimension, spatial_dimension);
for (; it != end; ++it){
Matrix<Real> & stress = (*it);
//do what you need
....
}
\end{cpp}
In that last example, the \code{Matrix} objects are
\code{spatial\_dimension} $\times$ \code{spatial\_dimension} matrices.
The light objects \code{Matrix} and \code{Vector} can be used and
combined to do most common linear algebra. If the number of component
is 1, it is possible to use a scalar\_iterator rather than the
vector/matrix one.
In general, a mesh consists of several kinds of elements.
Consequently, the amount of data to be stored can differ for each
element type. The straightforward example is the connectivity array,
namely the sequences of nodes belonging to each element (linear
triangular elements have fewer nodes than, say, rectangular quadratic
elements etc.). A particular data structure called
\code{ElementTypeMapArray} is provided to easily manage this kind of
data. It consists of a group of \code{Arrays}, each associated to an
element type. The following code can retrieve the
\code{ElementTypeMapArray} which stores the connectivity arrays for a
mesh:
\begin{cpp}
- const ElementTypeMapArray<UInt> & connectivities = mesh.getConnectivities();
+ const ElementTypeMapArray<Idx> & connectivities = mesh.getConnectivities();
\end{cpp}
Then, the specific array associated to a given element type can be obtained by
\begin{cpp}
- const Array<UInt> & connectivity_triangle = connectivities(_triangle_3);
+ const Array<Idx> & connectivity_triangle = connectivities(_triangle_3);
\end{cpp}
where the first order 3-node triangular element was used in the presented piece
of code.
\subsection{Vector \& Matrix}
The \code{Array} iterators as presented in the previous section can be shaped as
\code{Vector} or \code{Matrix}. This objects represent $1^{st}$ and $2^{nd}$
order tensors. As such they come with some functionalities that we will present
a bit more into detail in this here.
\subsubsection{\texttt{Vector<T>}}
\begin{enumerate}
\item Accessors:
\begin{itemize}
\item \code{v(i)} gives the $i^{th}$ component of the vector \code{v}
\item \code{v[i]} gives the $i^{th}$ component of the vector \code{v}
\item \code{v.size()} gives the number of component
\end{itemize}
\item Level 1: (results are scalars)
\begin{itemize}
\item \code{v.norm()} returns the geometrical norm ($L_2$)
\item \code{v.norm<N>()} returns the $L_N$ norm defined as $\left(\sum_i
|\code{v(i)}|^N\right)^{1/N}$. N can take any positive
integer value. There are also some particular values for the most commonly
used norms, \code{L\_1} for the Manhattan norm, \code{L\_2} for the
geometrical norm and \code{L\_inf} for the norm infinity.
\item \code{v.dot(x)} return the dot product of \code{v} and \code{x}
\item \code{v.distance(x)} return the geometrical norm of $\code{v} -
\code{x}$
\end{itemize}
\item Level 2: (results are vectors)
\begin{itemize}
\item \code{v += s}, \code{v -= s}, \code{v *= s}, \code{v /= s} those are
element-wise operators that sum, substract, multiply or divide all the
component of \code{v} by the scalar \code{s}
\item \code{v += x}, \code{v -= x} sums or substracts the vector \code{x}
to/from \code{v}
\item \code{v.mul(A, x, alpha)} stores the result of $\alpha \mat{A} \vec{x}$ in \code{v},
$\alpha$ is equal to 1 by default
\item \code{v.solve(A, b)} stores the result of the resolution of the system $\mat{A} \vec{x} =
\vec{b}$ in \code{v}
\item \code{v.crossProduct(v1, v2)} computes the cross product of \code{v1} and \code{v2} and
stores the result in \code{v}
\end{itemize}
\end{enumerate}
\subsubsection{\texttt{Matrix<T>}}
\begin{enumerate}
\item Accessors:
\begin{itemize}
\item \code{A(i, j)} gives the component $A_{ij}$ of the matrix \code{A}
\item \code{A(i)} gives the $i^{th}$ column of the matrix as a \code{Vector}
\item \code{A[k]} gives the $k^{th}$ component of the matrix, matrices are
stored in a column major way, which means that to access $A_{ij}$, $k = i +
j M$
\item \code{A.rows()} gives the number of rows of \code{A} ($M$)
\item \code{A.cols()} gives the number of columns of \code{A} ($N$)
\item \code{A.size()} gives the number of component in the matrix ($M \times N$)
\end{itemize}
\item Level 1: (results are scalars)
\begin{itemize}
\item \code{A.norm()} is equivalent to \code{A.norm<L\_2>()}
\item \code{A.norm<N>()} returns the $L_N$ norm defined as
$\left(\sum_i\sum_j |\code{A(i,j)}|^N\right)^{1/N}$. N can take
any positive integer value. There are also some particular values
for the most commonly used norms, \code{L\_1} for the Manhattan
norm, \code{L\_2} for the geometrical norm and \code{L\_inf} for
the norm infinity.
\item \code{A.trace()} return the trace of \code{A}
\item \code{A.det()} return the determinant of \code{A}
\item \code{A.doubleDot(B)} return the double dot product of \code{A} and
\code{B}, $\mat{A}:\mat{B}$
\end{itemize}
\item Level 3: (results are matrices)
\begin{itemize}
\item \code{A.eye(s)}, \code{Matrix<T>::eye(s)} fills/creates a matrix with
the $s\mat{I}$ with $\mat{I}$ the identity matrix
\item \code{A.inverse(B)} stores $\mat{B}^{-1}$ in \code{A}
\item \code{A.transpose()} returns $\mat{A}^{t}$
\item \code{A.outerProduct(v1, v2)} stores $\vec{v_1} \vec{v_2}^{t}$ in
\code{A}
\item \code{C.mul<t\_A, t\_B>(A, B, alpha)}: stores the result of the product of
\code{A} and code{B} time the scalar \code{alpha} in \code{C}. \code{t\_A}
and \code{t\_B} are boolean defining if \code{A} and \code{B} should be
transposed or not.
\begin{tabular}{ccl}
\toprule
\code{t\_A} & \code{t\_B} & result \\
\midrule
false & false & $\mat{C} = \alpha \mat{A} \mat{B}$\\
false & true & $\mat{C} = \alpha \mat{A} \mat{B}^t$\\
true & false & $\mat{C} = \alpha \mat{A}^t \mat{B}$\\
true & true & $\mat{C} = \alpha \mat{A}^t \mat{B}^t$\\
\bottomrule
\end{tabular}
\item \code{A.eigs(d, V)} this method computes the eigenvalues and
eigenvectors of \code{A} and store the results in \code{d} and \code{V} such
that $\code{d(i)} = \lambda_i$ and $\code{V(i)} = \vec{v_i}$ with
$\mat{A}\vec{v_i} = \lambda_i\vec{v_i}$ and $\lambda_1 > ... > \lambda_i >
... > \lambda_N$
\end{itemize}
\end{enumerate}
\subsubsection{\texttt{Tensor3<T>}}
Accessors:
\begin{itemize}
\item \code{t(i, j, k)} gives the component $T_{ijk}$ of the tensor \code{t}
\item \code{t(k)} gives the $k^{th}$ two-dimensional tensor as a \code{Matrix}
\item \code{t[k]} gives the $k^{th}$ two-dimensional tensor as a \code{Matrix}
\end{itemize}
\section{Manipulating group of nodes and/or elements\label{sect:common:groups}}
\akantu provides the possibility to manipulate
subgroups of elements and nodes.
Any \code{ElementGroup} and/or \code{NodeGroup} must be managed
by a \code{GroupManager}. Such a manager has the role to
associate group objects to names. This is a useful feature,
in particular for the application of the boundary conditions,
as will be demonstrated in section \ref{sect:smm:boundary}.
To most general group manager is the \code{Mesh} class
which inheritates from the \code{GroupManager} class.
For instance, the following code shows how to request
an element group to a mesh:
\begin{cpp}
// request creation of a group of nodes
NodeGroup & my_node_group = mesh.createNodeGroup("my_node_group");
// request creation of a group of elements
ElementGroup & my_element_group = mesh.createElementGroup("my_element_group");
/* fill and use the groups */
\end{cpp}
\subsection{The \texttt{NodeGroup} object}
A group of nodes is stored in \code{NodeGroup} objects.
They are quite simple objects which store the indexes
-of the selected nodes in a \code{Array<UInt>}.
+of the selected nodes in a \code{Array<Idx>}.
Nodes are selected by adding them when calling
\code{NodeGroup::add}. For instance you can select nodes
having a positive $X$ coordinate with the following code:
\begin{cpp}
const auto & nodes = mesh.getNodes();
auto & group = mesh.createNodeGroup("XpositiveNode");
for (auto && data : enumerate(make_view(nodes, spatial_dimension))){
auto node = std::get<0>(data);
const auto & position = std::get<1>(data);
if (position(0) > 0) group.add(node);
}
\end{cpp}
\subsection{The \texttt{ElementGroup} object}
A group of elements is stored in \code{ElementGroup} objects.
Since a group can contain elements of various types
the \code{ElementGroup} object stores indexes in
-a \code{ElementTypeMapArray<UInt>} object.
+a \code{ElementTypeMapArray<Idx>} object.
Then elements can be added to the group by calling \code{addElement}.
For instance, selecting the elements for which the barycenter of the nodes
has a positive $X$ coordinate can be made with:
\begin{cpp}
auto & group = mesh.createElementGroup("XpositiveElement");
Vector<Real> barycenter(spatial_dimension);
for(auto type : mesh.elementTypes()){
- UInt nb_element = mesh.getNbElement(type);
+ Int nb_element = mesh.getNbElement(type);
- for(UInt e = 0; e < nb_element; ++e) {
+ for(Int e = 0; e < nb_element; ++e) {
Element element{type, e, _not_ghost};
mesh.getBarycenter(element, barycenter);
if (barycenter(_x) > 0.) group.add(element);
}
}
\end{cpp}
\section{Compiling your simulation}
The easiest way to compile your simulation is to create a \code{cmake} project by putting all your code in some directory of your choosing. Then, make sure that you have \code{cmake} installed and create a \code{CMakeLists.txt} file. An example of a minimal \code{CMakeLists.txt} file would look like this:
\begin{cmake}
project(my_simu)
cmake_minimum_required(VERSION 3.0.0)
find_package(Akantu REQUIRED)
add_akantu_simulation(my_simu my_simu.cc)
\end{cmake}
%
Then create a directory called \code{build} and inside it execute \code{ccmake ..} which opens a configuration screen. If you installed \akantu in a standard directory such as \code{/usr/local} (using \code{make install}), you should be able to compile by hitting the \code{c} key, setting \code{CMAKE\textunderscore{}BUILD\textunderscore{}TYPE} to \code{Release}, hitting the \code{c} key again a few times and then finishing the configuration with the \code{g} key. After that, you can type \code{make} to build your simulation. If you change your simulation code later on, you only need to type \code{make} again.
If you get an error that \code{FindAkantu.cmake} was not found, you have to set the \code{Akantu\textunderscore{}DIR} variable, which will appear after dismissing the error message. If you built \akantu without running \code{make install}, the variable should be set to the \code{build} subdirectory of the \akantu source code. If you installed it in \code{\$PREFIX}, set the variable to \code{\$PREFIX/share/cmake/Akantu} instead.
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "manual"
%%% End:
diff --git a/doc/manual/manual-heattransfermodel.tex b/doc/manual/manual-heattransfermodel.tex
index cd980f706..d95a6d339 100644
--- a/doc/manual/manual-heattransfermodel.tex
+++ b/doc/manual/manual-heattransfermodel.tex
@@ -1,163 +1,163 @@
\chapter{Heat Transfer Model}
The heat transfer model is a specific implementation of the \code{Model} interface
dedicated to handle the dynamic heat equation.
\section{Theory}
The strong form of the dynamic heat equation
can be expressed as
\begin{equation}
\rho c_v \dot{T} + \nabla \cdot \vec{\kappa} \nabla T = b
\end{equation}
with $T$ the scalar temperature field,
$c_v$ the specific heat capacity,
$\rho$ the mass density,
$\mat{\kappa}$ the conductivity tensor, and $b$ the heat generation per unit of volume.
The discretized weak form with a finite number of elements is
\begin{equation}
\forall i \quad
\sum_j \left( \int_\Omega \rho c_v N_j N_i d\Omega \right) \dot{T}_j
- \sum_j \left( \int_\Omega \vec{\kappa} \nabla N_j \nabla N_i d\Omega \right) T_j =
- \int_{\Gamma} N_i \vec{q} \cdot \vec{n} d\Gamma + \int_\Omega b N_i d\Omega
\end{equation}
with $i$ and $j$ the node indices, $\vec{n}$ the normal field to the surface
$\Gamma = \partial \Omega$.
To simplify, we can define the capacity and the conductivity matrices as
\begin{equation}
C_{ij} = \int_\Omega \rho c_v N_j N_i d\Omega \qquad \textrm{and} \qquad
K_{ij} = - \int_\Omega \vec{\kappa} \nabla N_j \nabla N_i d\Omega
\end{equation}
and the system to solve can be written
\begin{equation}
\mat{C} \cdot \vec{\dot{T}} = \vec{Q}^{\text{ext}} -\mat{K} \cdot \vec{T}~,
\end{equation}
with $\vec{Q}^{\text{ext}}$ the consistent heat generated.
\section{Using the Heat Transfer Model}
A material file name has to be provided during initialization.
Currently, the \code{HeatTransferModel} object uses dynamic analysis
with an explicit time integration scheme. It can simply be created
like this
\begin{cpp}
HeatTransferModel model(mesh, spatial_dimension);
\end{cpp}
while an existing mesh has been used (see \ref{sect:common:mesh}).
Then the model object can be initialized with:
\begin{cpp}
model.initFull()
\end{cpp}
This function will load the material
properties, and allocate / initialize the nodes and element \code{Array}s
More precisely, the heat transfer model contains 4 \code{Arrays}:
\begin{description}
\item[temperature] contains the nodal temperature $T$ (zero by default after the
initialization).
\item[temperature\_rate] contains the variations of temperature $\dot{T}$
(zero by default after the
initialization).
\item[blocked\_dofs] contains a Boolean value for each degree of
freedom specifying whether the degree is blocked or not. A Dirichlet
boundary condition ($T_d$) can be prescribed by setting the
\textbf{blocked\_dofs} value of a degree of freedom to \code{true}.
The \textbf{temperature} and the \textbf{temperature\_rate} are
computed for all degrees of freedom where the \textbf{blocked\_dofs}
value is set to \code{false}. For the remaining degrees of freedom,
the imposed values (zero by default after initialization) are kept.
\item[external\_heat\_rate] contains the external heat generations. $\vec{Q^{ext}}$
on the nodes.
\item[internal\_heat\_rate] contains the internal heat generations. $\vec{Q^{int}} = -\mat{K} \cdot \vec{T}$ on the nodes.
\end{description}
Only a single material can be specified on the domain.
A material text file (\eg material.dat) provides the material properties as follows:
\begin{cpp}
model heat_transfer_model [
capacity = %\emph{XXX}%
density = %\emph{XXX}%
conductivity = [%\emph{XXX}% ... %\emph{XXX}%]
]
\end{cpp}
where the \code{capacity} and \code{density} are scalars, and the \code{conductivity} is specified as a $3\times 3$ tensor.
\subsection{Explicit Dynamic}
The explicit time integration scheme in \akantu uses a lumped capacity
matrix $\mat{C}$ (reducing the computational cost, see Chapter \ref{sect:smm}).
This matrix is assembled by
distributing the capacity of each element onto its nodes. Therefore, the resulting $\mat{C}$ is a diagonal matrix stored in the \code{capacity} \code{Array} of the model.
\begin{cpp}
model.assembleCapacityLumped();
\end{cpp}
\index{HeatTransferModel!assembleCapacityLumped}
\note{Currently, only the explicit time integration with lumped capacity matrix
is implemented within \akantu.} The explicit integration scheme is \index{Forward Euler} \emph{Forward Euler}
\cite{curnier92a}.
\begin{itemize}
\item Predictor: $\vec{T}_{n+1} = \vec{T}_{n} + \Delta t \dot{\vec{T}}_{n}$
\item Update residual: $\vec{R}_{n+1} = \left( \vec{Q^{ext}_{n+1}} - \vec{K}\vec{T}_{n+1} \right)$
\item Corrector : $\dot{\vec{T}}_{n+1} = \mat{C}^{-1} \vec{R}_{n+1}$
\end{itemize}
The explicit integration scheme is conditionally stable. The time step has to be smaller than the stable time step,
and it can be obtained in \akantu as follows:
\begin{cpp}
time_step = model.getStableTimeStep();
\end{cpp}
\index{HeatTransferModel!StableTimeStep}
The stable time step is defined as:
\begin{equation}\label{eqn:htm:explicit:stabletime}
\Delta t_{\st{crit}} = 2 \Delta x^2 \frac{\rho c_v}{\mid\mid \mat{\kappa} \mid\mid^\infty}
\end{equation}
where $\Delta x$ is the characteristic length (\eg the inradius in the
case of linear triangle element), $\rho$ is the density,
$\mat{\kappa}$ is the conductivity tensor, and $c_v$ is the specific
heat capacity. It is necessary to impose a time step which is smaller
than the stable time step, for instance, by multiplying the stable
time step by a safety factor smaller than one.
\begin{cpp}
const Real safety_time_factor = 0.1;
Real applied_time_step = time_step * safety_time_factor;
model.setTimeStep(applied_time_step);
\end{cpp}
The following loop allows, for each time step, to update the \code{temperature}, \code{residual} and
\code{temperature\_rate} fields following the previously described integration scheme.
\begin{cpp}
- for (UInt s = 1; (s-1)*applied_time_step < total_time; ++s) {
+ for (Int s = 1; (s-1)*applied_time_step < total_time; ++s) {
model.solveStep();
}
\end{cpp}
\index{HeatTransferModel!solveStep()}
An example of explicit dynamic heat propagation is presented in \\
\shellcode{\examplesdir/heat\_transfer/explicit\_heat\_transfer.cc}. \\
This example consists of a square 2D plate of \SI{1}{\metre^2}
having an initial temperature of \SI{100}{\kelvin} everywhere but a
none centered hot point maintained at
\SI{300}{\kelvin}. Figure~\ref{fig:htm:explicit:dynamic} presents
the geometry of this case. The material used is a linear fictitious
elastic material with a density of
\SI{8940}{\kilo\gram\per\metre^3}, a conductivity of
\SI{401}{\watt\per\metre\per\kelvin} and a specific heat capacity of
\SI{385}{\joule\per\kelvin\per\kilogram}. The time step used is
\SI{0.12}{\second}.
\begin{figure}[!htb]
\centering
\includegraphics[width=.4\textwidth]{figures/hot-point-1}
\hfill
\includegraphics[width=.4\textwidth]{figures/hot-point-2}
\caption{Initial temperature field (left) and after 15000 time steps = 30 minutes (right). The lines represent iso-surfaces.}
\label{fig:htm:explicit:dynamic}
\end{figure}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "manual"
%%% End:
diff --git a/doc/manual/manual-io.tex b/doc/manual/manual-io.tex
index b4aac0022..f0d5284a5 100644
--- a/doc/manual/manual-io.tex
+++ b/doc/manual/manual-io.tex
@@ -1,297 +1,297 @@
\chapter{Input/Output}\index{I\/O}
\section{Input file \label{sect:parser}}
The text input file of a simulation should be precised using the method \code{initialize} which will instantiate the static \code{Parser} object of \akantu. This section explains how to manipulate \code{Parser} objects to input data in \akantu.
\begin{cpp}
int main(int argc, char *argv[]) {
initialize("input_files.dat", argc, argv);
...
\end{cpp}
\subsection{Akantu Parser}
\akantu file parser has a tree organization.
\begin{itemize}
\item \code{Parser}, the root of the tree, can be accessed using
\begin{cpp}
Parser & parser = getStaticParser();
\end{cpp}
\item \code{ParserSection}, branch of the tree, contains map a of sub-sections (\code{SectionType}, \code{ParserSection}) and a \code{ParserSection *} pointing to the parent section. The user section of the input file can directly be accessed by
\begin{cpp}
const ParserSection & usersect = getUserParser();
\end{cpp}
\item \code{ParserParameter}, the leaf of the tree, carries data of the input file which can be casted to the correct type with
\begin{cpp}
Real mass = usersect.getParameter("mass");
\end{cpp}
or used directly within an expression
\begin{cpp}
Real dead_weight = 9.81 * usersect.getParameterValue<Real>("mass");
\end{cpp}
\end{itemize}
\subsection{Grammar}
The structure of text input files consists of different sections containing a list of parameters. As example, the file parsed in the previous section will look like
\begin{cpp}
user parameters [
mass = 10.5
]
\end{cpp}
Basically every standard arithmetic operations can be used inside of input files as well as the constant \code{pi} and \code{e} and the exponent operator \code{\^{}}. Operations between \code{ParserParameter} are also possible with the convention that only parameters of the current and the parent sections are available. \code{Vector} and \code{Matrix} can also be read according to the \code{NumPy}\cite{numpy} writing convention (a.e. cauchy$\_$stress$\_$tensor = [[$\sigma_{xx}$, $\sigma_{xy}$],[$\sigma_{yx}$,$\sigma_{yy}$]]).
An example illustrating how to parse the following input file can be found in \code{example$\backslash$io$\backslash$parser$\backslash$example$\_$parser.cc}.
\begin{cpp}
user parameters [
spatial$\_$dimension = 2
mesh$\_$file = swiss$\_$cheese.msh
inner$\_$holes = holes
outter$\_$crust = crust
lactostatic$\_$p = 30e3
stress = [[lactostatic$\_$p,0],[0,lactostatic$\_$p]]
max$\_$nb$\_$iterations = 100
precision = 1e-9
]
\end{cpp}
\subsection{Material section \label{sect:io:material}}
The input file should also be used to specify material characteristics (constitutive behavior and material properties). The dedicated material section is then read by \code{initFull} method of \code{SolidMechanicsModel} which initializes the different materials specified with the following convention:
\begin{cpp}
material %\emph{constitutive\_law}% %\emph{<optional flavor>}% [
name = $value$
rho = $value$
...
]
\end{cpp}
\index{Constitutive\_laws} where \emph{constitutive\_law} is the adopted
constitutive law, followed by the material properties listed one by line in the
bracket (\eg \code{name} and density \code{rho}). Some constitutive laws can
also have an \emph{optional flavor}. More information can be found in sections relative to material
constitutive laws \ref{sect:smm:CL} or in Appendix \ref{app:material-parameters}.
\section{Output data}
\subsection{Generic data}
In this chapter, we address ways to get the internal data in human-readable formats.
The models in \akantu handle data associated to the
mesh, but this data can be split into several \code{Arrays}. For example, the
data stored per element type in a \code{ElementTypeMapArray} is composed of as
many \code{Array}s as types in the mesh.
In order to get this data in a visualization software, the models contain a
object to dump \code{VTK} files. These files can be visualized in software such
as \code{ParaView}\cite{paraview}, \code{ViSit}\cite{visit} or \code{Mayavi}\cite{mayavi}.
The internal dumper of the model can be configured to specify which data fields
are to be written. This is done with the
\code{addDumpField}\index{I\/O!addDumpField} method. By default all the files
are generated in a folder called \code{paraview/}
\begin{cpp}
model.setBaseName("output"); // prefix for all generated files
model.addDumpField("displacement");
model.addDumpField("stress");
...
model.dump()
\end{cpp}
The fields are dumped with the number of components of the memory. For example, in 2D, the memory has
\code{Vector}s of 2 components, or the $2^{nd}$ order tensors with $2\times2$ components.
This memory can be dealt with \code{addDumpFieldVector}\index{I\/O!addDumpFieldVector} which always dumps
\code{Vector}s with 3 components or \code{addDumpFieldTensor}\index{I\/O!addDumpFieldTensor} which dumps $2^{nd}$
order tensors with $3\times3$ components respectively. The routines \code{addDumpFieldVector}\index{I\/O!addDumpFieldVector} and
\code{addDumpFieldTensor}\index{I\/O!addDumpFieldTensor} were introduced because of \code{ParaView} which mostly manipulate 3D data.
Those fields which are stored by quadrature point are modified to be seen in the
\code{VTK} file as elemental data. To do this, the default is to average the
values of all the quadrature points.
The list of fields depends on the models (for
\code{SolidMechanicsModel} see table~\ref{tab:io:smm_field_list}).
\begin{table}
\centering
\begin{tabular}{llll}
\toprule
key & type & support \\
\midrule
displacement & Vector<Real> & nodes \\
mass & Vector<Real> & nodes \\
velocity & Vector<Real> & nodes \\
acceleration & Vector<Real> & nodes \\
force & Vector<Real> & nodes \\
residual & Vector<Real> & nodes \\
increment & Vector<Real> & nodes \\
{blocked\_dofs} & Vector<bool> & nodes \\
partitions & Real & elements \\
material\_index & variable & elements\\
strain & Matrix<Real> & quadrature points \\
Green strain & Matrix<Real> & quadrature points \\
principal strain & Vector<Real> & quadrature points \\
principal Green strain & Vector<Real> & quadrature points \\
grad\_u & Matrix<Real> & quadrature points \\
stress & Matrix<Real> & quadrature points \\
Von Mises stress & Real & quadrature points \\
material\_index & variable & quadrature points \\
\bottomrule
\end{tabular}
\caption{List of dumpable fields for \code{SolidMechanicsModel}.}
\label{tab:io:smm_field_list}
\end{table}
\subsection{Cohesive elements' data}
Cohesive elements and their relative data can be easily dumped thanks
to a specific dumper contained in
\code{SolidMechanicsModelCohesive}. In order to use it, one has just
to add the string \code{"cohesive elements"} when calling each method
already illustrated. Here is an example on how to dump displacement
and damage:
\begin{cpp}
model.setBaseNameToDumper("cohesive elements", "cohesive_elements_output");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
...
model.dump("cohesive elements");
\end{cpp}
\subsubsection{Fragmentation data}
Whenever the \code{SolidMechanicsModelCohesive} is used, it is
possible to dump additional data about the fragments that get formed
in the simulation both in serial and parallel. This task is carried
out by the \code{FragmentManager} class, that takes care of computing
the following quantities for each fragment:
\begin{itemize}
\item index;
\item mass;
\item moments of inertia;
\item velocity;
\item number of elements.
\end{itemize}
These computations can be realized at once by calling the function
\code{computeAllData}, or individually by calling the other public
functions of the class. The data can be dumped to be visualized in
Paraview, or can be accessed within the simulation. An example of
usage is:
\begin{cpp}
FragmentManager fragment_manager(model);
fragment_manager.buildAllData();
...
model.addDumpField("fragments"); // this field contains the indices
model.addDumpField("fragments mass");
model.addDumpField("moments of inertia");
model.addDumpField("elements per fragment");
...
- for (UInt step = 1; step <= total_steps; ++step) {
+ for (Int step = 1; step <= total_steps; ++step) {
...
fragment_manager.buildAllData();
model.dump();
}
...
const Array<Real> & fragment_velocities = fragment_manager.getVelocity();
...
\end{cpp}
At the end of this example the velocities of the fragments are
accessed with a reference to a \code{const Array<Real>}. The size of
this array is the number of fragments, and its number of components is
the spatial dimension in this case.
\subsection{Advanced dumping}
\subsubsection{Arbitrary fields}
In addition to the predetermined fields from the models and materials, the user
can add any data to a dumper as long as the support is the same. That is to say
data that have the size of the full mesh on if the dumper is dumping the mesh,
or of the size of an element group if it is a filtered dumper.
For this the easiest is to use the ``external'' fields register functions\index{I\/O!addDumpFieldExternal}
The simple case force nodal and elemental data are to pass directly the data
container itself if it as the good size.
\begin{itemize}
\item For nodal fields :
\begin{cpp}
template<class T>
addDumpFieldExternal(const std::string & field_name,
const Array<T> & field);
\end{cpp}
It is assumed that the array as the same size as the number of nodes in the mesh
\begin{cpp}
Array<T> nodal_data(nb_nodes, nb_component);
mesh.addDumpFieldExternal("my_field", nodal_data);
\end{cpp}
\item For elemental fields :
\begin{cpp}
template<class T>
addDumpFieldExternal(const std::string & field_name,
const ElementTypeMapArray<T> & field);
\end{cpp}
It is assumed that the arrays in the map have the same sizes as the element numbers in the mesh for element types of dimension \code{spatial\_dimension}.
\begin{cpp}
ElementTypeMapArray<Real> elem_data;
elem_data.initialize(mesh,
_nb_component = 1,
_with_nb_element = true);
mesh.addDumpFieldExternal("my_field", elem_data);
\end{cpp}
\end{itemize}
If some changes have to be applied on the data as for example a padding for
\code{ParaView} vectors, this can be done by using the
field interface.
\begin{cpp}
mesh.addDumpFieldExternal(const std::string & field_name,
std::shared<dumpers::Field> & field);
\end{cpp}
All these functions use the default dumper registered in the mesh but also have the \code{ToDumper} variation with the dumper name specified.
For example:
\begin{cpp}
mesh.addDumpFieldExternalToDumper("cohesive elements",
"my_field",
my_field);
\end{cpp}
An example of code presenting this interface is present in the
\shellcode{\examplesdir/io/dumper}. This interface is part of the
\code{Dumpable} class from which the \code{Mesh} inherits.
\subsubsection{Creating a new dumper}
You can also create you own dumpers, \akantu uses a third-party library in order
to write the output files, \code{IOHelper}. \akantu supports the \code{ParaView}
format and a Text format defined by \code{IOHelper}.
This two files format are handled by the classes
\code{DumperParaview}\index{I\/O!DumperParaview} and
\code{DumperText}\index{I\/O!DumperText}.
In order to use them you can instantiate on of this object in your code. This
dumper have a simple interface. You can register a mesh
\code{registerMesh}\index{I\/O!registerMesh},
\code{registerFilteredMesh}\index{I\/O!registerFilteredMesh} or a field,
\code{registerField}\index{I\/O!registerField}.
An example of code presenting this low level interface is present in the
\shellcode{\examplesdir/io/dumper}. The different types of \code{Field} that can
be created are present in the source folder \shellcode{src/io/dumper}.
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "manual"
%%% End:
diff --git a/doc/manual/manual-solidmechanicsmodel.tex b/doc/manual/manual-solidmechanicsmodel.tex
index f0fe8760f..5e321d550 100644
--- a/doc/manual/manual-solidmechanicsmodel.tex
+++ b/doc/manual/manual-solidmechanicsmodel.tex
@@ -1,1138 +1,1138 @@
\chapter{Solid Mechanics Model\index{SolidMechanicsModel}\label{sect:smm}}
The solid mechanics model is a specific implementation of the
\code{Model} interface dedicated to handle the equations of motion or
equations of equilibrium. The model is created for a given mesh. It
will create its own \code{FEEngine} object to compute the interpolation,
gradient, integration and assembly operations. A
\code{SolidMechanicsModel} object can simply be created like this:
\begin{cpp}
SolidMechanicsModel model(mesh);
\end{cpp}
where \code{mesh} is the mesh for which the equations are to be
solved. A second parameter called \code{spatial\_dimension} can be
added after \code{mesh} if the spatial dimension of the problem is
different than that of the mesh.
This model contains at least the following six \code{Arrays}:
\begin{description}
\item[blocked\_dofs] contains a Boolean value for each degree of
freedom specifying whether that degree is blocked or not. A
Dirichlet boundary condition can be prescribed by setting the
\textbf{blocked\_dofs} value of a degree of freedom to \code{true}.
A Neumann boundary condition can be applied by setting the
\textbf{blocked\_dofs} value of a degree of freedom to \code{false}.
The \textbf{displacement}, \textbf{velocity} and
\textbf{acceleration} are computed for all degrees of freedom for
which the \textbf{blocked\_dofs} value is set to \code{false}. For
the remaining degrees of freedom, the imposed values (zero by
default after initialization) are kept.
\item[displacement] contains the displacements of all degrees of
freedom. It can be either a computed displacement for free degrees
of freedom or an imposed displacement in case of blocked ones
($\vec{u}$ in the following).
\item[velocity] contains the velocities of all degrees of freedom. As
\textbf{displacement}, it contains computed or imposed velocities
depending on the nature of the degrees of freedom ($\dot{\vec{u}}$
in the following).
\item[acceleration] contains the accelerations of all degrees of
freedom. As \textbf{displacement}, it contains computed or imposed
accelerations depending on the nature of the degrees of freedom
($\ddot{\vec{u}}$ in the following).
\item[external\_force] contains the external forces applied on the nodes
($\vec{f}_{\st{ext}}$ in the following).
\item[internal\_force] contains the internal forces on the nodes
($\vec{f}_{\st{int}}$ in the following).
\end{description}
Some examples to help to understand how to use this model will be
presented in the next sections.
\section{Model Setup}
\subsection{Setting Initial Conditions \label{sect:smm:initial_condition}}
For a unique solution of the equations of motion, initial
displacements and velocities for all degrees of freedom must be
specified:
\begin{eqnarray}
\vec{u}(t=0) = \vec{u}_0\\
\dot{\vec u}(t=0) =\vec{v}_0
\end{eqnarray} The solid mechanics model can be initialized as
follows:
\begin{cpp}
model.initFull()
\end{cpp}
This function initializes the internal arrays and sets them to
zero. Initial displacements and velocities that are not equal to zero
can be prescribed by running a loop over the total number of
nodes. Here, the initial displacement in $x$-direction and the
initial velocity in $y$-direction for all nodes is set to $0.1$ and $1$,
respectively.
\begin{cpp}
auto & disp = model.getDisplacement();
auto & velo = model.getVelocity();
-for (UInt node = 0; node < mesh.getNbNodes(); ++node) {
+for (Int node = 0; node < mesh.getNbNodes(); ++node) {
disp(node, 0) = 0.1;
velo(node, 1) = 1.;
}
\end{cpp}
\subsection{Setting Boundary Conditions\label{sect:smm:boundary}}
This section explains how to impose Dirichlet or Neumann boundary
conditions. A Dirichlet boundary condition specifies the values that
the displacement needs to take for every point $x$ at the boundary
($\Gamma_u$) of the problem domain (Fig.~\ref{fig:smm:boundaries}):
\begin{equation}
\vec{u} = \bar{\vec u} \quad \forall \vec{x}\in
\Gamma_{u}
\end{equation}
A Neumann boundary condition imposes the value of the gradient of the
solution at the boundary $\Gamma_t$ of the problem domain
(Fig.~\ref{fig:smm:boundaries}):
\begin{equation}
\vec{t} = \mat{\sigma} \vec{n} = \bar{\vec t} \quad
\forall \vec{x}\in \Gamma_{t}
\end{equation}
\begin{figure} \centering
\def\svgwidth{0.5\columnwidth}
\input{figures/problemDomain.pdf_tex}
\caption{Problem domain $\Omega$ with boundary in three
dimensions. The Dirchelet and the Neumann regions of the boundary
are denoted with $\Gamma_u$ and $\Gamma_t$,
respecitvely.\label{fig:smm:boundaries}}
\label{fig:problemDomain}
\end{figure}
Different ways of imposing these boundary conditions exist. A basic
way is to loop over nodes or elements at the boundary and apply local
values. A more advanced method consists of using the notion of the
boundary of the mesh. In the following both ways are presented.
Starting with the basic approach, as mentioned, the Dirichlet boundary
conditions can be applied by looping over the nodes and assigning the
required values. Figure~\ref{fig:smm:dirichlet_bc} shows a beam with a
fixed support on the left side. On the right end of the beam, a load
is applied. At the fixed support, the displacement has a given
value. For this example, the displacements in both the $x$ and the
$y$-direction are set to zero. Implementing this displacement boundary
condition is similar to the implementation of initial displacement
conditions described above. However, in order to impose a displacement
boundary condition for all time steps, the corresponding nodes need to
be marked as boundary nodes using the function \code{blocked}. While,
in order to impose a load on the right side, the nodes are not marked.
The detail codes are shown as follows:
\begin{cpp}
auto & blocked = model.getBlockedDOFs();
const auto & pos = mesh.getNodes();
-UInt nb_nodes = mesh.getNbNodes();
+Int nb_nodes = mesh.getNbNodes();
-for (UInt node = 0; node < nb_nodes; ++node) {
+for (Int node = 0; node < nb_nodes; ++node) {
if(Math::are_float_equal(pos(node, _x), 0)) {
blocked(node, _x) = true; // block dof in x-direction
blocked(node, _y) = true; // block dof in y-direction
disp(node, _x) = 0.; // fixed displacement in x-direction
disp(node, _y) = 0.; // fixed displacement in y-direction
} else if (Math::are_float_equal(pos(node, _y), 0)) {
blocked(node, _x) = false; // unblock dof in x-direction
forces(node, _x) = 10.; // force in x-direction
}
}
\end{cpp}
\begin{figure}[!htb]
\centering
\includegraphics[scale=0.4]{figures/dirichlet}
\caption{Beam with fixed support and load.\label{fig:smm:dirichlet_bc}}
\end{figure}
For the more advanced approach, one needs the notion of a boundary in
the mesh. Therefore, the boundary should be created before boundary
condition functors can be applied. Generally the boundary can be
specified from the mesh file or the geometry. For the first case, the
function \code{createGroupsFromMeshData} is called. This function
can read any types of mesh data which are provided in the mesh
file. If the mesh file is created with Gmsh, the function takes one
input strings which is either \code{tag\_0}, \code{tag\_1} or
\code{physical\_names}. The first two tags are assigned by Gmsh to
each element which shows the physical group that they belong to. In
Gmsh, it is also possible to consider strings for different groups of
elements. These elements can be separated by giving a string
\code{physical\_names} to the function
\code{createGroupsFromMeshData}:
\begin{cpp}
mesh.createGroupsFromMeshData<std::string>("physical_names").
\end{cpp}
Boundary conditions support can also be
created from the geometry by calling
\code{createBoundaryGroupFromGeometry}. This function gathers all the
elements on the boundary of the geometry.
To apply the required boundary conditions, the function \code{applyBC}
needs to be called on a \code{SolidMechanicsModel}. This function
gets a Dirichlet or Neumann functor and a string which specifies the
desired boundary on which the boundary conditions is to be
applied. The functors specify the type of conditions to apply. Three
built-in functors for Dirichlet exist: \code{FlagOnly, FixedValue,}
and \code{IncrementValue}. The functor \code{FlagOnly} is used if a
point is fixed in a given direction. Therefore, the input parameter to
this functor is only the fixed direction. The \code{FixedValue}
functor is used when a displacement value is applied in a fixed
direction. The \code{IncrementValue} applies an increment to the
displacement in a given direction. The following code shows the
utilization of three functors for the top, bottom and side surface of
the mesh which were already defined in the Gmsh file:
\begin{cpp}
model.applyBC(BC::Dirichlet::FixedValue(13.0, _y), "Top");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "Bottom");
model.applyBC(BC::Dirichlet::IncrementValue(13.0, _x), "Side");
\end{cpp}
To apply a Neumann boundary condition, the applied traction or stress
should be specified before. In case of specifying the traction on the
surface, the functor \code{FromTraction} of Neumann boundary
conditions is called. Otherwise, the functor \code{FromStress} should
be called which gets the stress tensor as an input parameter.
\begin{cpp}
Vector<Real> surface_traction = {0., 0., 1.};
auto surface_stress(3, 3) = Matrix<Real>::eye(3);
model.applyBC(BC::Neumann::FromTraction(surface_traction), "Bottom");
model.applyBC(BC::Neumann::FromStress(surface_stress), "Top");
\end{cpp}
If the boundary conditions need to be removed during the simulation, a
functor is called from the Neumann boundary condition to free those
boundary conditions from the desired boundary.
\begin{cpp}
model.applyBC(BC::Neumann::FreeBoundary(), "Side");
\end{cpp}
User specified functors can also be implemented. A full example for
setting both initial and boundary conditions can be found in
\shellcode{\examplesdir/boundary\_conditions.cc}. The problem solved
in this example is shown in Fig.~\ref{fig:smm:bc_and_ic}. It consists
of a plate that is fixed with movable supports on the left and bottom
side. On the right side, a traction, which increases linearly with the
number of time steps, is applied. The initial displacement and
velocity in $x$-direction at all free nodes is zero and two
respectively.
\begin{figure}[!htb]
\centering
\includegraphics[scale=0.8]{figures/bc_and_ic_example}
\caption{Plate on movable supports.\label{fig:smm:bc_and_ic}}
\end{figure}
As it is mentioned in Section \ref{sect:common:groups}, node and
element groups can be used to assign the boundary conditions. A
generic example is given below with a Dirichlet boundary condition.
\begin{cpp}
// create a node group
NodeGroup & node_group = mesh.createNodeGroup("nodes_fix");
/*
fill the node group with the nodes you want
*/
// create an element group using the existing node group
mesh.createElementGroupFromNodeGroup("el_fix", "nodes_fix", spatial_dimension-1);
// boundary condition can be applied using the element group name
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "el_fix");
\end{cpp}
\subsection{Material Selector\label{sect:smm:materialselector}}
If the user wants to assign different materials to different
finite elements groups in \akantu, a material selector has to be
used. By default, \akantu assigns the first valid material in the
material file to all elements present in the model (regular continuum
materials are assigned to the regular elements and cohesive materials
are assigned to cohesive elements or element facets).
To assign different materials to specific elements, mesh data
information such as tag information or specified physical names can be
used. \code{MeshDataMaterialSelector} class uses this information to
assign different materials. With the proper physical name or tag name
and index, different materials can be assigned as demonstrated in the
examples below.
\begin{cpp}
auto mat_selector = std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names", model);
model.setMaterialSelector(mat_selector);
\end{cpp}
In this example the physical names specified in a GMSH geometry file will by
used to match the material names in the input file.
Another example would be to use the first (\code{tag\_0}) or the second
(\code{tag\_1}) tag associated to each elements in the mesh:
\begin{cpp}
- auto mat_selector = std::make_shared<MeshDataMaterialSelector<UInt>>(
+ auto mat_selector = std::make_shared<MeshDataMaterialSelector<Int>>(
"tag_1", model, first_index);
model.setMaterialSelector(*mat_selector);
\end{cpp}
where \code{first\_index} (default is 1) is the value of \code{tag\_1} that will
be associated to the first material in the material input file. The following
values of the tag will be associated with the following materials.
There are four different material selectors pre-defined in
\akantu. \code{MaterialSelector} and \code{DefaultMaterialSelector} is
used to assign a material to regular elements by default. For the
regular elements, as in the example above,
\code{MeshDataMaterialSelector} can be used to assign different
materials to different elements.
Apart from the \akantu's default material selectors, users can always
develop their own classes in the main code to tackle various
multi-material assignment situations.
% An application of \code{DefaultMaterialCohesiveSelector} and usage in
% a customly generated material selector class can be seen in
% \shellcode{\examplesdir/cohesive\_element/cohesive\_extrinsic\_IG\_TG/cohesive\_extrinsic\_IG\_TG.cc}.
\IfFileExists{manual-cohesive_elements_insertion.tex}{\input{manual-cohesive_elements_insertion}}{}
\section{Static Analysis\label{sect:smm:static}}
The \code{SolidMechanicsModel} class can handle different analysis
methods, the first one being presented is the static case. In this
case, the equation to solve is
\begin{equation}
\label{eqn:smm:static} \mat{K} \vec{u} =
\vec{f}_{\st{ext}}
\end{equation}
where $\mat{K}$ is the global stiffness matrix, $\vec{u}$ the
displacement vector and $\vec{f}_{\st{ext}}$ the vector of external
forces applied to the system.
To solve such a problem, the static solver of the
\code{SolidMechanicsModel}\index{SolidMechanicsModel} object is used.
First, a model has to be created and initialized. To create the
model, a mesh (which can be read from a file) is needed, as explained
in Section~\ref{sect:common:mesh}. Once an instance of a
\code{SolidMechanicsModel} is obtained, the easiest way to initialize
it is to use the \code{initFull}\index{SolidMechanicsModel!initFull}
method by giving the \code{SolidMechanicsModelOptions}. These options
specify the type of analysis to be performed and whether the materials
should be initialized with \code{initMaterials} or not.
\begin{cpp}
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _static);
\end{cpp}
Here, a static analysis is chosen by passing the argument
\code{\_static} to the method. By default, the Boolean for no
initialization of the materials is set to false, so that they are
initialized during the \code{initFull}. The method \code{initFull}
also initializes all appropriate vectors to zero. Once the model is
created and initialized, the boundary conditions can be set as
explained in Section~\ref{sect:smm:boundary}. Boundary conditions
will prescribe the external forces for some free degrees of freedom
$\vec{f}_{\st{ext}}$ and displacements for some others. At this point
of the analysis, the function
\code{solveStep}\index{SolidMechanicsModel!solveStep} can be called:
\begin{cpp}
model.solveStep<_scm_newton_raphson_tangent_modified, SolveConvergenceCriteria::_residual>(1e-4, 1);
\end{cpp}
This function is templated by the solving method and the convergence
criterion and takes two arguments: the tolerance and the maximum
number of iterations (100 by default), which are $\num{1e-4}$ and $1$ for this example. The
modified Newton-Raphson method is chosen to solve the system. In this
method, the equilibrium equation (\ref{eqn:smm:static}) is modified in
order to apply a Newton-Raphson convergence algorithm:
\begin{align}\label{eqn:smm:static-newton-raphson}
\mat{K}^{i+1}\delta\vec{u}^{i+1} &= \vec{r} \\
&= \vec{f}_{\st{ext}} -\vec{f}_{\st{int}}\\
&= \vec{f}_{\st{ext}} - \mat{K}^{i} \vec{u}^{i}\\
\vec{u}^{i+1} &= \vec{u}^{i} + \delta\vec{u}^{i+1}~,\nonumber
\end{align}
where $\delta\vec{u}$ is the increment of displacement to be added
from one iteration to the other, and $i$ is the Newton-Raphson
iteration counter. By invoking the \code{solveStep} method in the
first step, the global stiffness matrix $\mat{K}$ from
Equation~(\ref{eqn:smm:static}) is automatically assembled. A
Newton-Raphson iteration is subsequently started, $\mat{K}$ is updated
according to the displacement computed at the previous iteration and
one loops until the forces are balanced (\code{SolveConvergenceCriteria::\_residual}), \ie
$||\vec{r}|| < \mbox{\code{SolveConvergenceCriteria::\_residual}}$. One can also iterate
until the increment of displacement is zero (\code{SolveConvergenceCriteria::\_increment})
which also means that the equilibrium is found. For a linear elastic
problem, the solution is obtained in one iteration and therefore the
maximum number of iterations can be set to one. But for a non-linear
case, one needs to iterate as long as the norm of the residual exceeds
the tolerance threshold and therefore the maximum number of iterations
has to be higher, e.g. $100$:
\begin{cpp}
model.solveStep<_scm_newton_raphson_tangent_modified,SolveConvergenceCriteria::_residual>(1e-4, 100)
\end{cpp}
At the end of the analysis, the final solution is stored in the
\textbf{displacement} vector. A full example of how to solve a static
problem is presented in the code \code{\examplesdir/static/static.cc}.
This example is composed of a 2D plate of steel, blocked with rollers
on the left and bottom sides as shown in Figure \ref{fig:smm:static}.
The nodes from the right side of the sample are displaced by $0.01\%$
of the length of the plate.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1.05]{figures/static}
\caption{Numerical setup\label{fig:smm:static}}
\end{figure}
The results of this analysis is depicted in
Figure~\ref{fig:smm:implicit:static_solution}.
\begin{figure}[!htb]
\centering
\includegraphics[width=.7\linewidth]{figures/static_analysis}
\caption{Solution of the static analysis. Left: the initial
condition, right: the solution (deformation magnified 50 times)}
\label{fig:smm:implicit:static_solution}
\end{figure}
\subsection{Static implicit analysis with dynamic insertion of cohesive elements}
In order to solve problems with the extrinsic cohesive method in the
static implicit solution scheme, the function \code{solveStepCohesive}
has to be used:
\begin{cpp}
model.solveStepCohesive<_scm_newton_raphson_tangent, SolveConvergenceCriteria::_increment>(1e-13, error, 25, false, 1e5, true);
\end{cpp}
in which the arguments are: tolerance, error, max\_iteration,
load\_reduction, tol\_increase\_factor, do\_not\_factorize. This
function, first applies the Newton-Raphson procedure to solve the
problem. Then, it calls the method \code{checkCohesiveStress} to
check if cohesive elements have to be inserted. Since the approach is
implicit, only one element is added, the most stressed one (see
Section \ref{extrinsic_insertion}). After insertion, the
Newton-Raphson procedure is applied again to solve the same
incremental loading step, with the new inserted cohesive element. The
procedure loops in this way since no new cohesive elements have to be
inserted. At that point, the solution is saved, and the simulation
can advance to the next incremental loading step. In case the
convergence is not reached, the obtained solution is not saved and the
simulation return to the main file with the error given by the
solution saved in the argument of the function \emph{error}. In this
way, the user can intervene in the simulation in order to find anyhow
convergence. A possibility is, for instance, to reduce the last
incremental loading step. The variable \emph{load\_reduction} can be
used to identify if the load has been already reduced or not. At the
same time, with the variable \emph{tol\_increase\_factor} it is
possible to increase the tolerance by a factor defined by the user in
the main file, in order to accept a solution even with an error bigger
than the tolerance set at the beginning. It is possible to increase
the tolerance only in the phase of loading reduction, i.e., when
load\_reduction = true. A not converged solution is never saved. In
case the convergence is not reached even after the loading reduction
procedure, the displacement field is not updated and remains the one
of the last converged incremental steps. Also, cohesive elements are
inserted only if convergence is reached. An example of the extrinsic
cohesive method in the static implicit solution scheme is presented in
\shellcode{\examplesdir/cohesive\_element/cohesive\_extrinsic\_implicit}.
\section{Dynamic Methods} \label{sect:smm:Dynamic_methods}
Different ways to solve the equations of motion are implemented in the
solid mechanics model. The complete equations that should be solved
are:
\begin{equation}
\label{eqn:equation-motion}
\mat{M}\ddot{\vec{u}} +
\mat{C}\dot{\vec{u}} + \mat{K}\vec{u} = \vec{f}_{\st{ext}}~,
\end{equation}
where $\mat{M}$, $\mat{C}$ and $\mat{K}$ are the mass,
damping and stiffness matrices, respectively.
In the previous section, it has already been discussed how to solve this
equation in the static case, where $\ddot{\vec{u}} = \dot{\vec{u}} = 0$. Here
the method to solve this equation in the general case will be presented. For
this purpose, a time discretization has to be specified. The most common
discretization method in solid mechanics is the Newmark-$\beta$ method, which is
also the default in \akantu.
For the Newmark-$\beta$ method, (\ref{eqn:equation-motion}) becomes a
system of three equations (see \cite{curnier92a} \cite{hughes-83a} for
more details):
\begin{align}
\mat{M} \ddot{\vec{u}}_{n+1} + \mat{C}\dot{\vec{u}}_{n+1} + \mat{K} \vec{u}_{n+1} &={\vec{f}_{\st{ext}}}_{\, n+1}
\label{eqn:equation-motion-discret} \\
\vec{u}_{n+1} &=\vec{u}_{n} + \left(1 - \alpha\right) \Delta t \dot{\vec{u}}_{n} +
\alpha \Delta t \dot{\vec{u}}_{n+1} + \left(\frac{1}{2} -
\alpha\right) \Delta t^2
\ddot{\vec{u}}_{n} \label{eqn:finite-difference-1}\\
\dot{\vec{u}}_{n+1} &= \dot{\vec{u}}_{n} + \left(1 - \beta\right)
\Delta t \ddot{\vec{u}}_{n} + \beta \Delta t
\ddot{\vec{u}}_{n+1} \label{eqn:finite-difference-2}
\end{align}
In these new equations, $\ddot{\vec{u}}_{n}$, $\dot{\vec{u}}_{n}$ and
$\vec{u}_{n}$ are the approximations of $\ddot{\vec{u}}(t_n)$,
$\dot{\vec{u}}(t_n)$ and $\vec{u}(t_n)$.
Equation~(\ref{eqn:equation-motion-discret}) is the equation of motion
discretized in space (finite-element discretization), and equations
(\ref{eqn:finite-difference-1}) and (\ref{eqn:finite-difference-2})
are discretized in both space and time (Newmark discretization). The
$\alpha$ and $\beta$ parameters determine the stability and the
accuracy of the algorithm. Classical values for $\alpha$ and $\beta$
are usually $\beta = 1/2$ for no numerical damping and $0 < \alpha <
1/2$.
\begin{center}
\begin{tabular}{cll}
\toprule
$\alpha$ & Method ($\beta = 1/2$) & Type\\
\midrule
$0$ & central difference & explicit\\
$1/6$ & Fox-Goodwin (royal road) &implicit\\
$1/3$ & Linear acceleration &implicit\\
$1/2$ & Average acceleration (trapezoidal rule)& implicit\\
\bottomrule
\end{tabular}
\end{center}
The solution of this system of equations,
(\ref{eqn:equation-motion-discret})-(\ref{eqn:finite-difference-2}) is
split into a predictor and a corrector system of equations. Moreover,
in the case of a non-linear equations, an iterative algorithm such as
the Newton-Raphson method is applied. The system of equations can be
written as:
\begin{enumerate}
\item \textit{Predictor:}
\begin{align}
\vec{u}_{n+1}^{0} &= \vec{u}_{n} + \Delta t
\dot{\vec{u}}_{n} + \frac{\Delta t^2}{2} \ddot{\vec{u}}_{n} \\
\dot{\vec{u}}_{n+1}^{0} &= \dot{\vec{u}}_{n} + \Delta t
\ddot{\vec{u}}_{n} \\
\ddot{\vec{u}}_{n+1}^{0} &= \ddot{\vec{u}}_{n}
\end{align}
\item \textit{Solve:}
\begin{align}
\left(c \mat{M} + d \mat{C} + e \mat{K}_{n+1}^i\right)
\vec{w} = {\vec{f}_{\st{ext}}}_{\,n+1} - {\vec{f}_{\st{int}}}_{\,n+1}^i -
\mat{C} \dot{\vec{u}}_{n+1}^i - \mat{M} \ddot{\vec{u}}_{n+1}^i = \vec{r}_{n+1}^i
\end{align}
\item \textit{Corrector:}
\begin{align}
\ddot{\vec{u}}_{n+1}^{i+1} &= \ddot{\vec{u}}_{n+1}^{i} +c \vec{w} \\
\dot{\vec{u}}_{n+1}^{i+1} &= \dot{\vec{u}}_{n+1}^{i} + d\vec{w} \\
\vec{u}_{n+1}^{i+1} &= \vec{u}_{n+1}^{i} + e \vec{w}
\end{align}
\end{enumerate}
where $i$ is the Newton-Raphson iteration counter and $c$, $d$ and $e$
are parameters depending on the method used to solve the equations
\begin{center}
\begin{tabular}{lcccc}
\toprule
& $\vec{w}$ & $e$ & $d$ & $c$\\
\midrule
in acceleration &$ \delta\ddot{\vec{u}}$ & $\alpha \beta\Delta t^2$ &$\beta \Delta t$ &$1$\\
in velocity & $ \delta\dot{\vec{u}}$& $\alpha\Delta t$ & $1$ & $\frac{1}{\beta \Delta t}$\\
in displacement &$\delta\vec{u}$ & $ 1$ & $\frac{1}{\alpha \Delta t}$ & $\frac{1}{\alpha \beta \Delta t^2}$\\
\bottomrule
\end{tabular}
\end{center}
% \note{If you want to use the implicit solver \akantu should be compiled at
% least with one sparse matrix solver such as Mumps\cite{mumps}.}
\subsection{Implicit Time Integration}
To solve a problem with an implicit time integration scheme, first a
\code{SolidMechanicsModel} object has to be created and initialized.
Then the initial and boundary conditions have to be set. Everything
is similar to the example in the static case
(Section~\ref{sect:smm:static}), however, in this case the implicit
dynamic scheme is selected at the initialization of the model.
\begin{cpp}
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _implicit_dynamic);
/*Boundary conditions see Section ~ %\ref{sect:smm:boundary}% */
\end{cpp}
Because a dynamic simulation is conducted, an integration time step
$\Delta t$ has to be specified. In the case of implicit simulations,
\akantu implements a trapezoidal rule by default. That is to say
$\alpha = 1/2$ and $\beta = 1/2$ which is unconditionally
stable. Therefore the value of the time step can be chosen arbitrarily
within reason. \index{SolidMechanicsModel!setTimeStep}
\begin{cpp}
model.setTimeStep(time_step);
\end{cpp}
Since the system has to be solved for a given amount of time steps, the
method \code{solveStep()}, (which has already been used in the static
example in Section~\ref{sect:smm:static}), is called inside a time
loop:
\begin{cpp}
/// time loop
Real time = 0.;
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 100);
solver.set("threshold", 1e-12);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
-for (UInt s = 1; time <max_time; ++s, time += time_step) {
+for (Int s = 1; time <max_time; ++s, time += time_step) {
model.solveStep();
}
\end{cpp}
An example of solid mechanics with an implicit time integration scheme
is presented in
\shellcode{\examplesdir/implicit/implicit\_dynamic.cc}. This example
consists of a 3D beam of
$\SI{10}{\metre}\,\times\,\SI{1}{\metre}\,\times\,\SI{1}{\metre}$
blocked on one side and is on a roller on the other side. A constant
force of \SI{5}{\kilo\newton} is applied in its middle.
Figure~\ref{fig:smm:implicit:dynamic} presents the geometry of this
case. The material used is a fictitious linear elastic material with a
density of \SI{1000}{\kilo\gram\per\cubic\metre}, a Young's Modulus of
\SI{120}{\mega\pascal} and Poisson's ratio of $0.3$. These values
were chosen to simplify the analytical solution.
An approximation of the dynamic response of the middle point of the
beam is given by:
\begin{equation}
\label{eqn:smm:implicit}
u\left(\frac{L}{2}, t\right)
= \frac{1}{\pi^4} \left(1 - cos\left(\pi^2 t\right) +
\frac{1}{81}\left(1 - cos\left(3^2 \pi^2 t\right)\right) +
\frac{1}{625}\left(1 - cos\left(5^2 \pi^2 t\right)\right)\right)
\end{equation}
\begin{figure}[!htb]
\centering
\includegraphics[scale=.6]{figures/implicit_dynamic}
\caption{Numerical setup}
\label{fig:smm:implicit:dynamic}
\end{figure}
Figure \ref{fig:smm:implicit:dynamic_solution} presents the deformed
beam at 3 different times during the simulation: time steps 0, 1000 and
2000.
\begin{figure}[!htb]
\centering
\setlength{\unitlength}{0.1\textwidth}
\begin{tikzpicture}
\node[above right] (img) at (0,0)
{\includegraphics[width=.6\linewidth]{figures/dynamic_analysis}};
\node[left] at (0pt,20pt) {$0$}; \node[left] at (0pt,60pt) {$1000$};
\node[left] at (0pt,100pt) {$2000$};
\end{tikzpicture}
\caption{Deformed beam at 3 different times (displacement are
magnified by a factor 10).}
\label{fig:smm:implicit:dynamic_solution}
\end{figure}
\subsection{Explicit Time Integration}
\label{ssect:smm:expl-time-integr}
The explicit dynamic time integration scheme is based on the
Newmark-$\beta$ scheme with $\alpha=0$ (see equations
\ref{eqn:equation-motion-discret}-\ref{eqn:finite-difference-2}). In
\akantu, $\beta$ is defaults to $\beta=1/2$, see section
\ref{sect:smm:Dynamic_methods}.
The initialization of the simulation is similar to the static and
implicit dynamic version. The model is created from the
\code{SolidMechanicsModel} class. In the initialization, the explicit
scheme is selected using the \code{\_explicit\_lumped\_mass} constant.
\begin{cpp}
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _explicit_lumped_mass);
\end{cpp}
\index{SolidMechanicsModel!initFull}
\note{Writing \code{model.initFull()} or \code{model.initFull();} is
equivalent to use the \code{\_explicit\_lumped\_mass} keyword, as this
is the default case.}
The explicit time integration scheme implemented in \akantu uses a
lumped mass matrix $\mat{M}$ (reducing the computational cost). This
matrix is assembled by distributing the mass of each element onto its
nodes. The resulting $\mat{M}$ is therefore a diagonal matrix stored
in the \textbf{mass} vector of the model.
The explicit integration scheme is conditionally stable. The time step
has to be smaller than the stable time step which is obtained in
\akantu as follows:
\begin{cpp}
critical_time_step = model.getStableTimeStep();
\end{cpp} \index{SolidMechanicsModel!StableTimeStep}
The stable time step corresponds to the time the fastest wave (the compressive
wave) needs to travel the characteristic length of the mesh:
\begin{equation}
\label{eqn:smm:explicit:stabletime}
\Delta t_{\st{crit}} = \frac{\Delta x}{c}
\end{equation}
where $\Delta x$ is a characteristic length (\eg the inradius in the case of
linear triangle element) and $c$ is the celerity of the fastest wave in the
material. It is generally the compressive wave of celerity
$c = \sqrt{\frac{2 \mu + \lambda}{\rho}}$, $\mu$ and $\lambda$ are the first and
second Lame's coefficients and $\rho$ is the density. However, it is recommended
to impose a time step that is smaller than the stable time step, for instance,
by multiplying the stable time step by a safety factor smaller than one.
\begin{cpp}
const Real safety_time_factor = 0.8;
Real applied_time_step = critical_time_step * safety_time_factor;
model.setTimeStep(applied_time_step);
\end{cpp}
\index{SolidMechanicsModel!setTimeStep} The initial displacement and
velocity fields are, by default, equal to zero if not given
specifically by the user (see \ref{sect:smm:initial_condition}).
Like in implicit dynamics, a time loop is used in which the
displacement, velocity and acceleration fields are updated at each
time step. The values of these fields are obtained from the
Newmark$-\beta$ equations with $\beta=1/2$ and $\alpha=0$. In \akantu
these computations at each time step are invoked by calling the
function \code{solveStep}:
\begin{cpp}
-for (UInt s = 1; (s-1)*applied_time_step < total_time; ++s) {
+for (Int s = 1; (s-1)*applied_time_step < total_time; ++s) {
model.solveStep();
}
\end{cpp} \index{SolidMechanicsModel!solveStep}
The method
\code{solveStep} wraps the four following functions:
\begin{itemize}
\item \code{model.explicitPred()} allows to compute the displacement
field at $t+1$ and a part of the velocity field at $t+1$, denoted by
$\vec{\dot{u}^{\st{p}}}_{n+1}$, which will be used later in the method
\code{model.explicitCorr()}. The equations are:
\begin{align}
\vec{u}_{n+1} &= \vec{u}_{n} + \Delta t
\vec{\dot{u}}_{n} + \frac{\Delta t^2}{2} \vec{\ddot{u}}_{n}\\
\vec{\dot{u}^{\st{p}}}_{n+1} &= \vec{\dot{u}}_{n} + \Delta t
\vec{\ddot{u}}_{n}
\label{eqn:smm:explicit:onehalfvelocity}
\end{align}
\item \code{model.updateResidual()} and
\code{model.updateAcceleration()} compute the acceleration increment
$\delta \vec{\ddot{u}}$:
\begin{equation}
\left(\mat{M} + \frac{1}{2} \Delta t \mat{C}\right)
\delta \vec{\ddot{u}} = \vec{f_{\st{ext}}} - \vec{f}_{\st{int}\, n+1}
- \mat{C} \vec{\dot{u}^{\st{p}}}_{n+1} - \mat{M} \vec{\ddot{u}}_{n}
\end{equation}
\note{The internal force $\vec{f}_{\st{int}\, n+1}$ is computed from
the displacement $\vec{u}_{n+1}$ based on the constitutive law.}
\item \code{model.explicitCorr()} computes the velocity and
acceleration fields at $t+1$:
\begin{align}
\vec{\dot{u}}_{n+1} &= \vec{\dot{u}^{\st{p}}}_{n+1} + \frac{\Delta t}{2}
\delta \vec{\ddot{u}} \\ \vec{\ddot{u}}_{n+1} &=
\vec{\ddot{u}}_{n} + \delta \vec{\ddot{u}}
\end{align}
\end{itemize}
The use of an explicit time integration scheme is illustrated by the
example:\par
\noindent \shellcode{\examplesdir/explicit/explicit\_dynamic.cc}\par
\noindent This example models the propagation of a wave in a steel beam. The
beam and the applied displacement in the $x$ direction are shown in
Figure~\ref{fig:smm:explicit}.
\begin{figure}[!htb] \centering
\begin{tikzpicture}
\coordinate (c) at (0,2);
\draw[shift={(c)},thick, color=blue] plot [id=x, domain=-5:5, samples=50] ({\x, {(40 * sin(0.1*pi*3*\x) * exp(- (0.1*pi*3*\x)*(0.1*pi*3*\x) / 4))}});
\draw[shift={(c)},-latex] (-6,0) -- (6,0) node[right, below] {$x$};
\draw[shift={(c)},-latex] (0,-0.7) -- (0,1) node[right] {$u$};
\draw[shift={(c)}] (-0.1,0.6) node[left] {$A$}-- (1.5,0.6);
\coordinate (l) at (0,0.6);
\draw[shift={(0,-0.7)}] (-5, 0) -- (5,0) -- (5, 1) -- (-5, 1) -- cycle;
\draw[shift={(l)}, latex-latex] (-5,0)-- (5,0) node [midway, above] {$L$};
\draw[shift={(l)}] (5,0.2)-- (5,-0.2);
\draw[shift={(l)}] (-5,0.2)-- (-5,-0.2);
\coordinate (h) at (5.3,-0.7);
\draw[shift={(h)}, latex-latex] (0,0)-- (0,1) node [midway, right] {$h$};
\draw[shift={(h)}] (-0.2,1)-- (0.2,1);
\draw[shift={(h)}] (-0.2,0)-- (0.2,0);
\end{tikzpicture}
\caption{Numerical setup \label{fig:smm:explicit}}
\end{figure}
The length and height of the beam are $L=\SI{10}{\metre}$ and
$h = \SI{1}{\metre}$, respectively. The material is linear elastic,
homogeneous and isotropic (density:
\SI{7800}{\kilo\gram\per\cubic\metre}, Young's modulus:
\SI{210}{\giga\pascal} and Poisson's ratio: $0.3$). The imposed
displacement follow a Gaussian function with a maximum amplitude of $A = \SI{0.01}{\meter}$. The
potential, kinetic and total energies are computed. The safety factor
is equal to $0.8$.
\input{manual-constitutive-laws}
\section{Adding a New Constitutive Law}\index{Material!create a new
material}
There are several constitutive laws in \akantu as described in the
previous Section~\ref{sect:smm:CL}. It is also possible to use a
user-defined material for the simulation. These materials are referred
to as local materials since they are local to the example of the user
and not part of the \akantu library. To define a new local material,
two files (\code {material\_XXX.hh} and \code{material\_XXX.cc}) have
to be provided where \code{XXX} is the name of the new material. The
header file \code {material\_XXX.hh} defines the interface of your
custom material. Its implementation is provided in the
\code{material\_XXX.cc}. The new law must inherit from the
\code{Material} class or any other existing material class. It is
therefore necessary to include the interface of the parent material
in the header file of your local material and indicate the inheritance
in the declaration of the class:
\begin{cpp}
/* ---------------------------------------------------------------------- */
#include "material.hh"
/* ---------------------------------------------------------------------- */
#ifndef __AKANTU_MATERIAL_XXX_HH__
#define __AKANTU_MATERIAL_XXX_HH__
namespace akantu {
class MaterialXXX : public Material {
/// declare here the interface of your material
};
\end{cpp}
In the header file the user also needs to declare all the members of the new
material. These include the parameters that a read from the
material input file, as well as any other material parameters that will be
computed during the simulation and internal variables.
In the following the example of adding a new damage material will be
presented. In this case the parameters in the material will consist of the
Young's modulus, the Poisson coefficient, the resistance to damage and the
damage threshold. The material will then from these values compute its Lam\'{e}
coefficients and its bulk modulus. Furthermore, the user has to add a new
internal variable \code{damage} in order to store the amount of damage at each
quadrature point in each step of the simulation. For this specific material the
member declaration inside the class will look as follows:
\begin{cpp}
class LocalMaterialDamage : public Material {
/// declare constructors/destructors here
/// declare methods and accessors here
/* -------------------------------------------------------------------- */
/* Class Members */
/* -------------------------------------------------------------------- */
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real);
private:
/// the young modulus
Real E;
/// Poisson coefficient
Real nu;
/// First Lame coefficient
Real lambda;
/// Second Lame coefficient (shear modulus)
Real mu;
/// resistance to damage
Real Yd;
/// damage threshold
Real Sd;
/// Bulk modulus
Real kpa;
/// damage internal variable
InternalField<Real> damage;
};
\end{cpp}
In order to enable to print the material parameters at any point in
the user's example file using the standard output stream by typing:
\begin{cpp}
-for (UInt m = 0; m < model.getNbMaterials(); ++m)
+for (Int m = 0; m < model.getNbMaterials(); ++m)
std::cout << model.getMaterial(m) << std::endl;
\end{cpp}
the standard output stream operator has to be redefined. This should be done at the end of the header file:
\begin{cpp}
class LocalMaterialDamage : public Material {
/// declare here the interace of your material
}:
/* ---------------------------------------------------------------------- */
/* inline functions */
/* ---------------------------------------------------------------------- */
/// standard output stream operator
inline std::ostream & operator <<(std::ostream & stream, const LocalMaterialDamage & _this)
{
_this.printself(stream);
return stream;
}
\end{cpp}
However, the user still needs to register the material parameters that
should be printed out. The registration is done during the call of the
constructor. Like all definitions the implementation of the
constructor has to be written in the \code{material\_XXX.cc}
file. However, the declaration has to be provided in the
\code{material\_XXX.hh} file:
\begin{cpp}
class LocalMaterialDamage : public Material {
/* -------------------------------------------------------------------- */
/* Constructors/Destructors */
/* -------------------------------------------------------------------- */
public:
LocalMaterialDamage(SolidMechanicsModel & model, const ID & id = "");
};
\end{cpp}
The user can now define the implementation of the constructor in the
\code{material\_XXX.cc} file:
\begin{cpp}
/* ---------------------------------------------------------------------- */
#include "local_material_damage.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* ---------------------------------------------------------------------- */
LocalMaterialDamage::LocalMaterialDamage(SolidMechanicsModel & model,
const ID & id) :
Material(model, id),
damage("damage", *this) {
AKANTU_DEBUG_IN();
this->registerParam("E", E, 0., _pat_parsable, "Young's modulus");
this->registerParam("nu", nu, 0.5, _pat_parsable, "Poisson's ratio");
this->registerParam("lambda", lambda, _pat_readable, "First Lame coefficient");
this->registerParam("mu", mu, _pat_readable, "Second Lame coefficient");
this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
this->registerParam("Yd", Yd, 50., _pat_parsmod);
this->registerParam("Sd", Sd, 5000., _pat_parsmod);
damage.initialize(1);
AKANTU_DEBUG_OUT();
}
\end{cpp}
During the intializer list the reference to the model and the material id are
assigned and the constructor of the internal field is called. Inside the scope
of the constructor the internal values have to be initialized and the
parameters, that should be printed out, are registered with the function:
\code{registerParam}\index{Material!registerParam}:
\begin{cpp}
void registerParam(name of the parameter (key in the material file),
member variable,
default value (optional parameter),
access permissions,
description);
\end{cpp}
The available access permissions are as follows:
\begin{itemize}
\item \code{\_pat\_internal}: Parameter can only be output when the material is printed.
\item \code{\_pat\_writable}: User can write into the parameter. The parameter is output when the material is printed.
\item \code{\_pat\_readable}: User can read the parameter. The parameter is output when the material is printed.
\item \code{\_pat\_modifiable}: Parameter is writable and readable.
\item \code{\_pat\_parsable}: Parameter can be parsed, \textit{i.e.} read from the input file.
\item \code{\_pat\_parsmod}: Parameter is modifiable and parsable.
\end{itemize}
In order to implement the new constitutive law the user needs to
specify how the additional material parameters, that are not
defined in the input material file, should be calculated. Furthermore,
it has to be defined how stresses and the stable time step should be
computed for the new local material. In the case of implicit
simulations, in addition, the computation of the tangent stiffness needs
to be defined. Therefore, the user needs to redefine the following
functions of the parent material:
\begin{cpp}
void initMaterial();
// for explicit and implicit simulations void
computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
// for implicit simulations
void computeTangentStiffness(ElementType el_type,
Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost);
// for explicit and implicit simulations
Real getStableTimeStep(Real h, const Element & element);
\end{cpp}
In the following a detailed description of these functions is provided:
\begin{itemize}
\item \code{initMaterial}:~ This method is called after the material
file is fully read and the elements corresponding to each material
are assigned. Some of the frequently used constant parameters are
calculated in this method. For example, the Lam\'{e} constants of
elastic materials can be considered as such parameters.
\item \code{computeStress}:~ In this method, the stresses are
computed based on the constitutive law as a function of the strains of the
quadrature points. For example, the stresses for the elastic
material are calculated based on the following formula:
\begin{equation}
\label{eqn:smm:constitutive_elastic}
\mat{\sigma } =\lambda\mathrm{tr}(\mat{\varepsilon})\mat{I}+2 \mu \mat{\varepsilon}
\end{equation}
Therefore, this method contains a loop on all quadrature points
assigned to the material using the two macros:\par
\code{MATERIAL\_STRESS\_QUADRATURE\_POINT\_LOOP\_BEGIN}\par
\code{MATERIAL\_STRESS\_QUADRATURE\_POINT\_LOOP\_END}
\begin{cpp}
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(element_type);
// sigma <- f(grad_u)
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
\end{cpp}
\note{The strain vector in \akantu contains the values of $\nabla
\vec{u}$, i.e. it is really the \emph{displacement gradient},}
\item \code{computeTangentStiffness}:~ This method is called when
the tangent to the stress-strain curve is desired (see Fig \ref
{fig:smm:AL:K}). For example, it is called in the implicit solver
when the stiffness matrix for the regular elements is assembled
based on the following formula:
\begin{equation}
\label{eqn:smm:constitutive_elasc} \mat{K }
=\int{\mat{B^T}\mat{D(\varepsilon)}\mat{B}}
\end{equation}
Therefore, in this method, the \code{tangent} matrix (\mat{D}) is
computed for a given strain.
\note{ The \code{tangent} matrix is a $4^{th}$ order tensor which is
stored as a matrix in Voigt notation.}
\begin{figure}[!htb]
\begin{center}
\includegraphics[width=0.4\textwidth,keepaspectratio=true]{figures/tangent.pdf}
\caption{Tangent to the stress-strain curve.}
\label{fig:smm:AL:K}
\end{center}
\end{figure}
\item \code{getCelerity}:~The stability criterion of the explicit integration scheme depend on the fastest wave celerity~\eqref{eqn:smm:explicit:stabletime}. This celerity depend on the material, and therefore the value of this velocity should be defined in this method for each new material. By default, the fastest wave speed is the compressive wave whose celerity can be defined in~\code{getPushWaveSpeed}.
\end{itemize}
Once the declaration and implementation of the new material has been
completed, this material can be used in the user's example by including the header file:
\begin{cpp}
#include "material_XXX.hh"
\end{cpp}
For existing materials, as mentioned in Section~\ref{sect:smm:CL}, by
default, the materials are initialized inside the method
\code{initFull}. If a local material should be used instead, the
initialization of the material has to be postponed until the local
material is registered in the model. Therefore, the model is
initialized with the boolean for skipping the material initialization
equal to true:
\begin{cpp}
/// model initialization
model.initFull(_analysis_method = _explicit_lumped_mass);
\end{cpp}
Once the model has been initialized, the local material needs
to be registered in the model:
\begin{cpp}
model.registerNewCustomMaterials<XXX>("name_of_local_material");
\end{cpp}
Only at this point the material can be initialized:
\begin{cpp}
model.initMaterials();
\end{cpp}
A full example for adding a new damage law can be found in
\shellcode{\examplesdir/new\_material}.
\subsection{Adding a New Non-Local Constitutive Law}\index{Material!create a new non-local material}
In order to add a new non-local material we first have to add the local constitutive law in \akantu (see above). We can then add the non-local version of the constitutive law by adding the two files (\code{material\_XXX\_non\_local.hh} and \code{material\_XXX\_non\_local.cc}) where \code{XXX} is the name of the corresponding local material. The new law must inherit from the two classes, non-local parent class, such as the \code{MaterialNonLocal} class, and from the local version of the constitutive law, \textit{i.e.} \code{MaterialXXX}. It is therefore necessary to include the interface of those classes in the header file of your custom material and indicate the inheritance in the declaration of the class:
\begin{cpp}
/* ---------------------------------------------------------------------- */
#include "material_non_local.hh" // the non-local parent
#include "material_XXX.hh"
/* ---------------------------------------------------------------------- */
#ifndef __AKANTU_MATERIAL_XXX_HH__
#define __AKANTU_MATERIAL_XXX_HH__
namespace akantu {
class MaterialXXXNonLocal : public MaterialXXX,
public MaterialNonLocal {
/// declare here the interface of your material
};
\end{cpp}
As members of the class we only need to add the internal fields to store the non-local quantities, which are obtained from the averaging process:
\begin{cpp}
/* -------------------------------------------------------------------------- */
/* Class members */
/* -------------------------------------------------------------------------- *
protected:
InternalField<Real> grad_u_nl;
\end{cpp}
The following four functions need to be implemented in the non-local material:
\begin{cpp}
/// initialization of the material
void initMaterial();
/// loop over all element and invoke stress computation
virtual void computeNonLocalStresses(GhostType ghost_type);
/// compute stresses after local quantities have been averaged
virtual void computeNonLocalStress(ElementType el_type, GhostType ghost_type)
/// compute all local quantities
void computeStress(ElementType el_type, GhostType ghost_type);
\end{cpp}
In the intialization of the non-local material we need to register the local quantity for the averaging process. In our example the internal field \emph{grad\_u\_nl} is the non-local counterpart of the gradient of the displacement field (\emph{grad\_u\_nl}):
\begin{cpp}
void MaterialXXXNonLocal::initMaterial() {
MaterialXXX::initMaterial();
MaterialNonLocal::initMaterial();
/// register the non-local variable in the manager
this->model->getNonLocalManager().registerNonLocalVariable(this->grad_u.getName(), this->grad_u_nl.getName(), spatial_dimension * spatial_dimension);
}
\end{cpp}
The function to register the non-local variable takes as parameters the name of the local internal field, the name of the non-local counterpart and the number of components of the field we want to average.
In the \emph{computeStress} we now need to compute all the quantities we want to average. We can then write a loop for the stress computation in the function \emph{computeNonLocalStresses} and then provide the constitutive law on each integration point in the function \emph{computeNonLocalStress}.
%%% Local Variables: %%% mode: latex %%% TeX-master: "manual" %%% End:
diff --git a/doc/manual/manual-structuralmechanicsmodel.tex b/doc/manual/manual-structuralmechanicsmodel.tex
index bcf89724e..2703454f4 100644
--- a/doc/manual/manual-structuralmechanicsmodel.tex
+++ b/doc/manual/manual-structuralmechanicsmodel.tex
@@ -1,250 +1,250 @@
\chapter{Structural Mechanics Model}
Static structural mechanics problems can be handled using the
class \code{StructuralMechanicsModel}. So far, \akantu provides 2D and 3D
Bernoulli beam elements \cite{frey2009}. This model is instantiated for a given
\code{Mesh}, as for the \code{SolidMechanicsModel}. The model will create its own \code{FEEngine} object to
compute the interpolation, gradient, integration and assembly
operations. The \code{StructuralMechanicsModel} constructor is called
in the following way:
\begin{cpp}
StructuralMechanicsModel model(mesh, spatial_dimension);
\end{cpp}
where \code{mesh} is a \code{Mesh} object defining the structure for
which the equations of statics are to be solved, and
\code{spatial\_dimension} is the dimensionality of the problem. If
\code{spatial\_dimension} is omitted, the problem is assumed to have
the same dimensionality as the one specified by the mesh.
\note[\ 1]{Dynamic computations are not supported to date.}
\note[\ 2]{Structural meshes are created and loaded as described in
Section~\ref{sect:common:mesh} with \code{\_miot\_gmsh\_struct} instead of \code{\_miot\_gmsh}:}
\begin{cpp}
Mesh mesh;
mesh.read("structural_mesh.msh", _miot_gmsh_struct);
\end{cpp}
This model contains at least the following \code{Arrays}:
\begin{description}
\item[blocked\_dofs] contains a Boolean value for each degree of
freedom specifying whether that degree is blocked or not. A
Dirichlet boundary condition can be prescribed by setting the
\textbf{blocked\_dofs} value of a degree of freedom to
\code{true}. The \textbf{displacement} is computed for all degrees
of freedom for which the \textbf{blocked\_dofs} value is set to
\code{false}. For the remaining degrees of freedom, the imposed
values (zero by default after initialization) are kept.
\item[displacement\_rotation] contains the generalized displacements
(\textit{i.e.} displacements and rotations) of all degrees of freedom. It can be
either a computed displacement for free degrees of freedom or an
imposed displacement in case of blocked ones ($\vec{u}$ in the
following).
\item[external\_force] contains the generalized external forces (forces
and moments) applied to the nodes ($\vec{f_{\st{ext}}}$ in the
following).
\item[internal\_force] contains the generalized internal forces (forces
and moments) applied to the nodes ($\vec{f_{\st{int}}}$ in the
following).
\end{description}
An example to help understand how to use this model will be presented in the
next section.
\section{Model Setup}
\label{sec:structMechMod:setup}
\subsection{Initialization}
The easiest way to initialize the structural mechanics model is:
\begin{cpp}
model.initFull();
\end{cpp}
The method \code{initFull} computes the shape functions, initializes
the internal vectors mentioned above and allocates the memory for the
stiffness matrix, unlike the solid mechanics model, its default argument is \code{\_static}.
Material properties are defined using the \code{StructuralMaterial}
structure described in
Table~\ref{tab:structMechMod:strucMaterial}. Such a definition could,
for instance, look like
\begin{cpp}
StructuralMaterial mat1;
mat.E=3e10;
mat.I=0.0025;
mat.A=0.01;
\end{cpp}
\begin{table}[htb] \centering
\begin{tabular}{cl}
\toprule
Field & Description \\
\midrule
\code{E} & Young's modulus \\
\code{A} & Cross section area \\
\code{I} & Second cross sectional moment of inertia (for 2D elements)\\
\code{Iy} & \code{I} around beam $y$--axis (for 3D elements)\\
\code{Iz} & \code{I} around beam $z$--axis (for 3D elements)\\
\code{GJ} & Polar moment of inertia of beam cross section (for 3D elements)\\
\bottomrule
\end{tabular}
\caption{Material properties for structural elements defined in
the class \code{StructuralMaterial}.}
\label{tab:structMechMod:strucMaterial}
\end{table}
Materials can be added to the model's \code{element\_material} vector using
\begin{cpp}
model.addMaterial(mat1);
\end{cpp}
They are successively numbered and then assigned to specific elements.
\begin{cpp}
-for (UInt i = 0; i < nb_element_mat_1; ++i) {
+for (Int i = 0; i < nb_element_mat_1; ++i) {
model.getElementMaterial(_bernoulli_beam_2)(i,0) = 1;
}
\end{cpp}
\subsection{Setting Boundary Conditions}\label{sect:structMechMod:boundary}
As explained before, the Dirichlet boundary conditions are applied through the
array \textbf{blocked\_dofs}. Two options exist to define Neumann conditions.
If a nodal force is applied, it has to be directly set in the array
\textbf{force\_momentum}. For loads distributed along the beam length, the
method \code{computeForcesFromFunction} integrates them into nodal forces. The
method takes as input a function describing the distribution of loads along the
beam and a functor \code{BoundaryFunctionType} specifing if the function is
expressed in the local coordinates (\code{\_bft\_traction\_local}) or in the
global system of coordinates (\code{\_bft\_traction}).
\begin{cpp}
static void lin_load(double * position, double * load,
- Real * normal, UInt surface_id){
+ Real * normal, Int surface_id){
memset(load,0,sizeof(Real)*3);
load[1] = position[0]*position[0]-250;
}
int main(int argc, char *argv[]){
...
model.computeForcesFromFunction<_bernoulli_beam_2>(lin_load,
_bft_traction_local);
...}
\end{cpp}
\section{Static Analysis\label{sect:structMechMod:static}}
The \code{StructuralMechanicsModel} class can perform static analyses
of structures. In this case, the equation to solve is the same as for
the \code{SolidMechanicsModel} used for static analyses
\begin{equation}\label{eqn:structMechMod:static}
\mat{K} \vec{u} = \vec{f_{\st{ext}}}~,
\end{equation}
where $\mat{K}$ is the global stiffness matrix, $\vec{u}$ the
generalized displacement vector and $\vec{f_{\st{ext}}}$ the vector of
generalized external forces applied to the system.
To solve such a problem, the static solver of the
\code{StructuralMechanicsModel}\index{StructuralMechanicsModel} object
is used. First a model has to be created and initialized.
\begin{cpp}
StructuralMechanicsModel model(mesh);
model.initFull();
\end{cpp}
\begin{itemize}
\item \code{model.initFull} initializes all internal vectors to zero.
\end{itemize}
Once the model is created and initialized, the boundary conditions can
be set as explained in Section~\ref{sect:structMechMod:boundary}.
Boundary conditions will prescribe the external forces or moments for
the free degrees of freedom $\vec{f_{\st{ext}}}$ and displacements or
rotations for the others. To completely define the system represented
by equation (\ref{eqn:structMechMod:static}), the global stiffness
matrix $\mat{K}$ must be assembled.
\index{StructuralMechanicsModel!assembleStiffnessMatrix}
\begin{cpp}
model.assembleStiffnessMatrix();
\end{cpp}
The computation of the static equilibrium is performed using the same
Newton-Raphson algorithm as described in
Section~\ref{sect:smm:static}.
\note{To date,
\code{StructuralMechanicsModel} handles only constitutively and
geometrically linear problems, the algorithm is therefore guaranteed
to converge in two iterations.}
\begin{cpp}
model.updateResidual();
model.solve();
\end{cpp}
\index{StructuralMechanicsModel!updateResidual}
\index{StructuralMechanicsModel!solve}
\begin{itemize}
\item \code{model.updateResidual} assembles the internal forces and
removes them from the external forces.
\item \code{model.solve} solves the Equation (\ref{eqn:structMechMod:static}).
The \textbf{increment} vector of the model will contain the new
increment of displacements, and the \textbf{displacement\_rotation}
vector is also updated to the new displacements.
\end{itemize}
%At the end of the analysis, the final solution is stored in the
%\textbf{displacement} vector. A full example of how to solve a
%structural mechanics problem is presented in the code
%\shellcode{\examplesdir/structural\_mechanics/test\_structural\_mechanics\_model\_bernoulli\_beam\_2\_exemple\_1\_1.cc}.
%This example is composed of a 2D beam, clamped at the left end and
%supported by two rollers as shown in Figure
%\ref{fig:structMechMod:exem1_1}. The problem is defined by the
%applied load $q=\SI{6}{\kilo\newton\per\metre}$, moment $\bar{M} =
%\SI{3.6}{\kilo\newton\metre}$, moments of inertia $I_1 =
%\SI{250\,000}{\power{\centi\metre}{4}}$ and $I_2 =
%\SI{128\,000}{\power{\centi\metre}{4}}$ and lengths $L_1 =
%\SI{10}{\metre}$ and $L_2 = \SI{8}{\metre}$. The resulting
%rotations at node two and three are $ \varphi_2 = 0.001\,167\
%\mbox{and}\ \varphi_3 = -0.000\,771.$
At the end of the analysis, the final solution is stored in the
\textbf{displacement\_rotation} vector. A full example of how to
solve a structural mechanics problem is presented in the code
\shellcode{\examplesdir/structural\_mechanics/bernoulli\_beam\_2\_example.cc}.
This example is composed of a 2D beam, clamped at the left end and
supported by two rollers as shown in Figure
\ref{fig:structMechMod:exem1_1}. The problem is defined by the
applied load $q=\SI{6}{\kilo\newton\per\metre}$, moment $\bar{M} =
\SI{3.6}{\kilo\newton\metre}$, moments of inertia $I_1 =
\SI{250\,000}{\centi\metre\tothe{4}}$ and $I_2 =
\SI{128\,000}{\centi\metre\tothe{4}}$ and lengths $L_1 =
\SI{10}{\metre}$ and $L_2 = \SI{8}{\metre}$. The resulting
rotations at node two and three are $ \varphi_2 = 0.001\,167\
\mbox{and}\ \varphi_3 = -0.000\,771.$
\begin{figure}[htb]
\centering
\includegraphics[scale=1.1]{figures/beam_example}
\caption{2D beam example}
\label{fig:structMechMod:exem1_1}
\end{figure}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "manual"
%%% End:
diff --git a/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc b/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
index e3d3bede3..f5ce41455 100644
--- a/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
+++ b/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
@@ -1,97 +1,97 @@
/**
* @file python_user_defined_bc.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Tue Sep 08 2020
*
* @brief user define boundary condition example
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <iostream>
#include <pybind11/embed.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
using namespace akantu;
class PYBIND11_EXPORT SineBoundary : public BC::Dirichlet::DirichletFunctor {
public:
SineBoundary(Real amplitude, Real phase) {
py_module = py::module::import("boundary_condition");
py_sin_boundary = py_module.attr("SinBoundary")(amplitude, phase);
}
public:
inline void operator()(__attribute__((unused)) UInt node,
Vector<bool> & flags, Vector<Real> & primal,
const Vector<Real> & coord) const {
py_sin_boundary.attr("compute")(primal, coord, flags);
}
protected:
py::object py_sin_boundary;
py::module py_module;
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
py::scoped_interpreter guard{};
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("fine_mesh.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull();
/// boundary conditions
Vector<Real> traction(2, 0.2);
SineBoundary sin_boundary(.2, 10.);
model.applyBC(sin_boundary, "Fixed_x");
model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Fixed_y");
model.applyBC(BC::Neumann::FromTraction(traction), "Traction");
// output a paraview file with the boundary conditions
model.setBaseName("plate");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("external_force");
model.addDumpField("blocked_dofs");
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc b/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
index e31557e7d..50e1067dd 100644
--- a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
+++ b/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
@@ -1,90 +1,90 @@
/**
* @file user_defined_bc.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Wed Feb 06 2019
*
* @brief example of boundary conditions
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
class SineBoundary : public BC::Dirichlet::DirichletFunctor {
public:
SineBoundary(Real amp, Real phase, BC::Axis ax = _x)
: DirichletFunctor(ax), amplitude(amp), phase(phase) {}
public:
inline void operator()(__attribute__((unused)) UInt node,
Vector<bool> & flags, Vector<Real> & primal,
const Vector<Real> & coord) const {
DIRICHLET_SANITY_CHECK;
flags(axis) = true;
primal(axis) = -amplitude * std::sin(phase * coord(1));
}
protected:
Real amplitude;
Real phase;
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("fine_mesh.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull();
/// boundary conditions
- Vector<Real> traction(2, 0.2);
+ Vector<Real, 2> traction{.2, .2};
model.applyBC(SineBoundary(.2, 10., _x), "Fixed_x");
model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Fixed_y");
model.applyBC(BC::Neumann::FromTraction(traction), "Traction");
// output a paraview file with the boundary conditions
model.setBaseName("plate");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("external_force");
model.addDumpField("blocked_dofs");
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc b/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc
index 899e6b598..062bb31fe 100644
--- a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc
+++ b/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc
@@ -1,129 +1,132 @@
/**
* @file cohesive_extrinsic.cc
*
* @author Zineb Fouad <zineb.fouad@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue May 08 2012
* @date last modification: Wed Feb 06 2019
*
* @brief Cohesive element examples in extrinsic
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 2;
- const UInt max_steps = 1000;
+ const Int spatial_dimension = 2;
+ const Int max_steps = 1000;
Mesh mesh(spatial_dimension);
mesh.read("triangle.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = true);
Real time_step = model.getStableTimeStep() * 0.05;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
CohesiveElementInserter & inserter = model.getElementInserter();
inserter.setLimit(_y, 0.30, 0.20);
model.updateAutomaticInsertion();
Array<Real> & position = mesh.getNodes();
Array<Real> & velocity = model.getVelocity();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & displacement = model.getDisplacement();
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (UInt n = 0; n < nb_nodes; ++n) {
- if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
+ for (Int n = 0; n < nb_nodes; ++n) {
+ if (position(n, 1) > 0.99 || position(n, 1) < -0.99) {
boundary(n, 1) = true;
+ }
- if (position(n, 0) > 0.99 || position(n, 0) < -0.99)
+ if (position(n, 0) > 0.99 || position(n, 0) < -0.99) {
boundary(n, 0) = true;
+ }
}
model.setBaseName("extrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("internal_force");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.dump();
/// initial conditions
Real loading_rate = 0.5;
Real disp_update = loading_rate * time_step;
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
velocity(n, 1) = loading_rate * position(n, 1);
}
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
/// update displacement on extreme nodes
- for (UInt n = 0; n < nb_nodes; ++n) {
- if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
+ for (Int n = 0; n < nb_nodes; ++n) {
+ if (position(n, 1) > 0.99 || position(n, 1) < -0.99) {
displacement(n, 1) += disp_update * position(n, 1);
+ }
}
model.checkCohesiveStress();
model.solveStep();
if (s % 10 == 0) {
model.dump();
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
}
Real Ed = model.getEnergy("dissipated");
Real Edt = 200 * std::sqrt(2);
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
index d992c288b..ead1f6ee0 100644
--- a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
+++ b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
@@ -1,154 +1,154 @@
/**
* @file cohesive_extrinsic_ig_tg.cc
*
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Jan 19 2021
*
* @brief Cohesive element examples in extrinsic with 2 different bulk
* materials
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
class Velocity : public BC::Dirichlet::DirichletFunctor {
public:
explicit Velocity(SolidMechanicsModel & model, Real vel, BC::Axis ax = _x)
: DirichletFunctor(ax), model(model), vel(vel) {
disp = vel * model.getTimeStep();
}
public:
inline void operator()(UInt node, Vector<bool> & /*flags*/,
Vector<Real> & disp,
const Vector<Real> & coord) const {
Real sign = std::signbit(coord(axis)) ? -1. : 1.;
disp(axis) += sign * this->disp;
model.getVelocity()(node, axis) = sign * vel;
}
private:
SolidMechanicsModel & model;
Real vel, disp;
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 2;
- const UInt max_steps = 1000;
+ const Int spatial_dimension = 2;
+ const Int max_steps = 1000;
Mesh mesh(spatial_dimension);
mesh.read("square.msh");
SolidMechanicsModelCohesive model(mesh);
MaterialCohesiveRules rules{{{"btop", "bbottom"}, "tg_cohesive"},
{{"btop", "btop"}, "ig_cohesive"},
{{"bbottom", "bbottom"}, "ig_cohesive"}};
/// model initialization
auto cohesive_material_selector =
std::make_shared<MaterialCohesiveRulesSelector>(model, rules);
auto bulk_material_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
auto && current_selector = model.getMaterialSelector();
cohesive_material_selector->setFallback(bulk_material_selector);
bulk_material_selector->setFallback(current_selector);
model.setMaterialSelector(cohesive_material_selector);
model.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = true);
Real time_step = model.getStableTimeStep() * 0.05;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
auto & position = mesh.getNodes();
auto & velocity = model.getVelocity();
model.applyBC(BC::Dirichlet::FlagOnly(_y), "top");
model.applyBC(BC::Dirichlet::FlagOnly(_y), "bottom");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "left");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "right");
model.setBaseName("extrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("internal_force");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("material_index");
model.dump();
/// initial conditions
Real loading_rate = 0.1;
// bar_height = 2
Real VI = loading_rate * 2 * 0.5;
for (auto && data : zip(make_view(position, spatial_dimension),
make_view(velocity, spatial_dimension))) {
std::get<1>(data) = loading_rate * std::get<0>(data);
}
model.dump();
Velocity vely(model, VI, _y);
Velocity velx(model, VI, _x);
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.applyBC(vely, "top");
model.applyBC(vely, "bottom");
model.applyBC(velx, "left");
model.applyBC(velx, "right");
model.checkCohesiveStress();
model.solveStep();
if (s % 10 == 0) {
model.dump();
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
}
return 0;
}
diff --git a/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc b/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc
index a35ee428b..ad387bbe7 100644
--- a/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc
+++ b/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc
@@ -1,139 +1,139 @@
/**
* @file cohesive_intrinsic.cc
*
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue May 08 2012
* @date last modification: Fri Jul 19 2019
*
* @brief Cohesive element example in intrinsic
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "mesh_iterators.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
static void updateDisplacement(SolidMechanicsModelCohesive &,
const ElementGroup &, Real);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 2;
- const UInt max_steps = 350;
+ const Int spatial_dimension = 2;
+ const Int max_steps = 350;
Mesh mesh(spatial_dimension);
mesh.read("triangle.msh");
SolidMechanicsModelCohesive model(mesh);
model.getElementInserter().setLimit(_x, -0.26, -0.24);
/// model initialization
model.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = false);
Real time_step = model.getStableTimeStep() * 0.8;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
Array<bool> & boundary = model.getBlockedDOFs();
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int n = 0; n < nb_nodes; ++n) {
boundary(n, dim) = true;
}
}
model.setBaseName("intrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("external_force");
model.addDumpField("internal_force");
model.dump();
/// update displacement
auto && elements = mesh.createElementGroup("diplacement");
Vector<Real> barycenter(spatial_dimension);
for_each_element(
mesh,
[&](auto && el) {
mesh.getBarycenter(el, barycenter);
if (barycenter(_x) > -0.25)
elements.add(el, true);
},
_element_kind = _ek_regular);
Real increment = 0.01;
updateDisplacement(model, elements, increment);
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
updateDisplacement(model, elements, increment);
if (s % 1 == 0) {
model.dump();
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
}
Real Ed = model.getEnergy("dissipated");
Real Edt = 2 * sqrt(2);
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
static void updateDisplacement(SolidMechanicsModelCohesive & model,
const ElementGroup & group, Real increment) {
Array<Real> & displacement = model.getDisplacement();
for (auto && node : group.getNodeGroup().getNodes()) {
displacement(node, 0) += increment;
}
}
diff --git a/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc b/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc
index 67ab7ef25..8982a0eff 100644
--- a/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc
+++ b/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc
@@ -1,159 +1,159 @@
/**
* @file cohesive_contact_explicit_dynamic.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sat Jun 19 2021
* @date last modification: Wed Jun 23 2021
*
* @brief Contact mechanics test with cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "coupler_solid_cohesive_contact.hh"
#include "solid_mechanics_model_cohesive.hh"
#include "surface_selector.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize("material-cohesive.dat", argc, argv);
Real time_step{0.};
Real time_factor = 0.1;
UInt max_steps = 25000;
Real max_displacement = 1e-3;
Mesh mesh(spatial_dimension);
mesh.read("cohesive-contact.msh");
CouplerSolidCohesiveContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModelCohesive();
auto & contact = coupler.getContactMechanicsModel();
auto && material_selector =
std::make_shared<MeshDataMaterialCohesiveSelector>(solid);
material_selector->setFallback(solid.getMaterialSelector());
solid.setMaterialSelector(material_selector);
auto && surface_selector = std::make_shared<CohesiveSurfaceSelector>(mesh);
contact.getContactDetector().setSurfaceSelector(surface_selector);
coupler.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = true);
coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "sides");
time_step = solid.getStableTimeStep();
time_step *= time_factor;
std::cout << "Time Step = " << time_step << "s (" << time_step << "s)"
<< std::endl;
coupler.setTimeStep(time_step);
coupler.setBaseName("cohesive-contact-explicit-dynamic");
coupler.addDumpFieldVector("displacement");
coupler.addDumpFieldVector("velocity");
coupler.addDumpFieldVector("normals");
coupler.addDumpField("blocked_dofs");
coupler.addDumpField("grad_u");
coupler.addDumpField("stress");
coupler.addDumpField("gaps");
coupler.addDumpField("areas");
auto & velocity = solid.getVelocity();
auto & gaps = contact.getGaps();
Real damping_ratio = 0.99;
auto increment = max_displacement / max_steps;
for (auto i : arange(max_steps)) {
coupler.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "loading");
coupler.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "fixed");
coupler.solveStep();
solid.checkCohesiveStress();
// damping velocities only along the contacting zone
for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) {
auto & gap = std::get<0>(tuple);
auto & vel = std::get<1>(tuple);
if (gap > 0) {
vel *= damping_ratio;
}
}
// dumping energies
if (i % 1000 == 0) {
Real epot = solid.getEnergy("potential");
Real ekin = solid.getEnergy("kinetic");
std::cerr << i << "," << i * increment << "," << epot << "," << ekin
<< "," << epot + ekin << "," << std::endl;
}
if (i % 1000 == 0) {
coupler.dump();
}
}
for (auto i : arange(max_steps)) {
solid.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "loading");
solid.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "fixed");
coupler.solveStep();
coupler.checkCohesiveStress();
// damping velocities only along the contacting zone
for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) {
auto & gap = std::get<0>(tuple);
auto & vel = std::get<1>(tuple);
if (gap > 0) {
vel *= damping_ratio;
}
}
// dumping energies
if (i % 1000 == 0) {
Real epot = solid.getEnergy("potential");
Real ekin = solid.getEnergy("kinetic");
std::cerr << i << "," << i * increment << "," << epot << "," << ekin
<< "," << epot + ekin << "," << std::endl;
}
if (i % 1000 == 0) {
coupler.dump();
}
}
}
diff --git a/examples/contact_mechanics/contact_explicit_dynamic.cc b/examples/contact_mechanics/contact_explicit_dynamic.cc
index 6e6e36d5b..3956e9f91 100644
--- a/examples/contact_mechanics/contact_explicit_dynamic.cc
+++ b/examples/contact_mechanics/contact_explicit_dynamic.cc
@@ -1,132 +1,132 @@
/**
* @file contact_explicit_dynamic.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Sun Jun 06 2021
*
* @brief Contact mechanics example in dynamic
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "coupler_solid_contact.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "surface_selector.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize("material.dat", argc, argv);
Real time_step;
Real time_factor = 0.1;
UInt max_steps = 20000;
Real max_displacement = 5e-3;
Mesh mesh(spatial_dimension);
mesh.read("hertz.msh");
CouplerSolidContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModel();
auto & contact = coupler.getContactMechanicsModel();
auto && selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names", solid);
solid.setMaterialSelector(selector);
coupler.initFull(_analysis_method = _explicit_lumped_mass);
auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
contact.getContactDetector().setSurfaceSelector(surface_selector);
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "fixed");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "fixed");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "loading");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "symmetry");
time_step = solid.getStableTimeStep();
time_step *= time_factor;
std::cout << "Time Step = " << time_step << "s (" << time_step << "s)"
<< std::endl;
coupler.setTimeStep(time_step);
coupler.setBaseName("contact-explicit-dynamic");
coupler.addDumpFieldVector("displacement");
coupler.addDumpFieldVector("velocity");
coupler.addDumpFieldVector("normals");
coupler.addDumpFieldVector("contact_force");
coupler.addDumpFieldVector("external_force");
coupler.addDumpFieldVector("internal_force");
coupler.addDumpField("gaps");
coupler.addDumpField("areas");
coupler.addDumpField("blocked_dofs");
coupler.addDumpField("grad_u");
coupler.addDumpField("stress");
auto & velocity = solid.getVelocity();
auto & gaps = contact.getGaps();
Real damping_ratio = 0.99;
auto increment = max_displacement / max_steps;
for (auto i : arange(max_steps)) {
solid.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "loading");
coupler.solveStep();
// damping velocities only along the contacting zone
for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) {
auto & gap = std::get<0>(tuple);
auto & vel = std::get<1>(tuple);
if (gap > 0) {
vel *= damping_ratio;
}
}
// dumping energies
if (i % 1000 == 0) {
Real epot = solid.getEnergy("potential");
Real ekin = solid.getEnergy("kinetic");
std::cerr << i << "," << i * increment << "," << epot << "," << ekin
<< "," << epot + ekin << "," << std::endl;
}
if (i % 1000 == 0) {
coupler.dump();
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/contact_mechanics/contact_explicit_static.cc b/examples/contact_mechanics/contact_explicit_static.cc
index 9344e0306..d9bf2da2a 100644
--- a/examples/contact_mechanics/contact_explicit_static.cc
+++ b/examples/contact_mechanics/contact_explicit_static.cc
@@ -1,95 +1,95 @@
/**
* @file contact_explicit_static.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Wed Jun 23 2021
*
* @brief Example of contact mechanics in static
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "coupler_solid_contact.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "surface_selector.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize("material.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("hertz.msh");
CouplerSolidContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModel();
auto & contact = coupler.getContactMechanicsModel();
auto && selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names", solid);
solid.setMaterialSelector(selector);
coupler.initFull(_analysis_method = _static);
auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
contact.getContactDetector().setSurfaceSelector(surface_selector);
coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "fixed");
coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "fixed");
coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "loading");
coupler.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "symmetry");
coupler.setBaseName("contact-explicit-static");
coupler.addDumpFieldVector("displacement");
coupler.addDumpFieldVector("normals");
coupler.addDumpFieldVector("contact_force");
coupler.addDumpFieldVector("external_force");
coupler.addDumpFieldVector("internal_force");
coupler.addDumpField("gaps");
coupler.addDumpField("areas");
coupler.addDumpField("blocked_dofs");
coupler.addDumpField("grad_u");
coupler.addDumpField("stress");
auto max_steps = 100u;
for (auto _ [[gnu::unused]] : arange(max_steps)) {
auto increment = 1e-4;
coupler.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "loading");
coupler.solveStep();
coupler.dump();
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/embedded/embedded.cc b/examples/embedded/embedded.cc
index 6d3bdd6b0..e4b6ad4c1 100644
--- a/examples/embedded/embedded.cc
+++ b/examples/embedded/embedded.cc
@@ -1,99 +1,99 @@
/**
* @file embedded.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Tue Dec 01 2015
* @date last modification: Wed Feb 06 2019
*
* @brief Embedded solid mechanis model example
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "embedded_interface_model.hh"
#include "non_linear_solver.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt dim = 2;
+ const Int dim = 2;
// Loading the concrete mesh
Mesh mesh(dim);
mesh.read("concrete.msh");
// Loading the reinforcement mesh
Mesh reinforcement_mesh(dim, "reinforcement_mesh");
// Exception is raised because reinforcement
// mesh contains only segments, i.e. 1D elements
try {
reinforcement_mesh.read("reinforcement.msh");
} catch (debug::Exception & e) {
}
// Model creation
EmbeddedInterfaceModel model(mesh, reinforcement_mesh, dim);
model.initFull(EmbeddedInterfaceModelOptions(_static));
// Boundary conditions
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "XBlocked");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "YBlocked");
Vector<Real> force(dim);
force(0) = 0.0;
force(1) = -1.0;
model.applyBC(BC::Neumann::FromTraction(force), "Force");
// Dumping the concrete
model.setBaseName("concrete");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("external_force");
model.addDumpFieldVector("internal_force");
model.addDumpFieldTensor("stress");
// Dumping the reinforcement
model.setBaseNameToDumper("reinforcement", "reinforcement");
model.addDumpFieldTensorToDumper(
"reinforcement", "stress_embedded"); // dumping stress in reinforcement
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 1);
solver.set("threshold", 1e-6);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
model.solveStep();
// Dumping model
model.dump();
model.dump("reinforcement");
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/explicit/explicit_dynamic.cc b/examples/explicit/explicit_dynamic.cc
index 24a38bdcd..ffbe68e28 100644
--- a/examples/explicit/explicit_dynamic.cc
+++ b/examples/explicit/explicit_dynamic.cc
@@ -1,110 +1,110 @@
/**
* @file explicit_dynamic.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Jan 28 2021
*
* @brief Example of explicit dynamic simulation in solid mechanics
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
const Real pulse_width = 2.;
const Real A = 0.01;
Real time_step;
Real time_factor = 0.8;
- UInt max_steps = 1000;
+ Int max_steps = 1000;
Mesh mesh(spatial_dimension);
if (Communicator::getStaticCommunicator().whoAmI() == 0)
mesh.read("bar.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull(_analysis_method = _explicit_lumped_mass);
time_step = model.getStableTimeStep();
std::cout << "Time Step = " << time_step * time_factor << "s (" << time_step
<< "s)" << std::endl;
time_step *= time_factor;
model.setTimeStep(time_step);
/// boundary and initial conditions
Array<Real> & displacement = model.getDisplacement();
const Array<Real> & nodes = mesh.getNodes();
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
Real x = nodes(n) - 2;
// Sinus * Gaussian
Real L = pulse_width;
Real k = 0.1 * 2 * M_PI * 3 / L;
displacement(n) = A * sin(k * x) * exp(-(k * x) * (k * x) / (L * L));
}
std::ofstream energy;
energy.open("energy.csv");
energy << "id,rtime,epot,ekin,tot" << std::endl;
model.setBaseName("explicit_dynamic");
model.addDumpField("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("stress");
model.dump();
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
Real epot = model.getEnergy("potential");
Real ekin = model.getEnergy("kinetic");
energy << s << "," << s * time_step << "," << epot << "," << ekin << ","
<< epot + ekin << "," << std::endl;
if (s % 10 == 0)
std::cout << "passing step " << s << "/" << max_steps << std::endl;
model.dump();
}
energy.close();
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/heat_transfer/heat_transfer_dynamics_2d.cc b/examples/heat_transfer/heat_transfer_dynamics_2d.cc
index f6f2c3528..842c75d2a 100644
--- a/examples/heat_transfer/heat_transfer_dynamics_2d.cc
+++ b/examples/heat_transfer/heat_transfer_dynamics_2d.cc
@@ -1,104 +1,104 @@
/**
* @file heat_transfer_dynamics_2d.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun May 01 2011
* @date last modification: Fri Mar 16 2018
*
* @brief Example of heat transfer model
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "heat_transfer_model.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
// create mesh
Mesh mesh(spatial_dimension);
mesh.read("square.msh");
HeatTransferModel model(mesh);
// initialize everything
model.initFull();
// get stable time step
Real time_step = model.getStableTimeStep() * 0.8;
std::cout << "time step is:" << time_step << std::endl;
model.setTimeStep(time_step);
// boundary conditions
const Array<Real> & nodes = model.getFEEngine().getMesh().getNodes();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & temperature = model.getTemperature();
double length = 1.;
- UInt nb_nodes = model.getFEEngine().getMesh().getNbNodes();
- for (UInt i = 0; i < nb_nodes; ++i) {
+ auto nb_nodes = model.getFEEngine().getMesh().getNbNodes();
+ for (Int i = 0; i < nb_nodes; ++i) {
temperature(i) = 100.;
Real dx = nodes(i, 0) - length / 4.;
Real dy = 0.0;
Real dz = 0.0;
if (spatial_dimension > 1)
dy = nodes(i, 1) - length / 4.;
if (spatial_dimension == 3)
dz = nodes(i, 2) - length / 4.;
Real d = sqrt(dx * dx + dy * dy + dz * dz);
if (d < 0.1) {
boundary(i) = true;
temperature(i) = 300.;
}
}
model.setBaseName("heat_transfer_square2d");
model.addDumpField("temperature");
model.addDumpField("temperature_rate");
model.addDumpField("internal_heat_rate");
// main loop
int max_steps = 15000;
for (int i = 0; i < max_steps; i++) {
model.solveStep();
if (i % 100 == 0)
model.dump();
if (i % 10 == 0)
std::cout << "Step " << i << "/" << max_steps << std::endl;
}
std::cout << "\n\n Stable Time Step is : " << time_step << "\n \n"
<< std::endl;
return 0;
}
diff --git a/examples/heat_transfer/heat_transfer_dynamics_3d.cc b/examples/heat_transfer/heat_transfer_dynamics_3d.cc
index fa6490b60..0d043c1f2 100644
--- a/examples/heat_transfer/heat_transfer_dynamics_3d.cc
+++ b/examples/heat_transfer/heat_transfer_dynamics_3d.cc
@@ -1,110 +1,110 @@
/**
* @file heat_transfer_dynamics_3d.cc
*
* @author Srinivasa Babu Ramisetti <srinivasa.ramisetti@epfl.ch>
* @author Rui Wang <rui.wang@epfl.ch>
*
* @date creation: Sun May 01 2011
* @date last modification: Fri Mar 16 2018
*
* @brief Heat transfer model example in 3D
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "heat_transfer_model.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_io_msh.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
-UInt spatial_dimension = 3;
+Int spatial_dimension = 3;
ElementType type = _tetrahedron_4;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("cube.msh");
HeatTransferModel model(mesh);
// initialize everything
model.initFull();
// get and set stable time step
Real time_step = model.getStableTimeStep() * 0.8;
std::cout << "Stable Time Step is : " << time_step / .8 << std::endl;
std::cout << "time step is:" << time_step << std::endl;
model.setTimeStep(time_step);
/// boundary conditions
const Array<Real> & nodes = mesh.getNodes();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & temperature = model.getTemperature();
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
double length;
length = 1.;
- for (UInt i = 0; i < nb_nodes; ++i) {
+ for (Int i = 0; i < nb_nodes; ++i) {
temperature(i) = 100.;
// to insert a heat source
Real dx = nodes(i, 0) - length / 2.;
Real dy = nodes(i, 1) - length / 2.;
Real dz = nodes(i, 2) - length / 2.;
Real d = sqrt(dx * dx + dy * dy + dz * dz);
if (d < 0.1) {
boundary(i) = true;
temperature(i) = 300.;
}
}
model.setBaseName("heat_transfer_cube3d");
model.addDumpField("temperature");
model.addDumpField("temperature_rate");
model.addDumpField("internal_heat_rate");
// //for testing
int max_steps = 1000;
for (int i = 0; i < max_steps; i++) {
model.solveStep();
if (i % 100 == 0)
model.dump();
if (i % 10 == 0) {
std::cout << "Step " << i << "/" << max_steps << std::endl;
}
}
return 0;
}
diff --git a/examples/heat_transfer/heat_transfer_static_2d.cc b/examples/heat_transfer/heat_transfer_static_2d.cc
index ba3ebc0a7..0d86b59dc 100644
--- a/examples/heat_transfer/heat_transfer_static_2d.cc
+++ b/examples/heat_transfer/heat_transfer_static_2d.cc
@@ -1,95 +1,95 @@
/**
* @file heat_transfer_static_2d.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun May 01 2011
* @date last modification: Fri Mar 16 2018
*
* @brief Heat transfer model example in 2D
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "heat_transfer_model.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <fstream>
#include <iostream>
#include <string>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
-UInt spatial_dimension = 2;
+Int spatial_dimension = 2;
std::string base_name;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
// create mesh
Mesh mesh(spatial_dimension);
mesh.read("square.msh");
HeatTransferModel model(mesh);
// initialize everything
model.initFull(_analysis_method = _static);
// boundary conditions
const Array<Real> & nodes = mesh.getNodes();
Array<bool> & blocked_dofs = model.getBlockedDOFs();
Array<Real> & temperature = model.getTemperature();
double length = 1.;
- UInt nb_nodes = nodes.size();
- for (UInt i = 0; i < nb_nodes; ++i) {
+ Int nb_nodes = nodes.size();
+ for (Int i = 0; i < nb_nodes; ++i) {
temperature(i) = 100.;
Real dx = nodes(i, 0);
Real dy = nodes(i, 1);
Vector<Real> dX = {dx, dy};
- dX -= length / 4.;
+ dX.array() -= length / 4.;
Real d = dX.norm();
if (d < 0.1) {
blocked_dofs(i) = true;
temperature(i) = 300.;
}
if (std::abs(dx) < 1e-4 || std::abs(dy) < 1e-4)
blocked_dofs(i) = true;
if (std::abs(dx - length) < 1e-4 || std::abs(dy - length) < 1e-4)
blocked_dofs(i) = true;
}
model.setBaseName("heat_transfer_static_2d");
model.addDumpField("temperature");
model.addDumpField("internal_heat_rate");
model.addDumpField("conductivity");
model.addDumpField("blocked_dofs");
model.dump();
model.solveStep();
model.dump();
return 0;
}
diff --git a/examples/implicit/implicit_dynamic.cc b/examples/implicit/implicit_dynamic.cc
index cb365da58..d901d9a26 100644
--- a/examples/implicit/implicit_dynamic.cc
+++ b/examples/implicit/implicit_dynamic.cc
@@ -1,151 +1,151 @@
/**
* @file implicit_dynamic.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Feb 28 2020
*
* @brief Example of solid mechanics in implicit dynamic
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
const Real bar_length = 10.;
const Real bar_height = 1.;
const Real bar_depth = 1.;
const Real F = 5e3;
const Real L = bar_length;
const Real I = bar_depth * bar_height * bar_height * bar_height / 12.;
const Real E = 12e7;
const Real rho = 1000;
const Real m = rho * bar_height * bar_depth;
static Real w(UInt n) {
return n * n * M_PI * M_PI / (L * L) * sqrt(E * I / m);
}
static Real analytical_solution(Real time) {
return 2 * F * L * L * L / (pow(M_PI, 4) * E * I) *
((1. - cos(w(1) * time)) + (1. - cos(w(3) * time)) / 81. +
(1. - cos(w(5) * time)) / 625.);
}
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
const Real time_step = 1e-4;
const Real max_time = 0.62;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material_dynamic.dat", argc, argv);
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
if (prank == 0)
mesh.read("beam.msh");
mesh.distribute();
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull(_analysis_method = _implicit_dynamic);
Material & mat = model.getMaterial(0);
mat.setParam("E", E);
mat.setParam("rho", rho);
Array<Real> & force = model.getExternalForce();
Array<Real> & displacment = model.getDisplacement();
// boundary conditions
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "blocked");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "blocked");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "roller");
- const Array<UInt> & trac_nodes =
+ const Array<Idx> & trac_nodes =
mesh.getElementGroup("traction").getNodeGroup().getNodes();
bool dump_node = false;
if (trac_nodes.size() > 0 && mesh.isLocalOrMasterNode(trac_nodes(0))) {
force(trac_nodes(0), 1) = F;
dump_node = true;
}
// output setup
std::ofstream pos;
pos.open("position.csv");
if (!pos.good())
AKANTU_ERROR("Cannot open file \"position.csv\"");
pos << "id,time,position,solution" << std::endl;
model.setBaseName("dynamic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("external_force");
model.addDumpField("internal_force");
model.dump();
model.setTimeStep(time_step);
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 100);
solver.set("threshold", 1e-12);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
/// time loop
Real time = 0.;
- for (UInt s = 1; time < max_time; ++s, time += time_step) {
+ for (Int s = 1; time < max_time; ++s, time += time_step) {
if (prank == 0)
std::cout << s << "\r" << std::flush;
model.solveStep();
if (dump_node)
pos << s << "," << time << "," << displacment(trac_nodes(0), 1) << ","
<< analytical_solution(s * time_step) << std::endl;
if (s % 100 == 0)
model.dump();
}
std::cout << std::endl;
pos.close();
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/io/dumper/dumpable_interface.cc b/examples/io/dumper/dumpable_interface.cc
index 961c1db3a..ac666a0c2 100644
--- a/examples/io/dumper/dumpable_interface.cc
+++ b/examples/io/dumper/dumpable_interface.cc
@@ -1,192 +1,192 @@
/**
* @file dumpable_interface.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Aug 17 2015
* @date last modification: Tue Sep 29 2020
*
* @brief Example usnig the dumper interface directly
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "group_manager_inline_impl.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
#include "locomotive_tools.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
/*
In this example, we present dumpers::Dumpable which is an interface
for other classes who want to dump themselves.
Several classes of Akantu inheritate from Dumpable (Model, Mesh, ...).
In this example we reproduce the same tasks as example_dumper_low_level.cc
using this time Dumpable interface inherted by Mesh, NodeGroup and
ElementGroup.
It is then advised to read first example_dumper_low_level.cc.
*/
initialize(argc, argv);
// To start let us load the swiss train mesh and its mesh data information.
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("swiss_train.msh");
/*
swiss_train.msh has the following physical groups that can be viewed with
GMSH:
"$MeshFormat
2.2 0 8
$EndMeshFormat
$PhysicalNames
6
2 1 "red"
2 2 "white"
2 3 "lwheel_1"
2 4 "lwheel_2"
2 5 "rwheel_2"
2 6 "rwheel_1"
$EndPhysicalNames
..."
*/
// Grouping nodes and elements belonging to train wheels (=four mesh data).
ElementGroup & wheels_elements =
mesh.createElementGroup("wheels", spatial_dimension);
wheels_elements.append(mesh.getElementGroup("lwheel_1"));
wheels_elements.append(mesh.getElementGroup("lwheel_2"));
wheels_elements.append(mesh.getElementGroup("rwheel_1"));
wheels_elements.append(mesh.getElementGroup("rwheel_2"));
- const Array<UInt> & lnode_1 =
+ const Array<Idx> & lnode_1 =
(mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes();
- const Array<UInt> & lnode_2 =
+ const Array<Idx> & lnode_2 =
(mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes();
- const Array<UInt> & rnode_1 =
+ const Array<Idx> & rnode_1 =
(mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes();
- const Array<UInt> & rnode_2 =
+ const Array<Idx> & rnode_2 =
(mesh.getElementGroup("rwheel_2")).getNodeGroup().getNodes();
Array<Real> & node = mesh.getNodes();
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
// This time a 2D Array is created and a padding size of 3 is passed to
// NodalField in order to warp train deformation on Paraview.
Array<Real> displacement(nb_nodes, spatial_dimension);
// Create an ElementTypeMapArray for the colour
- ElementTypeMapArray<UInt> colour("colour");
+ ElementTypeMapArray<Int> colour("colour");
colour.initialize(mesh, _with_nb_element = true);
/* ------------------------------------------------------------------------ */
/* Creating dumpers */
/* ------------------------------------------------------------------------ */
// Create dumper for the complete mesh and register it as default dumper.
auto && dumper =
std::make_shared<DumperParaview>("train", "./paraview/dumpable", false);
mesh.registerExternalDumper(dumper, "train", true);
mesh.addDumpMesh(mesh);
// The dumper for the filtered mesh can be directly taken from the
// ElementGroup and then registered as "wheels_elements" dumper.
auto && wheels = mesh.getGroupDumper("paraview_wheels", "wheels");
mesh.registerExternalDumper(wheels.shared_from_this(), "wheels");
mesh.setDirectoryToDumper("wheels", "./paraview/dumpable");
// Arrays and ElementTypeMapArrays can be added as external fields directly
mesh.addDumpFieldExternal("displacement", displacement);
- ElementTypeMapArrayFilter<UInt> filtered_colour(
- colour, wheels_elements.getElements());
+ ElementTypeMapArrayFilter<Int> filtered_colour(colour,
+ wheels_elements.getElements());
auto colour_field_wheel =
- std::make_shared<dumpers::ElementalField<UInt, Vector, true>>(
+ std::make_shared<dumpers::ElementalField<Int, Vector<Int>, true>>(
filtered_colour);
mesh.addDumpFieldExternal("color", colour_field_wheel);
mesh.addDumpFieldExternalToDumper("wheels", "displacement", displacement);
mesh.addDumpFieldExternalToDumper("wheels", "colour", colour);
// For some specific cases the Fields should be created, as when you want to
// pad an array
auto displacement_vector_field =
mesh.createNodalField(&displacement, "all", 3);
mesh.addDumpFieldExternal("displacement_as_paraview_vector",
displacement_vector_field);
mesh.addDumpFieldExternalToDumper("wheels", "displacement_as_paraview_vector",
displacement_vector_field);
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
// Fill the ElementTypeMapArray colour.
fillColour(mesh, colour);
/// Apply displacement and wheels rotation.
Real tot_displacement = 50.;
Real radius = 1.;
- UInt nb_steps = 100;
+ auto nb_steps = 100;
Real theta = tot_displacement / radius;
Vector<Real> l_center(spatial_dimension);
Vector<Real> r_center(spatial_dimension);
- for (UInt i = 0; i < spatial_dimension; ++i) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
l_center(i) = node(14, i);
r_center(i) = node(2, i);
}
- for (UInt i = 0; i < nb_steps; ++i) {
+ for (Int i = 0; i < nb_steps; ++i) {
displacement.zero();
Real step_ratio = Real(i) / Real(nb_steps);
Real angle = step_ratio * theta;
applyRotation(l_center, angle, node, displacement, lnode_1);
applyRotation(l_center, angle, node, displacement, lnode_2);
applyRotation(r_center, angle, node, displacement, rnode_1);
applyRotation(r_center, angle, node, displacement, rnode_2);
- for (UInt j = 0; j < nb_nodes; ++j) {
+ for (Int j = 0; j < nb_nodes; ++j) {
displacement(j, _x) += step_ratio * tot_displacement;
}
/// Dump call is finally made through Dumpable interface.
mesh.dump();
mesh.dump("wheels");
}
finalize();
return 0;
}
diff --git a/examples/io/dumper/dumper_low_level.cc b/examples/io/dumper/dumper_low_level.cc
index 3d31ba3ba..a8f648395 100644
--- a/examples/io/dumper/dumper_low_level.cc
+++ b/examples/io/dumper/dumper_low_level.cc
@@ -1,200 +1,200 @@
/**
* @file dumper_low_level.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Aug 17 2015
* @date last modification: Tue Sep 29 2020
*
* @brief Example using the low level dumper interface
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "group_manager.hh"
#include "mesh.hh"
#include "dumper_elemental_field.hh"
#include "dumper_nodal_field.hh"
#include "dumper_iohelper_paraview.hh"
#include "locomotive_tools.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
/* This example aims at illustrating how to manipulate low-level methods of
DumperIOHelper.
The aims is to visualize a colorized moving train with Paraview */
initialize(argc, argv);
// To start let us load the swiss train mesh and its mesh data information.
// We aknowledge here a weel-known swiss industry for mesh donation.
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("swiss_train.msh");
Array<Real> & nodes = mesh.getNodes();
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
/* swiss_train.msh has the following physical groups that can be viewed with
GMSH:
"$MeshFormat
2.2 0 8
$EndMeshFormat
$PhysicalNames
6
2 1 "red"
2 2 "white"
2 3 "lwheel_1"
2 4 "lwheel_2"
2 5 "rwheel_2"
2 6 "rwheel_1"
$EndPhysicalNames
..."
*/
// Grouping nodes and elements belonging to train wheels (=four mesh data)
ElementGroup & wheels_elements =
mesh.createElementGroup("wheels", spatial_dimension);
wheels_elements.append(mesh.getElementGroup("lwheel_1"));
wheels_elements.append(mesh.getElementGroup("lwheel_2"));
wheels_elements.append(mesh.getElementGroup("rwheel_1"));
wheels_elements.append(mesh.getElementGroup("rwheel_2"));
- const Array<UInt> & lnode_1 =
+ const Array<Idx> & lnode_1 =
(mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes();
- const Array<UInt> & lnode_2 =
+ const Array<Idx> & lnode_2 =
(mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes();
- const Array<UInt> & rnode_1 =
+ const Array<Idx> & rnode_1 =
(mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes();
- const Array<UInt> & rnode_2 =
+ const Array<Idx> & rnode_2 =
(mesh.getElementGroup("rwheel_2")).getNodeGroup().getNodes();
/* Note this Array is constructed with three components in order to warp train
deformation on Paraview. A more appropriate way to do this is to set a
padding in the NodalField (See example_dumpable_interface.cc.) */
Array<Real> displacement(nb_nodes, 3);
// ElementalField are constructed with an ElementTypeMapArray.
- ElementTypeMapArray<UInt> colour;
+ ElementTypeMapArray<Int> colour;
colour.initialize(mesh, _with_nb_element = true);
/* ------------------------------------------------------------------------ */
/* Dumper creation */
/* ------------------------------------------------------------------------ */
// Creation of two DumperParaview. One for full mesh, one for a filtered
// mesh.
DumperParaview dumper("train", "./paraview/dumper", false);
DumperParaview wheels("wheels", "./paraview/dumper", false);
// Register the full mesh
dumper.registerMesh(mesh);
// Register a filtered mesh limited to nodes and elements from wheels groups
wheels.registerFilteredMesh(mesh, wheels_elements.getElements(),
wheels_elements.getNodeGroup().getNodes());
// Generate an output file of the two mesh registered.
dumper.dump();
wheels.dump();
/* At this stage no fields are attached to the two dumpers. To do so, a
dumpers::Field object has to be created. Several types of dumpers::Field
exist. In this example we present two of them.
NodalField to describe nodal displacements of our train.
ElementalField handling the color of our different part.
*/
// NodalField are constructed with an Array.
auto displ_field = std::make_shared<dumpers::NodalField<Real>>(displacement);
- auto colour_field = std::make_shared<dumpers::ElementalField<UInt>>(colour);
+ auto colour_field = std::make_shared<dumpers::ElementalField<Int>>(colour);
// Register the freshly created fields to our dumper.
dumper.registerField("displacement", displ_field);
dumper.registerField("colour", colour_field);
// For the dumper wheels, fields have to be filtered at registration.
// Filtered NodalField can be simply registered by adding an Array<UInt>
// listing the nodes.
auto displ_field_wheel = std::make_shared<dumpers::NodalField<Real, true>>(
displacement, 0, 0, &(wheels_elements.getNodeGroup().getNodes()));
wheels.registerField("displacement", displ_field_wheel);
// For the ElementalField, an ElementTypeMapArrayFilter has to be created.
- ElementTypeMapArrayFilter<UInt> filtered_colour(
- colour, wheels_elements.getElements());
+ ElementTypeMapArrayFilter<Int> filtered_colour(colour,
+ wheels_elements.getElements());
auto colour_field_wheel =
- std::make_shared<dumpers::ElementalField<UInt, Vector, true>>(
+ std::make_shared<dumpers::ElementalField<Int, Vector<Int>, true>>(
filtered_colour);
wheels.registerField("colour", colour_field_wheel);
/* ------------------------------------------------------------------------ */
// Now that the dumpers are created and the fields are associated, let's
// paint and move the train!
// Fill the ElementTypeMapArray colour according to mesh data information.
fillColour(mesh, colour);
// Apply displacement and wheels rotation.
Real tot_displacement = 50.;
Real radius = 1.;
- UInt nb_steps = 100;
+ Int nb_steps = 100;
Real theta = tot_displacement / radius;
Vector<Real> l_center(3);
Vector<Real> r_center(3);
- for (UInt i = 0; i < spatial_dimension; ++i) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
l_center(i) = nodes(14, i);
r_center(i) = nodes(2, i);
}
- for (UInt i = 0; i < nb_steps; ++i) {
+ for (Int i = 0; i < nb_steps; ++i) {
displacement.zero();
Real angle = (Real)i / (Real)nb_steps * theta;
applyRotation(l_center, angle, nodes, displacement, lnode_1);
applyRotation(l_center, angle, nodes, displacement, lnode_2);
applyRotation(r_center, angle, nodes, displacement, rnode_1);
applyRotation(r_center, angle, nodes, displacement, rnode_2);
- for (UInt j = 0; j < nb_nodes; ++j) {
+ for (Int j = 0; j < nb_nodes; ++j) {
displacement(j, 0) += (Real)i / (Real)nb_steps * tot_displacement;
}
// Output results after each moving steps for main and wheel dumpers.
dumper.dump();
wheels.dump();
}
finalize();
return 0;
}
diff --git a/examples/io/dumper/locomotive_tools.cc b/examples/io/dumper/locomotive_tools.cc
index 03a31bf90..a5232ce4c 100644
--- a/examples/io/dumper/locomotive_tools.cc
+++ b/examples/io/dumper/locomotive_tools.cc
@@ -1,92 +1,92 @@
/**
* @file locomotive_tools.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
*
* @date creation: Mon Aug 17 2015
* @date last modification: Fri Feb 28 2020
*
* @brief Small helper code for the dumper examples
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include "locomotive_tools.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
void applyRotation(const Vector<Real> & center, Real angle,
const Array<Real> & nodes, Array<Real> & displacement,
- const Array<UInt> & node_group) {
+ const Array<Idx> & node_group) {
auto nodes_it = nodes.begin(nodes.getNbComponent());
auto disp_it = displacement.begin(center.size());
- Array<UInt>::const_scalar_iterator node_num_it = node_group.begin();
- Array<UInt>::const_scalar_iterator node_num_end = node_group.end();
+ auto node_num_it = node_group.begin();
+ auto node_num_end = node_group.end();
Vector<Real> pos_rel(center.size());
for (; node_num_it != node_num_end; ++node_num_it) {
const Vector<Real> pos = nodes_it[*node_num_it];
- for (UInt i = 0; i < pos.size(); ++i)
+ for (Int i = 0; i < pos.size(); ++i)
pos_rel(i) = pos(i);
Vector<Real> dis = disp_it[*node_num_it];
pos_rel -= center;
Real radius = pos_rel.norm();
if (std::abs(radius) < Math::getTolerance())
continue;
Real phi_i = std::acos(pos_rel(_x) / radius);
if (pos_rel(_y) < 0)
phi_i *= -1;
dis(_x) = std::cos(phi_i - angle) * radius - pos_rel(_x);
dis(_y) = std::sin(phi_i - angle) * radius - pos_rel(_y);
}
}
/* -------------------------------------------------------------------------- */
-void fillColour(const Mesh & mesh, ElementTypeMapArray<UInt> & colour) {
+void fillColour(const Mesh & mesh, ElementTypeMapArray<Int> & colour) {
const ElementTypeMapArray<std::string> & phys_data =
mesh.getData<std::string>("physical_names");
const Array<std::string> & txt_colour = phys_data(_triangle_3);
- Array<UInt> & id_colour = colour(_triangle_3);
+ auto & id_colour = colour(_triangle_3);
- for (UInt i = 0; i < txt_colour.size(); ++i) {
+ for (Int i = 0; i < txt_colour.size(); ++i) {
std::string phy_name = txt_colour(i);
if (phy_name == "red")
id_colour(i) = 3;
else if (phy_name == "white" || phy_name == "lwheel_1" ||
phy_name == "rwheel_1")
id_colour(i) = 2;
else
id_colour(i) = 1;
}
}
diff --git a/examples/io/dumper/locomotive_tools.hh b/examples/io/dumper/locomotive_tools.hh
index cdf6d2c40..65effb69a 100644
--- a/examples/io/dumper/locomotive_tools.hh
+++ b/examples/io/dumper/locomotive_tools.hh
@@ -1,40 +1,40 @@
/**
* @file locomotive_tools.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Apr 13 2012
* @date last modification: Mon Aug 24 2015
*
* @brief Header for the locomotive helper for the dumpers
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-void applyRotation(const ::akantu::Vector<::akantu::Real> & center,
+void applyRotation(const ::akantu::Vector<::akantu::Real> &center,
::akantu::Real angle,
- const ::akantu::Array<::akantu::Real> & nodes,
- ::akantu::Array<::akantu::Real> & displacement,
- const ::akantu::Array<::akantu::UInt> & node_group);
+ const ::akantu::Array<::akantu::Real> &nodes,
+ ::akantu::Array<::akantu::Real> &displacement,
+ const ::akantu::Array<::akantu::Idx> &node_group);
-void fillColour(const ::akantu::Mesh & mesh,
- ::akantu::ElementTypeMapArray<::akantu::UInt> & colour);
+void fillColour(const ::akantu::Mesh &mesh,
+ ::akantu::ElementTypeMapArray<::akantu::Int> &colour);
diff --git a/examples/new_material/local_material_damage.cc b/examples/new_material/local_material_damage.cc
index 86ea0cda9..09f8c34e2 100644
--- a/examples/new_material/local_material_damage.cc
+++ b/examples/new_material/local_material_damage.cc
@@ -1,111 +1,111 @@
/**
* @file local_material_damage.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Specialization of the material class for the damage material
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "local_material_damage.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
LocalMaterialDamage::LocalMaterialDamage(SolidMechanicsModel & model,
const ID & id)
: Material(model, id), damage("damage", *this) {
AKANTU_DEBUG_IN();
this->registerParam("E", E, 0., _pat_parsable, "Young's modulus");
this->registerParam("nu", nu, 0.5, _pat_parsable, "Poisson's ratio");
this->registerParam("lambda", lambda, _pat_readable,
"First Lamé coefficient");
this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
this->registerParam("Yd", Yd, 50., _pat_parsmod);
this->registerParam("Sd", Sd, 5000., _pat_parsmod);
damage.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void LocalMaterialDamage::initMaterial() {
AKANTU_DEBUG_IN();
Material::initMaterial();
lambda = nu * E / ((1 + nu) * (1 - 2 * nu));
mu = E / (2 * (1 + nu));
kpa = lambda + 2. / 3. * mu;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void LocalMaterialDamage::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = damage(el_type, ghost_type).storage();
+ Real * dam = damage(el_type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
computeStressOnQuad(grad_u, sigma, *dam);
++dam;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void LocalMaterialDamage::computePotentialEnergy(ElementType el_type) {
AKANTU_DEBUG_IN();
- Real * epot = potential_energy(el_type).storage();
+ Real * epot = potential_energy(el_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
computePotentialEnergyOnQuad(grad_u, sigma, *epot);
epot++;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
static bool material_is_alocated_local_damage [[gnu::unused]] =
MaterialFactory::getInstance().registerAllocator(
"local_damage",
[](UInt, const ID &, SolidMechanicsModel & model,
const ID & id) -> std::unique_ptr<Material> {
return std::make_unique<LocalMaterialDamage>(model, id);
});
} // namespace akantu
diff --git a/examples/new_material/local_material_damage.hh b/examples/new_material/local_material_damage.hh
index 914d4f98e..d0c7faa87 100644
--- a/examples/new_material/local_material_damage.hh
+++ b/examples/new_material/local_material_damage.hh
@@ -1,119 +1,122 @@
/**
* @file local_material_damage.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief Material isotropic elastic
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_LOCAL_MATERIAL_DAMAGE_HH_
#define AKANTU_LOCAL_MATERIAL_DAMAGE_HH_
namespace akantu {
class LocalMaterialDamage : public Material {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- LocalMaterialDamage(SolidMechanicsModel & model, const ID & id = "");
+ LocalMaterialDamage(SolidMechanicsModel &model, const ID &id = "");
virtual ~LocalMaterialDamage(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the potential energy for all elements
void computePotentialEnergy(ElementType el_type) override;
protected:
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(Matrix<Real> & grad_u, Matrix<Real> & sigma,
- Real & damage);
+ template <typename D1, typename D2>
+ inline void computeStressOnQuad(Eigen::MatrixBase<D1> &grad_u,
+ Eigen::MatrixBase<D2> &sigma, Real &damage);
/// compute the potential energy for on element
- inline void computePotentialEnergyOnQuad(Matrix<Real> & grad_u,
- Matrix<Real> & sigma, Real & epot);
+ template <typename D1, typename D2>
+ inline void computePotentialEnergyOnQuad(Eigen::MatrixBase<D1> &grad_u,
+ Eigen::MatrixBase<D2> &sigma,
+ Real &epot);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// compute the celerity of the fastest wave in the material
- inline Real getCelerity(const Element & element) const override;
+ inline Real getCelerity(const Element &element) const override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real);
private:
/// the young modulus
Real E;
/// Poisson coefficient
Real nu;
/// First Lamé coefficient
Real lambda;
/// Second Lamé coefficient (shear modulus)
Real mu;
/// resistance to damage
Real Yd;
/// damage threshold
Real Sd;
/// Bulk modulus
Real kpa;
/// damage internal variable
InternalField<Real> damage;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "local_material_damage_inline_impl.hh"
#endif /* AKANTU_LOCAL_MATERIAL_DAMAGE_HH_ */
diff --git a/examples/new_material/local_material_damage_inline_impl.hh b/examples/new_material/local_material_damage_inline_impl.hh
index aa5f42b0f..cad8a1b70 100644
--- a/examples/new_material/local_material_damage_inline_impl.hh
+++ b/examples/new_material/local_material_damage_inline_impl.hh
@@ -1,92 +1,93 @@
/**
* @file local_material_damage_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Tue Sep 29 2020
*
* @brief Implementation of the inline functions of the material damage
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH_
#define AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline void LocalMaterialDamage::computeStressOnQuad(Matrix<Real> & grad_u,
- Matrix<Real> & sigma,
- Real & dam) {
+template <typename D1, typename D2>
+inline void LocalMaterialDamage::computeStressOnQuad(
+ Eigen::MatrixBase<D1> &grad_u, Eigen::MatrixBase<D2> &sigma, Real &dam) {
Real trace = grad_u.trace();
/// \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla
/// u_{ij} + \nabla u_{ji})
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = 0; j < spatial_dimension; ++j) {
sigma(i, j) =
(i == j) * lambda * trace + mu * (grad_u(i, j) + grad_u(j, i));
}
}
Real Y = 0;
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = 0; j < spatial_dimension; ++j) {
Y += sigma(i, j) * grad_u(i, j);
}
}
Y *= 0.5;
Real Fd = Y - Yd - Sd * dam;
if (Fd > 0)
dam = (Y - Yd) / Sd;
dam = std::min(dam, 1.);
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
+template <typename D1, typename D2>
inline void LocalMaterialDamage::computePotentialEnergyOnQuad(
- Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & epot) {
+ Eigen::MatrixBase<D1> &grad_u, Eigen::MatrixBase<D2> &sigma, Real &epot) {
epot = 0.;
- for (UInt i = 0, t = 0; i < spatial_dimension; ++i)
- for (UInt j = 0; j < spatial_dimension; ++j, ++t)
+ for (Int i = 0, t = 0; i < spatial_dimension; ++i)
+ for (Int j = 0; j < spatial_dimension; ++j, ++t)
epot += sigma(i, j) * (grad_u(i, j) - (i == j));
epot *= .5;
}
/* -------------------------------------------------------------------------- */
inline Real LocalMaterialDamage::getCelerity(__attribute__((unused))
- const Element & element) const {
+ const Element &element) const {
// Here the fastest celerity is the push wave speed
return (std::sqrt((2 * mu + lambda) / rho));
}
} // namespace akantu
#endif /* AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH_ */
diff --git a/examples/new_material/new_local_material.cc b/examples/new_material/new_local_material.cc
index 96a2a0414..62fd95faa 100644
--- a/examples/new_material/new_local_material.cc
+++ b/examples/new_material/new_local_material.cc
@@ -1,104 +1,104 @@
/**
* @file new_local_material.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Wed Jan 15 2020
*
* @brief test of the class SolidMechanicsModel
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "local_material_damage.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
#define bar_length 10.
#define bar_height 4.
akantu::Real eps = 1e-10;
int main(int argc, char * argv[]) {
akantu::initialize("material.dat", argc, argv);
- UInt max_steps = 10000;
+ Int max_steps = 10000;
Real epot, ekin;
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("barre_trou.msh");
/// model creation
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull(_analysis_method = _explicit_lumped_mass);
std::cout << model.getMaterial(0) << std::endl;
Real time_step = model.getStableTimeStep();
model.setTimeStep(time_step / 10.);
/// Dirichlet boundary conditions
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed_x");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed_y");
// Neumann boundary condition
Matrix<Real> stress(2, 2);
stress.eye(3e2);
model.applyBC(BC::Neumann::FromStress(stress), "Traction");
model.setBaseName("local_material");
model.addDumpField("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("external_force");
model.addDumpField("internal_force");
model.addDumpField("grad_u");
model.addDumpField("stress");
model.addDumpField("damage");
model.dump();
- for (UInt s = 0; s < max_steps; ++s) {
+ for (Int s = 0; s < max_steps; ++s) {
model.solveStep();
epot = model.getEnergy("potential");
ekin = model.getEnergy("kinetic");
if (s % 100 == 0)
std::cout << s << " " << epot << " " << ekin << " " << epot + ekin
<< std::endl;
if (s % 1000 == 0)
model.dump();
}
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc b/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc
index a1087207d..12b621947 100644
--- a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc
+++ b/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc
@@ -1,179 +1,168 @@
/**
* @file material_viscoelastic_maxwell_energies.cc
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
*
* @date creation: Tue Nov 20 2018
* @date last modification: Sun Dec 30 2018
*
* @brief Example of using viscoelastic material and computing energies
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
/* -------------------------------------------------------------------------- */
#include "material_viscoelastic_maxwell.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "sparse_matrix.hh"
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material_viscoelastic_maxwell.dat", argc, argv);
// sim data
Real eps = 0.1;
- const UInt dim = 2;
+ const Int dim = 2;
Real sim_time = 100.;
Real T = 10.;
Mesh mesh(dim);
mesh.read("material_viscoelastic_maxwell_mesh.msh");
SolidMechanicsModel model(mesh);
/* ------------------------------------------------------------------------ */
/* Initialization */
/* ------------------------------------------------------------------------ */
model.initFull(_analysis_method = _static);
std::cout << model.getMaterial(0) << std::endl;
std::stringstream filename_sstr;
filename_sstr << "material_viscoelastic_maxwell_output.out";
std::ofstream output_data;
output_data.open(filename_sstr.str().c_str());
Material & mat = model.getMaterial(0);
Real time_step = 0.1;
- UInt nb_nodes = mesh.getNbNodes();
const Array<Real> & coordinate = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
Array<bool> & blocked = model.getBlockedDOFs();
/// Setting time step
model.setTimeStep(time_step);
model.setBaseName("dynamic");
model.addDumpFieldVector("displacement");
model.addDumpField("blocked_dofs");
model.addDumpField("external_force");
model.addDumpField("internal_force");
model.addDumpField("grad_u");
model.addDumpField("stress");
model.addDumpField("strain");
- UInt max_steps = sim_time / time_step + 1;
+ Int max_steps = sim_time / time_step + 1;
Real time = 0.;
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 10);
solver.set("threshold", 1e-7);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
/* ------------------------------------------------------------------------ */
/* Main loop */
/* ------------------------------------------------------------------------ */
- for (UInt s = 0; s <= max_steps; ++s) {
+ for (Int s = 0; s <= max_steps; ++s) {
std::cout << "Time Step = " << time_step << "s" << std::endl;
std::cout << "Time = " << time << std::endl;
// impose displacement
Real epsilon = 0;
if (time < T) {
epsilon = eps * time / T;
} else {
epsilon = eps;
}
- for (UInt n = 0; n < nb_nodes; ++n) {
- if (Math::are_float_equal(coordinate(n, 0), 0.0)) {
- displacement(n, 0) = 0;
- blocked(n, 0) = true;
- displacement(n, 1) = epsilon * coordinate(n, 1);
- blocked(n, 1) = true;
- } else if (Math::are_float_equal(coordinate(n, 1), 0.0)) {
- displacement(n, 0) = epsilon * coordinate(n, 0);
- blocked(n, 0) = true;
- displacement(n, 1) = 0;
- blocked(n, 1) = true;
- } else if (Math::are_float_equal(coordinate(n, 0), 0.001)) {
- displacement(n, 0) = epsilon * coordinate(n, 0);
- blocked(n, 0) = true;
- displacement(n, 1) = epsilon * coordinate(n, 1);
- blocked(n, 1) = true;
- } else if (Math::are_float_equal(coordinate(n, 1), 0.001)) {
- displacement(n, 0) = epsilon * coordinate(n, 0);
- blocked(n, 0) = true;
- displacement(n, 1) = epsilon * coordinate(n, 1);
- blocked(n, 1) = true;
+ for (auto && [coord, disp, block] :
+ zip(make_view(coordinate, dim), make_view(displacement, dim),
+ make_view(blocked, dim))) {
+ if (Math::are_float_equal(coord(_x), 0.0)) {
+ disp(_x) = 0;
+ disp(_y) = epsilon * coord(_y);
+ block.set(true);
+ } else if (Math::are_float_equal(coord(_y), 0.0)) {
+ disp(_x) = epsilon * coord(_x);
+ disp(_y) = 0;
+ block.set(true);
+ } else if (Math::are_float_equal(coord(_x), 0.001)) {
+ disp = epsilon * coord;
+ block.set(true);
+ } else if (Math::are_float_equal(coord(_y), 0.001)) {
+ disp = epsilon * coord;
+ block.set(true);
}
}
try {
model.solveStep();
- } catch (debug::Exception & e) {
+ } catch (debug::NLSNotConvergedException & e) {
+ std::cout << "Didn't converge after " << e.niter
+ << " iterations. Error is " << e.error << std::endl;
+ return EXIT_FAILURE;
}
// for debugging
// auto int_force = model.getInternalForce();
// auto &K = model.getDOFManager().getMatrix("K");
// K.saveMatrix("K.mtx");
Int nb_iter = solver.get("nb_iterations");
- Real error = solver.get("error");
- bool converged = solver.get("converged");
-
- if (converged) {
- std::cout << "Converged in " << nb_iter << " iterations" << std::endl;
- } else {
- std::cout << "Didn't converge after " << nb_iter
- << " iterations. Error is " << error << std::endl;
- return EXIT_FAILURE;
- }
+ std::cout << "Converged in " << nb_iter << " iterations" << std::endl;
model.dump();
Real epot = mat.getEnergy("potential");
Real edis = mat.getEnergy("dissipated");
Real work = mat.getEnergy("work");
// data output
output_data << s * time_step << " " << epsilon << " " << epot << " " << edis
<< " " << work << std::endl;
time += time_step;
}
output_data.close();
finalize();
}
diff --git a/examples/parallel/parallel_2d.cc b/examples/parallel/parallel_2d.cc
index e08a0074f..ab26c1e11 100644
--- a/examples/parallel/parallel_2d.cc
+++ b/examples/parallel/parallel_2d.cc
@@ -1,108 +1,108 @@
/**
* @file parallel_2d.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Aug 09 2010
* @date last modification: Thu Mar 22 2018
*
* @brief Parallel example
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- UInt spatial_dimension = 2;
- UInt max_steps = 10000;
+ Int spatial_dimension = 2;
+ Int max_steps = 10000;
Real time_factor = 0.8;
Real max_disp = 1e-6;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
if (prank == 0) {
// Read the mesh
mesh.read("square_2d.msh");
}
mesh.distribute();
SolidMechanicsModel model(mesh);
model.initFull();
if (prank == 0)
std::cout << model.getMaterial(0) << std::endl;
model.setBaseName("multi");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("velocity");
model.addDumpFieldVector("acceleration");
model.addDumpFieldTensor("stress");
model.addDumpFieldTensor("grad_u");
/// boundary conditions
Real eps = 1e-16;
const Array<Real> & pos = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & boun = model.getBlockedDOFs();
Real left_side = mesh.getLowerBounds()(0);
Real right_side = mesh.getUpperBounds()(0);
- for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
+ for (Int i = 0; i < mesh.getNbNodes(); ++i) {
if (std::abs(pos(i, 0) - left_side) < eps) {
disp(i, 0) = max_disp;
boun(i, 0) = true;
}
if (std::abs(pos(i, 0) - right_side) < eps) {
disp(i, 0) = -max_disp;
boun(i, 0) = true;
}
}
Real time_step = model.getStableTimeStep() * time_factor;
std::cout << "Time Step = " << time_step << "s" << std::endl;
model.setTimeStep(time_step);
model.dump();
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
if (s % 200 == 0)
model.dump();
if (prank == 0 && s % 100 == 0)
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/phase_field/phase_field_notch.cc b/examples/phase_field/phase_field_notch.cc
index 14deb3da7..29a53ab7c 100644
--- a/examples/phase_field/phase_field_notch.cc
+++ b/examples/phase_field/phase_field_notch.cc
@@ -1,120 +1,120 @@
/**
* @file phase_field_notch.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Tue Oct 02 2018
* @date last modification: Wed Apr 07 2021
*
* @brief Example of phase field model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_phasefield.hh"
#include "non_linear_solver.hh"
#include "phase_field_model.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <chrono>
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
using clk = std::chrono::high_resolution_clock;
using second = std::chrono::duration<double>;
using millisecond = std::chrono::duration<double, std::milli>;
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material_notch.dat", argc, argv);
// create mesh
Mesh mesh(spatial_dimension);
mesh.read("square_notch.msh");
CouplerSolidPhaseField coupler(mesh);
auto & model = coupler.getSolidMechanicsModel();
auto & phase = coupler.getPhaseFieldModel();
model.initFull(_analysis_method = _static);
auto && mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
model.applyBC(BC::Dirichlet::FixedValue(0., _y), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(0., _x), "left");
model.setBaseName("phase_notch");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
model.dump();
- UInt nbSteps = 1500;
+ auto nbSteps = 1500;
Real increment = 1e-5;
auto start_time = clk::now();
- for (UInt s = 1; s < nbSteps; ++s) {
+ for (Int s = 1; s < nbSteps; ++s) {
if (s >= 500) {
increment = 1.e-6;
}
if (s % 10 == 0) {
constexpr char wheel[] = "/-\\|";
auto elapsed = clk::now() - start_time;
auto time_per_step = elapsed / s;
std::cout << "\r[" << wheel[(s / 10) % 4] << "] " << std::setw(5) << s
<< "/" << nbSteps << " (" << std::setprecision(2) << std::fixed
<< std::setw(8) << millisecond(time_per_step).count()
<< "ms/step - elapsed: " << std::setw(8)
<< second(elapsed).count() << "s - ETA: " << std::setw(8)
<< second((nbSteps - s) * time_per_step).count() << "s)"
<< std::string(' ', 20) << std::flush;
}
model.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "top");
coupler.solve();
if (s % 100 == 0) {
model.dump();
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/python/cohesive/custom_material.py b/examples/python/cohesive/custom_material.py
index 509c7d10f..ecc76aea6 100755
--- a/examples/python/cohesive/custom_material.py
+++ b/examples/python/cohesive/custom_material.py
@@ -1,181 +1,189 @@
#!/usr/bin/env python3
# pylint: disable=missing-module-docstring
# pylint: disable=missing-function-docstring
+"""Example of custom cohesive material written in python."""
import numpy as np
import akantu as aka
spatial_dimension = 2
-# ------------------------------------------------------------------------------
+
class LinearCohesive(aka.MaterialCohesive):
"""Material Cohesive Linear."""
def __init__(self, model, _id):
+ """Construct the material and register the parameters to the parser."""
super().__init__(model, _id)
super().registerParamReal(
"G_c", aka._pat_readable | aka._pat_parsable, "Fracture energy"
)
- super().registerParamReal("beta", aka._pat_readable | aka._pat_parsable, "beta")
+ super().registerParamReal("beta",
+ aka._pat_readable | aka._pat_parsable)
self.registerInternalReal("delta_max", 1)
- self.beta = 0
- self.sigma_c = 0
- self.delta_c = 0
+ self.beta = 0.
+ self.sigma_c = 0.
+ self.delta_c = 0.
+ self.G_c = 0.
def initMaterial(self):
+ """Initialize the parameters for the material."""
super().initMaterial()
self.sigma_c = self.getReal("sigma_c")
self.G_c = self.getReal("G_c")
self.beta = self.getReal("beta")
self.delta_c = 2 * self.G_c / self.sigma_c
def checkInsertion(self, check_only):
+ """Check if need to insert a cohesive element."""
model = self.getModel()
facets = self.getFacetFilter()
inserter = model.getElementInserter()
for type_facet in facets.elementTypes(dim=(spatial_dimension - 1)):
facet_filter = facets(type_facet)
nb_facet = facet_filter.shape[0]
if nb_facet == 0:
continue
fe_engine = model.getFEEngine("FacetsFEEngine")
facets_check = inserter.getCheckFacets(type_facet)
insertion = inserter.getInsertionFacets(type_facet)
nb_quad_facet = fe_engine.getNbIntegrationPoints(type_facet)
normals = fe_engine.getNormalsOnIntegrationPoints(type_facet)
facets_stresses = model.getStressOnFacets(type_facet).reshape(
normals.shape[0] // nb_quad_facet,
nb_quad_facet,
2,
spatial_dimension,
spatial_dimension,
)
tangents = model.getTangents(type_facet)
for facet, facet_stresses in zip(facet_filter, facets_stresses):
if not facets_check[facet]:
continue
ref_stress = 0
for q, quad_stresses in enumerate(facet_stresses):
current_quad = facet * nb_quad_facet + q
normal = normals[current_quad, :].ravel()
tangent = tangents[current_quad, :].ravel()
stress_1 = quad_stresses.T[0]
stress_2 = quad_stresses.T[1]
avg_stress = stress_1 + stress_2 / 2.0
traction = avg_stress.dot(normal)
n = traction.dot(normal)
n = max(0, n)
t = traction.dot(tangent)
ref_stress = max(
ref_stress, np.sqrt(n * n + t * t / (self.beta**2))
)
if ref_stress > self.sigma_c:
insertion[facet] = True
# constitutive law
def computeTraction(self, normals, el_type, ghost_type):
+ """Compute the traction for a given opening."""
openings = self.getOpening(el_type, ghost_type)
tractions = self.getTraction(el_type, ghost_type)
delta_max = self.getInternalReal("delta_max")(el_type)
for el in range(normals.shape[0]):
normal = normals[el].ravel()
opening = openings[el].ravel()
delta_n = opening.dot(normal) * normal
delta_s = opening - delta_n
delta = (
- self.beta * np.linalg.norm(delta_s) ** 2 + np.linalg.norm(delta_n) ** 2
+ self.beta * np.linalg.norm(delta_s) ** 2 +
+ np.linalg.norm(delta_n) ** 2
)
delta_max[el] = max(delta_max[el], delta)
tractions[el, :] = (
(delta * delta_s + delta_n)
* self.sigma_c
/ delta
* (1 - delta / self.delta_c)
)
-# register material to the MaterialFactory
def allocator(_dim, unused, model, _id):
+ """Register the material to the material factory."""
return LinearCohesive(model, _id)
mat_factory = aka.MaterialFactory.getInstance()
mat_factory.registerAllocator("local_cohesive", allocator)
# -------------------------------------------------------------------------
# Initialization
# -------------------------------------------------------------------------
aka.parseInput("local_material.dat")
mesh = aka.Mesh(spatial_dimension)
mesh.read("plate.msh")
model = aka.SolidMechanicsModelCohesive(mesh)
model.initFull(_analysis_method=aka._static, _is_extrinsic=True)
model.initNewSolver(aka._explicit_lumped_mass)
model.setBaseName("plate")
model.addDumpFieldVector("displacement")
model.addDumpFieldVector("external_force")
model.addDumpField("strain")
model.addDumpField("stress")
model.addDumpField("blocked_dofs")
model.setBaseNameToDumper("cohesive elements", "cohesive")
model.addDumpFieldVectorToDumper("cohesive elements", "displacement")
model.addDumpFieldToDumper("cohesive elements", "damage")
model.addDumpFieldVectorToDumper("cohesive elements", "tractions")
model.addDumpFieldVectorToDumper("cohesive elements", "opening")
# -------------------------------------------------------------------------
# Boundary conditions
# -------------------------------------------------------------------------
model.applyBC(aka.FixedValue(0.0, aka._x), "XBlocked")
model.applyBC(aka.FixedValue(0.0, aka._y), "YBlocked")
trac = np.zeros(spatial_dimension)
traction = 0.095
trac[int(aka._y)] = traction
model.getExternalForce()[:] = 0
model.applyBC(aka.FromTraction(trac), "Traction")
print("Solve for traction ", traction)
solver = model.getNonLinearSolver("static")
solver.set("max_iterations", 100)
solver.set("threshold", 1e-10)
solver.set("convergence_type", aka.SolveConvergenceCriteria.residual)
model.solveStep("static")
model.dump()
model.dump("cohesive elements")
model.setTimeStep(model.getStableTimeStep() * 0.1)
maxsteps = 100
for i in range(0, maxsteps):
print("{0}/{1}".format(i, maxsteps))
model.checkCohesiveStress()
model.solveStep("explicit_lumped")
if i % 10 == 0:
model.dump()
model.dump("cohesive elements")
diff --git a/examples/python/cohesive/plate.py b/examples/python/cohesive/plate.py
index 5f223c289..5547f78ec 100644
--- a/examples/python/cohesive/plate.py
+++ b/examples/python/cohesive/plate.py
@@ -1,97 +1,100 @@
#!/usr/bin/env python3
"""plate.py: Python example: plate with a hole breaking with cohesive
elements"""
__author__ = "Guillaume Anciaux"
__credits__ = [
"Guillaume Anciaux <guillaume.anciaux@epfl.ch>",
]
__copyright__ = (
"Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale"
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation"
" en Mécanique des Solides)"
)
__license__ = "LGPLv3"
import akantu as aka
import numpy as np
+def set_dumpers(model):
+ model.setBaseName("plate")
+ model.addDumpFieldVector("displacement")
+ model.addDumpFieldVector("external_force")
+ model.addDumpField("strain")
+ model.addDumpField("stress")
+ model.addDumpField("blocked_dofs")
+
+ model.setBaseNameToDumper("cohesive elements", "cohesive")
+ model.addDumpFieldVectorToDumper("cohesive elements", "displacement")
+ model.addDumpFieldToDumper("cohesive elements", "damage")
+ model.addDumpFieldVectorToDumper("cohesive elements", "tractions")
+ model.addDumpFieldVectorToDumper("cohesive elements", "opening")
+
def solve(material_file, mesh_file, traction):
aka.parseInput(material_file)
spatial_dimension = 2
# -------------------------------------------------------------------------
# Initialization
# -------------------------------------------------------------------------
mesh = aka.Mesh(spatial_dimension)
mesh.read(mesh_file)
model = aka.SolidMechanicsModelCohesive(mesh)
model.initFull(_analysis_method=aka._static, _is_extrinsic=True)
model.initNewSolver(aka._explicit_lumped_mass)
- model.setBaseName("plate")
- model.addDumpFieldVector("displacement")
- model.addDumpFieldVector("external_force")
- model.addDumpField("strain")
- model.addDumpField("stress")
- model.addDumpField("blocked_dofs")
-
- model.setBaseNameToDumper("cohesive elements", "cohesive")
- model.addDumpFieldVectorToDumper("cohesive elements", "displacement")
- model.addDumpFieldToDumper("cohesive elements", "damage")
- model.addDumpFieldVectorToDumper("cohesive elements", "tractions")
- model.addDumpFieldVectorToDumper("cohesive elements", "opening")
+ set_dumpers(model)
# -------------------------------------------------------------------------
# Boundary conditions
# -------------------------------------------------------------------------
model.applyBC(aka.FixedValue(0.0, aka._x), "XBlocked")
model.applyBC(aka.FixedValue(0.0, aka._y), "YBlocked")
trac = np.zeros(spatial_dimension)
trac[int(aka._y)] = traction
print("Solve for traction ", traction)
model.getExternalForce()[:] = 0
model.applyBC(aka.FromTraction(trac), "Traction")
solver = model.getNonLinearSolver("static")
solver.set("max_iterations", 100)
solver.set("threshold", 1e-10)
solver.set("convergence_type", aka.SolveConvergenceCriteria.residual)
model.solveStep("static")
model.dump()
model.dump("cohesive elements")
model.setTimeStep(model.getStableTimeStep() * 0.1)
maxsteps = 100
for i in range(0, maxsteps):
print("{0}/{1}".format(i, maxsteps))
model.checkCohesiveStress()
model.solveStep("explicit_lumped")
if i % 10 == 0:
model.dump()
model.dump("cohesive elements")
# -----------------------------------------------------------------------------
# main
# -----------------------------------------------------------------------------
def main():
mesh_file = "plate.msh"
material_file = "material.dat"
traction = 0.095
solve(material_file, mesh_file, traction)
# -----------------------------------------------------------------------------
if __name__ == "__main__":
main()
diff --git a/examples/python/contact-mechanics/compression.py b/examples/python/contact-mechanics/compression.py
index f35cb57a1..e587d8da4 100755
--- a/examples/python/contact-mechanics/compression.py
+++ b/examples/python/contact-mechanics/compression.py
@@ -1,81 +1,81 @@
#!/usr/bin/env python3
-""" compression.py: Python contact mechanics example"""
+"""compression.py: Python contact mechanics example."""
__author__ = "Mohit Pundir"
__credits__ = [
"Mohit Pundir <mohit.pundir@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import akantu as aka
-max_steps = 20000
+MAX_STEPS = 20000
max_displacement = 1e-2
damping_interval = 10
damping_ratio = 0.9
spatial_dimension = 2
aka.parseInput('compression.dat')
mesh = aka.Mesh(spatial_dimension)
mesh.read('compression.msh')
coupler = aka.CouplerSolidContact(mesh)
solid = coupler.getSolidMechanicsModel()
contact = coupler.getContactMechanicsModel()
material_selector = aka.MeshDataMaterialSelectorString("physical_names", solid)
solid.setMaterialSelector(material_selector)
coupler.initFull(_analysis_method=aka._explicit_lumped_mass)
surface_selector = aka.PhysicalSurfaceSelector(mesh)
detector = contact.getContactDetector()
detector.setSurfaceSelector(surface_selector)
solid.applyBC(aka.FixedValue(0.0, aka._x), "sides")
time_step = solid.getStableTimeStep()
time_step *= 0.1
coupler.setTimeStep(time_step)
coupler.setBaseName("compression")
coupler.addDumpFieldVector("displacement")
coupler.addDumpFieldVector("contact_force")
coupler.addDumpFieldVector("external_force")
coupler.addDumpFieldVector("internal_force")
coupler.addDumpField("gaps")
coupler.addDumpField("areas")
coupler.addDumpField("blocked_dofs")
coupler.addDumpField("grad_u")
coupler.addDumpField("stress")
coupler.dump()
velocity = solid.getVelocity()
-increment = max_displacement / max_steps
+increment = max_displacement / MAX_STEPS
-for s in range(0, max_steps):
+for s in range(0, MAX_STEPS):
print("Step : ", s)
solid.applyBC(aka.IncrementValue(-increment, aka._y), "loading")
solid.applyBC(aka.IncrementValue(increment, aka._y), "fixed")
coupler.solveStep()
if s % damping_interval == 0:
velocity *= damping_ratio
if s % 100 == 0:
coupler.dump()
diff --git a/examples/python/phase-field/phasefield-static.py b/examples/python/phase-field/phasefield-static.py
index 8962cf70e..765a58422 100644
--- a/examples/python/phase-field/phasefield-static.py
+++ b/examples/python/phase-field/phasefield-static.py
@@ -1,124 +1,132 @@
#!/usr/bin/env python
# coding: utf-8
""" phasefield-static.py: Static phase field example"""
__author__ = "Mohit Pundir"
__credits__ = [
"Mohit Pundir <mohit.pundir@epfl.ch>",
]
-__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
- " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
- " en Mécanique des Solides)"
+__copyright__ = (
+ "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale"
+ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation"
+ " en Mécanique des Solides)"
+)
__license__ = "LGPLv3"
import numpy as np
import akantu as aka
aka.parseInput("material_static.dat")
dim = 2
mesh = aka.Mesh(dim)
mesh.read("plate_static.msh")
model = aka.CouplerSolidPhaseField(mesh)
solid = model.getSolidMechanicsModel()
phase = model.getPhaseFieldModel()
solid.initFull(_analysis_method=aka._static)
-solver = solid.getNonLinearSolver('static')
-solver.set('max_iterations', 100)
-solver.set('threshold', 1e-9)
+solver = solid.getNonLinearSolver("static")
+solver.set("max_iterations", 100)
+solver.set("threshold", 1e-8)
solver.set("convergence_type", aka.SolveConvergenceCriteria.solution)
-solid.getNewSolver("linear_static", aka.TimeStepSolverType.static,
- aka.NonLinearSolverType.linear)
-solid.setIntegrationScheme("linear_static", "displacement",
- aka.IntegrationSchemeType.pseudo_time)
+solid.getNewSolver(
+ "linear_static", aka.TimeStepSolverType.static, aka.NonLinearSolverType.linear
+)
+solid.setIntegrationScheme(
+ "linear_static", "displacement", aka.IntegrationSchemeType.pseudo_time
+)
phase.initFull(_analysis_method=aka._static)
-phase.getNewSolver("nonlinear_static", aka.TimeStepSolverType.static,
- aka.NonLinearSolverType.newton_raphson)
-phase.setIntegrationScheme("nonlinear_static", "damage",
- aka.IntegrationSchemeType.pseudo_time)
-
-solver = phase.getNonLinearSolver('nonlinear_static')
-solver.set('max_iterations', 100)
-solver.set('threshold', 1e-4)
+phase.getNewSolver(
+ "nonlinear_static",
+ aka.TimeStepSolverType.static,
+ aka.NonLinearSolverType.newton_raphson,
+)
+phase.setIntegrationScheme(
+ "nonlinear_static", "damage", aka.IntegrationSchemeType.pseudo_time
+)
+
+solver = phase.getNonLinearSolver("nonlinear_static")
+solver.set("max_iterations", 100)
+solver.set("threshold", 1e-4)
solver.set("convergence_type", aka.SolveConvergenceCriteria.solution)
solid.applyBC(aka.FixedValue(0, aka._y), "bottom")
solid.applyBC(aka.FixedValue(0, aka._x), "left")
# Initialization for bulk vizualisation
-solid.setBaseName('phasefield-static')
-solid.addDumpFieldVector('displacement')
-solid.addDumpFieldVector('external_force')
-solid.addDumpField('strain')
-solid.addDumpField('stress')
-solid.addDumpField('damage')
-solid.addDumpField('blocked_dofs')
+solid.setBaseName("phasefield-static")
+solid.addDumpFieldVector("displacement")
+solid.addDumpFieldVector("external_force")
+solid.addDumpField("strain")
+solid.addDumpField("stress")
+solid.addDumpField("damage")
+solid.addDumpField("blocked_dofs")
nb_dofs = solid.getMesh().getNbNodes() * dim
increment = solid.getIncrement()
displacement = solid.getDisplacement()
displacement = displacement.reshape(nb_dofs)
blocked_dofs = solid.getBlockedDOFs()
blocked_dofs = blocked_dofs.reshape(nb_dofs)
damage = phase.getDamage()
tolerance = 1e-5
steps = 1000
increment = 5e-6
for n in range(steps):
print("Computing iteration " + str(n + 1) + "/" + str(steps))
- solid.applyBC(aka.IncrementValue(increment, aka._y), 'top')
+ solid.applyBC(aka.IncrementValue(increment, aka._y), "top")
mask = blocked_dofs == False # NOQA: E712
iiter = 0
error_disp = 1
error_dam = 1
displacement_prev = displacement[mask].copy()
damage_prev = damage.copy()
damage_prev = damage_prev
# solve using staggered scheme
- while (error_disp > tolerance or error_dam > tolerance):
+ while error_disp > tolerance or error_dam > tolerance:
model.solve("linear_static", "")
displacement_new = displacement[mask]
damage_new = damage
delta_disp = displacement_new - displacement_prev
delta_dam = damage_new - damage_prev
error_disp = np.linalg.norm(delta_disp)
error_dam = np.linalg.norm(delta_dam)
iiter += 1
displacement_prev = displacement_new.copy()
damage_prev = damage_new.copy()
print(error_dam, error_disp)
if iiter > 500:
- raise Exception('Convergence not reached')
+ raise Exception("Convergence not reached")
if n % 50 == 0:
solid.dump()
solid.dump()
diff --git a/examples/python/structural_mechanics/structural_mechanics.py b/examples/python/structural_mechanics/structural_mechanics.py
index 4b65c2fd6..855107200 100644
--- a/examples/python/structural_mechanics/structural_mechanics.py
+++ b/examples/python/structural_mechanics/structural_mechanics.py
@@ -1,151 +1,150 @@
#!/usr/bin/env python
# coding: utf-8
-
-""" structural_mechanics.py: Simple structural mechanics example"""
+"""structural_mechanics.py: Simple structural mechanics example."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
# # Test of Structural Mechanics
# In this example a beam, consisting of two elements, three nodes, is created.
# The left most node is fixed and a force is applied at the right most node.
import numpy as np
try:
import matplotlib.pyplot as plt
- has_matplotlib = True
+ HAS_MATPLOTLIB = True
except ImportError:
- has_matplotlib = False
+ HAS_MATPLOTLIB = False
import akantu as aka
# ### Creating the Mesh
# Create a mesh for the two dimensional case
beam = aka.Mesh(2)
# We now create the connectivity array for the beam.
beam.addConnectivityType(aka._bernoulli_beam_2)
# We need a `MeshAccessor` in order to change the size of the mesh entities.
beamAcc = aka.MeshAccessor(beam)
# Now we create the array to store the nodes and the connectivities and give
# them their size.
beamAcc.resizeConnectivity(2, aka._bernoulli_beam_2)
beamAcc.resizeNodes(3)
Nodes = beam.getNodes()
Nodes[0, :] = [0., 0.]
Nodes[1, :] = [1., 0.]
Nodes[2, :] = [2., 0.]
# #### Setting the Connections
Conn = beam.getConnectivity(aka._bernoulli_beam_2)
Conn[0, :] = [0, 1]
Conn[1, :] = [1, 2]
# #### Ready
# We have to make the mesh ready.
beamAcc.makeReady()
# ### Creating the Model
model = aka.StructuralMechanicsModel(beam)
# #### Setting up the Modell
# ##### Creating and Inserting the Materials
mat1 = aka.StructuralMaterial()
mat1.E = 1e9
mat1.rho = 1.
mat1.I = 1. # noqa: E741
mat1.Iz = 1.
mat1.Iy = 1.
mat1.A = 1.
mat1.GJ = 1.
model.addMaterial(mat1)
mat2 = aka.StructuralMaterial()
mat2.E = 1e9
mat2.rho = 1.
mat2.I = 1. # noqa: E741
mat2.Iz = 1.
mat2.Iy = 1.
mat2.A = 1.
mat2.GJ = 1.
model.addMaterial(mat2)
# ##### Initializing the Model
model.initFull(aka._implicit_dynamic)
# ##### Assigning the Materials
materials = model.getElementMaterial(aka._bernoulli_beam_2)
materials[0][0] = 0
materials[1][0] = 1
# ##### Setting Boundaries
# Neumann
# Apply a force of `10` at the last (right most) node.
forces = model.getExternalForce()
forces[:] = 0
forces[2, 0] = 100.
# Dirichlets
# Block all dofs of the first node, since it is fixed.
# All other nodes have no restrictions
boundary = model.getBlockedDOFs()
boundary[0, :] = True
boundary[1, :] = False
boundary[2, :] = False
# ### Solving the System
# Set up the system
deltaT = 1e-10
model.setTimeStep(deltaT)
solver = model.getNonLinearSolver()
solver.set("max_iterations", 100)
solver.set("threshold", 1e-8)
solver.set("convergence_type", aka.SolveConvergenceCriteria.solution)
# Perform N time steps.
# At each step records the displacement of all three nodes in x direction.
N = 1000000
disp1 = np.zeros(N)
disp2 = np.zeros(N)
disp0 = np.zeros(N)
times = np.zeros(N)
for i in range(N):
model.solveStep()
disp = model.getDisplacement()
disp0[i] = disp[0, 0]
disp1[i] = disp[1, 0]
disp2[i] = disp[2, 0]
times[i] = deltaT * i
disps = [disp0, disp1, disp2]
maxMin = [-1.0, 1.0]
for d in disps:
maxMin[0] = max(np.max(d), maxMin[0])
maxMin[1] = min(np.min(d), maxMin[1])
-if has_matplotlib:
+if HAS_MATPLOTLIB:
plt.plot(disp1, times, color='g', label="middle node")
plt.plot(disp2, times, color='b', label="right node")
plt.title("Displacement in $x$ of the nodes")
plt.ylabel("Time [S]")
plt.xlabel("displacement [m]")
plt.xlim((maxMin[1] * 1.3, maxMin[0] * 1.1))
plt.legend()
plt.show()
diff --git a/examples/python/structural_mechanics/structural_mechanics_dynamics.py b/examples/python/structural_mechanics/structural_mechanics_dynamics.py
index cdb3577cd..254474d23 100644
--- a/examples/python/structural_mechanics/structural_mechanics_dynamics.py
+++ b/examples/python/structural_mechanics/structural_mechanics_dynamics.py
@@ -1,185 +1,187 @@
#!/usr/bin/env python
-# coding: utf-8
-""" structural_mechanics_dynamics.py: Dynamics structural mechanics example"""
+"""Structural_mechanics_dynamics.py: Dynamics structural mechanics example."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import numpy as np
try:
import matplotlib.pyplot as plt
has_matplotlib = True
except ImportError:
has_matplotlib = False
import akantu as aka
# ### Creating the Mesh
# Create a mesh for the two dimensional case
el_type = aka._bernoulli_beam_2
beam = aka.Mesh(2)
# We now create the connectivity array for the beam.
beam.addConnectivityType(el_type)
# We need a `MeshAccessor` in order to change the size of the mesh entities.
beamAcc = aka.MeshAccessor(beam)
# Now we create the array to store the nodes and the connectivities and give
# them their size.
nb_elem = 40
L = 2
beamAcc.resizeConnectivity(nb_elem, el_type)
beamAcc.resizeNodes(nb_elem + 1)
# #### Setting the Nodes
Nodes = beam.getNodes()
length = L / nb_elem
Nodes[:, :] = 0.
Nodes[:, 0] = np.arange(nb_elem+1) * length
# #### Setting the Connections
Conn = beam.getConnectivity(el_type)
for e in range(nb_elem):
Conn[e, :] = [e, e + 1]
# #### Ready
# We have to make the mesh ready.
beamAcc.makeReady()
# ### Creating the Model
model = aka.StructuralMechanicsModel(beam)
if el_type == aka._bernoulli_beam_3:
normal = beam.getDataReal("extra_normal", el_type)
for e in range(nb_elem):
normal[e, :] = [0, 0, 1]
# #### Setting up the Modell
# ##### Creating and Inserting the Materials
mat1 = aka.StructuralMaterial()
mat1.E = 1e9
mat1.rho = 10.
mat1.I = 1. # noqa: E741
mat1.Iz = 1.
mat1.Iy = 1.
mat1.A = 1.
mat1.GJ = 1.
model.addMaterial(mat1, 'mat1')
# ##### Initializing the Model
model.initFull(aka.AnalysisMethod._implicit_dynamic)
# ##### Assigning the Materials
materials = model.getElementMaterial(el_type)
materials[:, :] = 0
# ##### Setting Boundaries
# Neumann
F = 1e4
no_print = int(nb_elem / 2)
# Apply a force of `10` at the last (right most) node.
forces = model.getExternalForce()
forces[:, :] = 0
forces[no_print, 1] = F
# Dirichlets
# Block all dofs of the first node, since it is fixed.
# All other nodes have no restrictions
boundary = model.getBlockedDOFs()
boundary[:, :] = False
boundary[0, 0] = True
boundary[0, 1] = True
if el_type == aka._bernoulli_beam_3:
boundary[0, 2] = True
boundary[nb_elem, 1] = True
# ### Solving the System
# Set up the system
deltaT = 1e-6
model.setTimeStep(deltaT)
solver = model.getNonLinearSolver()
solver.set("max_iterations", 100)
solver.set("threshold", 1e-8)
solver.set("convergence_type", aka.SolveConvergenceCriteria.solution)
model.assembleMatrix("M")
M_ = model.getDOFManager().getMatrix("M")
M = aka.AkantuSparseMatrix(M_)
model.assembleMatrix("K")
K_ = model.getDOFManager().getMatrix("K")
K = aka.AkantuSparseMatrix(K_)
C_ = model.getDOFManager().getMatrix("C")
C_.add(M_, 0.00001)
C_.add(K_, 0.00001)
-def analytical_solution(time, L, rho, E, A, I, F): # noqa: E741
+def analytical_solution(time, L=1., rho=1.,
+ E=1., A=1., I=1., F=1.): # noqa: E741
+ """Compute the analytical solution of the beam bending at a give time."""
omega = np.pi**2 / L**2 * np.sqrt(E * I / rho)
sum = 0.
N = 110
for n in range(1, N, 2):
sum += (1. - np.cos(n * n * omega * time)) / n**4
return 2. * F * L**3 / np.pi**4 / E / I * sum
# Perform N time steps.
# At each step records the displacement of all three nodes in x direction.
N = 900
mat1 = model.getMaterial('mat1')
disp = model.getDisplacement()
velo = model.getVelocity()
disp[:, :] = 0.
displs = np.zeros(N)
ekin = np.zeros(N)
epot = np.zeros(N)
ework = np.zeros(N)
_ework = 0.
for i in range(1, N):
model.solveStep()
displs[i] = disp[no_print, 1]
_ework += F * velo[no_print, 1] * deltaT
ekin[i] = model.getEnergy("kinetic")
epot[i] = model.getEnergy("potential")
ework[i] = _ework
def sol(x):
- return analytical_solution(x, L, mat1.rho, mat1.E,
- mat1.A, mat1.I, F)
+ """Wrap the call to the analytical solution using mat1."""
+ return analytical_solution(x, L=L, rho=mat1.rho, E=mat1.E,
+ A=mat1.A, I=mat1.I, F=F)
if has_matplotlib:
times = np.arange(N) * deltaT
plt.plot(times, sol(times))
plt.plot(times, displs)
plt.plot(times, displs - sol(times))
# What I do not fully understand is why the middle node first go backwards
# until it goes forward. I could imagine that there is some vibration,
# because everything is in rest.
np.max(displs - sol(times))
plt.plot(times, ekin+epot)
plt.plot(times, ework)
diff --git a/examples/static/static.cc b/examples/static/static.cc
index ff3dfa20f..27148e417 100644
--- a/examples/static/static.cc
+++ b/examples/static/static.cc
@@ -1,81 +1,81 @@
/**
* @file static.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Oumaima Sabir <oumaima.sabir@epfl.ch>
*
* @date creation: Mon Aug 09 2010
* @date last modification: Sun Dec 30 2018
*
* @brief This code refers to the implicit static example from the user manual
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
#define bar_length 0.01
#define bar_height 0.01
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("square.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull(_analysis_method = _static);
model.setBaseName("static");
model.addDumpFieldVector("displacement");
model.addDumpField("external_force");
model.addDumpField("internal_force");
model.addDumpField("grad_u");
model.addDumpField("stress");
/// Dirichlet boundary conditions
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed_x");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed_y");
model.applyBC(BC::Dirichlet::FixedValue(0.0001, _y), "Traction");
model.dump();
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 2);
solver.set("threshold", 2e-4);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
model.solveStep();
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/structural_mechanics/bernoulli_beam_2_example.cc b/examples/structural_mechanics/bernoulli_beam_2_example.cc
index be255f5c3..1692b2afd 100644
--- a/examples/structural_mechanics/bernoulli_beam_2_example.cc
+++ b/examples/structural_mechanics/bernoulli_beam_2_example.cc
@@ -1,142 +1,142 @@
/**
* @file bernoulli_beam_2_example.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
*
* @date creation: Fri Jul 15 2011
* @date last modification: Mon Mar 15 2021
*
* @brief Computation of the analytical exemple 1.1 in the TGC vol 6
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_accessor.hh"
#include "structural_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
#define TYPE _bernoulli_beam_2
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
// Defining the mesh
Mesh beams(2);
const auto q = 6000.;
const auto L = 10.;
const auto M = -3600.; // Momentum at 3
auto nb_nodes = 3;
auto nb_element = nb_nodes - 1;
MeshAccessor mesh_accessor(beams);
Array<Real> & nodes = mesh_accessor.getNodes();
nodes.resize(nb_nodes);
beams.addConnectivityType(_bernoulli_beam_2);
- Array<UInt> & connectivity = mesh_accessor.getConnectivity(_bernoulli_beam_2);
+ auto & connectivity = mesh_accessor.getConnectivity(_bernoulli_beam_2);
connectivity.resize(nb_element);
nodes.zero();
nodes(1, 0) = 10;
nodes(2, 0) = 18;
for (int i = 0; i < nb_element; ++i) {
connectivity(i, 0) = i;
connectivity(i, 1) = i + 1;
}
mesh_accessor.makeReady();
// Defining the materials
StructuralMechanicsModel model(beams);
StructuralMaterial mat1;
mat1.E = 3e10;
mat1.I = 0.0025;
mat1.A = 0.01;
model.addMaterial(mat1);
StructuralMaterial mat2;
mat2.E = 3e10;
mat2.I = 0.00128;
mat2.A = 0.01;
model.addMaterial(mat2);
// Defining the forces
model.initFull();
auto & forces = model.getExternalForce();
auto & displacement = model.getDisplacement();
auto & boundary = model.getBlockedDOFs();
const auto & N_M = model.getStress(_bernoulli_beam_2);
auto & element_material = model.getElementMaterial(_bernoulli_beam_2);
boundary.set(false);
forces.zero();
displacement.zero();
element_material(1) = 1;
forces(0, 1) = -q * L / 2.;
forces(0, 2) = -q * L * L / 12.;
forces(1, 1) = -q * L / 2.;
forces(1, 2) = q * L * L / 12.;
forces(2, 2) = M;
forces(2, 0) = mat2.E * mat2.A / 18;
// Defining the boundary conditions
boundary(0, 0) = true;
boundary(0, 1) = true;
boundary(0, 2) = true;
boundary(1, 1) = true;
boundary(2, 1) = true;
model.addDumpFieldVector("displacement");
model.addDumpField("rotation");
model.addDumpFieldVector("force");
model.addDumpField("momentum");
model.solveStep();
model.assembleResidual();
// Post-Processing
std::cout << " d1 = " << displacement(1, 2) << std::endl;
std::cout << " d2 = " << displacement(2, 2) << std::endl;
std::cout << " d3 = " << displacement(1, 0) << std::endl;
std::cout << " M1 = " << N_M(0, 1) << std::endl;
std::cout << " M2 = " << N_M(2 * (nb_nodes - 2), 1) << std::endl;
model.dump();
finalize();
}
diff --git a/extra_packages/extra-materials/src/material_FE2/material_FE2.cc b/extra_packages/extra-materials/src/material_FE2/material_FE2.cc
index 31ba698b5..39ed9675e 100644
--- a/extra_packages/extra-materials/src/material_FE2/material_FE2.cc
+++ b/extra_packages/extra-materials/src/material_FE2/material_FE2.cc
@@ -1,198 +1,198 @@
/**
* @file material_FE2.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @brief Material for multi-scale simulations. It stores an
* underlying RVE on each integration point of the material.
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_FE2.hh"
#include "communicator.hh"
#include "solid_mechanics_model_RVE.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialFE2<spatial_dimension>::MaterialFE2(SolidMechanicsModel & model,
const ID & id)
: Parent(model, id), C("material_stiffness", *this) {
AKANTU_DEBUG_IN();
this->C.initialize(voigt_h::size * voigt_h::size);
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialFE2<spatial_dimension>::~MaterialFE2() = default;
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialFE2<dim>::initialize() {
+template <Int dim> void MaterialFE2<dim>::initialize() {
this->registerParam("element_type", el_type, _triangle_3,
_pat_parsable | _pat_modifiable,
"element type in RVE mesh");
this->registerParam("mesh_file", mesh_file, _pat_parsable | _pat_modifiable,
"the mesh file for the RVE");
this->registerParam("nb_gel_pockets", nb_gel_pockets,
_pat_parsable | _pat_modifiable,
"the number of gel pockets in each RVE");
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialFE2<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
Parent::initMaterial();
/// create a Mesh and SolidMechanicsModel on each integration point of the
/// material
auto C_it = this->C(this->el_type).begin(voigt_h::size, voigt_h::size);
for (auto && data :
enumerate(make_view(C(this->el_type), voigt_h::size, voigt_h::size))) {
auto q = std::get<0>(data);
auto & C = std::get<1>(data);
meshes.emplace_back(std::make_unique<Mesh>(
spatial_dimension, "RVE_mesh_" + std::to_string(q), q + 1));
auto & mesh = *meshes.back();
mesh.read(mesh_file);
RVEs.emplace_back(std::make_unique<SolidMechanicsModelRVE>(
mesh, true, this->nb_gel_pockets, _all_dimensions,
"SMM_RVE_" + std::to_string(q), q + 1));
auto & RVE = *RVEs.back();
RVE.initFull(_analysis_method = _static);
/// compute intial stiffness of the RVE
RVE.homogenizeStiffness(C);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialFE2<spatial_dimension>::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
// Compute thermal stresses first
Parent::computeStress(el_type, ghost_type);
Array<Real>::const_scalar_iterator sigma_th_it =
this->sigma_th(el_type, ghost_type).begin();
// Wikipedia convention:
// 2*eps_ij (i!=j) = voigt_eps_I
// http://en.wikipedia.org/wiki/Voigt_notation
Array<Real>::const_matrix_iterator C_it =
this->C(el_type, ghost_type).begin(voigt_h::size, voigt_h::size);
// create vectors to store stress and strain in Voigt notation
// for efficient computation of stress
Vector<Real> voigt_strain(voigt_h::size);
Vector<Real> voigt_stress(voigt_h::size);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
const Matrix<Real> & C_mat = *C_it;
const Real & sigma_th = *sigma_th_it;
/// copy strains in Voigt notation
- for (UInt I = 0; I < voigt_h::size; ++I) {
+ for (Int I = 0; I < voigt_h::size; ++I) {
/// copy stress in
Real voigt_factor = voigt_h::factors[I];
UInt i = voigt_h::vec[I][0];
UInt j = voigt_h::vec[I][1];
voigt_strain(I) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.;
}
// compute stresses in Voigt notation
voigt_stress.mul<false>(C_mat, voigt_strain);
/// copy stresses back in full vectorised notation
- for (UInt I = 0; I < voigt_h::size; ++I) {
+ for (Int I = 0; I < voigt_h::size; ++I) {
UInt i = voigt_h::vec[I][0];
UInt j = voigt_h::vec[I][1];
sigma(i, j) = sigma(j, i) = voigt_stress(I) + (i == j) * sigma_th;
}
++C_it;
++sigma_th_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialFE2<spatial_dimension>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Array<Real>::const_matrix_iterator C_it =
this->C(el_type, ghost_type).begin(voigt_h::size, voigt_h::size);
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
tangent.copy(*C_it);
++C_it;
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialFE2<spatial_dimension>::advanceASR(
const Matrix<Real> & prestrain) {
AKANTU_DEBUG_IN();
for (auto && data :
zip(RVEs,
make_view(this->gradu(this->el_type), spatial_dimension,
spatial_dimension),
make_view(this->eigengradu(this->el_type), spatial_dimension,
spatial_dimension),
make_view(this->C(this->el_type), voigt_h::size, voigt_h::size),
this->delta_T(this->el_type))) {
auto & RVE = *(std::get<0>(data));
/// apply boundary conditions based on the current macroscopic displ.
/// gradient
RVE.applyBoundaryConditions(std::get<1>(data));
/// apply homogeneous temperature field to each RVE to obtain thermoelastic
/// effect
RVE.applyHomogeneousTemperature(std::get<4>(data));
/// advance the ASR in every RVE
RVE.advanceASR(prestrain);
/// compute the average eigen_grad_u
RVE.homogenizeEigenGradU(std::get<2>(data));
/// compute the new effective stiffness of the RVE
RVE.homogenizeStiffness(std::get<3>(data));
}
AKANTU_DEBUG_OUT();
}
INSTANTIATE_MATERIAL(material_FE2, MaterialFE2);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc
index 87262a9f1..30770fa01 100644
--- a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc
+++ b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.cc
@@ -1,602 +1,602 @@
/**
* @file solid_mechanics_model_RVE.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Wed Jan 13 15:32:35 2016
*
* @brief Implementation of SolidMechanicsModelRVE
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_RVE.hh"
#include "element_group.hh"
#include "material_damage_iterative.hh"
#include "node_group.hh"
#include "non_linear_solver.hh"
#include "non_local_manager.hh"
#include "parser.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
#include <string>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
SolidMechanicsModelRVE::SolidMechanicsModelRVE(Mesh & mesh,
bool use_RVE_mat_selector,
- UInt nb_gel_pockets, UInt dim,
+ UInt nb_gel_pockets, Int dim,
const ID & id)
: SolidMechanicsModel(mesh, dim, id), volume(0.),
use_RVE_mat_selector(use_RVE_mat_selector),
nb_gel_pockets(nb_gel_pockets), nb_dumps(0) {
AKANTU_DEBUG_IN();
/// find the four corner nodes of the RVE
findCornerNodes();
/// remove the corner nodes from the surface node groups:
/// This most be done because corner nodes a not periodic
mesh.getElementGroup("top").removeNode(corner_nodes(2));
mesh.getElementGroup("top").removeNode(corner_nodes(3));
mesh.getElementGroup("left").removeNode(corner_nodes(3));
mesh.getElementGroup("left").removeNode(corner_nodes(0));
mesh.getElementGroup("bottom").removeNode(corner_nodes(1));
mesh.getElementGroup("bottom").removeNode(corner_nodes(0));
mesh.getElementGroup("right").removeNode(corner_nodes(2));
mesh.getElementGroup("right").removeNode(corner_nodes(1));
const auto & bottom = mesh.getElementGroup("bottom").getNodeGroup();
bottom_nodes.insert(bottom.begin(), bottom.end());
const auto & left = mesh.getElementGroup("left").getNodeGroup();
left_nodes.insert(left.begin(), left.end());
// /// enforce periodicity on the displacement fluctuations
// auto surface_pair_1 = std::make_pair("top", "bottom");
// auto surface_pair_2 = std::make_pair("right", "left");
// SurfacePairList surface_pairs_list;
// surface_pairs_list.push_back(surface_pair_1);
// surface_pairs_list.push_back(surface_pair_2);
// TODO: To Nicolas correct the PBCs
// this->setPBC(surface_pairs_list);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
SolidMechanicsModelRVE::~SolidMechanicsModelRVE() = default;
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::initFullImpl(const ModelOptions & options) {
AKANTU_DEBUG_IN();
auto options_cp(options);
options_cp.analysis_method = AnalysisMethod::_static;
SolidMechanicsModel::initFullImpl(options_cp);
// this->initMaterials();
auto & fem = this->getFEEngine("SolidMechanicsFEEngine");
/// compute the volume of the RVE
GhostType gt = _not_ghost;
for (auto element_type :
this->mesh.elementTypes(spatial_dimension, gt, _ek_not_defined)) {
Array<Real> Volume(this->mesh.getNbElement(element_type) *
fem.getNbIntegrationPoints(element_type),
1, 1.);
this->volume = fem.integrate(Volume, element_type);
}
std::cout << "The volume of the RVE is " << this->volume << std::endl;
/// dumping
std::stringstream base_name;
base_name << this->id;
this->setBaseName(base_name.str());
this->addDumpFieldVector("displacement");
this->addDumpField("stress");
this->addDumpField("grad_u");
this->addDumpField("eigen_grad_u");
this->addDumpField("blocked_dofs");
this->addDumpField("material_index");
this->addDumpField("damage");
this->addDumpField("Sc");
this->addDumpField("external_force");
this->addDumpField("equivalent_stress");
this->addDumpField("internal_force");
this->addDumpField("delta_T");
this->dump();
this->nb_dumps += 1;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::applyBoundaryConditions(
const Matrix<Real> & displacement_gradient) {
AKANTU_DEBUG_IN();
/// get the position of the nodes
const Array<Real> & pos = mesh.getNodes();
/// storage for the coordinates of a given node and the displacement that will
/// be applied
Vector<Real> x(spatial_dimension);
Vector<Real> appl_disp(spatial_dimension);
/// fix top right node
UInt node = this->corner_nodes(2);
x(0) = pos(node, 0);
x(1) = pos(node, 1);
appl_disp.mul<false>(displacement_gradient, x);
(*this->blocked_dofs)(node, 0) = true;
(*this->displacement)(node, 0) = appl_disp(0);
(*this->blocked_dofs)(node, 1) = true;
(*this->displacement)(node, 1) = appl_disp(1);
// (*this->blocked_dofs)(node,0) = true; (*this->displacement)(node,0) = 0.;
// (*this->blocked_dofs)(node,1) = true; (*this->displacement)(node,1) = 0.;
/// apply Hx at all the other corner nodes; H: displ. gradient
node = this->corner_nodes(0);
x(0) = pos(node, 0);
x(1) = pos(node, 1);
appl_disp.mul<false>(displacement_gradient, x);
(*this->blocked_dofs)(node, 0) = true;
(*this->displacement)(node, 0) = appl_disp(0);
(*this->blocked_dofs)(node, 1) = true;
(*this->displacement)(node, 1) = appl_disp(1);
node = this->corner_nodes(1);
x(0) = pos(node, 0);
x(1) = pos(node, 1);
appl_disp.mul<false>(displacement_gradient, x);
(*this->blocked_dofs)(node, 0) = true;
(*this->displacement)(node, 0) = appl_disp(0);
(*this->blocked_dofs)(node, 1) = true;
(*this->displacement)(node, 1) = appl_disp(1);
node = this->corner_nodes(3);
x(0) = pos(node, 0);
x(1) = pos(node, 1);
appl_disp.mul<false>(displacement_gradient, x);
(*this->blocked_dofs)(node, 0) = true;
(*this->displacement)(node, 0) = appl_disp(0);
(*this->blocked_dofs)(node, 1) = true;
(*this->displacement)(node, 1) = appl_disp(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::applyHomogeneousTemperature(
const Real & temperature) {
for (UInt m = 0; m < this->getNbMaterials(); ++m) {
Material & mat = this->getMaterial(m);
- const ElementTypeMapArray<UInt> & filter_map = mat.getElementFilter();
+ const ElementTypeMapArray<Idx> & filter_map = mat.getElementFilter();
// Loop over all element types
for (auto && type : filter_map.elementTypes(spatial_dimension)) {
- const Array<UInt> & filter = filter_map(type);
+ const Array<Idx> & filter = filter_map(type);
if (filter.size() == 0)
continue;
Array<Real> & delta_T = mat.getArray<Real>("delta_T", type);
Array<Real>::scalar_iterator delta_T_it = delta_T.begin();
Array<Real>::scalar_iterator delta_T_end = delta_T.end();
for (; delta_T_it != delta_T_end; ++delta_T_it) {
*delta_T_it = temperature;
}
}
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::findCornerNodes() {
AKANTU_DEBUG_IN();
// find corner nodes
const auto & position = mesh.getNodes();
const auto & lower_bounds = mesh.getLowerBounds();
const auto & upper_bounds = mesh.getUpperBounds();
AKANTU_DEBUG_ASSERT(spatial_dimension == 2, "This is 2D only!");
corner_nodes.resize(4);
corner_nodes.set(UInt(-1));
for (auto && data : enumerate(make_view(position, spatial_dimension))) {
auto node = std::get<0>(data);
const auto & X = std::get<1>(data);
auto distance = X.distance(lower_bounds);
// node 1
if (Math::are_float_equal(distance, 0)) {
corner_nodes(0) = node;
}
// node 2
else if (Math::are_float_equal(X(_x), upper_bounds(_x)) &&
Math::are_float_equal(X(_y), lower_bounds(_y))) {
corner_nodes(1) = node;
}
// node 3
else if (Math::are_float_equal(X(_x), upper_bounds(_x)) &&
Math::are_float_equal(X(_y), upper_bounds(_y))) {
corner_nodes(2) = node;
}
// node 4
else if (Math::are_float_equal(X(_x), lower_bounds(_x)) &&
Math::are_float_equal(X(_y), upper_bounds(_y))) {
corner_nodes(3) = node;
}
}
for (UInt i = 0; i < corner_nodes.size(); ++i) {
if (corner_nodes(i) == UInt(-1))
AKANTU_ERROR("The corner node " << i + 1 << " wasn't found");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::advanceASR(const Matrix<Real> & prestrain) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(spatial_dimension == 2, "This is 2D only!");
/// apply the new eigenstrain
for (auto element_type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) {
Array<Real> & prestrain_vect =
const_cast<Array<Real> &>(this->getMaterial("gel").getInternal<Real>(
"eigen_grad_u")(element_type));
auto prestrain_it =
prestrain_vect.begin(spatial_dimension, spatial_dimension);
auto prestrain_end =
prestrain_vect.end(spatial_dimension, spatial_dimension);
for (; prestrain_it != prestrain_end; ++prestrain_it)
(*prestrain_it) = prestrain;
}
/// advance the damage
MaterialDamageIterative<2> & mat_paste =
dynamic_cast<MaterialDamageIterative<2> &>(*this->materials[1]);
MaterialDamageIterative<2> & mat_aggregate =
dynamic_cast<MaterialDamageIterative<2> &>(*this->materials[0]);
UInt nb_damaged_elements = 0;
Real max_eq_stress_aggregate = 0;
Real max_eq_stress_paste = 0;
auto & solver = this->getNonLinearSolver();
solver.set("max_iterations", 2);
solver.set("threshold", 1e-6);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
do {
this->solveStep();
/// compute damage
max_eq_stress_aggregate = mat_aggregate.getNormMaxEquivalentStress();
max_eq_stress_paste = mat_paste.getNormMaxEquivalentStress();
nb_damaged_elements = 0;
if (max_eq_stress_aggregate > max_eq_stress_paste)
nb_damaged_elements = mat_aggregate.updateDamage();
else if (max_eq_stress_aggregate < max_eq_stress_paste)
nb_damaged_elements = mat_paste.updateDamage();
else
nb_damaged_elements =
(mat_paste.updateDamage() + mat_aggregate.updateDamage());
std::cout << "the number of damaged elements is " << nb_damaged_elements
<< std::endl;
} while (nb_damaged_elements);
if (this->nb_dumps % 10 == 0) {
this->dump();
}
this->nb_dumps += 1;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModelRVE::averageTensorField(UInt row_index, UInt col_index,
const ID & field_type) {
AKANTU_DEBUG_IN();
auto & fem = this->getFEEngine("SolidMechanicsFEEngine");
Real average = 0;
GhostType gt = _not_ghost;
for (auto element_type :
mesh.elementTypes(spatial_dimension, gt, _ek_not_defined)) {
if (field_type == "stress") {
for (UInt m = 0; m < this->materials.size(); ++m) {
const auto & stress_vec = this->materials[m]->getStress(element_type);
const auto & elem_filter =
this->materials[m]->getElementFilter(element_type);
Array<Real> int_stress_vec(elem_filter.size(),
spatial_dimension * spatial_dimension,
"int_of_stress");
fem.integrate(stress_vec, int_stress_vec,
spatial_dimension * spatial_dimension, element_type,
_not_ghost, elem_filter);
for (UInt k = 0; k < elem_filter.size(); ++k)
average += int_stress_vec(k, row_index * spatial_dimension +
col_index); // 3 is the value
// for the yy (in
// 3D, the value is
// 4)
}
} else if (field_type == "strain") {
for (UInt m = 0; m < this->materials.size(); ++m) {
const auto & gradu_vec = this->materials[m]->getGradU(element_type);
const auto & elem_filter =
this->materials[m]->getElementFilter(element_type);
Array<Real> int_gradu_vec(elem_filter.size(),
spatial_dimension * spatial_dimension,
"int_of_gradu");
fem.integrate(gradu_vec, int_gradu_vec,
spatial_dimension * spatial_dimension, element_type,
_not_ghost, elem_filter);
for (UInt k = 0; k < elem_filter.size(); ++k)
/// averaging is done only for normal components, so stress and strain
/// are equal
average +=
0.5 *
(int_gradu_vec(k, row_index * spatial_dimension + col_index) +
int_gradu_vec(k, col_index * spatial_dimension + row_index));
}
} else if (field_type == "eigen_grad_u") {
for (UInt m = 0; m < this->materials.size(); ++m) {
const auto & eigen_gradu_vec =
this->materials[m]->getInternal<Real>("eigen_grad_u")(element_type);
const auto & elem_filter =
this->materials[m]->getElementFilter(element_type);
Array<Real> int_eigen_gradu_vec(elem_filter.size(),
spatial_dimension * spatial_dimension,
"int_of_gradu");
fem.integrate(eigen_gradu_vec, int_eigen_gradu_vec,
spatial_dimension * spatial_dimension, element_type,
_not_ghost, elem_filter);
for (UInt k = 0; k < elem_filter.size(); ++k)
/// averaging is done only for normal components, so stress and strain
/// are equal
average +=
int_eigen_gradu_vec(k, row_index * spatial_dimension + col_index);
}
} else {
AKANTU_ERROR("Averaging not implemented for this field!!!");
}
}
return average / this->volume;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::homogenizeStiffness(Matrix<Real> & C_macro) {
AKANTU_DEBUG_IN();
- const UInt dim = 2;
+ const Int dim = 2;
AKANTU_DEBUG_ASSERT(this->spatial_dimension == dim,
"Is only implemented for 2D!!!");
/// apply three independent loading states to determine C
/// 1. eps_el = (1;0;0) 2. eps_el = (0,1,0) 3. eps_el = (0,0,0.5)
/// clear the eigenstrain
Matrix<Real> zero_eigengradu(dim, dim, 0.);
GhostType gt = _not_ghost;
for (auto element_type : mesh.elementTypes(dim, gt, _ek_not_defined)) {
auto & prestrain_vect =
const_cast<Array<Real> &>(this->getMaterial("gel").getInternal<Real>(
"eigen_grad_u")(element_type));
auto prestrain_it =
prestrain_vect.begin(spatial_dimension, spatial_dimension);
auto prestrain_end =
prestrain_vect.end(spatial_dimension, spatial_dimension);
for (; prestrain_it != prestrain_end; ++prestrain_it)
(*prestrain_it) = zero_eigengradu;
}
/// storage for results of 3 different loading states
UInt voigt_size = VoigtHelper<dim>::size;
Matrix<Real> stresses(voigt_size, voigt_size, 0.);
Matrix<Real> strains(voigt_size, voigt_size, 0.);
Matrix<Real> H(dim, dim, 0.);
/// save the damage state before filling up cracks
// ElementTypeMapReal saved_damage("saved_damage");
// saved_damage.initialize(getFEEngine(), _nb_component = 1, _default_value =
// 0);
// this->fillCracks(saved_damage);
/// virtual test 1:
H(0, 0) = 0.01;
this->performVirtualTesting(H, stresses, strains, 0);
/// virtual test 2:
H.zero();
H(1, 1) = 0.01;
this->performVirtualTesting(H, stresses, strains, 1);
/// virtual test 3:
H.zero();
H(0, 1) = 0.01;
this->performVirtualTesting(H, stresses, strains, 2);
/// drain cracks
// this->drainCracks(saved_damage);
/// compute effective stiffness
Matrix<Real> eps_inverse(voigt_size, voigt_size);
eps_inverse.inverse(strains);
C_macro.mul<false, false>(stresses, eps_inverse);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::performVirtualTesting(const Matrix<Real> & H,
Matrix<Real> & eff_stresses,
Matrix<Real> & eff_strains,
const UInt test_no) {
AKANTU_DEBUG_IN();
this->applyBoundaryConditions(H);
auto & solver = this->getNonLinearSolver();
solver.set("max_iterations", 2);
solver.set("threshold", 1e-6);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
this->solveStep();
/// get average stress and strain
eff_stresses(0, test_no) = this->averageTensorField(0, 0, "stress");
eff_strains(0, test_no) = this->averageTensorField(0, 0, "strain");
eff_stresses(1, test_no) = this->averageTensorField(1, 1, "stress");
eff_strains(1, test_no) = this->averageTensorField(1, 1, "strain");
eff_stresses(2, test_no) = this->averageTensorField(1, 0, "stress");
eff_strains(2, test_no) = 2. * this->averageTensorField(1, 0, "strain");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::homogenizeEigenGradU(
Matrix<Real> & eigen_gradu_macro) {
AKANTU_DEBUG_IN();
eigen_gradu_macro(0, 0) = this->averageTensorField(0, 0, "eigen_grad_u");
eigen_gradu_macro(1, 1) = this->averageTensorField(1, 1, "eigen_grad_u");
eigen_gradu_macro(0, 1) = this->averageTensorField(0, 1, "eigen_grad_u");
eigen_gradu_macro(1, 0) = this->averageTensorField(1, 0, "eigen_grad_u");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::initMaterials() {
AKANTU_DEBUG_IN();
// make sure the material are instantiated
if (!are_materials_instantiated)
instantiateMaterials();
if (use_RVE_mat_selector) {
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real box_size = std::abs(top - bottom);
Real eps = box_size * 1e-6;
auto tmp = std::make_shared<GelMaterialSelector>(*this, box_size, "gel",
this->nb_gel_pockets, eps);
tmp->setFallback(material_selector);
material_selector = tmp;
}
this->assignMaterialToElements();
// synchronize the element material arrays
this->synchronize(SynchronizationTag::_material_id);
for (auto & material : materials) {
/// init internals properties
const auto type = material->getID();
if (type.find("material_FE2") != std::string::npos)
continue;
material->initMaterial();
}
this->synchronize(SynchronizationTag::_smm_init_mat);
if (this->non_local_manager) {
this->non_local_manager->initialize();
}
// SolidMechanicsModel::initMaterials();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::fillCracks(ElementTypeMapReal & saved_damage) {
const auto & mat_gel = this->getMaterial("gel");
Real E_gel = mat_gel.get("E");
Real E_homogenized = 0.;
for (auto && mat : materials) {
if (mat->getName() == "gel" || mat->getName() == "FE2_mat")
continue;
Real E = mat->get("E");
auto & damage = mat->getInternal<Real>("damage");
for (auto && type : damage.elementTypes()) {
const auto & elem_filter = mat->getElementFilter(type);
auto nb_integration_point = getFEEngine().getNbIntegrationPoints(type);
auto sav_dam_it =
make_view(saved_damage(type), nb_integration_point).begin();
for (auto && data :
zip(elem_filter, make_view(damage(type), nb_integration_point))) {
auto el = std::get<0>(data);
auto & dam = std::get<1>(data);
Vector<Real> sav_dam = sav_dam_it[el];
sav_dam = dam;
for (auto q : arange(dam.size())) {
E_homogenized = (E_gel - E) * dam(q) + E;
dam(q) = 1. - (E_homogenized / E);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelRVE::drainCracks(
const ElementTypeMapReal & saved_damage) {
for (auto && mat : materials) {
if (mat->getName() == "gel" || mat->getName() == "FE2_mat")
continue;
auto & damage = mat->getInternal<Real>("damage");
for (auto && type : damage.elementTypes()) {
const auto & elem_filter = mat->getElementFilter(type);
auto nb_integration_point = getFEEngine().getNbIntegrationPoints(type);
auto sav_dam_it =
make_view(saved_damage(type), nb_integration_point).begin();
for (auto && data :
zip(elem_filter, make_view(damage(type), nb_integration_point))) {
auto el = std::get<0>(data);
auto & dam = std::get<1>(data);
Vector<Real> sav_dam = sav_dam_it[el];
dam = sav_dam;
}
}
}
}
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh
index 771229c53..183397c12 100644
--- a/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh
+++ b/extra_packages/extra-materials/src/material_FE2/solid_mechanics_model_RVE.hh
@@ -1,231 +1,230 @@
/**
* @file solid_mechanics_model_RVE.hh
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Wed Jan 13 14:54:18 2016
*
* @brief SMM for RVE computations in FE2 simulations
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLID_MECHANICS_MODEL_RVE_HH_
#define AKANTU_SOLID_MECHANICS_MODEL_RVE_HH_
/* -------------------------------------------------------------------------- */
#include "aka_grid_dynamic.hh"
#include "solid_mechanics_model.hh"
#include <unordered_set>
/* -------------------------------------------------------------------------- */
namespace akantu {
class SolidMechanicsModelRVE : public SolidMechanicsModel {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SolidMechanicsModelRVE(Mesh & mesh, bool use_RVE_mat_selector = true,
UInt nb_gel_pockets = 400,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
const ID & id = "solid_mechanics_model");
virtual ~SolidMechanicsModelRVE();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
void initFullImpl(const ModelOptions & option) override;
/// initialize the materials
void initMaterials() override;
public:
/// apply boundary contions based on macroscopic deformation gradient
virtual void
applyBoundaryConditions(const Matrix<Real> & displacement_gradient);
/// apply homogeneous temperature field from the macroscale level to the RVEs
virtual void applyHomogeneousTemperature(const Real & temperature);
/// advance the reactions -> grow gel and apply homogenized properties
void advanceASR(const Matrix<Real> & prestrain);
/// compute average stress or strain in the model
Real averageTensorField(UInt row_index, UInt col_index,
const ID & field_type);
/// compute effective stiffness of the RVE
void homogenizeStiffness(Matrix<Real> & C_macro);
/// compute average eigenstrain
void homogenizeEigenGradU(Matrix<Real> & eigen_gradu_macro);
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
- inline void unpackData(CommunicationBuffer & buffer,
- const Array<UInt> & index,
+ inline void unpackData(CommunicationBuffer & buffer, const Array<Idx> & index,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(CornerNodes, corner_nodes, const Array<UInt> &);
+ AKANTU_GET_MACRO(CornerNodes, corner_nodes, const Array<Idx> &);
AKANTU_GET_MACRO(Volume, volume, Real);
private:
/// find the corner nodes
void findCornerNodes();
/// perform virtual testing
void performVirtualTesting(const Matrix<Real> & H,
Matrix<Real> & eff_stresses,
Matrix<Real> & eff_strains, const UInt test_no);
void fillCracks(ElementTypeMapReal & saved_damage);
void drainCracks(const ElementTypeMapReal & saved_damage);
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
/// volume of the RVE
Real volume;
/// corner nodes 1, 2, 3, 4 (see Leonardo's thesis, page 98)
- Array<UInt> corner_nodes;
+ Array<Idx> corner_nodes;
/// bottom nodes
std::unordered_set<UInt> bottom_nodes;
/// left nodes
std::unordered_set<UInt> left_nodes;
/// standard mat selector or user one
bool use_RVE_mat_selector;
/// the number of gel pockets inside the RVE
UInt nb_gel_pockets;
/// dump counter
UInt nb_dumps;
};
inline void SolidMechanicsModelRVE::unpackData(CommunicationBuffer & buffer,
- const Array<UInt> & index,
+ const Array<Idx> & index,
const SynchronizationTag & tag) {
SolidMechanicsModel::unpackData(buffer, index, tag);
// if (tag == SynchronizationTag::_smm_uv) {
// auto disp_it = displacement->begin(spatial_dimension);
//
// for (auto node : index) {
// Vector<Real> current_disp(disp_it[node]);
//
// // if node is at the bottom, u_bottom = u_top +u_2 -u_3
// if (bottom_nodes.count(node)) {
// current_disp += Vector<Real>(disp_it[corner_nodes(1)]);
// current_disp -= Vector<Real>(disp_it[corner_nodes(2)]);
// }
// // if node is at the left, u_left = u_right +u_4 -u_3
// else if (left_nodes.count(node)) {
// current_disp += Vector<Real>(disp_it[corner_nodes(3)]);
// current_disp -= Vector<Real>(disp_it[corner_nodes(2)]);
// }
// }
// }
}
/* -------------------------------------------------------------------------- */
/* ASR material selector */
/* -------------------------------------------------------------------------- */
class GelMaterialSelector : public MeshDataMaterialSelector<std::string> {
public:
GelMaterialSelector(SolidMechanicsModel & model, const Real box_size,
const std::string & gel_material,
const UInt nb_gel_pockets, Real /*tolerance*/ = 0.)
: MeshDataMaterialSelector<std::string>("physical_names", model),
model(model), gel_material(gel_material),
nb_gel_pockets(nb_gel_pockets), nb_placed_gel_pockets(0),
box_size(box_size) {
Mesh & mesh = this->model.getMesh();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Element el{_triangle_3, 0, _not_ghost};
UInt nb_element = mesh.getNbElement(el.type, el.ghost_type);
Array<Real> barycenter(nb_element, spatial_dimension);
for (auto && data : enumerate(make_view(barycenter, spatial_dimension))) {
el.element = std::get<0>(data);
auto & bary = std::get<1>(data);
mesh.getBarycenter(el, bary);
}
/// generate the gel pockets
srand(0.);
Vector<Real> center(spatial_dimension);
UInt placed_gel_pockets = 0;
std::set<int> checked_baries;
while (placed_gel_pockets != nb_gel_pockets) {
/// get a random bary center
UInt bary_id = rand() % nb_element;
if (checked_baries.find(bary_id) != checked_baries.end())
continue;
checked_baries.insert(bary_id);
el.element = bary_id;
if (MeshDataMaterialSelector<std::string>::operator()(el) == 1)
continue; /// element belongs to paste
gel_pockets.push_back(el);
placed_gel_pockets += 1;
}
}
UInt operator()(const Element & elem) {
UInt temp_index = MeshDataMaterialSelector<std::string>::operator()(elem);
if (temp_index == 1)
return temp_index;
std::vector<Element>::const_iterator iit = gel_pockets.begin();
std::vector<Element>::const_iterator eit = gel_pockets.end();
if (std::find(iit, eit, elem) != eit) {
nb_placed_gel_pockets += 1;
std::cout << nb_placed_gel_pockets << " gelpockets placed" << std::endl;
return model.getMaterialIndex(gel_material);
;
}
return 0;
}
protected:
SolidMechanicsModel & model;
std::string gel_material;
std::vector<Element> gel_pockets;
UInt nb_gel_pockets;
UInt nb_placed_gel_pockets;
Real box_size;
};
} // namespace akantu
///#include "material_selector_tmpl.hh"
#endif /* AKANTU_SOLID_MECHANICS_MODEL_RVE_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle.cc b/extra_packages/extra-materials/src/material_damage/material_brittle.cc
index 39da8979c..5d146f1f6 100644
--- a/extra_packages/extra-materials/src/material_damage/material_brittle.cc
+++ b/extra_packages/extra-materials/src/material_damage/material_brittle.cc
@@ -1,123 +1,123 @@
/**
* @file material_brittle.cc
*
* @author Aranda Ruiz Josue <josue.arandaruiz@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
*
* @brief Specialization of the material class for the brittle material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_brittle.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialBrittle<spatial_dimension>::MaterialBrittle(SolidMechanicsModel & model,
const ID & id)
: MaterialDamage<spatial_dimension>(model, id),
strain_rate_brittle("strain_rate_brittle", *this) {
AKANTU_DEBUG_IN();
this->registerParam("S_0", S_0, 157e6, _pat_parsable | _pat_modifiable);
this->registerParam("E_0", E_0, 27e3, _pat_parsable, "Strain rate threshold");
this->registerParam("A", A, 1.622e-5, _pat_parsable,
"Polynome cubic constant");
this->registerParam("B", B, -1.3274, _pat_parsable,
"Polynome quadratic constant");
this->registerParam("C", C, 3.6544e4, _pat_parsable,
"Polynome linear constant");
this->registerParam("D", D, -181.38e6, _pat_parsable, "Polynome constant");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialBrittle<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialDamage<spatial_dimension>::initMaterial();
this->strain_rate_brittle.initialize(spatial_dimension * spatial_dimension);
updateInternalParameters();
// this->Yd.resize();
// const Mesh & mesh = this->model.getFEEngine().getMesh();
// Mesh::type_iterator it = mesh.firstType(spatial_dimension);
// Mesh::type_iterator last_type = mesh.lastType(spatial_dimension);
// for(; it != last_type; ++it) {
// UInt nb_element = this->element_filter(*it).getSize();
// UInt nb_quad = this->model.getFEEngine().getNbQuadraturePoints(*it);
// Array <Real> & Yd_rand_vec = Yd_rand(*it);
// for(UInt e = 0; e < nb_element; ++e) {
// Real rand_part = (2 * drand48()-1) * Yd_randomness * Yd;
// for(UInt q = 0; q < nb_quad; ++q)
// Yd_rand_vec(nb_quad*e+q,0) = Yd + rand_part;
// }
// }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialBrittle<spatial_dimension>::updateInternalParameters() {
MaterialDamage<spatial_dimension>::updateInternalParameters();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialBrittle<spatial_dimension>::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = this->damage(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
Array<Real> & velocity = this->model.getVelocity();
Array<Real> & strain_rate_brittle =
this->strain_rate_brittle(el_type, ghost_type);
- Array<UInt> & elem_filter = this->element_filter(el_type, ghost_type);
+ Array<Idx> & elem_filter = this->element_filter(el_type, ghost_type);
this->model.getFEEngine().gradientOnIntegrationPoints(
velocity, strain_rate_brittle, spatial_dimension, el_type, ghost_type,
elem_filter);
Array<Real>::iterator<Matrix<Real>> strain_rate_it =
this->strain_rate_brittle(el_type, ghost_type)
.begin(spatial_dimension, spatial_dimension);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
Real sigma_equivalent = 0;
Real fracture_stress = 0;
Matrix<Real> & grad_v = *strain_rate_it;
computeStressOnQuad(grad_u, grad_v, sigma, *dam, sigma_equivalent,
fracture_stress);
++strain_rate_it;
++dam;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(brittle, MaterialBrittle);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle.hh b/extra_packages/extra-materials/src/material_damage/material_brittle.hh
index 89df33608..8bee2a94c 100644
--- a/extra_packages/extra-materials/src/material_damage/material_brittle.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_brittle.hh
@@ -1,111 +1,111 @@
/**
* @file material_brittle.hh
*
* @author Aranda Ruiz Josue <josue.arandaruiz@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
*
* @brief Brittle damage law
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_BRITTLE_HH_
#define AKANTU_MATERIAL_BRITTLE_HH_
namespace akantu {
/**
* Material brittle
*
* parameters in the material files :
* - S_0 : Critical stress at low strain rate (default: 157e6)
* - E_0 : Low strain rate threshold (default: 27e3)
* - A,B,C,D : Fitting parameters for the critical stress at high strain
* rates
* (default: 1.622e-11, -1.3274e-6, 3.6544e-2, -181.38)
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialBrittle : public MaterialDamage<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialBrittle(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
void updateInternalParameters() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
protected:
/// constitutive law for a given quadrature point
inline void computeStressOnQuad(Matrix<Real> & grad_u, Matrix<Real> & grad_v,
Matrix<Real> & sigma, Real & dam,
Real & sigma_equivalent,
Real & fracture_stress);
inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma, Real & dam,
Real & sigma_c,
Real & fracture_stress);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
inline UInt getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// strain rate arrays ordered by element types
InternalField<Real> strain_rate_brittle;
// polynome constants for critical stress value
Real A;
Real B;
Real C;
Real D;
// minimum strain rate
Real E_0;
// Critical stress at low strain rates
Real S_0;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_brittle_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_brittle_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh
index ae01b0f5e..46ed89288 100644
--- a/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_brittle_inline_impl.hh
@@ -1,101 +1,101 @@
/**
* @file material_brittle_inline_impl.hh
*
* @author Aranda Ruiz Josue <josue.arandaruiz@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
*
* @brief Implementation of the inline functions of the material brittle
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialBrittle<spatial_dimension>::computeStressOnQuad(
Matrix<Real> & grad_u, Matrix<Real> & grad_v, Matrix<Real> & sigma,
Real & dam, Real & sigma_equivalent, Real & fracture_stress) {
MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_u, sigma);
Real equiv_strain_rate = 0.;
Real volume_change_rate = grad_v.trace();
if (spatial_dimension == 2) {
equiv_strain_rate += 2. / 3. * pow(volume_change_rate / 3., 2.);
}
- for (UInt i = 0; i < spatial_dimension; ++i)
- for (UInt j = 0; j < spatial_dimension; ++j)
+ for (Int i = 0; i < spatial_dimension; ++i)
+ for (Int j = 0; j < spatial_dimension; ++j)
equiv_strain_rate += 2. / 3. *
pow(0.5 * (grad_v(i, j) + grad_v(j, i)) -
(i == j) * volume_change_rate / 3.,
2.);
equiv_strain_rate = sqrt(equiv_strain_rate);
fracture_stress = S_0;
if (equiv_strain_rate > E_0)
fracture_stress = A;
Vector<Real> principal_stress(spatial_dimension);
sigma.eig(principal_stress);
sigma_equivalent = principal_stress(0);
- for (UInt i = 1; i < spatial_dimension; ++i)
+ for (Int i = 1; i < spatial_dimension; ++i)
sigma_equivalent = std::max(sigma_equivalent, principal_stress(i));
if (!this->is_non_local) {
computeDamageAndStressOnQuad(sigma, dam, sigma_equivalent, fracture_stress);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialBrittle<spatial_dimension>::computeDamageAndStressOnQuad(
Matrix<Real> & sigma, Real & dam, Real & sigma_c, Real & fracture_stress) {
if (sigma_c > fracture_stress)
dam = 1.;
dam = std::min(dam, 1.);
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline UInt MaterialBrittle<spatial_dimension>::getNbData(
const Array<Element> & elements, const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
UInt size = MaterialDamage<spatial_dimension>::getNbData(elements, tag);
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialBrittle<spatial_dimension>::packData(
CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
MaterialDamage<spatial_dimension>::packData(buffer, elements, tag);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void
MaterialBrittle<spatial_dimension>::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
MaterialDamage<spatial_dimension>::unpackData(buffer, elements, tag);
AKANTU_DEBUG_OUT();
}
diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh
index e079ed307..2adff96f1 100644
--- a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local.hh
@@ -1,88 +1,88 @@
/**
* @file material_brittle_non_local.hh
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
*
* @brief MaterialBrittleNonLocal header for non-local damage
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_brittle.hh"
#include "material_damage_non_local.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_BRITTLE_NON_LOCAL_HH_
#define AKANTU_MATERIAL_BRITTLE_NON_LOCAL_HH_
namespace akantu {
/**
* Material Brittle Non local
*
* parameters in the material files :
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialBrittleNonLocal
: public MaterialDamageNonLocal<spatial_dimension,
MaterialBrittle<spatial_dimension>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef MaterialDamageNonLocal<spatial_dimension,
MaterialBrittle<spatial_dimension>>
MaterialBrittleNonLocalParent;
MaterialBrittleNonLocal(SolidMechanicsModel & model, const ID & id = "");
virtual ~MaterialBrittleNonLocal(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial();
protected:
/// constitutive law
void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
void computeNonLocalStress(ElementType type,
GhostType ghost_type = _not_ghost);
/// associate the non-local variables of the material to their neighborhoods
virtual void nonLocalVariableToNeighborhood();
private:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Sigma_max, Sigma_max, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
InternalField<Real> Sigma_max;
InternalField<Real> Sigma_maxnl;
InternalField<Real> Sigma_fracture;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_brittle_non_local_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_BRITTLE_NON_LOCAL_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh
index df37077c9..00998aea6 100644
--- a/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_brittle_non_local_inline_impl.hh
@@ -1,116 +1,116 @@
/**
* @file material_brittle_non_local_inline_impl.hh
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
*
* @brief MaterialBrittleNonLocal inline function implementation
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
} // namespace akantu
#if defined(AKANTU_DEBUG_TOOLS)
#include "aka_debug_tools.hh"
#include <string>
#endif
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialBrittleNonLocal<spatial_dimension>::MaterialBrittleNonLocal(
SolidMechanicsModel & model, const ID & id)
: Material(model, id), MaterialBrittleNonLocalParent(model, id),
Sigma_max("Sigma max", *this), Sigma_maxnl("Sigma_max non local", *this),
Sigma_fracture("Sigma_fracture", *this) {
AKANTU_DEBUG_IN();
this->is_non_local = true;
this->Sigma_max.initialize(1);
this->Sigma_maxnl.initialize(1);
this->Sigma_fracture.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialBrittleNonLocal<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
this->model.getNonLocalManager().registerNonLocalVariable(
this->Sigma_max.getName(), Sigma_maxnl.getName(), 1);
MaterialBrittleNonLocalParent::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialBrittleNonLocal<spatial_dimension>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = this->damage(el_type, ghost_type).storage();
- Real * Sigma_maxt = this->Sigma_max(el_type, ghost_type).storage();
- Real * fracture_stress = this->Sigma_fracture(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
+ Real * Sigma_maxt = this->Sigma_max(el_type, ghost_type).data();
+ Real * fracture_stress = this->Sigma_fracture(el_type, ghost_type).data();
Array<Real> & velocity = this->model.getVelocity();
Array<Real> & strain_rate_brittle =
this->strain_rate_brittle(el_type, ghost_type);
- Array<UInt> & elem_filter = this->element_filter(el_type, ghost_type);
+ Array<Idx> & elem_filter = this->element_filter(el_type, ghost_type);
this->model.getFEEngine().gradientOnIntegrationPoints(
velocity, strain_rate_brittle, spatial_dimension, el_type, ghost_type,
elem_filter);
Array<Real>::iterator<Matrix<Real>> strain_rate_it =
this->strain_rate_brittle(el_type, ghost_type)
.begin(spatial_dimension, spatial_dimension);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
Matrix<Real> & grad_v = *strain_rate_it;
MaterialBrittle<spatial_dimension>::computeStressOnQuad(
grad_u, grad_v, sigma, *dam, *Sigma_maxt, *fracture_stress);
++dam;
++strain_rate_it;
++Sigma_maxt;
++fracture_stress;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialBrittleNonLocal<spatial_dimension>::computeNonLocalStress(
ElementType type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = this->damage(type, ghost_type).storage();
- Real * Sigma_maxnlt = this->Sigma_maxnl(type, ghost_type).storage();
- Real * fracture_stress = this->Sigma_fracture(type, ghost_type).storage();
+ Real * dam = this->damage(type, ghost_type).data();
+ Real * Sigma_maxnlt = this->Sigma_maxnl(type, ghost_type).data();
+ Real * fracture_stress = this->Sigma_fracture(type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(type, ghost_type);
this->computeDamageAndStressOnQuad(sigma, *dam, *Sigma_maxnlt,
*fracture_stress);
++dam;
++Sigma_maxnlt;
++fracture_stress;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialBrittleNonLocal<
spatial_dimension>::nonLocalVariableToNeighborhood() {
this->model.getNonLocalManager().nonLocalVariableToNeighborhood(
Sigma_maxnl.getName(), this->name);
}
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc
index ec5bb0e5b..43e51614c 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.cc
@@ -1,246 +1,246 @@
/**
* @file material_damage_iterative.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Specialization of the class material damage to damage only one gauss
* point at a time and propagate damage in a linear way. Max principal stress
* criterion is used as a failure criterion.
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative.hh"
#include "communicator.hh"
#include "data_accessor.hh"
#include "solid_mechanics_model_RVE.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialDamageIterative<spatial_dimension>::MaterialDamageIterative(
SolidMechanicsModel & model, const ID & id)
: MaterialDamage<spatial_dimension>(model, id), Sc("Sc", *this),
reduction_step("damage_step", *this),
equivalent_stress("equivalent_stress", *this), max_reductions(0),
norm_max_equivalent_stress(0) {
AKANTU_DEBUG_IN();
this->registerParam("Sc", Sc, _pat_parsable, "critical stress threshold");
this->registerParam("prescribed_dam", prescribed_dam, 0.1,
_pat_parsable | _pat_modifiable, "prescribed damage");
this->registerParam(
"dam_threshold", dam_threshold, 0.8, _pat_parsable | _pat_modifiable,
"damage threshold at which damage damage will be set to 1");
this->registerParam(
"dam_tolerance", dam_tolerance, 0.01, _pat_parsable | _pat_modifiable,
"damage tolerance to decide if quadrature point will be damageed");
this->registerParam("max_damage", max_damage, 0.99999,
_pat_parsable | _pat_modifiable, "maximum damage value");
this->registerParam("max_reductions", max_reductions, UInt(10),
_pat_parsable | _pat_modifiable, "max reductions");
this->use_previous_stress = true;
this->use_previous_gradu = true;
this->Sc.initialize(1);
this->equivalent_stress.initialize(1);
this->reduction_step.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterative<spatial_dimension>::
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// Vector to store eigenvalues of current stress tensor
Vector<Real> eigenvalues(spatial_dimension);
auto Sc_it = Sc(el_type, ghost_type).begin();
auto equivalent_stress_it = equivalent_stress(el_type, ghost_type).begin();
Array<Real>::const_matrix_iterator grad_u_it =
grad_u.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_matrix_iterator grad_u_end =
grad_u.end(spatial_dimension, spatial_dimension);
- Real * dam = this->damage(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
Matrix<Real> sigma(spatial_dimension, spatial_dimension);
for (; grad_u_it != grad_u_end; ++grad_u_it) {
sigma.zero();
MaterialElastic<spatial_dimension>::computeStressOnQuad(*grad_u_it, sigma,
0.);
computeDamageAndStressOnQuad(sigma, *dam);
/// compute eigenvalues
sigma.eig(eigenvalues);
/// find max eigenvalue and normalize by tensile strength
*equivalent_stress_it =
- *(std::max_element(eigenvalues.storage(),
- eigenvalues.storage() + spatial_dimension)) /
+ *(std::max_element(eigenvalues.data(),
+ eigenvalues.data() + spatial_dimension)) /
*(Sc_it);
++Sc_it;
++equivalent_stress_it;
++dam;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterative<spatial_dimension>::computeAllStresses(
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// reset normalized maximum equivalent stress
if (ghost_type == _not_ghost)
norm_max_equivalent_stress = 0;
MaterialDamage<spatial_dimension>::computeAllStresses(ghost_type);
/// find global Gauss point with highest stress
auto rve_model = dynamic_cast<SolidMechanicsModelRVE *>(&this->model);
if (rve_model == NULL) {
/// is no RVE model
const auto & comm = this->model.getMesh().getCommunicator();
comm.allReduce(norm_max_equivalent_stress, SynchronizerOperation::_max);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterative<spatial_dimension>::
findMaxNormalizedEquivalentStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
if (ghost_type == _not_ghost) {
// const Array<Real> & e_stress = equivalent_stress(el_type);
// if (e_stress.begin() != e_stress.end() ) {
// auto equivalent_stress_it_max =
// std::max_element(e_stress.begin(),e_stress.end());
// /// check if max equivalent stress for this element type is greater
// than the current norm_max_eq_stress
// if (*equivalent_stress_it_max > norm_max_equivalent_stress)
// norm_max_equivalent_stress = *equivalent_stress_it_max;
// }
const Array<Real> & e_stress = equivalent_stress(el_type);
auto equivalent_stress_it = e_stress.begin();
auto equivalent_stress_end = e_stress.end();
Array<Real> & dam = this->damage(el_type);
auto dam_it = dam.begin();
for (; equivalent_stress_it != equivalent_stress_end;
++equivalent_stress_it, ++dam_it) {
/// check if max equivalent stress for this element type is greater than
/// the current norm_max_eq_stress and if the element is not already fully
/// damaged
if (*equivalent_stress_it > norm_max_equivalent_stress &&
*dam_it < max_damage) {
norm_max_equivalent_stress = *equivalent_stress_it;
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterative<spatial_dimension>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
MaterialDamage<spatial_dimension>::computeStress(el_type, ghost_type);
- Real * dam = this->damage(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
computeDamageAndStressOnQuad(sigma, *dam);
++dam;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
computeNormalizedEquivalentStress(this->gradu(el_type, ghost_type), el_type,
ghost_type);
norm_max_equivalent_stress = 0;
findMaxNormalizedEquivalentStress(el_type, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
UInt MaterialDamageIterative<spatial_dimension>::updateDamage() {
UInt nb_damaged_elements = 0;
AKANTU_DEBUG_ASSERT(prescribed_dam > 0.,
"Your prescribed damage must be greater than zero");
if (norm_max_equivalent_stress >= 1.) {
AKANTU_DEBUG_IN();
/// update the damage only on non-ghosts elements! Doesn't make sense to
/// update on ghost.
GhostType ghost_type = _not_ghost;
for (auto && el_type : this->model.getFEEngine().getMesh().elementTypes(
spatial_dimension, ghost_type)) {
const Array<Real> & e_stress = equivalent_stress(el_type);
auto equivalent_stress_it = e_stress.begin();
auto equivalent_stress_end = e_stress.end();
Array<Real> & dam = this->damage(el_type);
auto dam_it = dam.begin();
auto reduction_it = this->reduction_step(el_type, ghost_type).begin();
for (; equivalent_stress_it != equivalent_stress_end;
++equivalent_stress_it, ++dam_it, ++reduction_it) {
/// check if damage occurs
if (*equivalent_stress_it >=
(1 - dam_tolerance) * norm_max_equivalent_stress) {
/// check if this element can still be damaged
if (*reduction_it == this->max_reductions)
continue;
*reduction_it += 1;
if (*reduction_it == this->max_reductions) {
*dam_it = max_damage;
} else {
*dam_it += prescribed_dam;
}
nb_damaged_elements += 1;
}
}
}
}
auto * rve_model = dynamic_cast<SolidMechanicsModelRVE *>(&this->model);
if (rve_model == NULL) {
const auto & comm = this->model.getMesh().getCommunicator();
comm.allReduce(nb_damaged_elements, SynchronizerOperation::_sum);
}
AKANTU_DEBUG_OUT();
return nb_damaged_elements;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterative<spatial_dimension>::updateEnergiesAfterDamage(
ElementType el_type) {
MaterialDamage<spatial_dimension>::updateEnergies(el_type);
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(damage_iterative, MaterialDamageIterative);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh
index a9f2e05a7..9ae8a7d3a 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative.hh
@@ -1,145 +1,145 @@
/**
* @file material_damage_iterative.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Specialization of the class material damage to damage only one gauss
* point at a time and propagate damage in a linear way. Max principal stress
* criterion is used as a failure criterion.
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_DAMAGE_ITERATIVE_HH_
#define AKANTU_MATERIAL_DAMAGE_ITERATIVE_HH_
namespace akantu {
/**
* Material damage iterative
*
* parameters in the material files :
* - Sc
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialDamageIterative : public MaterialDamage<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialDamageIterative(SolidMechanicsModel & model, const ID & id = "");
~MaterialDamageIterative() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// virtual void updateInternalParameters();
void computeAllStresses(GhostType ghost_type = _not_ghost) override;
/// update internal field damage
virtual UInt updateDamage();
UInt updateDamage(UInt quad_index, Real eq_stress, ElementType el_type,
GhostType ghost_type);
/// update energies after damage has been updated
void updateEnergiesAfterDamage(ElementType el_type) override;
/// compute the equivalent stress on each Gauss point (i.e. the max prinicpal
/// stress) and normalize it by the tensile strength
virtual void
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type = _not_ghost);
/// find max normalized equivalent stress
void findMaxNormalizedEquivalentStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
protected:
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma, Real & dam);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
inline UInt getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get max normalized equivalent stress
AKANTU_GET_MACRO(NormMaxEquivalentStress, norm_max_equivalent_stress, Real);
/// get a non-const reference to the max normalized equivalent stress
AKANTU_GET_MACRO_NOT_CONST(NormMaxEquivalentStress,
norm_max_equivalent_stress, Real &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// resistance to damage
RandomInternalField<Real> Sc;
/// the reduction
InternalField<UInt> reduction_step;
/// internal field to store equivalent stress on each Gauss point
InternalField<Real> equivalent_stress;
/// the number of total reductions steps until complete failure
UInt max_reductions;
/// damage increment
Real prescribed_dam;
/// maximum equivalent stress
Real norm_max_equivalent_stress;
/// deviation from max stress at which Gauss point will still get damaged
Real dam_tolerance;
/// define damage threshold at which damage will be set to 1
Real dam_threshold;
/// maximum damage value
Real max_damage;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative_inline_impl.hh"
#endif /* AKANTU_MATERIAL_DAMAGE_ITERATIVE_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh
index 1e6f9c816..96b2799f1 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_inline_impl.hh
@@ -1,91 +1,91 @@
/**
* @file material_damage_iterative_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Implementation of inline functions of the material damage iterative
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void
MaterialDamageIterative<spatial_dimension>::computeDamageAndStressOnQuad(
Matrix<Real> & sigma, Real & dam) {
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
UInt MaterialDamageIterative<spatial_dimension>::updateDamage(
UInt quad_index, const Real /*eq_stress*/, ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_ASSERT(prescribed_dam > 0.,
"Your prescribed damage must be greater than zero");
Array<Real> & dam = this->damage(el_type, ghost_type);
Real & dam_on_quad = dam(quad_index);
/// check if damage occurs
if (equivalent_stress(el_type, ghost_type)(quad_index) >=
(1 - dam_tolerance) * norm_max_equivalent_stress) {
if (dam_on_quad < dam_threshold)
dam_on_quad += prescribed_dam;
else
dam_on_quad = max_damage;
return 1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline UInt MaterialDamageIterative<spatial_dimension>::getNbData(
const Array<Element> & elements, const SynchronizationTag & tag) const {
if (tag == SynchronizationTag::_user_2) {
return sizeof(Real) * this->getModel().getNbIntegrationPoints(elements);
}
return MaterialDamage<spatial_dimension>::getNbData(elements, tag);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialDamageIterative<spatial_dimension>::packData(
CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const {
if (tag == SynchronizationTag::_user_2) {
DataAccessor<Element>::packElementalDataHelper(
this->damage, buffer, elements, true, this->damage.getFEEngine());
}
return MaterialDamage<spatial_dimension>::packData(buffer, elements, tag);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialDamageIterative<spatial_dimension>::unpackData(
CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) {
if (tag == SynchronizationTag::_user_2) {
DataAccessor<Element>::unpackElementalDataHelper(
this->damage, buffer, elements, true, this->damage.getFEEngine());
}
return MaterialDamage<spatial_dimension>::unpackData(buffer, elements, tag);
}
} // namespace akantu
/* -------------------------------------------------------------------------- */
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc
index aaa58fc13..6ccc56a33 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.cc
@@ -1,41 +1,41 @@
/**
* @file material_damage_iterative.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Implementation of MaterialDamageIterativeNonLocal
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative_non_local.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterativeNonLocal<
spatial_dimension>::computeNonLocalStresses(GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// reset normalized maximum equivalent stress
if (ghost_type == _not_ghost)
this->norm_max_equivalent_stress = 0;
MaterialDamageIterativeNonLocalParent::computeNonLocalStresses(ghost_type);
/// find global Gauss point with highest stress
const auto & comm = this->model.getMesh().getCommunicator();
comm.allReduce(this->norm_max_equivalent_stress, SynchronizerOperation::_max);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(damage_iterative_non_local,
MaterialDamageIterativeNonLocal);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh
index af8b329eb..e760aa00b 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local.hh
@@ -1,80 +1,80 @@
/**
* @file material_damage_iterative_non_local.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief MaterialDamageIterativeNonLocal header for non-local damage
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_damage_iterative.hh"
#include "material_damage_non_local.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_DAMAGE_ITERATIVE_NON_LOCAL_HH_
#define AKANTU_MATERIAL_DAMAGE_ITERATIVE_NON_LOCAL_HH_
namespace akantu {
/**
* Material Damage Iterative Non local
*
* parameters in the material files :
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialDamageIterativeNonLocal
: public MaterialDamageNonLocal<
spatial_dimension, MaterialDamageIterative<spatial_dimension>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef MaterialDamageNonLocal<spatial_dimension,
MaterialDamageIterative<spatial_dimension>>
MaterialDamageIterativeNonLocalParent;
MaterialDamageIterativeNonLocal(SolidMechanicsModel & model,
const ID & id = "");
virtual ~MaterialDamageIterativeNonLocal(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial();
virtual void computeNonLocalStresses(GhostType ghost_type);
protected:
void computeStress(ElementType type, GhostType ghost_type);
void computeNonLocalStress(ElementType type,
GhostType ghost_type = _not_ghost);
private:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
InternalField<Real> grad_u_nl;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative_non_local_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_DAMAGE_ITERATIVE_NON_LOCAL_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh
index 906cc0802..190f0c6cc 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_iterative_non_local_inline_impl.hh
@@ -1,88 +1,88 @@
/**
* @file material_damage_iterative_non_local_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief MaterialDamageIterativeNonLocal inline function implementation
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
} // namespace akantu
#if defined(AKANTU_DEBUG_TOOLS)
#include "aka_debug_tools.hh"
#include <string>
#endif
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialDamageIterativeNonLocal<spatial_dimension>::
MaterialDamageIterativeNonLocal(SolidMechanicsModel & model, const ID & id)
: MaterialDamageIterativeNonLocalParent(model, id),
grad_u_nl("grad_u non local", *this) {
AKANTU_DEBUG_IN();
this->is_non_local = true;
this->grad_u_nl.initialize(spatial_dimension * spatial_dimension);
this->model.getNonLocalManager().registerNonLocalVariable(
this->gradu.getName(), grad_u_nl.getName(),
spatial_dimension * spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterativeNonLocal<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialDamageIterativeNonLocalParent::initMaterial();
this->model.getNonLocalManager().nonLocalVariableToNeighborhood(
grad_u_nl.getName(), this->name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterativeNonLocal<spatial_dimension>::computeStress(
ElementType /*type*/, GhostType /*ghost_type*/) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageIterativeNonLocal<spatial_dimension>::computeNonLocalStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// compute the stress (based on the elastic law)
MaterialDamage<spatial_dimension>::computeStress(el_type, ghost_type);
/// multiply the stress by (1-d) to get the effective stress
- Real * dam = this->damage(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
this->computeDamageAndStressOnQuad(sigma, *dam);
++dam;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
/// compute the normalized equivalent stress
this->computeNormalizedEquivalentStress(this->grad_u_nl(el_type, ghost_type),
el_type, ghost_type);
/// find the maximum
this->norm_max_equivalent_stress = 0;
this->findMaxNormalizedEquivalentStress(el_type, ghost_type);
AKANTU_DEBUG_OUT();
}
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc b/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc
index cfe635419..42accbd87 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_linear.cc
@@ -1,73 +1,73 @@
/**
* @file material_damage_linear.cc
*
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
*
*
* @brief Specialization of the material class for the damage material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_linear.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialDamageLinear<spatial_dimension>::MaterialDamageLinear(
SolidMechanicsModel & model, const ID & id)
: MaterialDamage<spatial_dimension>(model, id), K("K", *this) {
AKANTU_DEBUG_IN();
this->registerParam("Sigc", Sigc, 1e5, _pat_parsable, "Sigma Critique");
this->registerParam("Gc", Gc, 2., _pat_parsable, "Gc");
this->K.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageLinear<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialDamage<spatial_dimension>::initMaterial();
Epsmin = Sigc / this->E;
Epsmax = 2 * Gc / Sigc + Epsmin;
this->K.setDefaultValue(Epsmin);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialDamageLinear<spatial_dimension>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = this->damage(el_type, ghost_type).storage();
- Real * K = this->K(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
+ Real * K = this->K(el_type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
this->computeStressOnQuad(grad_u, sigma, *dam, *K);
++dam;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(damage_linear, MaterialDamageLinear);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh b/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh
index 7c00c44f3..08ca68f3e 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_linear.hh
@@ -1,85 +1,85 @@
/**
* @file material_damage_linear.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
*
*
* @brief Material isotropic elastic + linear softening
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_DAMAGE_LINEAR_HH_
#define AKANTU_MATERIAL_DAMAGE_LINEAR_HH_
namespace akantu {
/**
* Material liner damage
*
* parameters in the material files :
* - Sigc : (default: 1e5)
* - Gc : (default: 2)
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialDamageLinear : public MaterialDamage<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialDamageLinear(SolidMechanicsModel & model, const ID & id = "");
virtual ~MaterialDamageLinear(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial();
/// constitutive law for all element of a type
void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
protected:
/// constitutive law for a given quadrature point
inline void computeStressOnQuad(Matrix<Real> & F, Matrix<Real> & sigma,
Real & damage, Real & K);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// kind of toughness
Real Gc;
/// critical stress
Real Sigc;
/// damage internal variable
InternalField<Real> K;
Real Epsmin, Epsmax;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_damage_linear_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_DAMAGE_LINEAR_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh
index e3c27fbc9..b6110f852 100644
--- a/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_damage_linear_inline_impl.hh
@@ -1,43 +1,43 @@
/**
* @file material_damage_linear_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
*
*
* @brief Implementation of the inline functions of the material damage linear
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialDamageLinear<spatial_dimension>::computeStressOnQuad(
Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam, Real & K) {
Real Fdiag[3];
Real Fdiagp[3];
- Math::matrix33_eigenvalues(grad_u.storage(), Fdiag);
+ Math::matrix33_eigenvalues(grad_u.data(), Fdiag);
Fdiagp[0] = std::max(0., Fdiag[0]);
Fdiagp[1] = std::max(0., Fdiag[1]);
Fdiagp[2] = std::max(0., Fdiag[2]);
Real Ehat = sqrt(Fdiagp[0] * Fdiagp[0] + Fdiagp[1] * Fdiagp[1] +
Fdiagp[2] * Fdiagp[2]);
MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_u, sigma);
Real Fd = Ehat - K;
if (Fd > 0) {
dam = (Ehat - Epsmin) / (Epsmax - Epsmin) * (Ehat / Epsmax);
dam = std::min(dam, 1.);
K = Ehat;
}
sigma *= 1 - dam;
}
diff --git a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc
index 2b5046261..2297e400d 100644
--- a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc
+++ b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.cc
@@ -1,203 +1,203 @@
/**
* @file material_iterative_stiffness_reduction.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Feb 18 16:03:56 2016
*
* @brief Implementation of material iterative stiffness reduction
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_iterative_stiffness_reduction.hh"
#include "communicator.hh"
#include "solid_mechanics_model_RVE.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialIterativeStiffnessReduction<spatial_dimension>::
MaterialIterativeStiffnessReduction(SolidMechanicsModel & model,
const ID & id)
: MaterialDamageIterative<spatial_dimension>(model, id),
eps_u("ultimate_strain", *this), D("tangent", *this), Gf(0.),
crack_band_width(0.), reduction_constant(0.) {
AKANTU_DEBUG_IN();
this->registerParam("Gf", Gf, _pat_parsable | _pat_modifiable,
"fracture energy");
this->registerParam("crack_band_width", crack_band_width,
_pat_parsable | _pat_modifiable, "crack_band_width");
this->registerParam("reduction_constant", reduction_constant, 2.,
_pat_parsable | _pat_modifiable, "reduction constant");
this->eps_u.initialize(1);
this->D.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIterativeStiffnessReduction<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialDamageIterative<spatial_dimension>::initMaterial();
for (auto ghost_type : ghost_types) {
/// loop over all types in the filter
for (auto & el_type :
this->element_filter.elementTypes(_ghost_type = ghost_type)) {
/// get the stiffness on each quad point
auto Sc_it = this->Sc(el_type, ghost_type).begin();
/// get the tangent of the tensile softening on each quad point
auto D_it = this->D(el_type, ghost_type).begin();
auto D_end = this->D(el_type, ghost_type).end();
/// get the ultimate strain on each quad
auto eps_u_it = this->eps_u(el_type, ghost_type).begin();
// compute the tangent and the ultimate strain for each quad
for (; D_it != D_end; ++Sc_it, ++D_it, ++eps_u_it) {
*eps_u_it = ((2. * this->Gf) / (*Sc_it * this->crack_band_width));
*D_it = *(Sc_it) / ((*eps_u_it) - ((*Sc_it) / this->E));
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIterativeStiffnessReduction<spatial_dimension>::
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// storage for the current stress
Matrix<Real> sigma(spatial_dimension, spatial_dimension);
/// Vector to store eigenvalues of current stress tensor
Vector<Real> eigenvalues(spatial_dimension);
/// iterators on the needed internal fields
auto Sc_it = this->Sc(el_type, ghost_type).begin();
auto dam_it = this->damage(el_type, ghost_type).begin();
auto equivalent_stress_it =
this->equivalent_stress(el_type, ghost_type).begin();
auto grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension);
auto grad_u_end = grad_u.end(spatial_dimension, spatial_dimension);
/// loop over all the quadrature points and compute the equivalent stress
for (; grad_u_it != grad_u_end; ++grad_u_it) {
/// compute the stress
sigma.zero();
MaterialElastic<spatial_dimension>::computeStressOnQuad(*grad_u_it, sigma,
0.);
MaterialDamageIterative<spatial_dimension>::computeDamageAndStressOnQuad(
sigma, *dam_it);
/// compute eigenvalues
sigma.eig(eigenvalues);
/// find max eigenvalue and normalize by tensile strength
*equivalent_stress_it =
- *(std::max_element(eigenvalues.storage(),
- eigenvalues.storage() + spatial_dimension)) /
+ *(std::max_element(eigenvalues.data(),
+ eigenvalues.data() + spatial_dimension)) /
(*Sc_it);
++Sc_it;
++equivalent_stress_it;
++dam_it;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
UInt MaterialIterativeStiffnessReduction<spatial_dimension>::updateDamage() {
UInt nb_damaged_elements = 0;
if (this->norm_max_equivalent_stress >= 1.) {
AKANTU_DEBUG_IN();
/// update the damage only on non-ghosts elements! Doesn't make sense to
/// update on ghost.
GhostType ghost_type = _not_ghost;
/// loop over all the elements
for (auto && el_type : this->model.getFEEngine().getMesh().elementTypes(
spatial_dimension, ghost_type)) {
/// get iterators on the needed internal fields
auto equivalent_stress_it =
this->equivalent_stress(el_type, ghost_type).begin();
auto equivalent_stress_end =
this->equivalent_stress(el_type, ghost_type).end();
auto dam_it = this->damage(el_type, ghost_type).begin();
auto reduction_it = this->reduction_step(el_type, ghost_type).begin();
auto eps_u_it = this->eps_u(el_type, ghost_type).begin();
auto Sc_it = this->Sc(el_type, ghost_type).begin();
auto D_it = this->D(el_type, ghost_type).begin();
/// loop over all the quads of the given element type
for (; equivalent_stress_it != equivalent_stress_end;
++equivalent_stress_it, ++dam_it, ++reduction_it, ++eps_u_it,
++Sc_it, ++D_it) {
/// check if damage occurs
if (*equivalent_stress_it >=
(1 - this->dam_tolerance) * this->norm_max_equivalent_stress) {
/// check if this element can still be damaged
if (*reduction_it == this->max_reductions)
continue;
/// increment the counter of stiffness reduction steps
*reduction_it += 1;
if (*reduction_it == this->max_reductions)
*dam_it = this->max_damage;
else {
/// update the damage on this quad
*dam_it =
1. - (1. / std::pow(this->reduction_constant, *reduction_it));
/// update the stiffness on this quad
*Sc_it = (*eps_u_it) * (1. - (*dam_it)) * this->E * (*D_it) /
((1. - (*dam_it)) * this->E + (*D_it));
}
nb_damaged_elements += 1;
}
}
}
}
auto rve_model = dynamic_cast<SolidMechanicsModelRVE *>(&this->model);
if (rve_model == NULL) {
const auto & comm = this->model.getMesh().getCommunicator();
comm.allReduce(nb_damaged_elements, SynchronizerOperation::_sum);
}
AKANTU_DEBUG_OUT();
return nb_damaged_elements;
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(iterative_stiffness_reduction,
MaterialIterativeStiffnessReduction);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh
index 0d8a00349..10435a4c7 100644
--- a/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_iterative_stiffness_reduction.hh
@@ -1,104 +1,104 @@
/**
* @file material_iterative_stiffness_reduction.hh
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Feb 18 15:25:05 2016
*
* @brief Damage material with constant stiffness reduction
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ITERATIVE_STIFFNESS_REDUCTION_HH_
#define AKANTU_MATERIAL_ITERATIVE_STIFFNESS_REDUCTION_HH_
namespace akantu {
/**
* Material damage iterative
*
* parameters in the material files :
* - Gfx
* - h
* - Sc
*/
/// Proposed by Rots and Invernizzi, 2004: Regularized sequentially linear
// saw-tooth softening model (section 4.2)
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialIterativeStiffnessReduction
: public MaterialDamageIterative<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialIterativeStiffnessReduction(SolidMechanicsModel & model,
const ID & id = "");
virtual ~MaterialIterativeStiffnessReduction(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// init the material
virtual void initMaterial();
/// compute the equivalent stress on each Gauss point (i.e. the max prinicpal
/// stress) and normalize it by the tensile stiffness
virtual void
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type = _not_ghost);
/// update internal field damage
virtual UInt updateDamage();
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// the ultimate strain
InternalField<Real> eps_u;
/// the tangent of the tensile stress-strain softening
InternalField<Real> D;
/// fracture energy
Real Gf;
/// crack_band_width for normalization of fracture energy
Real crack_band_width;
/// the reduction constant (denoated by a in the paper of rots)
Real reduction_constant;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_ITERATIVE_STIFFNESS_REDUCTION_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh
index d15c70cbc..778827ec5 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage.hh
@@ -1,145 +1,144 @@
/**
* @file material_orthotropic_damage.hh
* @author Aurelia Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Sun Mar 8 12:49:56 2015
*
* @brief Material for orthotropic damage
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_HH_
#define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_HH_
namespace akantu {
-template <UInt spatial_dimension,
- template <UInt> class Parent = MaterialElastic>
+template <Int spatial_dimension, template <UInt> class Parent = MaterialElastic>
class MaterialOrthotropicDamage : public Parent<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialOrthotropicDamage(SolidMechanicsModel & model, const ID & id = "");
virtual ~MaterialOrthotropicDamage(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
protected:
/// update the dissipated energy, must be called after the stress have been
/// computed
void updateEnergies(ElementType el_type) override;
/// compute the tangent stiffness matrix for a given quadrature point
inline void computeTangentModuliOnQuad(
Matrix<Real> & tangent, const Matrix<Real> C, const Matrix<Real> & dam,
const Matrix<Real> & dam_directions, Matrix<Real> & O_prime,
Matrix<Real> & S_prime, Matrix<Real> & O, Matrix<Real> & S,
Matrix<Real> & rotation_tmp);
inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma,
Matrix<Real> & one_minus_D,
Matrix<Real> & root_one_minus_D,
Matrix<Real> & damage,
Matrix<Real> & first_term,
Matrix<Real> & third_term);
/// rotate a Matrix of size dim*dim into the coordinate system of the FE
/// computation
inline void rotateIntoComputationFrame(const Matrix<Real> & to_rotate,
Matrix<Real> & rotated,
const Matrix<Real> & damage_directions,
Matrix<Real> & rotation_tmp);
/// rotate a Matrix of size dim*dim into the coordinate system of the damage
inline void rotateIntoNewFrame(const Matrix<Real> & to_rotate,
Matrix<Real> & rotated,
const Matrix<Real> & damage_directions,
Matrix<Real> & rotation_tmp);
/// compute (1-D)
inline void computeOneMinusD(Matrix<Real> & one_minus_D,
const Matrix<Real> & damage);
/// compute (1-D)^(1/2)
inline void computeSqrtOneMinusD(const Matrix<Real> & one_minus_D,
Matrix<Real> & sqrt_one_minus_D);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// give the dissipated energy for the time step
Real getDissipatedEnergy() const;
// virtual Real getEnergy(std::string type);
// virtual Real getEnergy(std::string energy_id, ElementType type, UInt index)
// {
// return Parent<spatial_dimension>::getEnergy(energy_id, type, index);
// };
AKANTU_GET_MACRO_NOT_CONST(Damage, damage, ElementTypeMapArray<Real> &);
AKANTU_GET_MACRO(Damage, damage, const ElementTypeMapArray<Real> &);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real)
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// damage internal variable
InternalField<Real> damage;
/// dissipated energy
InternalField<Real> dissipated_energy;
/// contain the current value of @f$ \int_0^{\epsilon}\sigma(\omega)d\omega
/// @f$ the dissipated energy
InternalField<Real> int_sigma;
/// direction vectors for the damage frame
InternalField<Real> damage_dir_vecs;
Real eta;
/// maximum damage value
Real max_damage;
};
} // namespace akantu
#include "material_orthotropic_damage_tmpl.hh"
#endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc
index c96f40708..9017808ae 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.cc
@@ -1,375 +1,375 @@
/**
* @file material_damage_iterative.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date Sun Mar 8 12:54:30 2015
*
* @brief Specialization of the class material damage to damage only one gauss
* point at a time and propagate damage in a linear way. Max principal stress
* criterion is used as a failure criterion.
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_orthotropic_damage_iterative.hh"
#include "communicator.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialOrthotropicDamageIterative<spatial_dimension>::
MaterialOrthotropicDamageIterative(SolidMechanicsModel & model,
const ID & id)
: MaterialOrthotropicDamage<spatial_dimension>(model, id), Sc("Sc", *this),
equivalent_stress("equivalent_stress", *this),
stress_dir("equiv_stress_dir", *this), norm_max_equivalent_stress(0) {
AKANTU_DEBUG_IN();
this->registerParam("Sc", Sc, _pat_parsable, "critical stress threshold");
this->registerParam("prescribed_dam", prescribed_dam, 0.1,
_pat_parsable | _pat_modifiable,
"increase of damage in every step");
this->registerParam(
"dam_threshold", dam_threshold, 0.8, _pat_parsable | _pat_modifiable,
"damage threshold at which damage damage will be set to 1");
this->use_previous_stress = true;
this->use_previous_gradu = true;
this->Sc.initialize(1);
this->equivalent_stress.initialize(1);
this->stress_dir.initialize(spatial_dimension * spatial_dimension);
/// the Gauss point with the highest stress can only be of type _not_ghost
q_max.ghost_type = _not_ghost;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterative<spatial_dimension>::
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// Vector to store eigenvalues of current stress tensor
Vector<Real> eigenvalues(spatial_dimension);
auto Sc_it = Sc(el_type).begin();
auto equivalent_stress_it = equivalent_stress(el_type).begin();
Array<Real>::const_matrix_iterator grad_u_it =
grad_u.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_matrix_iterator grad_u_end =
grad_u.end(spatial_dimension, spatial_dimension);
Array<Real>::matrix_iterator stress_dir_it =
this->stress_dir(el_type).begin(spatial_dimension, spatial_dimension);
/// initialize matrix to store the stress for the criterion (only different in
/// non-local)
Matrix<Real> sigma(spatial_dimension, spatial_dimension);
Array<Real>::matrix_iterator damage_iterator =
this->damage(el_type, ghost_type)
.begin(this->spatial_dimension, this->spatial_dimension);
Array<Real>::matrix_iterator damage_dir_it =
this->damage_dir_vecs(el_type, ghost_type)
.begin(this->spatial_dimension, this->spatial_dimension);
/// for the computation of the Cauchy stress the matrices (1-D) and
/// (1-D)^(1/2) are needed. For the formulation see Engineering
/// Damage Mechanics by Lemaitre and Desmorat.
Matrix<Real> one_minus_D(this->spatial_dimension, this->spatial_dimension);
Matrix<Real> sqrt_one_minus_D(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> one_minus_D_rotated(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> sqrt_one_minus_D_rotated(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> rotation_tmp(this->spatial_dimension, this->spatial_dimension);
/// create matrix to store the first term of the computation of the
/// Cauchy stress
Matrix<Real> first_term(this->spatial_dimension, this->spatial_dimension);
Matrix<Real> third_term(this->spatial_dimension, this->spatial_dimension);
for (; grad_u_it != grad_u_end;
++Sc_it, ++equivalent_stress_it, ++stress_dir_it, ++grad_u_it) {
sigma.zero();
MaterialOrthotropicDamage<spatial_dimension>::computeStressOnQuad(
*grad_u_it, sigma, 0.);
/// rotate the tensors from the damage principal coordinate system to the CS
/// of the computation
if (!(Math::are_float_equal((*damage_iterator).trace(), 0))) {
/// compute (1-D) and (1-D)^1/2
this->computeOneMinusD(one_minus_D, *damage_iterator);
this->computeSqrtOneMinusD(one_minus_D, sqrt_one_minus_D);
this->rotateIntoComputationFrame(one_minus_D, one_minus_D_rotated,
*damage_dir_it, rotation_tmp);
this->rotateIntoComputationFrame(sqrt_one_minus_D,
sqrt_one_minus_D_rotated, *damage_dir_it,
rotation_tmp);
} else {
this->computeOneMinusD(one_minus_D_rotated, *damage_iterator);
this->computeSqrtOneMinusD(one_minus_D_rotated, sqrt_one_minus_D_rotated);
}
computeDamageAndStressOnQuad(sigma, one_minus_D_rotated,
sqrt_one_minus_D_rotated, *damage_iterator,
first_term, third_term);
/// compute the maximum principal stresses and their directions
sigma.eig(eigenvalues, *stress_dir_it);
*equivalent_stress_it = eigenvalues(0) / *(Sc_it);
++damage_dir_it;
++damage_iterator;
}
// for(;sigma_it != sigma_end; ++sigma_it,
// ++Sc_it, ++equivalent_stress_it, ++stress_dir_it) {
// /// compute the maximum principal stresses and their directions
// (*sigma_it).eig(eigenvalues, *stress_dir_it);
// *equivalent_stress_it = eigenvalues(0) / *(Sc_it);
// }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterative<spatial_dimension>::computeAllStresses(
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// reset normalized maximum equivalent stress
if (ghost_type == _not_ghost)
norm_max_equivalent_stress = 0;
MaterialOrthotropicDamage<spatial_dimension>::computeAllStresses(ghost_type);
/// find global Gauss point with highest stress
this->model.getMesh().getCommunicator().allReduce(
norm_max_equivalent_stress, SynchronizerOperation::_max);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterative<spatial_dimension>::
findMaxNormalizedEquivalentStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
if (ghost_type == _not_ghost) {
/// initialize the iterators for the equivalent stress and the damage
const Array<Real> & e_stress = equivalent_stress(el_type);
auto equivalent_stress_it = e_stress.begin();
auto equivalent_stress_end = e_stress.end();
Array<Real> & dam = this->damage(el_type);
auto dam_it = dam.begin(this->spatial_dimension, this->spatial_dimension);
auto damage_directions_it =
this->damage_dir_vecs(el_type, _not_ghost)
.begin(this->spatial_dimension, this->spatial_dimension);
auto stress_dir_it = this->stress_dir(el_type, _not_ghost)
.begin(spatial_dimension, spatial_dimension);
/// initialize the matrices for damage rotation results
Matrix<Real> tmp(spatial_dimension, spatial_dimension);
Matrix<Real> dam_in_computation_frame(spatial_dimension, spatial_dimension);
Matrix<Real> dam_in_stress_frame(spatial_dimension, spatial_dimension);
for (; equivalent_stress_it != equivalent_stress_end;
++equivalent_stress_it, ++dam_it, ++damage_directions_it,
++stress_dir_it) {
/// check if max equivalent stress for this element type is greater than
/// the current norm_max_eq_stress
if (*equivalent_stress_it > norm_max_equivalent_stress &&
(spatial_dimension * this->max_damage - (*dam_it).trace() >
Math::getTolerance())) {
if (Math::are_float_equal((*dam_it).trace(), 0)) {
/// gauss point has not been damaged yet
norm_max_equivalent_stress = *equivalent_stress_it;
q_max.type = el_type;
q_max.global_num = equivalent_stress_it - e_stress.begin();
}
else {
/// find the damage increment on this Gauss point
/// rotate damage into stress frame
this->rotateIntoComputationFrame(*dam_it, dam_in_computation_frame,
*damage_directions_it, tmp);
this->rotateIntoNewFrame(dam_in_computation_frame,
dam_in_stress_frame, *stress_dir_it, tmp);
/// add damage increment
dam_in_stress_frame(0, 0) += prescribed_dam;
/// find new principal directions of damage
Vector<Real> dam_eigenvalues(spatial_dimension);
dam_in_stress_frame.eig(dam_eigenvalues);
bool limit_reached = false;
- for (UInt i = 0; i < spatial_dimension; ++i) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
if (dam_eigenvalues(i) + Math::getTolerance() > this->max_damage)
limit_reached = true;
}
if (!limit_reached) {
norm_max_equivalent_stress = *equivalent_stress_it;
q_max.type = el_type;
q_max.global_num = equivalent_stress_it - e_stress.begin();
}
}
} /// end if equiv_stress > max_equiv_stress
} /// end loop over all gauss points of this element type
} // end if(_not_ghost)
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterative<spatial_dimension>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
MaterialOrthotropicDamage<spatial_dimension>::computeStress(el_type,
ghost_type);
auto damage_iterator =
this->damage(el_type, ghost_type)
.begin(this->spatial_dimension, this->spatial_dimension);
auto damage_dir_it =
this->damage_dir_vecs(el_type, ghost_type)
.begin(this->spatial_dimension, this->spatial_dimension);
/// for the computation of the Cauchy stress the matrices (1-D) and
/// (1-D)^(1/2) are needed. For the formulation see Engineering
/// Damage Mechanics by Lemaitre and Desmorat.
Matrix<Real> one_minus_D(this->spatial_dimension, this->spatial_dimension);
Matrix<Real> sqrt_one_minus_D(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> one_minus_D_rotated(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> sqrt_one_minus_D_rotated(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> rotation_tmp(this->spatial_dimension, this->spatial_dimension);
/// create matrix to store the first term of the computation of the
/// Cauchy stress
Matrix<Real> first_term(this->spatial_dimension, this->spatial_dimension);
Matrix<Real> third_term(this->spatial_dimension, this->spatial_dimension);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
/// rotate the tensors from the damage principal coordinate system to the CS
/// of the computation
if (!(Math::are_float_equal((*damage_iterator).trace(), 0))) {
/// compute (1-D) and (1-D)^1/2
this->computeOneMinusD(one_minus_D, *damage_iterator);
this->computeSqrtOneMinusD(one_minus_D, sqrt_one_minus_D);
this->rotateIntoComputationFrame(one_minus_D, one_minus_D_rotated,
*damage_dir_it, rotation_tmp);
this->rotateIntoComputationFrame(sqrt_one_minus_D, sqrt_one_minus_D_rotated,
*damage_dir_it, rotation_tmp);
} else {
this->computeOneMinusD(one_minus_D_rotated, *damage_iterator);
this->computeSqrtOneMinusD(one_minus_D_rotated, sqrt_one_minus_D_rotated);
}
computeDamageAndStressOnQuad(sigma, one_minus_D_rotated,
sqrt_one_minus_D_rotated, *damage_iterator,
first_term, third_term);
++damage_dir_it;
++damage_iterator;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
computeNormalizedEquivalentStress(this->gradu(el_type, ghost_type), el_type,
ghost_type);
norm_max_equivalent_stress = 0;
findMaxNormalizedEquivalentStress(el_type, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
UInt MaterialOrthotropicDamageIterative<spatial_dimension>::updateDamage() {
UInt nb_damaged_elements = 0;
AKANTU_DEBUG_ASSERT(prescribed_dam > 0.,
"Your prescribed damage must be greater than zero");
if (norm_max_equivalent_stress >= 1.) {
AKANTU_DEBUG_IN();
/// get the arrays and iterators for the element_type of the highest
/// quadrature point
ElementType el_type = q_max.type;
UInt q_global_num = q_max.global_num;
Array<Real> & dam = this->damage(el_type, _not_ghost);
auto dam_it = dam.begin(this->spatial_dimension, this->spatial_dimension);
auto damage_directions_it =
this->damage_dir_vecs(el_type, _not_ghost)
.begin(this->spatial_dimension, this->spatial_dimension);
auto stress_dir_it = this->stress_dir(el_type, _not_ghost)
.begin(spatial_dimension, spatial_dimension);
/// initialize the matrices for damage rotation results
Matrix<Real> tmp(spatial_dimension, spatial_dimension);
Matrix<Real> dam_in_computation_frame(spatial_dimension, spatial_dimension);
Matrix<Real> dam_in_stress_frame(spatial_dimension, spatial_dimension);
/// references to damage and directions of highest Gauss point
Matrix<Real> q_dam = dam_it[q_global_num];
Matrix<Real> q_dam_dir = damage_directions_it[q_global_num];
Matrix<Real> q_stress_dir = stress_dir_it[q_global_num];
/// increment damage
/// find the damage increment on this Gauss point
/// rotate damage into stress frame
this->rotateIntoComputationFrame(q_dam, dam_in_computation_frame, q_dam_dir,
tmp);
this->rotateIntoNewFrame(dam_in_computation_frame, dam_in_stress_frame,
q_stress_dir, tmp);
/// add damage increment
dam_in_stress_frame(0, 0) += prescribed_dam;
/// find new principal directions of damage
Vector<Real> dam_eigenvalues(spatial_dimension);
dam_in_stress_frame.eig(dam_eigenvalues, q_dam_dir);
- for (UInt i = 0; i < spatial_dimension; ++i) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
q_dam(i, i) = dam_eigenvalues(i);
if (q_dam(i, i) + Math::getTolerance() >= dam_threshold)
q_dam(i, i) = this->max_damage;
}
nb_damaged_elements += 1;
}
this->model.getMesh().getCommunicator().allReduce(
nb_damaged_elements, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
return nb_damaged_elements;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterative<
spatial_dimension>::updateEnergiesAfterDamage(ElementType el_type) {
MaterialOrthotropicDamage<spatial_dimension>::updateEnergies(el_type);
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(orthotropic_damage_iterative,
MaterialOrthotropicDamageIterative);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh
index 8a54d3998..ec03ca85b 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative.hh
@@ -1,127 +1,127 @@
/**
* @file material_orthtropic_damage_iterative.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date Sun Mar 8 12:54:30 2015
*
* @brief Specialization of the class material orthotropic damage to
* damage only one gauss point at a time and propagate damage in a
* linear way. Max principal stress criterion is used as a failure
* criterion.
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_orthotropic_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_HH_
#define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_HH_
namespace akantu {
/**
* Material damage iterative
*
* parameters in the material files :
* - Sc
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialOrthotropicDamageIterative
: public MaterialOrthotropicDamage<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialOrthotropicDamageIterative(SolidMechanicsModel & model,
const ID & id = "");
virtual ~MaterialOrthotropicDamageIterative(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// virtual void updateInternalParameters();
virtual void computeAllStresses(GhostType ghost_type = _not_ghost);
/// update internal field damage
UInt updateDamage();
/// update energies after damage has been updated
virtual void updateEnergiesAfterDamage(ElementType el_type);
protected:
/// constitutive law for all element of a type
virtual void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
/// compute the equivalent stress on each Gauss point (i.e. the max prinicpal
/// stress) and normalize it by the tensile strength
void computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type = _not_ghost);
/// find max normalized equivalent stress
void findMaxNormalizedEquivalentStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma,
Matrix<Real> & one_minus_D,
Matrix<Real> & root_one_minus_D,
Matrix<Real> & damage,
Matrix<Real> & first_term,
Matrix<Real> & third_term);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get max normalized equivalent stress
AKANTU_GET_MACRO(NormMaxEquivalentStress, norm_max_equivalent_stress, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// resistance to damage
RandomInternalField<Real> Sc;
/// internal field to store equivalent stress on each Gauss point
InternalField<Real> equivalent_stress;
/// internal field to store the direction of the current damage frame
InternalField<Real> stress_dir;
/// damage increment
Real prescribed_dam;
/// maximum equivalent stress
Real norm_max_equivalent_stress;
/// define damage threshold at which damage will be set to 1
Real dam_threshold;
/// quadrature point with highest equivalent Stress
IntegrationPoint q_max;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_orthotropic_damage_iterative_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh
index 0db4cc577..d52c8cae1 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_inline_impl.hh
@@ -1,69 +1,69 @@
/**
* @file material_damage_iterative_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date Sun Mar 8 12:54:30 2015
*
* @brief Implementation of inline functions of the material damage iterative
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialOrthotropicDamageIterative<spatial_dimension>::
computeDamageAndStressOnQuad(Matrix<Real> & sigma,
Matrix<Real> & one_minus_D,
Matrix<Real> & sqrt_one_minus_D,
Matrix<Real> & damage,
Matrix<Real> & first_term,
Matrix<Real> & third_term) {
- // Real dmax = *(std::max_element(damage.storage(), damage.storage() +
+ // Real dmax = *(std::max_element(damage.data(), damage.data() +
// spatial_dimension*spatial_dimension) );
Real eta_effective = 0;
// if ( (1 - dmax*dmax) < (1 - this->eta / spatial_dimension *
// damage.trace()) ) {
// eta_effective = this->spatial_dimension * dmax * dmax / damage.trace();
// }
// else
eta_effective = this->eta;
/// hydrostatic sensitivity parameter
// Real eta = 3.;
/// Definition of Cauchy stress based on second order damage tensor:
/// "Anisotropic damage modelling of biaxial behaviour and rupture
/// of concrete strucutres", Ragueneau et al., 2008, Eq. 7
first_term.mul<false, false>(sqrt_one_minus_D, sigma);
first_term *= sqrt_one_minus_D;
Real second_term = 0;
- for (UInt i = 0; i < this->spatial_dimension; ++i) {
- for (UInt j = 0; j < this->spatial_dimension; ++j)
+ for (Int i = 0; i < this->spatial_dimension; ++i) {
+ for (Int j = 0; j < this->spatial_dimension; ++j)
second_term += sigma(i, j) * one_minus_D(i, j);
}
second_term /= (this->spatial_dimension - damage.trace());
- // for (UInt i = 0; i < this->spatial_dimension; ++i) {
- // for (UInt j = 0; j < this->spatial_dimension; ++j)
+ // for (Int i = 0; i < this->spatial_dimension; ++i) {
+ // for (Int j = 0; j < this->spatial_dimension; ++j)
// one_minus_D(i,j) *= second_term;
// }
one_minus_D *= second_term;
third_term.eye(
1. / this->spatial_dimension * sigma.trace() *
(1 - std::min(eta_effective / (this->spatial_dimension) * damage.trace(),
this->max_damage)));
sigma.copy(first_term);
sigma -= one_minus_D;
sigma += third_term;
}
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh
index 0f3cd4585..6154b3f8f 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local.hh
@@ -1,84 +1,84 @@
/**
* @file material_orthotropic_damage_iterative_non_local.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief MaterialOrthotropicDamageIterativeNonLocal header for non-local
* damage
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_damage_non_local.hh"
#include "material_orthotropic_damage_iterative.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_NON_LOCAL_HH_
#define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_NON_LOCAL_HH_
namespace akantu {
/**
* Material Damage Iterative Non local
*
* parameters in the material files :
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialOrthotropicDamageIterativeNonLocal
: public MaterialDamageNonLocal<
spatial_dimension,
MaterialOrthotropicDamageIterative<spatial_dimension>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef MaterialDamageNonLocal<
spatial_dimension, MaterialOrthotropicDamageIterative<spatial_dimension>>
MaterialOrthotropicDamageIterativeNonLocalParent;
MaterialOrthotropicDamageIterativeNonLocal(SolidMechanicsModel & model,
const ID & id = "");
virtual ~MaterialOrthotropicDamageIterativeNonLocal(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial();
protected:
void computeStress(ElementType type, GhostType ghost_type);
void computeNonLocalStress(ElementType type,
GhostType ghost_type = _not_ghost);
/// associate the non-local variables of the material to their neighborhoods
virtual void nonLocalVariableToNeighborhood();
private:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
InternalField<Real> grad_u_nl;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_orthotropic_damage_iterative_non_local_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_ITERATIVE_NON_LOCAL_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh
index 7e60ec245..f20fbdade 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh
@@ -1,140 +1,140 @@
/**
* @file material_orthotropic_damage_iterative_non_local_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief MaterialOrthotropicDamageIterativeNonLocal inline function
* implementation
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
} // namespace akantu
#if defined(AKANTU_DEBUG_TOOLS)
#include "aka_debug_tools.hh"
#include <string>
#endif
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialOrthotropicDamageIterativeNonLocal<spatial_dimension>::
MaterialOrthotropicDamageIterativeNonLocal(SolidMechanicsModel & model,
const ID & id)
: Material(model, id),
MaterialOrthotropicDamageIterativeNonLocalParent(model, id),
grad_u_nl("grad_u non local", *this) {
AKANTU_DEBUG_IN();
this->is_non_local = true;
this->grad_u_nl.initialize(spatial_dimension * spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterativeNonLocal<
spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
this->model.getNonLocalManager().registerNonLocalVariable(
this->gradu.getName(), grad_u_nl.getName(),
spatial_dimension * spatial_dimension);
MaterialOrthotropicDamageIterativeNonLocalParent::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterativeNonLocal<
spatial_dimension>::computeStress(ElementType type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterativeNonLocal<
spatial_dimension>::computeNonLocalStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
MaterialOrthotropicDamage<spatial_dimension>::computeStress(el_type,
ghost_type);
Array<Real>::matrix_iterator damage_iterator =
this->damage(el_type, ghost_type)
.begin(this->spatial_dimension, this->spatial_dimension);
Array<Real>::matrix_iterator damage_dir_it =
this->damage_dir_vecs(el_type, ghost_type)
.begin(this->spatial_dimension, this->spatial_dimension);
/// for the computation of the Cauchy stress the matrices (1-D) and
/// (1-D)^(1/2) are needed. For the formulation see Engineering
/// Damage Mechanics by Lemaitre and Desmorat.
Matrix<Real> one_minus_D(this->spatial_dimension, this->spatial_dimension);
Matrix<Real> sqrt_one_minus_D(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> one_minus_D_rotated(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> sqrt_one_minus_D_rotated(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> rotation_tmp(this->spatial_dimension, this->spatial_dimension);
/// create matrix to store the first term of the computation of the
/// Cauchy stress
Matrix<Real> first_term(this->spatial_dimension, this->spatial_dimension);
Matrix<Real> third_term(this->spatial_dimension, this->spatial_dimension);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
/// rotate the tensors from the damage principal coordinate system to the CS
/// of the computation
if (!(Math::are_float_equal((*damage_iterator).trace(), 0))) {
/// compute (1-D) and (1-D)^1/2
this->computeOneMinusD(one_minus_D, *damage_iterator);
this->computeSqrtOneMinusD(one_minus_D, sqrt_one_minus_D);
this->rotateIntoComputationFrame(one_minus_D, one_minus_D_rotated,
*damage_dir_it, rotation_tmp);
this->rotateIntoComputationFrame(sqrt_one_minus_D, sqrt_one_minus_D_rotated,
*damage_dir_it, rotation_tmp);
} else {
MaterialOrthotropicDamage<spatial_dimension>::computeOneMinusD(
one_minus_D_rotated, *damage_iterator);
MaterialOrthotropicDamage<spatial_dimension>::computeSqrtOneMinusD(
one_minus_D_rotated, sqrt_one_minus_D_rotated);
}
this->computeDamageAndStressOnQuad(sigma, one_minus_D_rotated,
sqrt_one_minus_D_rotated, *damage_iterator,
first_term, third_term);
++damage_dir_it;
++damage_iterator;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
this->computeNormalizedEquivalentStress(this->grad_u_nl(el_type, ghost_type),
el_type, ghost_type);
this->norm_max_equivalent_stress = 0;
this->findMaxNormalizedEquivalentStress(el_type, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialOrthotropicDamageIterativeNonLocal<
spatial_dimension>::nonLocalVariableToNeighborhood() {
this->model.getNonLocalManager().nonLocalVariableToNeighborhood(
grad_u_nl.getName(), this->name);
}
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh
index 840c6d582..16a573db9 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_non_local.hh
@@ -1,103 +1,103 @@
/**
* @file material_orthotropic_damage_non_local.hh
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Sun Mar 22 21:10:27 2015
*
* @brief interface for non local orthotropic damage material
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_non_local.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_NON_LOCAL_HH_
#define AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_NON_LOCAL_HH_
namespace akantu {
-template <UInt spatial_dimension, class MaterialOrthotropicDamageLocal>
+template <Int spatial_dimension, class MaterialOrthotropicDamageLocal>
class MaterialOrthotropicDamageNonLocal
: public MaterialOrthotropicDamageLocal,
public MaterialNonLocal<spatial_dimension> {
public:
typedef MaterialNonLocal<spatial_dimension> MaterialNonLocalParent;
typedef MaterialOrthotropicDamageLocal MaterialOrthotropicDamageParent;
MaterialOrthotropicDamageNonLocal(SolidMechanicsModel & model, const ID & id)
: Material(model, id), MaterialOrthotropicDamageParent(model, id),
MaterialNonLocalParent(model, id){};
/* ------------------------------------------------------------------------ */
virtual void initMaterial() {
MaterialOrthotropicDamageParent::initMaterial();
MaterialNonLocalParent::initMaterial();
}
protected:
/* --------------------------------------------------------------------------
*/
virtual void computeNonLocalStress(ElementType type,
GhostType ghost_type = _not_ghost) = 0;
/* ------------------------------------------------------------------------ */
void computeNonLocalStresses(GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh::type_iterator it = this->model.getFEEngine().getMesh().firstType(
spatial_dimension, ghost_type);
Mesh::type_iterator last_type =
this->model.getFEEngine().getMesh().lastType(spatial_dimension,
ghost_type);
for (; it != last_type; ++it) {
computeNonLocalStress(*it, ghost_type);
}
AKANTU_DEBUG_OUT();
}
public:
/* ------------------------------------------------------------------------ */
virtual inline UInt getNbDataForElements(const Array<Element> & elements,
SynchronizationTag tag) const {
return MaterialNonLocalParent::getNbDataForElements(elements, tag) +
MaterialOrthotropicDamageParent::getNbDataForElements(elements, tag);
}
virtual inline void packElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) const {
MaterialNonLocalParent::packElementData(buffer, elements, tag);
MaterialOrthotropicDamageParent::packElementData(buffer, elements, tag);
}
virtual inline void unpackElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) {
MaterialNonLocalParent::unpackElementData(buffer, elements, tag);
MaterialOrthotropicDamageParent::unpackElementData(buffer, elements, tag);
}
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_ORTHOTROPIC_DAMAGE_NON_LOCAL_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh
index 0d752a8d7..81e13e3da 100644
--- a/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_orthotropic_damage_tmpl.hh
@@ -1,320 +1,320 @@
/**
* @file material_orthotropic_damage_tmpl.hh
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Sun Mar 8 12:54:30 2015
*
* @brief Specialization of the material class for the orthotropic
* damage material
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_orthotropic_damage.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
MaterialOrthotropicDamage<spatial_dimension, Parent>::MaterialOrthotropicDamage(
SolidMechanicsModel & model, const ID & id)
: Parent<spatial_dimension>(model, id), damage("damage", *this),
dissipated_energy("damage dissipated energy", *this),
int_sigma("integral of sigma", *this),
damage_dir_vecs("damage_principal_directions", *this) {
AKANTU_DEBUG_IN();
this->registerParam("eta", eta, 2., _pat_parsable | _pat_modifiable,
"Damage sensitivity parameter");
this->registerParam("max_damage", max_damage, 0.99999,
_pat_parsable | _pat_modifiable, "maximum damage value");
this->is_non_local = false;
this->use_previous_stress = true;
this->use_previous_gradu = true;
/// use second order tensor for description of damage state
this->damage.initialize(spatial_dimension * spatial_dimension);
this->dissipated_energy.initialize(1);
this->int_sigma.initialize(1);
this->damage_dir_vecs.initialize(spatial_dimension * spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
void MaterialOrthotropicDamage<spatial_dimension, Parent>::initMaterial() {
AKANTU_DEBUG_IN();
Parent<spatial_dimension>::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Compute the dissipated energy in each element by a trapezoidal approximation
* of
* @f$ Ed = \int_0^{\epsilon}\sigma(\omega)d\omega -
* \frac{1}{2}\sigma:\epsilon@f$
*/
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
void MaterialOrthotropicDamage<spatial_dimension, Parent>::updateEnergies(
ElementType el_type) {
Parent<spatial_dimension>::updateEnergies(el_type);
this->computePotentialEnergy(el_type);
auto epsilon_p =
this->gradu.previous(el_type).begin(spatial_dimension, spatial_dimension);
auto sigma_p = this->stress.previous(el_type).begin(spatial_dimension,
spatial_dimension);
auto epot = this->potential_energy(el_type).begin();
auto ints = this->int_sigma(el_type).begin();
auto ed = this->dissipated_energy(el_type).begin();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
Matrix<Real> delta_gradu_it(grad_u);
delta_gradu_it -= *epsilon_p;
Matrix<Real> sigma_h(sigma);
sigma_h += *sigma_p;
Real dint = .5 * sigma_h.doubleDot(delta_gradu_it);
*ints += dint;
*ed = *ints - *epot;
++epsilon_p;
++sigma_p;
++epot;
++ints;
++ed;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
void MaterialOrthotropicDamage<spatial_dimension, Parent>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Parent<spatial_dimension>::computeTangentModuli(el_type, tangent_matrix,
ghost_type);
/// get the damage array for current element type
Array<Real> & dam = this->damage(el_type);
auto dam_it = dam.begin(this->spatial_dimension, this->spatial_dimension);
/// get the directions of damage for the current element type
Array<Real> & dam_dirs = this->damage_dir_vecs(el_type);
auto damage_directions_it =
dam_dirs.begin(this->spatial_dimension, this->spatial_dimension);
/// for the computation of the Cauchy stress the matrices (1-D) and
/// (1-D)^(1/2) are needed. For the formulation see Engineering
/// Damage Mechanics by Lemaitre and Desmorat.
Matrix<Real> one_minus_D(this->spatial_dimension, this->spatial_dimension);
Matrix<Real> sqrt_one_minus_D(this->spatial_dimension,
this->spatial_dimension);
Matrix<Real> one_minus_D_rot(spatial_dimension, spatial_dimension);
Matrix<Real> sqrt_one_minus_D_rot(spatial_dimension, spatial_dimension);
Matrix<Real> rotation_tmp(spatial_dimension, spatial_dimension);
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
if (!(Math::are_float_equal((*dam_it).trace(), 0)))
computeTangentModuliOnQuad(tangent, tangent, *dam_it, *damage_directions_it,
one_minus_D, sqrt_one_minus_D, one_minus_D_rot,
sqrt_one_minus_D_rot, rotation_tmp);
++dam_it;
++damage_directions_it;
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
void MaterialOrthotropicDamage<spatial_dimension, Parent>::
computeTangentModuliOnQuad(Matrix<Real> & tangent, const Matrix<Real> C,
const Matrix<Real> & dam,
const Matrix<Real> & dam_directions,
Matrix<Real> & O_prime, Matrix<Real> & S_prime,
Matrix<Real> & O, Matrix<Real> & S,
Matrix<Real> & rotation_tmp) {
/// effect of damage on stiffness matrix: See Ragueneau et al. 2008, p. 423,
/// ep. 7
Real trace_D = dam.trace();
this->computeOneMinusD(O_prime, dam);
this->computeSqrtOneMinusD(O_prime, S_prime);
this->rotateIntoComputationFrame(O_prime, O, dam_directions, rotation_tmp);
this->rotateIntoComputationFrame(S_prime, S, dam_directions, rotation_tmp);
/// compute new stiffness matrix in damage coordinate system
if (spatial_dimension == 1)
tangent *= (1 - dam(0, 0));
if (spatial_dimension == 2) {
Real min_val =
std::min((this->eta / spatial_dimension * trace_D), this->max_damage);
/// first row
tangent(0, 0) =
(C(0, 0) * S(0, 0) * S(0, 0) + C(1, 0) * S(0, 1) * S(0, 1) -
(min_val / 2. - 1. / 2) * (C(0, 0) + C(1, 0)) +
(O(0, 0) * (C(0, 0) * O(0, 0) + C(1, 0) * O(1, 1))) / (trace_D - 2.));
tangent(0, 1) =
(C(0, 1) * S(0, 0) * S(0, 0) + C(1, 1) * S(0, 1) * S(0, 1) -
(min_val / 2. - 1. / 2) * (C(0, 1) + C(1, 1)) +
(O(0, 0) * (C(0, 1) * O(0, 0) + C(1, 1) * O(1, 1))) / (trace_D - 2.));
tangent(0, 2) = (2. * C(2, 2) * S(0, 0) * S(0, 1) +
(2. * C(2, 2) * O(0, 0) * O(0, 1)) / (trace_D - 2.));
/// second row
tangent(1, 0) =
(C(0, 0) * S(0, 1) * S(0, 1) + C(1, 0) * S(1, 1) * S(1, 1) -
(min_val / 2. - 1. / 2) * (C(0, 0) + C(1, 0)) +
(O(1, 1) * (C(0, 0) * O(0, 0) + C(1, 0) * O(1, 1))) / (trace_D - 2.));
tangent(1, 1) =
(C(0, 1) * S(0, 1) * S(0, 1) + C(1, 1) * S(1, 1) * S(1, 1) -
(min_val / 2. - 1. / 2) * (C(0, 1) + C(1, 1)) +
(O(1, 1) * (C(0, 1) * O(0, 0) + C(1, 1) * O(1, 1))) / (trace_D - 2.));
tangent(1, 2) = (2. * C(2, 2) * S(0, 1) * S(1, 1) +
(2. * C(2, 2) * O(0, 1) * O(1, 1)) / (trace_D - 2.));
/// third row
tangent(2, 0) =
((O(0, 1) * (C(0, 0) * O(0, 0) + C(1, 0) * O(1, 1))) / (trace_D - 2.) +
C(0, 0) * S(0, 0) * S(0, 1) + C(1, 0) * S(0, 1) * S(1, 1));
tangent(2, 1) =
((O(0, 1) * (C(0, 1) * O(0, 0) + C(1, 1) * O(1, 1))) / (trace_D - 2.) +
C(0, 1) * S(0, 0) * S(0, 1) + C(1, 1) * S(0, 1) * S(1, 1));
tangent(2, 2) = ((2. * C(2, 2) * O(0, 1) * O(0, 1)) / (trace_D - 2.) +
C(2, 2) * S(0, 1) * S(0, 1) + C(2, 2) * S(0, 0) * S(1, 1));
}
if (spatial_dimension == 3) {
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
inline void MaterialOrthotropicDamage<spatial_dimension, Parent>::
computeDamageAndStressOnQuad(Matrix<Real> & sigma,
Matrix<Real> & one_minus_D,
Matrix<Real> & sqrt_one_minus_D,
Matrix<Real> & damage,
Matrix<Real> & first_term,
Matrix<Real> & third_term) {
/// Definition of Cauchy stress based on second order damage tensor:
/// "Anisotropic damage modelling of biaxial behaviour and rupture
/// of concrete strucutres", Ragueneau et al., 2008, Eq. 7
first_term.mul<false, false>(sqrt_one_minus_D, sigma);
first_term *= sqrt_one_minus_D;
Real second_term = 0;
for (UInt i = 0; i < this->spatial_dimension; ++i) {
for (UInt j = 0; j < this->spatial_dimension; ++j)
second_term += sigma(i, j) * one_minus_D(i, j);
}
second_term /= (this->spatial_dimension - damage.trace());
one_minus_D *= second_term;
third_term.eye(1. / this->spatial_dimension * sigma.trace() *
(1 - eta / (this->spatial_dimension) * damage.trace()));
sigma.copy(first_term);
sigma -= one_minus_D;
sigma += third_term;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
inline void MaterialOrthotropicDamage<spatial_dimension, Parent>::
rotateIntoComputationFrame(const Matrix<Real> & to_rotate,
Matrix<Real> & rotated,
const Matrix<Real> & damage_directions,
Matrix<Real> & rotation_tmp) {
rotation_tmp.mul<false, true>(to_rotate, damage_directions);
rotated.mul<false, false>(damage_directions, rotation_tmp);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
inline void
MaterialOrthotropicDamage<spatial_dimension, Parent>::rotateIntoNewFrame(
const Matrix<Real> & to_rotate, Matrix<Real> & rotated,
const Matrix<Real> & damage_directions, Matrix<Real> & rotation_tmp) {
rotation_tmp.mul<false, false>(to_rotate, damage_directions);
rotated.mul<true, false>(damage_directions, rotation_tmp);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
inline void
MaterialOrthotropicDamage<spatial_dimension, Parent>::computeOneMinusD(
Matrix<Real> & one_minus_D, const Matrix<Real> & damage) {
/// compute one minus
one_minus_D.eye();
one_minus_D -= damage;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
+template <Int spatial_dimension, template <UInt> class Parent>
inline void
MaterialOrthotropicDamage<spatial_dimension, Parent>::computeSqrtOneMinusD(
const Matrix<Real> & one_minus_D, Matrix<Real> & sqrt_one_minus_D) {
/// To compute (1-D)^1/2 we need to check that we are in the
/// principal coordinate system of the damage
#ifndef AKANTU_NDEBUG
- for (UInt i = 0; i < this->spatial_dimension; ++i) {
- for (UInt j = 0; j < this->spatial_dimension; ++j) {
+ for (Int i = 0; i < this->spatial_dimension; ++i) {
+ for (Int j = 0; j < this->spatial_dimension; ++j) {
if (i != j)
AKANTU_DEBUG_ASSERT(Math::are_float_equal(one_minus_D(i, j), 0),
"The damage tensor has off-diagonal parts");
}
}
#endif // AKANTU_NDEBUG
/// compute (1-D)^1/2
sqrt_one_minus_D.copy(one_minus_D);
- for (UInt i = 0; i < this->spatial_dimension; ++i)
+ for (Int i = 0; i < this->spatial_dimension; ++i)
sqrt_one_minus_D(i, i) = std::sqrt(sqrt_one_minus_D(i, i));
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh
index 54bcafe6b..a844a7dda 100644
--- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings.hh
@@ -1,141 +1,141 @@
/**
* @file material_vreepeerlings.hh
*
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
*
* @brief Specialization of the material class for the VreePeerlings material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_VREEPEERLINGS_HH_
#define AKANTU_MATERIAL_VREEPEERLINGS_HH_
namespace akantu {
/**
* Material vreepeerlings
*
* parameters in the material files :
* - Kapaoi : (default: 0.0001) Initial threshold (of the equivalent strain)
* >= Crate
* - Kapac : (default: 0.0002) Final threshold (of the equivalent strain)
* - Arate : (default: 1.) Fitting parameter (must be close to 1 to do tend
* to 0 the stress in the damaged element)
* - Brate : (default: 1.) This parameter determines the rate at which the
* damage grows
* - Crate : (default: 0.0001) This parameter determines the rate at which
* the damage grows
* - Kct : (default: 1.) Ratio between compressive and tensile strength
*/
-template <UInt spatial_dimension,
+template <Int spatial_dimension,
template <UInt> class MatParent = MaterialElastic>
class MaterialVreePeerlings
: public MaterialDamage<spatial_dimension, MatParent> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef MaterialDamage<spatial_dimension, MatParent>
MaterialVreePeerlingsParent;
MaterialVreePeerlings(SolidMechanicsModel & model, const ID & id = "");
virtual ~MaterialVreePeerlings(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial();
/// constitutive law for all element of a type
void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
protected:
/// constitutive law for a given quadrature point
inline void computeStressOnQuad(Matrix<Real> & F, Matrix<Real> & sigma,
Real & dam, Real & Equistrain_rate,
Real & Equistrain, Real & Kapaq, Real dt,
Matrix<Real> & strain_rate_vrpgls,
Real & FullDam_ValStrain,
Real & FullDam_ValStrain_rate,
Real & Nb_damage);
inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma, Real & dam,
Real & Equistrain_rate,
Real & Equistrain, Real & Kapaq,
Real dt, Real & FullDam_Valstrain,
Real & FullDam_Valstrain_rate,
Real & Nb_damage);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// Initial threshold (of the equivalent strain) (used in the initial step)
Real Kapaoi;
/// Final threshold (of the equivalent strain) (used in the initial step)
Real Kapac;
/// This parameter determines the rate at which the damage grows
Real Arate;
/// This parameter determines the rate at which the damage grows
Real Brate;
/// This parameter determines the rate at which the damage grows
Real Crate;
/// Ratio between compressive and tensile strength
Real Kct;
/// Randomness on Kapaoi
Real Kapao_randomness;
/// Kapa vector which contains the initial damage threshold
RandomInternalField<Real> Kapa;
/// Strain rate tensor to compute the rate dependent damage law
InternalField<Real> strain_rate_vreepeerlings;
/// Value of the equivalent strain when damage = 1
InternalField<Real> Full_dam_value_strain;
/// Value of the equivalent strain rate when damage = 1
InternalField<Real> Full_dam_value_strain_rate;
/// Count the number of times that the material is damaged to damage = 0 until
/// damage = 1
InternalField<Real> Number_damage;
/// Equivalent strain used to compute the damage evolution
InternalField<Real> equi_strain;
/// Equivalent strain rate used to compute the damage evolution
InternalField<Real> equi_strain_rate;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_vreepeerlings_inline_impl.hh"
#include "material_vreepeerlings_tmpl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_VREEPEERLINGS_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh
index d688f9a31..b51dcdb4b 100644
--- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_inline_impl.hh
@@ -1,184 +1,184 @@
/**
* @file material_vreepeerlings_inline_impl.hh
*
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
*
* @brief Specialization of the material class for the VreePeerlings material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
inline void
MaterialVreePeerlings<spatial_dimension, MatParent>::computeStressOnQuad(
Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam, Real & Equistrain,
Real & Equistrain_rate, Real & Kapaq, Real dt,
Matrix<Real> & strain_rate_vrplgs, Real & FullDam_ValStrain,
Real & FullDam_ValStrain_rate, Real & Nb_damage) {
Real I1 = 0.; /// trace initialization of the strain tensor
Real J2 = 0.; /// J2 [J2=1/6(3 strain:strain - I1*I1)] initialization
Real I1rate = 0.; /// trace initialization of the strain rate tensor
Real J2rate =
0.; /// J2 [J2=1/3(3 strain:strainrate - I1*I1rate)] initialization
if (spatial_dimension == 1) {
I1 = grad_u.trace();
J2 = .5 * grad_u(0, 0) * grad_u(0, 0) - I1 * I1 / 6.;
I1rate = strain_rate_vrplgs.trace();
J2rate = grad_u(0, 0) * strain_rate_vrplgs(0, 0) - I1 * I1rate / 6.;
} else {
// if(this->plane_stress) {
// Real tmp = this->nu/(this->nu - 1);
// tmp *= tmp;
// I1 = (grad_u(0,0) + grad_u(1,1))*(1 - 2*this->nu)/(1 - this->nu);
// J2 = .5*(grad_u(0,0)*grad_u(0,0) +
// grad_u(1,1)*grad_u(1,1) +
// tmp*(grad_u(0,0) + grad_u(1,1))*(grad_u(0,0) + grad_u(1,1)) +
// .5*(grad_u(0,1) + grad_u(1,0))*(grad_u(0,1) + grad_u(1,0))) -
// I1*I1/6.;
// I1rate = (strain_rate_vrplgs(0,0) + strain_rate_vrplgs(1,1))*(1 -
// 2*this->nu)/(1 - this->nu);
// J2rate = (grad_u(0,0)*strain_rate_vrplgs(0,0) +
// grad_u(1,1)*strain_rate_vrplgs(1,1) +
// tmp*(grad_u(0,0) + grad_u(1,1))*(strain_rate_vrplgs(0,0) +
// strain_rate_vrplgs(1,1)) +
// (grad_u(0,1)*strain_rate_vrplgs(1,0)) +
// (grad_u(0,1)*strain_rate_vrplgs(1,0))) -
// I1*I1rate/3.;
// }
// else {
I1 = grad_u.trace();
for (UInt i = 0; i < spatial_dimension; ++i)
for (UInt j = i; j < spatial_dimension; ++j)
J2 += 0.5 * ((i == j) * grad_u(i, i) * grad_u(i, i) +
0.5 * (1 - (i == j)) *
((grad_u(i, j) + grad_u(j, i)) *
(grad_u(i, j) + grad_u(j, i))));
J2 -= I1 * I1 / 6.;
I1rate = strain_rate_vrplgs.trace();
bool is3D = spatial_dimension == 3;
J2rate = (grad_u(0, 0) * strain_rate_vrplgs(0, 0) +
grad_u(1, 1) * strain_rate_vrplgs(1, 1) +
is3D * grad_u(2, 2) * strain_rate_vrplgs(2, 2) +
(grad_u(0, 1) * strain_rate_vrplgs(1, 0)) +
(grad_u(0, 1) * strain_rate_vrplgs(1, 0)) +
is3D * (grad_u(1, 2) * strain_rate_vrplgs(2, 1)) +
is3D * (grad_u(1, 2) * strain_rate_vrplgs(2, 1)) +
is3D * (grad_u(2, 0) * strain_rate_vrplgs(0, 2)) +
is3D * (grad_u(2, 0) * strain_rate_vrplgs(0, 2))) -
I1 * I1rate / 3.;
// }
}
Real tmp_1 = (Kct - 1) / (1 - 2 * this->nu);
Real tmp_2 = (12 * Kct) / ((1 + this->nu) * (1 + this->nu));
Equistrain = tmp_1 * I1 / (2 * Kct) +
1. / (2 * Kct) * std::sqrt(tmp_1 * tmp_1 * I1 * I1 + tmp_2 * J2);
if (I1 * I1rate > 0 || J2rate > 0) {
Equistrain_rate = tmp_1 * std::abs(I1rate) / (2 * Kct) +
1. / (4 * Kct) *
(2 * tmp_1 * tmp_1 * I1 * I1rate + tmp_2 * J2rate) /
std::sqrt(tmp_1 * tmp_1 * I1 * I1 + tmp_2 * J2);
} else {
AKANTU_ERROR("This instruction here was commented but has to be checked");
// Equistrain_rate = Equistrain_rate;
}
if (!this->is_non_local) {
computeDamageAndStressOnQuad(sigma, dam, Equistrain, Equistrain_rate, Kapaq,
dt, FullDam_ValStrain, FullDam_ValStrain_rate,
Nb_damage);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
inline void MaterialVreePeerlings<spatial_dimension, MatParent>::
computeDamageAndStressOnQuad(Matrix<Real> & sigma, Real & dam,
Real & Equistrain, Real & Equistrain_rate,
Real & Kapaq, Real dt,
Real & FullDam_ValStrain,
Real & FullDam_ValStrain_rate,
Real & Nb_damage) {
//---------------------------------------------------------------------------------------
// rate-dependence model
//
//---------------------------------------------------------------------------------------
Real Kapao = Crate *
(1. + (std::pow(std::abs(Equistrain_rate) * Arate, Brate))) *
(1. - Kapao_randomness) +
Kapao_randomness * Kapaq;
Real Kapac_99 = Kapac * .99;
Real Kapaodyn = 0;
if (Kapao > Kapaoi) {
if (Kapao < Kapac_99) {
Kapaodyn = Kapao;
} else {
Kapaodyn = Kapac_99;
}
} else {
Kapaodyn = Kapaoi;
}
Real Fd1 = Equistrain - Kapaoi;
if (Fd1 > 0) {
Real dam1 = 1. - Kapaodyn / Equistrain *
((Kapac - Equistrain) / (Kapac - Kapaodyn));
if (dam1 > dam) {
dam = std::min(dam1, 1.);
Nb_damage = Nb_damage + 1.;
if (dam >= 1.) {
FullDam_ValStrain = Equistrain;
FullDam_ValStrain_rate = Equistrain_rate;
}
}
}
//---------------------------------------------------------------------------------------
// delayed damage (see Marions thesis page 68)
//---------------------------------------------------------------------------------------
// Real viscosity = 10.;
// Real damRateInfini = 10000000.;
// Real gequi = 1. - Kapaq/Equistrain * ((Kapac-Equistrain)/(Kapac -
// Kapaq));
// if (gequi - dam > 0){
//
// Real damRate = damRateInfini * (1. - std::exp(-1*viscosity * (gequi -
// dam)));
// if (damrate > 0){
//
// if (dam < 1.){
// dam = dam + damRate*dt;
// } else {
// dam = 1.;
// }
// }
// }
//
//---------------------------------------------------------------------------------------
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh
index 1d0b1db19..7df371fd9 100644
--- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local.hh
@@ -1,89 +1,89 @@
/**
* @file material_vreepeerlings_non_local.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
*
* @brief MaterialVreePeerlings header for non-local damage
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_damage_non_local.hh"
#include "material_vreepeerlings.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_VREEPEERLINGS_NON_LOCAL_HH_
#define AKANTU_MATERIAL_VREEPEERLINGS_NON_LOCAL_HH_
namespace akantu {
/**
* Material VreePeerlings Non local
*
* parameters in the material files :
*/
-template <UInt spatial_dimension,
+template <Int spatial_dimension,
template <UInt> class MatParent = MaterialElastic>
class MaterialVreePeerlingsNonLocal
: public MaterialDamageNonLocal<
spatial_dimension,
MaterialVreePeerlings<spatial_dimension, MatParent>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef MaterialVreePeerlings<spatial_dimension, MatParent> Parent;
typedef MaterialDamageNonLocal<spatial_dimension, Parent>
MaterialVreePeerlingsNonLocalParent;
MaterialVreePeerlingsNonLocal(SolidMechanicsModel & model,
const ID & id = "");
virtual ~MaterialVreePeerlingsNonLocal(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial();
/// constitutive law for all element of a type
// void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
/// constitutive law
virtual void computeNonLocalStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// non local version of equivalent strain
InternalField<Real> equi_strain_non_local;
/// non local version of equivalent strain rate
InternalField<Real> equi_strain_rate_non_local;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_vreepeerlings_non_local_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_VREEPEERLINGS_NON_LOCAL_HH_ */
diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh
index 6f7eddf59..bd6560d33 100644
--- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_non_local_inline_impl.hh
@@ -1,159 +1,159 @@
/**
* @file material_vreepeerlings_non_local_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
*
* @brief Specialization of the material class for the non-local Vree-Peerlings
* material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
MaterialVreePeerlingsNonLocal<spatial_dimension, MatParent>::
MaterialVreePeerlingsNonLocal(SolidMechanicsModel & model, const ID & id)
: Material(model, id), MaterialVreePeerlingsNonLocalParent(model, id),
equi_strain_non_local("equi-strain_non_local", *this),
equi_strain_rate_non_local("equi-strain-rate_non_local", *this) {
AKANTU_DEBUG_IN();
this->is_non_local = true;
this->equi_strain_non_local.initialize(1);
this->equi_strain_rate_non_local.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
void MaterialVreePeerlingsNonLocal<spatial_dimension,
MatParent>::initMaterial() {
AKANTU_DEBUG_IN();
this->registerNonLocalVariable(this->equi_strain, this->equi_strain_non_local,
1);
this->registerNonLocalVariable(this->equi_strain_rate,
this->equi_strain_rate_non_local, 1);
MaterialVreePeerlingsNonLocalParent::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-// template<UInt spatial_dimension, class WeigthFunction, template <UInt> class
+// template<Int spatial_dimension, class WeigthFunction, template <UInt> class
// MatParent>
// void MaterialVreePeerlingsNonLocal<spatial_dimension, WeigthFunction,
// MatParent>::computeStress(ElementType el_type,
// GhostType ghost_type) {
// AKANTU_DEBUG_IN();
//
-// Real * dam = this->damage(el_type, ghost_type).storage();
-// Real * equi_straint = equi_strain(el_type, ghost_type).storage();
-// Real * equi_straint_rate = equi_strain_rate(el_type, ghost_type).storage();
-// Real * Kapaq = this->Kapa(el_type, ghost_type).storage();
-// Real * crit_strain = this->critical_strain(el_type, ghost_type).storage();
+// Real * dam = this->damage(el_type, ghost_type).data();
+// Real * equi_straint = equi_strain(el_type, ghost_type).data();
+// Real * equi_straint_rate = equi_strain_rate(el_type, ghost_type).data();
+// Real * Kapaq = this->Kapa(el_type, ghost_type).data();
+// Real * crit_strain = this->critical_strain(el_type, ghost_type).data();
// Real * crit_strain_rate = this->critical_strain_rate(el_type,
-// ghost_type).storage();
-// Real * rdr_damage = this->recorder_damage(el_type, ghost_type).storage();
-// Real * nb_damage = this->number_damage(el_type, ghost_type).storage();
+// ghost_type).data();
+// Real * rdr_damage = this->recorder_damage(el_type, ghost_type).data();
+// Real * nb_damage = this->number_damage(el_type, ghost_type).data();
// Real dt = this->model.getTimeStep();
//
// Vector<UInt> & elem_filter = this->element_filter(el_type, ghost_type);
// Vector<Real> & velocity = this->model.getVelocity();
// Vector<Real> & strain_rate_vrplgs = this->strain_rate_vreepeerlings(el_type,
// ghost_type);
//
//
// this->model.getFEEngine().gradientOnQuadraturePoints(velocity,
// strain_rate_vrplgs,
// spatial_dimension,
// el_type, ghost_type, &elem_filter);
//
// Vector<Real>::iterator<types::RMatrix> strain_rate_vrplgs_it =
// strain_rate_vrplgs.begin(spatial_dimension, spatial_dimension);
//
//
// MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
//
// types::RMatrix & strain_rate = *strain_rate_vrplgs_it;
//
//
//
// MaterialVreePeerlings<spatial_dimension>::computeStressOnQuad(grad_u, sigma,
// *dam,
// *equi_straint,
// *equi_straint_rate,
// *Kapaq,
// dt,
// strain_rate,
// *crit_strain,
// *crit_strain_rate,
// *rdr_damage,
// *nb_damage);
// ++dam;
// ++equi_straint;
// ++equi_straint_rate;
// ++Kapaq;
// ++strain_rate_vrplgs_it;
// ++crit_strain;
// ++crit_strain_rate;
// ++rdr_damage;
// ++nb_damage;
//
// MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
//
// AKANTU_DEBUG_OUT();
//}
//
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
void MaterialVreePeerlingsNonLocal<
spatial_dimension, MatParent>::computeNonLocalStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = this->damage(el_type, ghost_type).storage();
- Real * Kapaq = this->Kapa(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
+ Real * Kapaq = this->Kapa(el_type, ghost_type).data();
Real * equi_strain_nl =
- this->equi_strain_non_local(el_type, ghost_type).storage();
+ this->equi_strain_non_local(el_type, ghost_type).data();
Real * equi_strain_rate_nl =
- this->equi_strain_rate_non_local(el_type, ghost_type).storage();
+ this->equi_strain_rate_non_local(el_type, ghost_type).data();
// Real * equi_strain_rate_nl = this->equi_strain_rate(el_type,
- // ghost_type).storage();
+ // ghost_type).data();
Real dt = this->model.getTimeStep();
Real * FullDam_Valstrain =
- this->Full_dam_value_strain(el_type, ghost_type).storage();
+ this->Full_dam_value_strain(el_type, ghost_type).data();
Real * FullDam_Valstrain_rate =
- this->Full_dam_value_strain_rate(el_type, ghost_type).storage();
- Real * Nb_damage = this->Number_damage(el_type, ghost_type).storage();
+ this->Full_dam_value_strain_rate(el_type, ghost_type).data();
+ Real * Nb_damage = this->Number_damage(el_type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
this->computeDamageAndStressOnQuad(
sigma, *dam, *equi_strain_nl, *equi_strain_rate_nl, *Kapaq, dt,
*FullDam_Valstrain, *FullDam_Valstrain_rate, *Nb_damage);
++dam;
++equi_strain_nl;
++equi_strain_rate_nl;
++Kapaq;
++FullDam_Valstrain;
++FullDam_Valstrain_rate;
++Nb_damage;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
diff --git a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh
index 2becb9bf1..51fa9d3d3 100644
--- a/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh
+++ b/extra_packages/extra-materials/src/material_damage/material_vreepeerlings_tmpl.hh
@@ -1,106 +1,105 @@
/**
* @file material_vreepeerlings_tmpl.hh
*
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
*
* @brief Specialization of the material class for the VreePeerlings material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
MaterialVreePeerlings<spatial_dimension, MatParent>::MaterialVreePeerlings(
SolidMechanicsModel & model, const ID & id)
: Material(model, id), MaterialVreePeerlingsParent(model, id),
Kapa("Kapa", *this),
strain_rate_vreepeerlings("strain-rate-vreepeerlings", *this),
Full_dam_value_strain("fulldam-valstrain", *this),
Full_dam_value_strain_rate("fulldam-valstrain-rate", *this),
Number_damage("number-damage", *this), equi_strain("equi-strain", *this),
equi_strain_rate("equi-strain-rate", *this) {
AKANTU_DEBUG_IN();
this->registerParam("Kapaoi", Kapaoi, 0.0001, _pat_parsable);
this->registerParam("Kapac", Kapac, 0.0002, _pat_parsable);
this->registerParam("Arate", Arate, 0., _pat_parsable);
this->registerParam("Brate", Brate, 1., _pat_parsable);
this->registerParam("Crate", Brate, 1., _pat_parsable);
this->registerParam("Kct", Kct, 1., _pat_parsable);
this->registerParam("Kapao_randomness", Kapao_randomness, 0., _pat_parsable);
this->Kapa.initialize(1);
this->equi_strain.initialize(1);
this->equi_strain_rate.initialize(1);
this->Full_dam_value_strain.initialize(1);
this->Full_dam_value_strain_rate.initialize(1);
this->Number_damage.initialize(1);
this->strain_rate_vreepeerlings.initialize(spatial_dimension *
spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
void MaterialVreePeerlings<spatial_dimension, MatParent>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialVreePeerlingsParent::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class MatParent>
+template <Int spatial_dimension, template <UInt> class MatParent>
void MaterialVreePeerlings<spatial_dimension, MatParent>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
MaterialVreePeerlingsParent::computeStress(el_type, ghost_type);
- Real * dam = this->damage(el_type, ghost_type).storage();
- Real * equi_straint = equi_strain(el_type, ghost_type).storage();
- Real * equi_straint_rate = equi_strain_rate(el_type, ghost_type).storage();
- Real * Kapaq = Kapa(el_type, ghost_type).storage();
- Real * FullDam_Valstrain =
- Full_dam_value_strain(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
+ Real * equi_straint = equi_strain(el_type, ghost_type).data();
+ Real * equi_straint_rate = equi_strain_rate(el_type, ghost_type).data();
+ Real * Kapaq = Kapa(el_type, ghost_type).data();
+ Real * FullDam_Valstrain = Full_dam_value_strain(el_type, ghost_type).data();
Real * FullDam_Valstrain_rate =
- Full_dam_value_strain_rate(el_type, ghost_type).storage();
- Real * Nb_damage = Number_damage(el_type, ghost_type).storage();
+ Full_dam_value_strain_rate(el_type, ghost_type).data();
+ Real * Nb_damage = Number_damage(el_type, ghost_type).data();
Real dt = this->model.getTimeStep();
- Array<UInt> & elem_filter = this->element_filter(el_type, ghost_type);
+ Array<Idx> & elem_filter = this->element_filter(el_type, ghost_type);
Array<Real> & velocity = this->model.getVelocity();
Array<Real> & strain_rate_vrplgs =
this->strain_rate_vreepeerlings(el_type, ghost_type);
this->model.getFEEngine().gradientOnIntegrationPoints(
velocity, strain_rate_vrplgs, spatial_dimension, el_type, ghost_type,
elem_filter);
Array<Real>::matrix_iterator strain_rate_vrplgs_it =
strain_rate_vrplgs.begin(spatial_dimension, spatial_dimension);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
Matrix<Real> & strain_rate = *strain_rate_vrplgs_it;
computeStressOnQuad(grad_u, sigma, *dam, *equi_straint, *equi_straint_rate,
*Kapaq, dt, strain_rate, *FullDam_Valstrain,
*FullDam_Valstrain_rate, *Nb_damage);
++dam;
++equi_straint;
++equi_straint_rate;
++Kapaq;
++strain_rate_vrplgs_it;
++FullDam_Valstrain;
++FullDam_Valstrain_rate;
++Nb_damage;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
diff --git a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc
index e93deff2c..e49d20e0f 100644
--- a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc
+++ b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.cc
@@ -1,106 +1,106 @@
/**
* @file material_viscoplastic.cc
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
*
*
* @brief Specialization of the material class for isotropic viscoplastic
* (small deformation)
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_viscoplastic.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialViscoPlastic<dim>::MaterialViscoPlastic(SolidMechanicsModel & model,
const ID & id)
: MaterialPlastic<dim>(model, id) {
AKANTU_DEBUG_IN();
this->registerParam("rate", rate, 0., _pat_parsable | _pat_modifiable,
"Rate sensitivity component");
this->registerParam("edot0", edot0, 0., _pat_parsable | _pat_modifiable,
"Reference strain rate");
this->registerParam("ts", ts, 0., _pat_parsable | _pat_modifiable,
"Time Step");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialViscoPlastic<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * iso_hardening = this->iso_hardening(el_type, ghost_type).storage();
+ Real * iso_hardening = this->iso_hardening(el_type, ghost_type).data();
auto previous_grad_u_it =
this->gradu.previous(el_type, ghost_type).begin(dim, dim);
auto previous_sigma_it =
this->stress.previous(el_type, ghost_type).begin(dim, dim);
auto inelastic_strain_it =
this->inelastic_strain(el_type, ghost_type).begin(dim, dim);
auto previous_inelastic_strain_it =
this->inelastic_strain.previous(el_type, ghost_type).begin(dim, dim);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
computeStressOnQuad(grad_u, *previous_grad_u_it, sigma, *previous_sigma_it,
*inelastic_strain_it, *previous_inelastic_strain_it,
*iso_hardening);
++inelastic_strain_it;
++iso_hardening;
++previous_grad_u_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialViscoPlastic<dim>::computeTangentModuli(
__attribute__((unused)) ElementType el_type, Array<Real> & tangent_matrix,
__attribute__((unused)) GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto previous_sigma_it =
this->stress.previous(el_type, ghost_type).begin(dim, dim);
auto previous_strain_it =
this->gradu.previous(el_type, ghost_type).begin(dim, dim);
- Real * iso_hardening = this->iso_hardening(el_type, ghost_type).storage();
+ Real * iso_hardening = this->iso_hardening(el_type, ghost_type).data();
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
Matrix<Real> & previous_grad_u = *previous_strain_it;
Matrix<Real> & previous_sigma_tensor = *previous_sigma_it;
computeTangentModuliOnQuad(tangent, grad_u, previous_grad_u, sigma,
previous_sigma_tensor, *iso_hardening);
++previous_sigma_it;
++previous_strain_it;
++iso_hardening;
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
INSTANTIATE_MATERIAL(visco_plastic, MaterialViscoPlastic);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh
index 31976de37..ad9da3b9d 100644
--- a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh
+++ b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic.hh
@@ -1,98 +1,98 @@
/**
* @file material_viscoplastic.hh
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
*
*
* @brief Specialization of the material class for
* MaterialLinearIsotropicHardening to include viscous effects (small
* deformation)
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_voigthelper.hh"
#include "material_plastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_VISCOPLASTIC_HH_
#define AKANTU_MATERIAL_VISCOPLASTIC_HH_
namespace akantu {
/**
* Material plastic isotropic
*
* parameters in the material files :
* - h : Hardening parameter (default: 0)
* - sigmay : Yield stress
* - rate : Rate sensitivity
* - edot0 : Reference strain rate
*
* - ts: Time step
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialViscoPlastic : public MaterialPlastic<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialViscoPlastic(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// constitutive law for all element of a type
virtual void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost);
protected:
inline void
computeStressOnQuad(const Matrix<Real> & grad_u,
const Matrix<Real> & previous_grad_u,
Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
Matrix<Real> & inelastic_strain,
const Matrix<Real> & previous_inelastic_strain,
Real & iso_hardening) const;
inline void computeTangentModuliOnQuad(
Matrix<Real> & tangent, const Matrix<Real> & grad_u,
const Matrix<Real> & previous_grad_u, const Matrix<Real> & sigma_tensor,
const Matrix<Real> & previous_sigma_tensor,
const Real & iso_hardening) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// Rate sensitivity component (rate)
Real rate;
/// Reference strain rate (edot0)
Real edot0;
/// Time step (ts)
Real ts;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_viscoplastic_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_VISCOPLASTIC_HH_ */
diff --git a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh
index c149c9531..3c95b100a 100644
--- a/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh
+++ b/extra_packages/extra-materials/src/material_plastic/material_viscoplastic_inline_impl.hh
@@ -1,89 +1,89 @@
/**
* @file material_viscoplastic_inline_impl.hh
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
*
*
* @brief Implementation of the inline functions of the material viscoplastic
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
#include "material_viscoplastic.hh"
#include <cmath>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
inline void MaterialViscoPlastic<dim>::computeStressOnQuad(
const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
Matrix<Real> & inelastic_strain,
const Matrix<Real> & previous_inelastic_strain,
Real & iso_hardening) const {
// Infinitesimal plastic
// Compute stress magnitude
Real s = sigma.doubleDot(sigma);
Real sigma_mag = sqrt(s);
// Compute plastic strain increment
Real factor = (this->ts * this->edot0 * pow(sigma_mag, (this->rate - 1.)) /
pow(this->sigma_y + iso_hardening, this->rate));
Matrix<Real> delta_inelastic_strain(sigma);
delta_inelastic_strain *= factor;
// Compute plastic strain increment magnitude
s = delta_inelastic_strain.doubleDot(delta_inelastic_strain);
Real dep_mag = std::sqrt(s);
Matrix<Real> grad_delta_u(grad_u);
grad_delta_u -= previous_grad_u;
// Update stress and plastic strain
Matrix<Real> grad_u_elastic(dim, dim);
grad_u_elastic = grad_delta_u;
grad_u_elastic -= delta_inelastic_strain;
Matrix<Real> sigma_elastic(dim, dim);
MaterialElastic<dim>::computeStressOnQuad(grad_u_elastic, sigma_elastic);
sigma += sigma_elastic;
inelastic_strain += delta_inelastic_strain;
// Update resistance stress
iso_hardening = iso_hardening + this->h * dep_mag;
MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(
grad_delta_u, sigma, previous_sigma, inelastic_strain,
previous_inelastic_strain, delta_inelastic_strain);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
inline void MaterialViscoPlastic<dim>::computeTangentModuliOnQuad(
Matrix<Real> & tangent, const Matrix<Real> & /*grad_u*/,
const Matrix<Real> & /*previous_grad_u*/,
const Matrix<Real> & /*sigma_tensor*/,
const Matrix<Real> & /*previous_sigma_tensor*/,
const Real & /*iso_hardening*/) const {
UInt cols = tangent.cols();
UInt rows = tangent.rows();
- for (UInt m = 0; m < rows; ++m) {
+ for (Int m = 0; m < rows; ++m) {
UInt i = VoigtHelper<dim>::vec[m][0];
UInt j = VoigtHelper<dim>::vec[m][1];
- for (UInt n = 0; n < cols; ++n) {
+ for (Int n = 0; n < cols; ++n) {
UInt k = VoigtHelper<dim>::vec[n][0];
UInt l = VoigtHelper<dim>::vec[n][1];
tangent(m, n) = (i == k) * (j == l) * 2. * this->mu +
(i == j) * (k == l) * this->lambda;
tangent(m, n) -= (m == n) * (m >= dim) * this->mu;
}
}
}
diff --git a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc
index 2bdf201b2..d27bc071b 100644
--- a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc
+++ b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.cc
@@ -1,121 +1,121 @@
/**
* @file material_stiffness_proportional.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
*
* @brief Special. of the material class for the caughey viscoelastic material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_stiffness_proportional.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialStiffnessProportional<spatial_dimension>::MaterialStiffnessProportional(
SolidMechanicsModel & model, const ID & id)
: MaterialElastic<spatial_dimension>(model, id),
stress_viscosity("stress_viscosity", *this),
stress_elastic("stress_elastic", *this) {
AKANTU_DEBUG_IN();
this->registerParam("Alpha", alpha, 0., _pat_parsable | _pat_modifiable,
"Artificial viscous ratio");
this->stress_viscosity.initialize(spatial_dimension * spatial_dimension);
this->stress_elastic.initialize(spatial_dimension * spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialStiffnessProportional<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialElastic<spatial_dimension>::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialStiffnessProportional<spatial_dimension>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Array<UInt> & elem_filter = this->element_filter(el_type, ghost_type);
+ Array<Idx> & elem_filter = this->element_filter(el_type, ghost_type);
Array<Real> & stress_visc = stress_viscosity(el_type, ghost_type);
Array<Real> & stress_el = stress_elastic(el_type, ghost_type);
MaterialElastic<spatial_dimension>::computeStress(el_type, ghost_type);
Array<Real> & velocity = this->model.getVelocity();
Array<Real> strain_rate(0, spatial_dimension * spatial_dimension,
"strain_rate");
this->model.getFEEngine().gradientOnIntegrationPoints(
velocity, strain_rate, spatial_dimension, el_type, ghost_type,
elem_filter);
Array<Real>::matrix_iterator strain_rate_it =
strain_rate.begin(spatial_dimension, spatial_dimension);
Array<Real>::matrix_iterator stress_visc_it =
stress_visc.begin(spatial_dimension, spatial_dimension);
Array<Real>::matrix_iterator stress_el_it =
stress_el.begin(spatial_dimension, spatial_dimension);
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
Matrix<Real> & grad_v = *strain_rate_it;
Matrix<Real> & sigma_visc = *stress_visc_it;
Matrix<Real> & sigma_el = *stress_el_it;
MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_v, sigma_visc);
sigma_visc *= alpha;
sigma_el.copy(sigma);
sigma += sigma_visc;
++strain_rate_it;
++stress_visc_it;
++stress_el_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialStiffnessProportional<spatial_dimension>::computePotentialEnergy(
ElementType el_type) {
AKANTU_DEBUG_IN();
Array<Real> & stress_el = stress_elastic(el_type);
Array<Real>::matrix_iterator stress_el_it =
stress_el.begin(spatial_dimension, spatial_dimension);
- Real * epot = this->potential_energy(el_type).storage();
+ Real * epot = this->potential_energy(el_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
Matrix<Real> & sigma_el = *stress_el_it;
MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad(
grad_u, sigma_el, *epot);
epot++;
++stress_el_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(ve_stiffness_prop, MaterialStiffnessProportional);
} // namespace akantu
diff --git a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh
index 4b40c5f6f..e14274d35 100644
--- a/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh
+++ b/extra_packages/extra-materials/src/material_viscoelastic/material_stiffness_proportional.hh
@@ -1,99 +1,99 @@
/**
* @file material_stiffness_proportional.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
*
* @brief Material isotropic visco-elastic with viscosity proportional to the
* stiffness
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_STIFFNESS_PROPORTIONAL_HH_
#define AKANTU_MATERIAL_STIFFNESS_PROPORTIONAL_HH_
namespace akantu {
/**
* Material visco-elastic @f[\sigma = E\epsilon + \alpha E*
* \frac{d\epsilon}{dt}@f]
* it can be seen as a Kelvin-Voigt solid with @f[\eta = \alpha E @f]
*
* The material satisfies the Caughey condition, the visco-elastic solid has the
* same eigen-modes as the elastic one. (T.K. Caughey 1960 - Journal of Applied
* Mechanics 27, 269-271. Classical normal modes in damped linear systems.)
*
* parameters in the material files :
* - rho : density (default: 0)
* - E : Young's modulus (default: 0)
* - nu : Poisson's ratio (default: 1/2)
* - Plane_Stress : if 0: plane strain, else: plane stress (default: 0)
* - alpha : viscous ratio
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialStiffnessProportional
: public MaterialElastic<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialStiffnessProportional(SolidMechanicsModel & model,
const ID & id = "");
virtual ~MaterialStiffnessProportional(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the potential energy for all elements
void computePotentialEnergy(ElementType el_type) override;
protected:
/// constitutive law for a given quadrature point
// inline void computeStress(Real * F, Real * sigma);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// stress due to viscosity
InternalField<Real> stress_viscosity;
/// stress due to elasticity
InternalField<Real> stress_elastic;
/// viscous ratio
Real alpha;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
//#include "material_elastic_caughey_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_STIFFNESS_PROPORTIONAL_HH_ */
diff --git a/extra_packages/extra-materials/test/test_material_FE2/test_eigenstrain_homogenization.cc b/extra_packages/extra-materials/test/test_material_FE2/test_eigenstrain_homogenization.cc
index 93b3aac12..ecce0cd70 100644
--- a/extra_packages/extra-materials/test/test_material_FE2/test_eigenstrain_homogenization.cc
+++ b/extra_packages/extra-materials/test/test_material_FE2/test_eigenstrain_homogenization.cc
@@ -1,90 +1,90 @@
/**
* @file test_eigenstrain_homogenization.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Sun Jan 31 12:27:02 2016
*
* @brief test the eigenstrain homogenization
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_RVE.hh"
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("mesoscale_materials.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("one_inclusion.msh");
SolidMechanicsModelRVE model(mesh, false);
auto mat_selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names", model);
model.setMaterialSelector(mat_selector);
/// model initialization
model.initFull();
/// apply boundary conditions
Matrix<Real> grad_u_macro(spatial_dimension, spatial_dimension, 0.);
model.applyBoundaryConditions(grad_u_macro);
model.setBaseName("one-inclusion");
model.addDumpFieldVector("displacement");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("blocked_dofs");
model.addDumpField("material_index");
model.addDumpField("eigen_grad_u");
model.dump();
/// apply eigenstrain
Matrix<Real> prestrain(spatial_dimension, spatial_dimension, 0.);
- for (UInt i = 0; i < spatial_dimension; ++i)
+ for (Int i = 0; i < spatial_dimension; ++i)
prestrain(i, i) = 0.02;
model.advanceASR(prestrain);
model.dump();
Matrix<Real> macro_strain(spatial_dimension, spatial_dimension, 0.);
model.homogenizeEigenGradU(macro_strain);
std::cout << "the average eigen_gradu is " << macro_strain << std::endl;
Matrix<Real> exact_eigenstrain(spatial_dimension, spatial_dimension, 0.);
- for (UInt i = 0; i < spatial_dimension; ++i)
+ for (Int i = 0; i < spatial_dimension; ++i)
exact_eigenstrain(i, i) = 0.00125;
macro_strain -= exact_eigenstrain;
if (macro_strain.norm<L_2>() > 1.e-10) {
std::cout << "the test failed!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/extra-materials/test/test_material_FE2/test_elastic_homogenization.cc b/extra_packages/extra-materials/test/test_material_FE2/test_elastic_homogenization.cc
index 9246ddc5b..fa01eb807 100644
--- a/extra_packages/extra-materials/test/test_material_FE2/test_elastic_homogenization.cc
+++ b/extra_packages/extra-materials/test/test_material_FE2/test_elastic_homogenization.cc
@@ -1,88 +1,88 @@
/**
* @file test_elastic_homogenization.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Mon Jan 25 18:32:09 2016
*
* @brief Test elastic homogenization of stiffness tensor
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic_linear_anisotropic.hh"
#include "solid_mechanics_model_RVE.hh"
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material_orthotropic.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const ElementType element_type = _triangle_3;
const GhostType ghost_type = _not_ghost;
Mesh mesh(spatial_dimension);
mesh.read("homogenized_plate.msh");
SolidMechanicsModelRVE model(mesh, false);
/// model initialization
model.initFull();
/// apply eigenstrain
Array<Real> & prestrain_vect =
const_cast<Array<Real> &>(model.getMaterial(0).getInternal<Real>(
"eigen_grad_u")(element_type, ghost_type));
Array<Real>::iterator<Matrix<Real>> prestrain_it =
prestrain_vect.begin(spatial_dimension, spatial_dimension);
Array<Real>::iterator<Matrix<Real>> prestrain_end =
prestrain_vect.end(spatial_dimension, spatial_dimension);
//(*prestrain_it)(0,0) = 0.2;
//(*prestrain_it)(1,1) = 0.2;
for (; prestrain_it != prestrain_end; ++prestrain_it)
(*prestrain_it) += 1.0;
/// storage for results of 3 different loading states
UInt voigt_size = VoigtHelper<spatial_dimension>::size;
MaterialElasticLinearAnisotropic<spatial_dimension> & mat =
dynamic_cast<MaterialElasticLinearAnisotropic<spatial_dimension> &>(
model.getMaterial(0));
Matrix<Real> voigt_stiffness = mat.getVoigtStiffness();
/// homogenize
Matrix<Real> C(voigt_size, voigt_size);
model.homogenizeStiffness(C);
- for (UInt i = 0; i < voigt_size; ++i) {
- for (UInt j = 0; j < voigt_size; ++j) {
+ for (Int i = 0; i < voigt_size; ++i) {
+ for (Int j = 0; j < voigt_size; ++j) {
std::cout << "exact: " << voigt_stiffness(i, j)
<< " approximated: " << C(i, j) << std::endl;
if (std::abs(voigt_stiffness(i, j) - C(i, j)) > 1.e-10) {
std::cout << "The material homogenization failed" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/extra-materials/test/test_material_FE2/test_material_FE2.cc b/extra_packages/extra-materials/test/test_material_FE2/test_material_FE2.cc
index 06063b5bd..6d0ae82c4 100644
--- a/extra_packages/extra-materials/test/test_material_FE2/test_material_FE2.cc
+++ b/extra_packages/extra-materials/test/test_material_FE2/test_material_FE2.cc
@@ -1,120 +1,120 @@
/**
* @file test_material_FE2.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Sun Jan 31 12:27:02 2016
*
* @brief test the material FE2
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "material_FE2.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
debug::setDebugLevel(dblWarning);
initialize("material.dat", argc, argv);
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
/// input parameters for the simulation
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const ParserSection & parser = getUserParser();
std::string mesh_file = parser.getParameter("mesh_file");
Matrix<Real> prestrain_increment = parser.getParameter("prestrain_increment");
UInt total_steps = parser.getParameter("total_steps");
Mesh mesh(spatial_dimension);
if (prank == 0) {
mesh.read(mesh_file);
}
mesh.distribute();
/// model creation
SolidMechanicsModel model(mesh);
/// set the material selector
auto mat_selector = std::make_shared<MaterialSelector>();
mat_selector->setFallback(3);
model.setMaterialSelector(mat_selector);
model.initFull(SolidMechanicsModelOptions(_static));
/* --------------------------------------------------------------------------
*/
/// boundary conditions
mesh.createGroupsFromMeshData<std::string>(
"physical_names"); // creates groups from mesh names
model.applyBC(BC::Dirichlet::FixedValue(0, _x), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(0, _y), "bottom");
// model.applyBC(BC::Dirichlet::FixedValue(1.e-2, _y), "top");
model.setBaseName("macro_mesh");
model.addDumpFieldVector("displacement");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("eigen_grad_u");
model.addDumpField("blocked_dofs");
model.addDumpField("material_index");
model.addDumpField("material_stiffness");
model.dump();
/// solve system
model.assembleStiffnessMatrix();
std::cout << "first solve step" << std::endl;
model.solveStep();
std::cout << "second solve step" << std::endl;
model.solveStep();
std::cout << "finished solve steps" << std::endl;
/// simulate the advancement of the reaction
MaterialFE2<spatial_dimension> & mat =
dynamic_cast<MaterialFE2<spatial_dimension> &>(
model.getMaterial("FE2_mat"));
Matrix<Real> current_prestrain(spatial_dimension, spatial_dimension, 0.);
- for (UInt i = 0; i < total_steps; ++i) {
+ for (Int i = 0; i < total_steps; ++i) {
model.dump();
current_prestrain += prestrain_increment;
mat.advanceASR(current_prestrain);
model.dump();
/// solve for new displacement at the macro-scale
model.solveStep();
}
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/extra-materials/test/test_material_FE2/test_node_selection.cc b/extra_packages/extra-materials/test/test_material_FE2/test_node_selection.cc
index a47308d72..786900b5d 100644
--- a/extra_packages/extra-materials/test/test_material_FE2/test_node_selection.cc
+++ b/extra_packages/extra-materials/test/test_material_FE2/test_node_selection.cc
@@ -1,78 +1,78 @@
/**
* @file test_periodic_plate.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Jan 21 10:11:04 2016
*
* @brief Test for correct application of periodic boundary conditions
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_RVE.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
akantu::initialize("material_test_boundary.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("periodic_plate.msh");
SolidMechanicsModelRVE model(mesh, false);
auto mat_selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names", model);
model.setMaterialSelector(mat_selector);
/// model initialization
model.initFull();
/// apply macroscopic deformation gradient at corner nodes
/// consider a constant strain field
Matrix<Real> grad_u_macro(spatial_dimension, spatial_dimension, 0.);
grad_u_macro(0, 1) = 1.;
model.applyBoundaryConditions(grad_u_macro);
model.setBaseName("periodic-plate");
model.addDumpFieldVector("displacement");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("blocked_dofs");
model.addDumpField("material_index");
// model.addDumpField ("" );
model.dump();
model.solveStep();
Real average_strain = model.averageTensorField(0, 1, "strain");
std::cout << "the average strain is: " << average_strain << std::endl;
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative.cc b/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative.cc
index cc030baf3..4cf031ed4 100644
--- a/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative.cc
+++ b/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative.cc
@@ -1,182 +1,182 @@
/**
* @file test_material_damage_iterative.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the material damage iterative
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "material_damage_iterative.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
ElementType element_type = _triangle_3;
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
if (prank == 0) {
mesh.read("plate.msh");
}
mesh.distribute();
/// model creation
SolidMechanicsModel model(mesh);
/// initialization of the model
model.initFull(_analysis_method = _static);
/// boundary conditions
/// Dirichlet BC
mesh.createGroupsFromMeshData<std::string>(
"physical_names"); // creates groups from mesh names
model.applyBC(BC::Dirichlet::FixedValue(0, _x), "left");
model.applyBC(BC::Dirichlet::FixedValue(0, _y), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(2., _y), "top");
/// add fields that should be dumped
model.setBaseName("material_damage_iterative_test");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("material_index");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.dump();
MaterialDamageIterative<spatial_dimension> & material =
dynamic_cast<MaterialDamageIterative<spatial_dimension> &>(
model.getMaterial(0));
UInt nb_damaged_elements = 0;
Real max_eq_stress = 0;
/// solve the system
model.solveStep();
model.dump();
/// check that the normalized equivalent stress
Array<Real> & eq_stress =
material.getInternal<Real>("equivalent_stress")(element_type, _not_ghost);
Array<Real>::const_scalar_iterator eq_stress_it = eq_stress.begin();
UInt nb_elements = mesh.getNbElement(element_type, _not_ghost);
- for (UInt e = 0; e < nb_elements; ++e, ++eq_stress_it) {
+ for (Int e = 0; e < nb_elements; ++e, ++eq_stress_it) {
if (!Math::are_float_equal(*eq_stress_it, 0.1)) {
std::cout << "Error in the equivalent normalized stress" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
/// get the maximum equivalent stress
max_eq_stress = material.getNormMaxEquivalentStress();
nb_damaged_elements = 0;
if (max_eq_stress > 1.)
nb_damaged_elements = material.updateDamage();
if (nb_damaged_elements) {
std::cout << "Damage occured even though the normalized stress is below 1"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
/// weaken material locally to cause damage
Array<Real> & strength = const_cast<Array<Real> &>(
material.getInternal<Real>("Sc")(element_type, _not_ghost));
Array<Real>::scalar_iterator strength_it = strength.begin();
++strength_it;
*strength_it = 0.9;
strength_it += 4;
*strength_it = 0.898;
/// solve the system again
model.solveStep();
/// get the maximum equivalent stress
max_eq_stress = material.getNormMaxEquivalentStress();
nb_damaged_elements = 0;
if (max_eq_stress > 1.)
nb_damaged_elements = material.updateDamage();
UInt nb_damaged_elements_per_proc = 2;
if (nb_damaged_elements != psize * nb_damaged_elements_per_proc) {
std::cout << "Error in number of damaged elements" << std::endl;
finalize();
return EXIT_FAILURE;
}
/// check that damage occured in correct elements
Real dam_diff = 0.;
Array<Real> & damage =
material.getInternal<Real>("damage")(element_type, _not_ghost);
Array<Real>::const_scalar_iterator damage_it = damage.begin();
- for (UInt e = 0; e < nb_elements; ++e, ++damage_it) {
+ for (Int e = 0; e < nb_elements; ++e, ++damage_it) {
if (e == 1 || e == 5)
dam_diff += std::abs(0.1 - *damage_it);
else
dam_diff += (*damage_it);
}
if (dam_diff > 1.e-13) {
std::cout << "Error in damage pattern" << std::endl;
finalize();
return EXIT_FAILURE;
}
/// solve to compute the stresses correctly for dumping
model.solveStep();
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_parallel.cc b/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_parallel.cc
index 02c42a19e..bbb6581fc 100644
--- a/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_parallel.cc
+++ b/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_parallel.cc
@@ -1,359 +1,359 @@
/**
* @file test_material_damage_iterative_non_local_parallel.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the material damage iterative non local in parallel
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
bool checkDisplacement(SolidMechanicsModel & model, ElementType type,
std::ofstream & error_output, UInt step,
bool barycenters);
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
debug::setDebugLevel(dblWarning);
ElementType element_type = _triangle_3;
initialize("two_materials.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("one_circular_inclusion.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModel model(mesh);
model.initParallel(partition);
delete partition;
/// assign the material
MeshDataMaterialSelector<std::string> * mat_selector;
mat_selector =
new MeshDataMaterialSelector<std::string>("physical_names", model);
model.setMaterialSelector(*mat_selector);
mesh.createGroupsFromMeshData<std::string>(
"physical_names"); // creates groups from mesh names
/// initialization of the model
model.initFull(SolidMechanicsModelOptions(_static));
/// boundary conditions
/// Dirichlet BC
model.applyBC(BC::Dirichlet::FixedValue(0, _x), "left");
model.applyBC(BC::Dirichlet::FixedValue(0, _y), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(2., _y), "top");
/// add fields that should be dumped
model.setBaseName("material_damage_iterative_test");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("material_index");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.dump();
std::stringstream error_stream;
error_stream << "error"
<< ".csv";
std::ofstream error_output;
error_output.open(error_stream.str().c_str());
error_output << "# Step, Average, Max, Min" << std::endl;
checkDisplacement(model, element_type, error_output, 0, true);
MaterialDamageIterative<spatial_dimension> & aggregate =
dynamic_cast<MaterialDamageIterative<spatial_dimension> &>(
model.getMaterial(0));
MaterialDamageIterative<spatial_dimension> & paste =
dynamic_cast<MaterialDamageIterative<spatial_dimension> &>(
model.getMaterial(1));
Real error;
bool converged = false;
UInt nb_damaged_elements = 0;
Real max_eq_stress_agg = 0;
Real max_eq_stress_paste = 0;
/// solve the system
converged =
model.solveStep<_scm_newton_raphson_tangent_modified,
SolveConvergenceCriteria::_increment>(1e-12, error, 2);
if (converged == false) {
std::cout << "The error is: " << error << std::endl;
AKANTU_DEBUG_ASSERT(converged, "Did not converge");
}
if (!checkDisplacement(model, element_type, error_output, 1, false)) {
finalize();
return EXIT_FAILURE;
}
model.dump();
/// get the maximum equivalent stress in both materials
max_eq_stress_agg = aggregate.getNormMaxEquivalentStress();
max_eq_stress_paste = paste.getNormMaxEquivalentStress();
nb_damaged_elements = 0;
if (max_eq_stress_agg > max_eq_stress_paste)
nb_damaged_elements = aggregate.updateDamage();
else
nb_damaged_elements = paste.updateDamage();
if (prank == 0 && nb_damaged_elements)
std::cout << nb_damaged_elements << " elements damaged" << std::endl;
/// resolve the system
converged =
model.solveStep<_scm_newton_raphson_tangent_modified,
SolveConvergenceCriteria::_increment>(1e-12, error, 2);
if (converged == false) {
std::cout << "The error is: " << error << std::endl;
AKANTU_DEBUG_ASSERT(converged, "Did not converge");
}
if (!checkDisplacement(model, element_type, error_output, 2, false)) {
finalize();
return EXIT_FAILURE;
}
model.dump();
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
bool checkDisplacement(SolidMechanicsModel & model, ElementType type,
std::ofstream & error_output, UInt step,
bool barycenters) {
Mesh & mesh = model.getMesh();
- UInt spatial_dimension = mesh.getSpatialDimension();
- const Array<UInt> & connectivity = mesh.getConnectivity(type);
+ Int spatial_dimension = mesh.getSpatialDimension();
+ const Array<Idx> & connectivity = mesh.getConnectivity(type);
const Array<Real> & displacement = model.getDisplacement();
UInt nb_element = mesh.getNbElement(type);
UInt nb_nodes_per_elem = Mesh::getNbNodesPerElement(type);
StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
if (psize == 1) {
std::stringstream displacement_file;
displacement_file << "displacement/displacement_" << std::setfill('0')
<< std::setw(6) << step;
std::ofstream displacement_output;
displacement_output.open(displacement_file.str().c_str());
for (UInt el = 0; el < nb_element; ++el) {
for (UInt n = 0; n < nb_nodes_per_elem; ++n) {
UInt node = connectivity(el, n);
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
displacement_output << std::setprecision(15)
<< displacement(node, dim) << " ";
}
displacement_output << std::endl;
}
}
displacement_output.close();
if (barycenters) {
std::stringstream barycenter_file;
barycenter_file << "displacement/barycenters";
std::ofstream barycenter_output;
barycenter_output.open(barycenter_file.str().c_str());
Element element(type, 0);
Vector<Real> bary(spatial_dimension);
for (UInt el = 0; el < nb_element; ++el) {
element.element = el;
mesh.getBarycenter(element, bary);
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
barycenter_output << std::setprecision(15) << bary(dim) << " ";
}
barycenter_output << std::endl;
}
barycenter_output.close();
}
} else {
if (barycenters)
return true;
/// read data
std::stringstream displacement_file;
displacement_file << "displacement/displacement_" << std::setfill('0')
<< std::setw(6) << step;
std::ifstream displacement_input;
displacement_input.open(displacement_file.str().c_str());
Array<Real> displacement_serial(0, spatial_dimension);
Vector<Real> disp_tmp(spatial_dimension);
while (displacement_input.good()) {
for (UInt i = 0; i < spatial_dimension; ++i)
displacement_input >> disp_tmp(i);
displacement_serial.push_back(disp_tmp);
}
std::stringstream barycenter_file;
barycenter_file << "displacement/barycenters";
std::ifstream barycenter_input;
barycenter_input.open(barycenter_file.str().c_str());
Array<Real> barycenter_serial(0, spatial_dimension);
while (barycenter_input.good()) {
- for (UInt dim = 0; dim < spatial_dimension; ++dim)
+ for (Int dim = 0; dim < spatial_dimension; ++dim)
barycenter_input >> disp_tmp(dim);
barycenter_serial.push_back(disp_tmp);
}
Element element(type, 0);
Vector<Real> bary(spatial_dimension);
Array<Real>::iterator<Vector<Real>> it;
Array<Real>::iterator<Vector<Real>> begin =
barycenter_serial.begin(spatial_dimension);
Array<Real>::iterator<Vector<Real>> end =
barycenter_serial.end(spatial_dimension);
Array<Real>::const_iterator<Vector<Real>> disp_it;
Array<Real>::iterator<Vector<Real>> disp_serial_it;
Vector<Real> difference(spatial_dimension);
Array<Real> error;
/// compute error
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
element.element = el;
mesh.getBarycenter(element, bary);
/// find element
for (it = begin; it != end; ++it) {
UInt matched_dim = 0;
while (matched_dim < spatial_dimension &&
Math::are_float_equal(bary(matched_dim), (*it)(matched_dim)))
++matched_dim;
if (matched_dim == spatial_dimension)
break;
}
if (it == end) {
std::cout << "Element barycenter not found!" << std::endl;
return false;
}
UInt matched_el = it - begin;
disp_serial_it = displacement_serial.begin(spatial_dimension) +
matched_el * nb_nodes_per_elem;
- for (UInt n = 0; n < nb_nodes_per_elem; ++n, ++disp_serial_it) {
+ for (Int n = 0; n < nb_nodes_per_elem; ++n, ++disp_serial_it) {
UInt node = connectivity(el, n);
if (!mesh.isLocalOrMasterNode(node))
continue;
disp_it = displacement.begin(spatial_dimension) + node;
difference = *disp_it;
difference -= *disp_serial_it;
error.push_back(difference.norm());
}
}
/// compute average error
Real average_error = std::accumulate(error.begin(), error.end(), 0.);
comm.allReduce(&average_error, 1, _so_sum);
UInt error_size = error.getSize();
comm.allReduce(&error_size, 1, _so_sum);
average_error /= error_size;
/// compute maximum and minimum
Real max_error = *std::max_element(error.begin(), error.end());
comm.allReduce(&max_error, 1, _so_max);
Real min_error = *std::min_element(error.begin(), error.end());
comm.allReduce(&min_error, 1, _so_min);
/// output data
if (prank == 0) {
error_output << step << ", " << average_error << ", " << max_error << ", "
<< min_error << std::endl;
}
if (max_error > 1.e-9) {
std::cout << "Displacement error of " << max_error << " is too big!"
<< std::endl;
return false;
}
}
return true;
}
diff --git a/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_serial.cc b/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_serial.cc
index 2995a6616..4ee9eb1dd 100644
--- a/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_serial.cc
+++ b/extra_packages/extra-materials/test/test_material_damage/test_material_damage_iterative_non_local_serial.cc
@@ -1,235 +1,235 @@
/**
* @file test_material_damage_iterative_non_local_serial.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the material damage iterative non local in serial
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative_non_local.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material_non_local.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
ElementType element_type = _triangle_3;
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
mesh.read("plate.msh");
/// model creation
SolidMechanicsModel model(mesh);
/// initialization of the model
model.initFull(SolidMechanicsModelOptions(_static));
/// boundary conditions
/// Dirichlet BC
mesh.createGroupsFromMeshData<std::string>(
"physical_names"); // creates groups from mesh names
model.applyBC(BC::Dirichlet::FixedValue(0, _x), "left");
model.applyBC(BC::Dirichlet::FixedValue(0, _y), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(2., _y), "top");
/// add fields that should be dumped
model.setBaseName("material_damage_iterative_test");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("grad_u non local");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("material_index");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.dump();
MaterialDamageIterativeNonLocal<spatial_dimension> & material =
dynamic_cast<MaterialDamageIterativeNonLocal<spatial_dimension> &>(
model.getMaterial(0));
Real error;
bool converged = false;
Real max_eq_stress = 0;
/// solve the system
converged =
model.solveStep<_scm_newton_raphson_tangent_modified,
SolveConvergenceCriteria::_increment>(1e-4, error, 2);
if (converged == false) {
std::cout << "The error is: " << error << std::endl;
AKANTU_DEBUG_ASSERT(converged, "Did not converge");
}
model.dump();
/// check the non-local grad_u: since grad_u is constant everywhere
/// also the grad_u non-local has to be constant
Array<Real> & grad_u_nl =
material.getInternal<Real>("grad_u non local")(element_type, _not_ghost);
Array<Real>::const_matrix_iterator grad_u_nl_it =
grad_u_nl.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_matrix_iterator grad_u_nl_end =
grad_u_nl.end(spatial_dimension, spatial_dimension);
Real diff = 0.;
Matrix<Real> diff_matrix(spatial_dimension, spatial_dimension);
Matrix<Real> const_grad_u(spatial_dimension, spatial_dimension, 0.);
const_grad_u(1, 1) = 1.;
for (; grad_u_nl_it != grad_u_nl_end; ++grad_u_nl_it) {
diff_matrix = (*grad_u_nl_it) - const_grad_u;
diff += diff_matrix.norm<L_2>();
}
if (diff > 10.e-13) {
std::cout << "Error in the non-local grad_u computation" << std::endl;
return EXIT_FAILURE;
}
/// change the displacement in one node to modify grad_u
Array<Real> & displ = model.getDisplacement();
displ(0, 1) = 2.6;
/// compute stresses: this will average grad_u and compute the max. eq. stress
model.updateResidual();
model.dump();
/// due to the change in the displacement element 33 and 37 will
/// have a grad_u different then one
const Array<Real> & grad_u =
material.getInternal<Real>("grad_u")(element_type, _not_ghost);
Array<Real>::const_matrix_iterator grad_u_it =
grad_u.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_matrix_iterator grad_u_end =
grad_u.end(spatial_dimension, spatial_dimension);
diff = 0.;
diff_matrix.zero();
UInt counter = 0;
for (; grad_u_it != grad_u_end; ++grad_u_it) {
diff_matrix = (*grad_u_it) - const_grad_u;
if (counter == 34 || counter == 38) {
if ((diff_matrix.norm<L_2>()) < 0.1) {
std::cout << "Error in the grad_u computation" << std::endl;
return EXIT_FAILURE;
}
} else
diff += diff_matrix.norm<L_2>();
++counter;
}
if (diff > 10.e-13) {
std::cout << "Error in the grad_u computation" << std::endl;
return EXIT_FAILURE;
}
/// check that the non-local grad_u
diff = 0.;
diff_matrix.zero();
Real nl_radius = 1.0; /// same values as in material file
grad_u_nl_it = grad_u_nl.begin(spatial_dimension, spatial_dimension);
ElementTypeMapReal quad_coords("quad_coords");
mesh.initElementTypeMapArray(quad_coords, spatial_dimension,
spatial_dimension, false, _ek_regular, true);
model.getFEEngine().computeIntegrationPointsCoordinates(quad_coords);
UInt nb_elements = mesh.getNbElement(element_type, _not_ghost);
UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(element_type);
Array<Real> & coords = quad_coords(element_type, _not_ghost);
auto coord_it = coords.begin(spatial_dimension);
Vector<Real> q1(spatial_dimension);
Vector<Real> q2(spatial_dimension);
q1 = coord_it[34];
q2 = coord_it[38];
- for (UInt e = 0; e < nb_elements; ++e) {
- for (UInt q = 0; q < nb_quads; ++q, ++coord_it, ++grad_u_nl_it) {
+ for (Int e = 0; e < nb_elements; ++e) {
+ for (Int q = 0; q < nb_quads; ++q, ++coord_it, ++grad_u_nl_it) {
diff_matrix = (*grad_u_nl_it) - const_grad_u;
if ((q1.distance(*coord_it) <= (nl_radius + Math::getTolerance())) ||
(q2.distance(*coord_it) <= (nl_radius + Math::getTolerance()))) {
if ((diff_matrix.norm<L_2>()) < 1.e-6) {
std::cout << (diff_matrix.norm<L_2>()) << std::endl;
std::cout << "Error in the non-local grad_u computation" << std::endl;
return EXIT_FAILURE;
}
} else
diff += diff_matrix.norm<L_2>();
}
}
if (diff > 10.e-13) {
std::cout << "Error in the non-local grad_u computation" << std::endl;
return EXIT_FAILURE;
}
/// make sure that the normalized equivalent stress is based on the
/// non-local grad_u for this test check the elements that have the
/// constant stress of 1 but different non-local gradu because they
/// are in the neighborhood of the modified elements
coord_it = coords.begin(spatial_dimension);
const Array<Real> & eq_stress =
material.getInternal<Real>("equivalent_stress")(element_type, _not_ghost);
Array<Real>::const_scalar_iterator eq_stress_it = eq_stress.begin();
counter = 0;
- for (UInt e = 0; e < nb_elements; ++e) {
- for (UInt q = 0; q < nb_quads;
+ for (Int e = 0; e < nb_elements; ++e) {
+ for (Int q = 0; q < nb_quads;
++q, ++coord_it, ++grad_u_nl_it, ++eq_stress_it) {
if (counter == 34 || counter == 38)
continue;
if (((q1.distance(*coord_it) <= (nl_radius + Math::getTolerance())) ||
(q2.distance(*coord_it) <= (nl_radius + Math::getTolerance()))) &&
Math::are_float_equal(*eq_stress_it, 0.1)) {
std::cout << "the normalized equivalent stress is most likely based on "
"the local, not the non-local grad_u!!!!"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
++counter;
}
}
max_eq_stress = material.getNormMaxEquivalentStress();
if (!Math::are_float_equal(max_eq_stress, 0.1311267235941873)) {
std::cout << "the maximum equivalent stress is wrong" << std::endl;
finalize();
return EXIT_FAILURE;
}
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/extra-materials/test/test_material_damage/test_material_iterative_stiffness_reduction.cc b/extra_packages/extra-materials/test/test_material_damage/test_material_iterative_stiffness_reduction.cc
index 0f85fdd39..7fdde751f 100644
--- a/extra_packages/extra-materials/test/test_material_damage/test_material_iterative_stiffness_reduction.cc
+++ b/extra_packages/extra-materials/test/test_material_damage/test_material_iterative_stiffness_reduction.cc
@@ -1,114 +1,114 @@
/**
* @file test_material_iterative_strength_reduction.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the material iterative stiffness reduction
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "material_damage_iterative.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material_stiffness_reduction.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
ElementType element_type = _triangle_3;
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
if (prank == 0) {
mesh.read("two_elements.msh");
}
mesh.distribute();
/// model creation
SolidMechanicsModel model(mesh);
/// initialization of the model
model.initFull(SolidMechanicsModelOptions(_static));
/// boundary conditions
/// Dirichlet BC
mesh.createGroupsFromMeshData<std::string>(
"physical_names"); // creates groups from mesh names
model.applyBC(BC::Dirichlet::FixedValue(0, _x), "left");
model.applyBC(BC::Dirichlet::FixedValue(0, _y), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(2., _y), "top");
/// add fields that should be dumped
model.setBaseName("material_iterative_stiffness_reduction_test");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.addDumpField("ultimate_strain");
model.dump();
MaterialDamageIterative<spatial_dimension> & material =
dynamic_cast<MaterialDamageIterative<spatial_dimension> &>(
model.getMaterial(0));
UInt nb_damaged_elements = 0;
Real E = material.get("E");
std::cout << std::setprecision(12);
const Array<Real> & damage =
material.getInternal<Real>("damage")(element_type, _not_ghost);
const Array<Real> & Sc =
material.getInternal<Real>("Sc")(element_type, _not_ghost);
/// solve the system
do {
model.solveStep();
nb_damaged_elements = material.updateDamage();
- for (UInt e = 0; e < mesh.getNbElement(element_type, _not_ghost); ++e) {
+ for (Int e = 0; e < mesh.getNbElement(element_type, _not_ghost); ++e) {
std::cout << "the new modulus is " << (1 - damage(0)) * E << std::endl;
std::cout << "the new strength is " << Sc(0) << std::endl;
}
model.dump();
} while (nb_damaged_elements);
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/igfem/package.cmake b/extra_packages/igfem/package.cmake
index 509f61cb0..13a4b642d 100644
--- a/extra_packages/igfem/package.cmake
+++ b/extra_packages/igfem/package.cmake
@@ -1,104 +1,78 @@
#===============================================================================
# @file package.cmake
#
# @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
#
# @brief package description for interface-enriched generalized IGFEM
#
# @section LICENSE
#
# Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
#===============================================================================
package_declare(IGFEM ADVANCED
DESCRIPTION "Use Interface-enriched generalized FEM"
DEPENDS CGAL)
package_declare_sources(igfem
element_class_igfem.cc
element_class_igfem.hh
element_classes_igfem/element_class_igfem_segment_3_inline_impl.hh
element_classes_igfem/element_class_igfem_triangle_4_inline_impl.hh
element_classes_igfem/element_class_igfem_triangle_5_inline_impl.hh
integrator_gauss_igfem.hh
integrator_gauss_igfem_inline_impl.hh
interpolation_element_igfem.cc
interpolation_element_igfem_tmpl.hh
geometrical_element_igfem.hh
shape_igfem.hh
shape_igfem.cc
shape_igfem_inline_impl.hh
fe_engine_template_tmpl_igfem.hh
dumper_igfem_connectivity.hh
dumper_igfem_elemental_field.hh
dumper_igfem_generic_elemental_field.hh
dumper_igfem_element_iterator.hh
dumper_igfem_material_internal_field.hh
dumper_igfem_quadrature_points_field.hh
dumper_igfem_element_partition.hh
igfem_helper.hh
igfem_helper.cc
igfem_enrichment.hh
igfem_enrichment.cc
igfem_enrichment_inline_impl.hh
solid_mechanics_model_igfem.hh
solid_mechanics_model_igfem.cc
solid_mechanics_model_igfem_inline_impl.hh
mesh_igfem_spherical_growing_gel.hh
mesh_igfem_spherical_growing_gel_tmpl.hh
material_igfem/material_igfem_includes.hh
material_igfem/material_igfem.hh
material_igfem/material_igfem.cc
material_igfem/material_igfem_inline_impl.hh
material_igfem/material_igfem_elastic.hh
material_igfem/material_igfem_elastic.cc
material_igfem/material_igfem_elastic_inline_impl.hh
material_igfem/material_igfem_saw_tooth_damage.hh
material_igfem/material_igfem_saw_tooth_damage.cc
material_igfem/material_igfem_saw_tooth_damage_inline_impl.hh
material_igfem/material_igfem_iterative_stiffness_reduction.hh
material_igfem/material_igfem_iterative_stiffness_reduction.cc
material_igfem/igfem_internal_field.hh
material_igfem/igfem_internal_field_tmpl.hh
non_local_manager_igfem.hh
non_local_manager_igfem.cc
)
-package_declare_elements(igfem
- ELEMENT_TYPES
- _igfem_segment_3
- _igfem_triangle_4
- _igfem_triangle_5
- KIND igfem
- GEOMETRICAL_TYPES
- _gt_igfem_segment_3
- _gt_igfem_triangle_4
- _gt_igfem_triangle_5
- INTERPOLATION_TYPES
- _itp_igfem_segment_3
- _itp_igfem_triangle_4
- _itp_igfem_triangle_5
- INTERPOLATION_KIND
- _itk_igfem
- FE_ENGINE_LISTS
- gradient_on_integration_points
- interpolate_on_integration_points
- interpolate
- compute_normals_on_integration_points
- inverse_map
- contains
- get_shapes_derivatives
- )
-
package_declare_material_infos(igfem
LIST AKANTU_IGFEM_MATERIAL_LIST
INCLUDE material_igfem_includes.hh
)
diff --git a/extra_packages/igfem/src/dumper_igfem_connectivity.hh b/extra_packages/igfem/src/dumper_igfem_connectivity.hh
index 3f2c4c99e..832845042 100644
--- a/extra_packages/igfem/src/dumper_igfem_connectivity.hh
+++ b/extra_packages/igfem/src/dumper_igfem_connectivity.hh
@@ -1,133 +1,133 @@
/**
* @file dumper_igfem_connectivity.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Iterator for the IGFEM connectivity
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
#ifndef AKANTU_DUMPER_IGFEM_CONNECTIVITY_HH_
#define AKANTU_DUMPER_IGFEM_CONNECTIVITY_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_igfem_element_iterator.hh"
#include "dumper_igfem_generic_elemental_field.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
template <class types>
class igfem_connectivity_field_iterator
: public igfem_element_iterator<types,
igfem_connectivity_field_iterator> {
public:
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
typedef igfem_element_iterator<types,
dumpers::igfem_connectivity_field_iterator>
parent;
typedef typename types::return_type return_type;
typedef typename types::field_type field_type;
typedef typename types::array_iterator array_iterator;
public:
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
igfem_connectivity_field_iterator(
const field_type & field,
const typename field_type::type_iterator & t_it,
const typename field_type::type_iterator & t_it_end,
const array_iterator & array_it, const array_iterator & array_it_end,
const GhostType ghost_type = _not_ghost, UInt sub_element = 0)
: parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type,
sub_element) {}
/* ------------------------------------------------------------------------
*/
/* Methods */
/* ------------------------------------------------------------------------
*/
return_type operator*() {
const Vector<UInt> & element_connect = *this->array_it;
/// get the local sub_element connectivity and the nodes per sub-element
UInt * sub_connec_ptr =
IGFEMHelper::getSubElementConnectivity(*this->tit, this->sub_element);
UInt nb_nodes_sub_el =
IGFEMHelper::getNbNodesPerSubElement(*this->tit, this->sub_element);
/// get the global sub element connectivity
Vector<UInt> sub_element_connect(nb_nodes_sub_el);
for (UInt i = 0; i < nb_nodes_sub_el; ++i) {
UInt lc = sub_connec_ptr[i];
sub_element_connect(i) = element_connect(lc);
}
return sub_element_connect;
}
/* ------------------------------------------------------------------------
*/
/* Class Members */
/* ------------------------------------------------------------------------
*/
private:
};
/* --------------------------------------------------------------------------
*/
class IGFEMConnectivityField
: public IGFEMGenericElementalField<SingleType<UInt, Vector, false>,
igfem_connectivity_field_iterator> {
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
public:
typedef SingleType<UInt, Vector, false> types;
typedef igfem_connectivity_field_iterator<types> iterator;
typedef types::field_type field_type;
typedef IGFEMGenericElementalField<types, igfem_connectivity_field_iterator>
parent;
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
IGFEMConnectivityField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost)
: parent(field, spatial_dimension, ghost_type) {}
};
/* --------------------------------------------------------------------------
*/
} // namespace dumpers
} // namespace akantu
/* -------------------------------------------------------------------------- */
#endif /*AKANTU_DUMPER_IGFEM_CONNECTIVITY_HH_ */
diff --git a/extra_packages/igfem/src/dumper_igfem_element_partition.hh b/extra_packages/igfem/src/dumper_igfem_element_partition.hh
index e098b69d0..88b3ce91c 100644
--- a/extra_packages/igfem/src/dumper_igfem_element_partition.hh
+++ b/extra_packages/igfem/src/dumper_igfem_element_partition.hh
@@ -1,122 +1,122 @@
/**
* @file dumper_igfem_element_partition.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Element partition field for IGFEM sub-elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
template <class types>
class igfem_element_partition_field_iterator
: public igfem_element_iterator<types,
igfem_element_partition_field_iterator> {
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
public:
typedef igfem_element_iterator<
types, dumpers::igfem_element_partition_field_iterator>
parent;
typedef typename types::return_type return_type;
typedef typename types::array_iterator array_iterator;
typedef typename types::field_type field_type;
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
public:
igfem_element_partition_field_iterator(
const field_type & field,
const typename field_type::type_iterator & t_it,
const typename field_type::type_iterator & t_it_end,
const array_iterator & array_it, const array_iterator & array_it_end,
const GhostType ghost_type = _not_ghost, UInt sub_element = 0)
: parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type,
sub_element) {
prank = StaticCommunicator::getStaticCommunicator().whoAmI();
}
/* ------------------------------------------------------------------------
*/
/* Methods */
/* ------------------------------------------------------------------------
*/
public:
return_type operator*() { return return_type(1, prank); }
/* ------------------------------------------------------------------------
*/
/* Class Members */
/* ------------------------------------------------------------------------
*/
protected:
UInt prank;
};
/* --------------------------------------------------------------------------
*/
template <bool filtered = false>
class IGFEMElementPartitionField
: public IGFEMGenericElementalField<
SingleType<UInt, Vector, filtered>,
igfem_element_partition_field_iterator> {
public:
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
typedef SingleType<UInt, Vector, filtered> types;
typedef igfem_element_partition_field_iterator<types> iterator;
typedef IGFEMGenericElementalField<types,
igfem_element_partition_field_iterator>
parent;
typedef typename types::field_type field_type;
public:
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
IGFEMElementPartitionField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_igfem)
: parent(field, spatial_dimension, ghost_type, kind) {
this->homogeneous = true;
}
/* ------------------------------------------------------------------------
*/
/* Methods */
/* ------------------------------------------------------------------------
*/
UInt getDim() { return 1; }
};
/* --------------------------------------------------------------------------
*/
} // namespace dumpers
} // namespace akantu
diff --git a/extra_packages/igfem/src/dumper_igfem_elemental_field.hh b/extra_packages/igfem/src/dumper_igfem_elemental_field.hh
index c3e53d4f6..f21882b52 100644
--- a/extra_packages/igfem/src/dumper_igfem_elemental_field.hh
+++ b/extra_packages/igfem/src/dumper_igfem_elemental_field.hh
@@ -1,61 +1,61 @@
/**
* @file dumper_igfem_elemental_field.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief description of IGFEM elemental fields
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
#ifndef AKANTU_DUMPER_IGFEM_ELEMENTAL_FIELD_HH_
#define AKANTU_DUMPER_IGFEM_ELEMENTAL_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_field.hh"
#include "dumper_igfem_generic_elemental_field.hh"
#include "static_communicator.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
template <typename T, template <class> class ret = Vector,
bool filtered = false>
class IGFEMElementalField
: public IGFEMGenericElementalField<SingleType<T, ret, filtered>,
igfem_elemental_field_iterator> {
public:
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
typedef SingleType<T, ret, filtered> types;
typedef typename types::field_type field_type;
typedef elemental_field_iterator<types> iterator;
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
IGFEMElementalField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_igfem)
: IGFEMGenericElementalField<types, igfem_elemental_field_iterator>(
field, spatial_dimension, ghost_type, element_kind) {}
};
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_IGFEM_ELEMENTAL_FIELD_HH_ */
diff --git a/extra_packages/igfem/src/dumper_igfem_generic_elemental_field.hh b/extra_packages/igfem/src/dumper_igfem_generic_elemental_field.hh
index b88a98a72..ddff1aea1 100644
--- a/extra_packages/igfem/src/dumper_igfem_generic_elemental_field.hh
+++ b/extra_packages/igfem/src/dumper_igfem_generic_elemental_field.hh
@@ -1,152 +1,152 @@
/**
* @file dumper_igfem_generic_elemental_field.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief generic interface IGFEM elemental fields
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DUMPER_IGFEM_GENERIC_ELEMENTAL_FIELD_HH_
#define AKANTU_DUMPER_IGFEM_GENERIC_ELEMENTAL_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_generic_elemental_field.hh"
#include "dumper_igfem_element_iterator.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
template <class _types, template <class> class iterator_type>
class IGFEMGenericElementalField
: public GenericElementalField<_types, iterator_type> {
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
public:
typedef _types types;
typedef typename types::data_type data_type;
typedef typename types::it_type it_type;
typedef typename types::field_type field_type;
typedef typename types::array_type array_type;
typedef typename types::array_iterator array_iterator;
typedef typename field_type::type_iterator field_type_iterator;
typedef iterator_type<types> iterator;
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
public:
IGFEMGenericElementalField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_igfem)
:
GenericElementalField<types, iterator_type>(field, spatial_dimension,
ghost_type, kind) {
this->checkHomogeneity();
}
/* ------------------------------------------------------------------------
*/
/* Methods */
/* ------------------------------------------------------------------------
*/
public:
/// return the size of the contained data: i.e. the number of elements ?
virtual UInt size() {
this->checkHomogeneity();
return ((this->nb_total_element) * 2);
}
virtual iterator begin() {
field_type_iterator tit;
field_type_iterator end;
UInt sub_element = 0;
/// type iterators on the elemental field
tit = this->field.firstType(this->spatial_dimension, this->ghost_type,
this->element_kind);
end = this->field.lastType(this->spatial_dimension, this->ghost_type,
this->element_kind);
/// skip all types without data
ElementType type = *tit;
for (; tit != end && this->field(*tit, this->ghost_type).getSize() == 0;
++tit) {
}
type = *tit;
if (tit == end)
return this->end();
/// getting information for the field of the given type
const array_type & vect = this->field(type, this->ghost_type);
UInt nb_data_per_elem = this->getNbDataPerElem(type);
UInt nb_component = vect.getNbComponent();
UInt size = (vect.getSize() * nb_component) / nb_data_per_elem;
/// define element-wise iterator
array_iterator it = vect.begin_reinterpret(nb_data_per_elem, size);
array_iterator it_end = vect.end_reinterpret(nb_data_per_elem, size);
/// define data iterator
iterator rit = iterator(this->field, tit, end, it, it_end,
this->ghost_type, sub_element);
rit.setNbDataPerElem(this->nb_data_per_elem);
return rit;
}
virtual iterator end() {
field_type_iterator tit;
field_type_iterator end;
UInt sub_element = 0;
tit = this->field.firstType(this->spatial_dimension, this->ghost_type,
this->element_kind);
end = this->field.lastType(this->spatial_dimension, this->ghost_type,
this->element_kind);
ElementType type = *tit;
for (; tit != end; ++tit)
type = *tit;
const array_type & vect = this->field(type, this->ghost_type);
UInt nb_data = this->getNbDataPerElem(type);
UInt nb_component = vect.getNbComponent();
UInt size = (vect.getSize() * nb_component) / nb_data;
array_iterator it = vect.end_reinterpret(nb_data, size);
iterator rit = iterator(this->field, end, end, it, it, this->ghost_type,
sub_element);
rit.setNbDataPerElem(this->nb_data_per_elem);
return rit;
}
/* ------------------------------------------------------------------------
*/
/* Class Members */
/* ------------------------------------------------------------------------
*/
protected:
};
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_IGFEM_GENERIC_ELEMENTAL_FIELD_HH_ */
diff --git a/extra_packages/igfem/src/dumper_igfem_material_internal_field.hh b/extra_packages/igfem/src/dumper_igfem_material_internal_field.hh
index 5af3c8299..acbdebef2 100644
--- a/extra_packages/igfem/src/dumper_igfem_material_internal_field.hh
+++ b/extra_packages/igfem/src/dumper_igfem_material_internal_field.hh
@@ -1,58 +1,58 @@
/**
* @file dumper_igfem_material_internal_field.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief description of IGFEM material internal field
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
#ifndef AKANTU_DUMPER_IGFEM_MATERIAL_INTERNAL_FIELD_HH_
#define AKANTU_DUMPER_IGFEM_MATERIAL_INTERNAL_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_igfem_quadrature_points_field.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
template <typename T, bool filtered = false>
class IGFEMInternalMaterialField
: public IGFEMGenericElementalField<SingleType<T, Vector, filtered>,
igfem_quadrature_point_iterator> {
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
public:
typedef SingleType<T, Vector, filtered> types;
typedef IGFEMGenericElementalField<types, igfem_quadrature_point_iterator>
parent;
typedef typename types::field_type field_type;
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
IGFEMInternalMaterialField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_igfem)
: parent(field, spatial_dimension, ghost_type, kind) {}
};
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_IGFEM_MATERIAL_INTERNAL_FIELD_HH_ */
diff --git a/extra_packages/igfem/src/dumper_igfem_quadrature_points_field.hh b/extra_packages/igfem/src/dumper_igfem_quadrature_points_field.hh
index ca9d90dce..3ae7aff07 100644
--- a/extra_packages/igfem/src/dumper_igfem_quadrature_points_field.hh
+++ b/extra_packages/igfem/src/dumper_igfem_quadrature_points_field.hh
@@ -1,156 +1,156 @@
/**
* @file dumper_igfem_quadrature_points_field.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief description of IGFEM quadrature points field
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
#ifndef AKANTU_DUMPER_IGFEM_QUADRATURE_POINTS_FIELD_HH_
#define AKANTU_DUMPER_IGFEM_QUADRATURE_POINTS_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_igfem_elemental_field.hh"
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
template <typename types>
class igfem_quadrature_point_iterator
: public igfem_element_iterator<types, igfem_quadrature_point_iterator> {
/* ------------------------------------------------------------------------
*/
/* Typedefs */
/* ------------------------------------------------------------------------
*/
public:
typedef igfem_element_iterator<types,
dumpers::igfem_quadrature_point_iterator>
parent;
typedef typename types::data_type data_type;
typedef typename types::return_type return_type;
typedef typename types::field_type field_type;
typedef typename types::array_iterator array_iterator;
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
public:
igfem_quadrature_point_iterator(
const field_type & field,
const typename field_type::type_iterator & t_it,
const typename field_type::type_iterator & t_it_end,
const array_iterator & array_it, const array_iterator & array_it_end,
const GhostType ghost_type = _not_ghost, UInt sub_element = 0)
: parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type,
sub_element) {}
return_type operator*() {
const Vector<data_type> & mat_internal_field = *this->array_it;
/// get nb data per sub element
UInt nb_sub_1_internal_points =
IGFEMHelper::getNbQuadraturePoints(*this->tit, 0);
UInt nb_sub_2_internal_points =
IGFEMHelper::getNbQuadraturePoints(*this->tit, 1);
UInt nb_data = this->getNbDataPerElem(*(this->tit)) /
(nb_sub_1_internal_points + nb_sub_2_internal_points);
UInt nb_sub_components = 0;
if (!(this->sub_element))
nb_sub_components = nb_data * nb_sub_1_internal_points;
else
nb_sub_components = nb_data * nb_sub_2_internal_points;
Vector<data_type> sub_mat_internal_field(nb_sub_components);
if (!(this->sub_element)) {
for (UInt i = 0; i < nb_sub_components; ++i)
sub_mat_internal_field(i) = mat_internal_field(i);
} else {
for (UInt i = 0; i < nb_sub_components; ++i)
sub_mat_internal_field(i) =
mat_internal_field(nb_data * nb_sub_1_internal_points + i);
}
return sub_mat_internal_field;
}
};
// /*
// --------------------------------------------------------------------------
// */
// /* Fields type description */
// /*
// --------------------------------------------------------------------------
// */
// template<class types, template <class> class iterator_type>
// class GenericQuadraturePointsField :
// public GenericElementalField<types,iterator_type> {
// public:
// /*
// ------------------------------------------------------------------------
// */
// /* Typedefs */
// /*
// ------------------------------------------------------------------------
// */
// typedef iterator_type<types> iterator;
// typedef typename types::field_type field_type;
// typedef typename iterator::it_type T;
// typedef GenericElementalField<types,iterator_type> parent;
// /*
// ------------------------------------------------------------------------
// */
// /* Constructors/Destructors */
// /*
// ------------------------------------------------------------------------
// */
// GenericQuadraturePointsField(const field_type & field,
- // UInt spatial_dimension = _all_dimensions,
+ // Int spatial_dimension = _all_dimensions,
// GhostType ghost_type = _not_ghost,
// ElementKind element_kind = _ek_not_defined) :
// parent(field, spatial_dimension, ghost_type, element_kind) { }
// /*
// ------------------------------------------------------------------------
// */
// /* Methods */
// /*
// ------------------------------------------------------------------------
// */
// virtual iterator begin() {
// iterator it = parent::begin();
// return it;
// }
// virtual iterator end () {
// iterator it = parent::end();
// return it;
// }
// };
/* --------------------------------------------------------------------------
*/
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_IGFEM_QUADRATURE_POINTS_FIELD_HH_ */
diff --git a/extra_packages/igfem/src/element_class_igfem.hh b/extra_packages/igfem/src/element_class_igfem.hh
index c98cc6cf6..f791bd46e 100644
--- a/extra_packages/igfem/src/element_class_igfem.hh
+++ b/extra_packages/igfem/src/element_class_igfem.hh
@@ -1,304 +1,304 @@
/**
* @file element_class_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
*
* @brief Specialization for interface-enriched finite elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_CLASS_IGFEM_HH_
#define AKANTU_ELEMENT_CLASS_IGFEM_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <InterpolationType interpolation_type>
class InterpolationElement<interpolation_type, _itk_igfem> {
public:
using interpolation_property = InterpolationProperty<interpolation_type>;
/* ------------------------------------------------------------------------ */
/* Member functions */
/* ------------------------------------------------------------------------ */
public:
static void assembleShapes(const Vector<Real> & parent_interpolation,
const Vector<Real> & sub_interpolation,
Vector<Real> & interpolation,
UInt sub_element = 0) {
/// N1, N2, N3 of parent triangle
UInt nb_nodes_parent = InterpolationElement<
interpolation_property::parent_interpolation_type>::getShapeSize();
for (UInt i = 0; i < nb_nodes_parent; ++i) {
interpolation(i) = parent_interpolation(i);
}
/// add the enrichment
UInt * enriched_node = enrichments[sub_element];
for (UInt e = 0; e < nb_enrichments; ++e) {
interpolation(nb_nodes_parent + e) = sub_interpolation(enriched_node[e]);
}
}
static void
assembleShapeDerivatives(const Matrix<Real> & parent_interpolation,
const Matrix<Real> & sub_interpolation,
Matrix<Real> & interpolation, UInt sub_element = 0) {
/// N1, N2, N3 of parent triangle
UInt nb_nodes_parent = InterpolationElement<
interpolation_property::parent_interpolation_type>::getShapeSize();
for (UInt i = 0; i < nb_nodes_parent; ++i) {
Vector<Real> ip(interpolation(i));
ip = parent_interpolation(i);
}
/// add the enrichment
UInt * enriched_node = enrichments[sub_element];
for (UInt e = 0; e < nb_enrichments; ++e) {
Vector<Real> ip(interpolation(nb_nodes_parent + e));
ip = sub_interpolation(enriched_node[e]);
}
}
static void interpolate(const Matrix<Real> & nodal_values,
const Vector<Real> & shapes,
Vector<Real> & interpolated) {
Matrix<Real> interpm(interpolated.storage(), nodal_values.rows(), 1);
Matrix<Real> shapesm(shapes.storage(),
interpolation_property::nb_nodes_per_element, 1);
interpm.mul<false, false>(nodal_values, shapesm);
}
public:
static AKANTU_GET_MACRO_NOT_CONST(
ShapeSize, interpolation_property::nb_nodes_per_element, UInt);
static AKANTU_GET_MACRO_NOT_CONST(
ShapeDerivativesSize,
(interpolation_property::nb_nodes_per_element *
interpolation_property::natural_space_dimension),
UInt);
static AKANTU_GET_MACRO_NOT_CONST(
NaturalSpaceDimension, interpolation_property::natural_space_dimension,
UInt);
static AKANTU_GET_MACRO_NOT_CONST(
NbNodesPerInterpolationElement,
interpolation_property::nb_nodes_per_element, UInt);
static AKANTU_GET_MACRO_NOT_CONST(NbSubElements,
interpolation_property::nb_sub_elements,
UInt);
static UInt * getSubElementConnectivity(UInt t = 0) {
return &(interpolation_property::sub_element_connectivity[t]);
};
static UInt getNbEnrichments() {
return interpolation_property::nb_enrichments;
};
static UInt * getSubElementEnrichments(UInt t = 0) {
return &(interpolation_property::enrichments[t]);
};
protected:
/// storage of the subelement local connectivity
static UInt sub_element_connectivity_vect[];
/// local connectivity of subelements
static UInt * sub_element_connectivity[];
/// nb of subelements
static UInt nb_sub_elements;
/// storage of enrichments
static UInt enrichment_vect[];
static UInt * enrichments[];
static UInt nb_enrichments;
};
} // namespace akantu
#include "interpolation_element_igfem_tmpl.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
#define AKANTU_DEFINE_IGFEM_ELEMENT_CLASS_PROPERTY( \
elem_type, geom_type, interp_type, parent_el_type, sub_el_type_1, \
sub_el_type_2, elem_kind, sp, min_int_order) \
template <> struct ElementClassProperty<elem_type> { \
static const GeometricalType geometrical_type{geom_type}; \
static const InterpolationType interpolation_type{interp_type}; \
static const ElementType parent_element_type{parent_el_type}; \
static const ElementType sub_element_type_1{sub_el_type_1}; \
static const ElementType sub_element_type_2{sub_el_type_2}; \
static const ElementKind element_kind{elem_kind}; \
- static const UInt spatial_dimension{sp}; \
+ static const Int spatial_dimension{sp}; \
static const UInt minimal_integration_order{min_int_order}; \
}
/* -------------------------------------------------------------------------- */
template <ElementType element_type>
class ElementClass<element_type, _ek_igfem>
: public GeometricalElement<
ElementClassProperty<element_type>::geometrical_type>,
public InterpolationElement<
ElementClassProperty<element_type>::interpolation_type> {
protected:
using geometrical_element =
GeometricalElement<ElementClassProperty<element_type>::geometrical_type>;
using interpolation_element = InterpolationElement<
ElementClassProperty<element_type>::interpolation_type>;
using parent_element =
ElementClass<ElementClassProperty<element_type>::parent_element_type>;
using element_property = ElementClassProperty<element_type>;
using interpolation_property =
typename interpolation_element::interpolation_property;
/* ------------------------------------------------------------------------ */
/* Member functions */
/* ------------------------------------------------------------------------ */
public:
static void getSubElementCoords(const Matrix<Real> & element_coords,
Matrix<Real> & sub_coords,
const UInt sub_element) {
/// get the sub_element_type
/// constexrp ElementType sub_el_type = getSubElementType(sub_element);
UInt nb_nodes_sub_el = 0;
switch (sub_element) {
case 0:
nb_nodes_sub_el =
ElementClass<ElementClassProperty<element_type>::sub_element_type_1>::
getNbNodesPerInterpolationElement();
break;
case 1:
nb_nodes_sub_el =
ElementClass<ElementClassProperty<element_type>::sub_element_type_2>::
getNbNodesPerInterpolationElement();
break;
}
- for (UInt i = 0; i < nb_nodes_sub_el; ++i) {
+ for (Int i = 0; i < nb_nodes_sub_el; ++i) {
UInt lc = InterpolationElement<
ElementClassProperty<element_type>::interpolation_type>::
sub_element_connectivity[sub_element][i];
Vector<Real> sub_c(sub_coords(i));
sub_c = element_coords(lc);
}
}
static void getParentCoords(const Matrix<Real> & element_coords,
Matrix<Real> & parent_coords) {
const ElementType parent_type =
ElementClassProperty<element_type>::parent_element_type;
UInt nb_nodes_parent_el =
ElementClass<parent_type>::getNbNodesPerInterpolationElement();
- for (UInt i = 0; i < nb_nodes_parent_el; ++i) {
+ for (Int i = 0; i < nb_nodes_parent_el; ++i) {
Vector<Real> parent_c(parent_coords(i));
parent_c = element_coords(i);
}
}
/// map the points from the reference domain of the subelement to the physical
/// domain
static void mapToPhysicalDomain(const Matrix<Real> & element_coords,
Matrix<Real> & sub_coords,
Matrix<Real> & sub_shapes,
Matrix<Real> & physical_points,
UInt sub_element = 0) {
/// get the sub_element_type
getSubElementCoords(element_coords, sub_coords, sub_element);
/// map the points of the subelements in the physical domain
switch (sub_element) {
case 0:
ElementClass<ElementClassProperty<element_type>::sub_element_type_1>::
interpolate(sub_coords, sub_shapes, physical_points);
break;
case 1:
ElementClass<ElementClassProperty<element_type>::sub_element_type_2>::
interpolate(sub_coords, sub_shapes, physical_points);
break;
}
}
/// map the points from the physical domain to the parent reference domain
static void mapToParentRefDomain(const Matrix<Real> & element_coords,
Matrix<Real> & parent_coords,
Matrix<Real> & physical_points,
Matrix<Real> & natural_coords) {
const ElementType parent_type =
ElementClassProperty<element_type>::parent_element_type;
getParentCoords(element_coords, parent_coords);
/// map the points from the physical domain into the parent reference domain
ElementClass<parent_type>::inverseMap(physical_points, parent_coords,
natural_coords);
}
/// map the points from the subelement reference domain to the parent
/// reference domain
static void mapFromSubRefToParentRef(const Matrix<Real> & element_coords,
Matrix<Real> & parent_coords,
Matrix<Real> & sub_coords,
Matrix<Real> & sub_shapes,
Matrix<Real> & physical_points,
Matrix<Real> & natural_points,
UInt /*nb_points*/, UInt sub_element) {
mapToPhysicalDomain(element_coords, sub_coords, sub_shapes, physical_points,
sub_element);
mapToParentRefDomain(element_coords, parent_coords, physical_points,
natural_points);
}
static void mapFromSubRefToParentRef(const Matrix<Real> & element_coords,
Matrix<Real> & sub_coords,
Matrix<Real> & parent_coords,
Matrix<Real> & sub_shapes,
Matrix<Real> & physical_points,
Matrix<Real> & parent_el_natural_coords,
UInt sub_element) {
mapToPhysicalDomain(element_coords, sub_coords, sub_shapes, physical_points,
sub_element);
mapToParentRefDomain(element_coords, parent_coords, physical_points,
parent_el_natural_coords);
}
/// compute the normal of a surface defined by the function f
static inline void
computeNormalsOnNaturalCoordinates(const Matrix<Real> & /*coord*/,
Matrix<Real> & /*f*/,
Matrix<Real> & /*normals*/) {
AKANTU_TO_IMPLEMENT();
}
/// determine orientation of the element with respect to the interface
static inline UInt getOrientation(const Vector<bool> & is_inside);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
static AKANTU_GET_MACRO_NOT_CONST(Kind, _ek_igfem, ElementKind);
static ElementType getP1ElementType() { AKANTU_TO_IMPLEMENT(); };
static AKANTU_GET_MACRO_NOT_CONST(
SpatialDimension, ElementClassProperty<element_type>::spatial_dimension,
UInt);
static ElementType & getFacetType(UInt /*t*/ = 0) { AKANTU_TO_IMPLEMENT(); }
static ElementType * getFacetTypeInternal() { AKANTU_TO_IMPLEMENT(); }
private:
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
#include "geometrical_element_igfem.hh"
/* -------------------------------------------------------------------------- */
#include "element_class_igfem_segment_3_inline_impl.hh"
#include "element_class_igfem_triangle_4_inline_impl.hh"
#include "element_class_igfem_triangle_5_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_ELEMENT_CLASS_IGFEM_HH_ */
diff --git a/extra_packages/igfem/src/fe_engine_template_tmpl_igfem.hh b/extra_packages/igfem/src/fe_engine_template_tmpl_igfem.hh
index 276ab296d..40c02c0a9 100644
--- a/extra_packages/igfem/src/fe_engine_template_tmpl_igfem.hh
+++ b/extra_packages/igfem/src/fe_engine_template_tmpl_igfem.hh
@@ -1,115 +1,115 @@
/**
* @file shape_igfem_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @brief ShapeIGFEM inline implementation
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "integrator_gauss_igfem.hh"
#include "shape_igfem.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_FE_ENGINE_TEMPLATE_TMPL_IGFEM_HH_
#define AKANTU_FE_ENGINE_TEMPLATE_TMPL_IGFEM_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* compatibility functions */
/* -------------------------------------------------------------------------- */
template <>
inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem,
DefaultIntegrationOrderFunctor>::
initShapeFunctions(const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh::type_iterator it =
mesh.firstType(element_dimension, ghost_type, _ek_igfem);
Mesh::type_iterator end =
mesh.lastType(element_dimension, ghost_type, _ek_igfem);
for (; it != end; ++it) {
ElementType type = *it;
integrator.initIntegrator(nodes, type, ghost_type);
#define INIT(_type) \
do { \
const Matrix<Real> & all_quads = \
integrator.getIntegrationPoints<_type>(ghost_type); \
const Matrix<Real> & quads_1 = integrator.getIntegrationPoints< \
ElementClassProperty<_type>::sub_element_type_1>(ghost_type); \
const Matrix<Real> & quads_2 = integrator.getIntegrationPoints< \
ElementClassProperty<_type>::sub_element_type_2>(ghost_type); \
shape_functions.initShapeFunctions(nodes, all_quads, quads_1, quads_2, \
_type, ghost_type); \
} while (0)
AKANTU_BOOST_IGFEM_ELEMENT_SWITCH(INIT);
#undef INIT
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <>
inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem,
DefaultIntegrationOrderFunctor>::
computeIntegrationPointsCoordinates(
Array<Real> & quadrature_points_coordinates, ElementType type,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ GhostType ghost_type, const Array<Int> & filter_elements) const {
const Array<Real> & nodes_coordinates = mesh.getNodes();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
/// create an array with the nodal coordinates that need to be
/// interpolated. The nodal coordinates of the enriched nodes need
/// to be set to zero, because they represent the enrichment of the
/// position field, and the enrichments for this field are all zero!
/// There is no gap in the mesh!
Array<Real> igfem_nodes(nodes_coordinates.getSize(), spatial_dimension);
shape_functions.extractValuesAtStandardNodes(nodes_coordinates, igfem_nodes,
ghost_type);
interpolateOnIntegrationPoints(igfem_nodes, quadrature_points_coordinates,
spatial_dimension, type, ghost_type,
filter_elements);
}
/* -------------------------------------------------------------------------- */
template <>
inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem,
DefaultIntegrationOrderFunctor>::
computeIntegrationPointsCoordinates(
ElementTypeMapArray<Real> & quadrature_points_coordinates,
- const ElementTypeMapArray<UInt> * filter_elements) const {
+ const ElementTypeMapArray<Idx> * filter_elements) const {
const Array<Real> & nodes_coordinates = mesh.getNodes();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
/// create an array with the nodal coordinates that need to be
/// interpolated. The nodal coordinates of the enriched nodes need
/// to be set to zero, because they represent the enrichment of the
/// position field, and the enrichments for this field are all zero!
/// There is no gap in the mesh!
Array<Real> igfem_nodes(nodes_coordinates.getSize(), spatial_dimension);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
shape_functions.extractValuesAtStandardNodes(nodes_coordinates, igfem_nodes,
ghost_type);
}
interpolateOnIntegrationPoints(igfem_nodes, quadrature_points_coordinates,
filter_elements);
}
} // namespace akantu
#endif /* AKANTU_FE_ENGINE_TEMPLATE_TMPL_IGFEM_HH_ */
diff --git a/extra_packages/igfem/src/geometrical_element_igfem.hh b/extra_packages/igfem/src/geometrical_element_igfem.hh
index e817f30c4..7f7ca44eb 100644
--- a/extra_packages/igfem/src/geometrical_element_igfem.hh
+++ b/extra_packages/igfem/src/geometrical_element_igfem.hh
@@ -1,66 +1,66 @@
/**
* @file element_class_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
*
* @brief Specialization for interface-enriched finite elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <> class GeometricalElement<_gt_igfem_segment_3> {
- static constexpr UInt spatial_dimension{1};
+ static constexpr Int spatial_dimension{1};
static constexpr UInt nb_nodes_per_element{3};
static constexpr UInt nb_facet_types{1};
static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{1}};
static constexpr std::array<UInt, 2> facet_connectivity_vect{{0, 1}};
};
/* -------------------------------------------------------------------------- */
template <> class GeometricalElement<_gt_igfem_triangle_4> {
- static constexpr UInt spatial_dimension{2};
+ static constexpr Int spatial_dimension{2};
static constexpr UInt nb_nodes_per_element{4};
static constexpr UInt nb_facet_types{2};
static constexpr std::array<UInt, nb_facet_types> nb_facets{{2, 1}};
static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{2, 3}};
// clang-format off
static constexpr std::array<UInt, 7> facet_connectivity_vect{{
// first type
0, 2,
1, 0,
// second type
1, 2, 3}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
template <> class GeometricalElement<_gt_igfem_triangle_5> {
- static constexpr UInt spatial_dimension{2};
+ static constexpr Int spatial_dimension{2};
static constexpr UInt nb_nodes_per_element{5};
static constexpr UInt nb_facet_types{2};
static constexpr std::array<UInt, nb_facet_types> nb_facets{{1, 2}};
static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{2, 3}};
// clang-format off
static constexpr std::array<UInt, 8> facet_connectivity_vect{{
// first type
1, 2,
// second type
0, 2, 1,
0, 3, 4}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/extra_packages/igfem/src/integrator_gauss_igfem.hh b/extra_packages/igfem/src/integrator_gauss_igfem.hh
index 02f75885d..3c35b3840 100644
--- a/extra_packages/igfem/src/integrator_gauss_igfem.hh
+++ b/extra_packages/igfem/src/integrator_gauss_igfem.hh
@@ -1,119 +1,119 @@
/**
* @file integrator_gauss_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Gauss integration facilities for IGFEM
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_INTEGRATOR_IGFEM_HH_
#define AKANTU_INTEGRATOR_IGFEM_HH_
/* -------------------------------------------------------------------------- */
#include "integrator.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
template <class IOF> class IntegratorGauss<_ek_igfem, IOF> : public Integrator {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
IntegratorGauss(const Mesh & mesh, const ID & id = "integrator_gauss");
virtual ~IntegratorGauss(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
inline void initIntegrator(const Array<Real> & nodes, ElementType type,
GhostType ghost_type);
/// precompute jacobians on elements of type "type"
template <ElementType type>
void precomputeJacobiansOnQuadraturePoints(const Array<Real> & nodes,
GhostType ghost_type);
/// integrate f on the element "elem" of type "type"
template <ElementType type>
inline void integrateOnElement(const Array<Real> & f, Real * intf,
UInt nb_degree_of_freedom, UInt elem,
GhostType ghost_type) const;
/// integrate f for all elements of type "type"
template <ElementType type>
void integrate(const Array<Real> & in_f, Array<Real> & intf,
UInt nb_degree_of_freedom, GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ const Array<Int> & filter_elements) const;
/// integrate one element scalar value on all elements of type "type"
template <ElementType type>
Real integrate(const Vector<Real> & in_f, UInt index,
GhostType ghost_type) const;
/// integrate scalar field in_f
template <ElementType type>
Real integrate(const Array<Real> & in_f, GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ const Array<Int> & filter_elements) const;
/// integrate partially around a quadrature point (@f$ intf_q = f_q * J_q *
/// w_q @f$)
template <ElementType type>
void
integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf,
UInt nb_degree_of_freedom, GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ const Array<Int> & filter_elements) const;
/// return a vector with quadrature points natural coordinates
template <ElementType type>
const Matrix<Real> & getIntegrationPoints(GhostType ghost_type) const;
/// return the number of quadrature points for a given element type
template <ElementType type>
inline UInt getNbIntegrationPoints(GhostType ghost_type = _not_ghost) const;
/// compute the vector of quadrature points natural coordinates
template <ElementType type>
void computeQuadraturePoints(GhostType ghost_type);
/// check that the jacobians are not negative
template <ElementType type> void checkJacobians(GhostType ghost_type) const;
public:
/// compute the jacobians on quad points for a given element
template <ElementType type>
void computeJacobianOnQuadPointsByElement(const Matrix<Real> & node_coords,
Vector<Real> & jacobians);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
inline void integrate(Real * f, Real * jac, Real * inte,
UInt nb_degree_of_freedom,
UInt nb_quadrature_points) const;
private:
ElementTypeMap<Matrix<Real>> quadrature_points;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "integrator_gauss_igfem_inline_impl.hh"
} // namespace akantu
#endif /*AKANTU_INTEGRATOR_IGFEM_HH_ */
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
diff --git a/extra_packages/igfem/src/integrator_gauss_igfem_inline_impl.hh b/extra_packages/igfem/src/integrator_gauss_igfem_inline_impl.hh
index 6d182f7e6..9d8442b91 100644
--- a/extra_packages/igfem/src/integrator_gauss_igfem_inline_impl.hh
+++ b/extra_packages/igfem/src/integrator_gauss_igfem_inline_impl.hh
@@ -1,449 +1,449 @@
/**
* @file integrator_gauss_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Inline functions of gauss integrator for the case of IGFEM
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
} // namespace akantu
#include "fe_engine.hh"
#if defined(AKANTU_DEBUG_TOOLS)
#include "aka_debug_tools.hh"
#endif
namespace akantu {
/* -------------------------------------------------------------------------- */
#define INIT_INTEGRATOR(type) \
computeQuadraturePoints<type>(ghost_type); \
precomputeJacobiansOnQuadraturePoints<type>(nodes, ghost_type); \
checkJacobians<type>(ghost_type);
template <class IOF>
inline void IntegratorGauss<_ek_igfem, IOF>::initIntegrator(
const Array<Real> & nodes, ElementType type, GhostType ghost_type) {
AKANTU_BOOST_IGFEM_ELEMENT_SWITCH(INIT_INTEGRATOR);
}
#undef INIT_INTEGRATOR
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline UInt
IntegratorGauss<_ek_igfem, IOF>::getNbIntegrationPoints(GhostType) const {
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
UInt nb_quad_points_sub_1 =
GaussIntegrationElement<sub_type_1>::getNbQuadraturePoints();
UInt nb_quad_points_sub_2 =
GaussIntegrationElement<sub_type_2>::getNbQuadraturePoints();
return (nb_quad_points_sub_1 + nb_quad_points_sub_2);
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline void IntegratorGauss<_ek_igfem, IOF>::integrateOnElement(
const Array<Real> & f, Real * intf, UInt nb_degree_of_freedom,
const UInt elem, GhostType ghost_type) const {
Array<Real> & jac_loc = jacobians(type, ghost_type);
UInt nb_quadrature_points = getNbIntegrationPoints<type>();
AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom,
"The vector f do not have the good number of component.");
- Real * f_val = f.storage() + elem * f.getNbComponent();
- Real * jac_val = jac_loc.storage() + elem * nb_quadrature_points;
+ Real * f_val = f.data() + elem * f.getNbComponent();
+ Real * jac_val = jac_loc.data() + elem * nb_quadrature_points;
integrate(f_val, jac_val, intf, nb_degree_of_freedom, nb_quadrature_points);
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline Real IntegratorGauss<_ek_igfem, IOF>::integrate(
const Vector<Real> & in_f, UInt index, GhostType ghost_type) const {
const Array<Real> & jac_loc = jacobians(type, ghost_type);
UInt nb_quadrature_points = getNbIntegrationPoints<type>();
AKANTU_DEBUG_ASSERT(in_f.size() == nb_quadrature_points,
"The vector f do not have nb_quadrature_points entries.");
- Real * jac_val = jac_loc.storage() + index * nb_quadrature_points;
+ Real * jac_val = jac_loc.data() + index * nb_quadrature_points;
Real intf;
- integrate(in_f.storage(), jac_val, &intf, 1, nb_quadrature_points);
+ integrate(in_f.data(), jac_val, &intf, 1, nb_quadrature_points);
return intf;
return 0.;
}
/* -------------------------------------------------------------------------- */
template <class IOF>
inline void
IntegratorGauss<_ek_igfem, IOF>::integrate(Real * f, Real * jac, Real * inte,
UInt nb_degree_of_freedom,
UInt nb_quadrature_points) const {
memset(inte, 0, nb_degree_of_freedom * sizeof(Real));
Real * cjac = jac;
for (UInt q = 0; q < nb_quadrature_points; ++q) {
for (UInt dof = 0; dof < nb_degree_of_freedom; ++dof) {
inte[dof] += *f * *cjac;
++f;
}
++cjac;
}
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline const Matrix<Real> &
IntegratorGauss<_ek_igfem, IOF>::getIntegrationPoints(
GhostType ghost_type) const {
AKANTU_DEBUG_ASSERT(
quadrature_points.exists(type, ghost_type),
"Quadrature points for type "
<< quadrature_points.printType(type, ghost_type)
<< " have not been initialized."
<< " Did you use 'computeQuadraturePoints' function ?");
return quadrature_points(type, ghost_type);
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline void
IntegratorGauss<_ek_igfem, IOF>::computeQuadraturePoints(GhostType ghost_type) {
/// typedef for the two subelement_types and the parent element type
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
/// store the quadrature points on the two subelements
Matrix<Real> & quads_sub_1 = quadrature_points(sub_type_1, ghost_type);
Matrix<Real> & quads_sub_2 = quadrature_points(sub_type_2, ghost_type);
quads_sub_1 = GaussIntegrationElement<sub_type_1>::getQuadraturePoints();
quads_sub_2 = GaussIntegrationElement<sub_type_2>::getQuadraturePoints();
/// store all quad points for the current type
UInt nb_quad_points_sub_1 =
GaussIntegrationElement<sub_type_1>::getNbQuadraturePoints();
UInt nb_quad_points_sub_2 =
GaussIntegrationElement<sub_type_2>::getNbQuadraturePoints();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
Matrix<Real> & quads = quadrature_points(type, ghost_type);
quads = Matrix<Real>(spatial_dimension,
nb_quad_points_sub_1 + nb_quad_points_sub_2);
- Matrix<Real> quads_1(quads.storage(), quads.rows(), nb_quad_points_sub_1);
+ Matrix<Real> quads_1(quads.data(), quads.rows(), nb_quad_points_sub_1);
quads_1 = quads_sub_1;
- Matrix<Real> quads_2(quads.storage() + quads.rows() * nb_quad_points_sub_1,
+ Matrix<Real> quads_2(quads.data() + quads.rows() * nb_quad_points_sub_1,
quads.rows(), nb_quad_points_sub_2);
quads_2 = quads_sub_2;
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline void
IntegratorGauss<_ek_igfem, IOF>::computeJacobianOnQuadPointsByElement(
const Matrix<Real> & node_coords, Vector<Real> & jacobians) {
/// optimize: get the matrix from the ElementTypeMap
Matrix<Real> quad = GaussIntegrationElement<type>::getQuadraturePoints();
// jacobian
ElementClass<type>::computeJacobian(quad, node_coords, jacobians);
}
/* -------------------------------------------------------------------------- */
template <class IOF>
inline IntegratorGauss<_ek_igfem, IOF>::IntegratorGauss(const Mesh & mesh,
const ID & id)
: Integrator(mesh, id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline void
IntegratorGauss<_ek_igfem, IOF>::checkJacobians(GhostType ghost_type) const {
AKANTU_DEBUG_IN();
/// typedef for the two subelement_types and the parent element type
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
UInt nb_quad_points_sub_1 =
GaussIntegrationElement<sub_type_1>::getNbQuadraturePoints();
UInt nb_quad_points_sub_2 =
GaussIntegrationElement<sub_type_2>::getNbQuadraturePoints();
UInt nb_quadrature_points = nb_quad_points_sub_1 + nb_quad_points_sub_2;
UInt nb_element;
nb_element = mesh.getConnectivity(type, ghost_type).getSize();
- Real * jacobians_val = jacobians(type, ghost_type).storage();
+ Real * jacobians_val = jacobians(type, ghost_type).data();
for (UInt i = 0; i < nb_element * nb_quadrature_points;
++i, ++jacobians_val) {
if (*jacobians_val < 0)
AKANTU_ERROR(
"Negative jacobian computed,"
<< " possible problem in the element node ordering (Quadrature Point "
<< i % nb_quadrature_points << ":" << i / nb_quadrature_points << ":"
<< type << ":" << ghost_type << ")");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline void
IntegratorGauss<_ek_igfem, IOF>::precomputeJacobiansOnQuadraturePoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// typedef for the two subelement_types and the parent element type
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
/// get the number of nodes for the subelements and the parent element
UInt nb_nodes_sub_1 =
ElementClass<sub_type_1>::getNbNodesPerInterpolationElement();
UInt nb_nodes_sub_2 =
ElementClass<sub_type_2>::getNbNodesPerInterpolationElement();
UInt nb_quadrature_points_sub_1 =
GaussIntegrationElement<sub_type_1>::getNbQuadraturePoints();
UInt nb_quadrature_points_sub_2 =
GaussIntegrationElement<sub_type_2>::getNbQuadraturePoints();
UInt nb_quadrature_points =
nb_quadrature_points_sub_1 + nb_quadrature_points_sub_2;
UInt nb_element = mesh.getNbElement(type, ghost_type);
Array<Real> * jacobians_tmp;
if (!jacobians.exists(type, ghost_type))
jacobians_tmp = &jacobians.alloc(nb_element * nb_quadrature_points, 1, type,
ghost_type);
else {
jacobians_tmp = &jacobians(type, ghost_type);
jacobians_tmp->resize(nb_element * nb_quadrature_points);
}
Array<Real>::vector_iterator jacobians_it =
jacobians_tmp->begin_reinterpret(nb_quadrature_points, nb_element);
Vector<Real> weights_sub_1 =
GaussIntegrationElement<sub_type_1>::getWeights();
Vector<Real> weights_sub_2 =
GaussIntegrationElement<sub_type_2>::getWeights();
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
Array<Real>::const_matrix_iterator x_it =
x_el.begin(spatial_dimension, nb_nodes_per_element);
// Matrix<Real> local_coord(spatial_dimension, nb_nodes_per_element);
- for (UInt elem = 0; elem < nb_element; ++elem, ++jacobians_it, ++x_it) {
+ for (Int elem = 0; elem < nb_element; ++elem, ++jacobians_it, ++x_it) {
const Matrix<Real> & X = *x_it;
Matrix<Real> sub_1_coords(spatial_dimension, nb_nodes_sub_1);
Matrix<Real> sub_2_coords(spatial_dimension, nb_nodes_sub_2);
ElementClass<type>::getSubElementCoords(X, sub_1_coords, 0);
ElementClass<type>::getSubElementCoords(X, sub_2_coords, 1);
Vector<Real> & J = *jacobians_it;
/// initialize vectors to store the jacobians for each subelement
Vector<Real> J_sub_1(nb_quadrature_points_sub_1);
Vector<Real> J_sub_2(nb_quadrature_points_sub_2);
computeJacobianOnQuadPointsByElement<sub_type_1>(sub_1_coords, J_sub_1);
computeJacobianOnQuadPointsByElement<sub_type_2>(sub_2_coords, J_sub_2);
J_sub_1 *= weights_sub_1;
J_sub_2 *= weights_sub_2;
/// copy results into the jacobian vector for this element
- for (UInt i = 0; i < nb_quadrature_points_sub_1; ++i) {
+ for (Int i = 0; i < nb_quadrature_points_sub_1; ++i) {
J(i) = J_sub_1(i);
}
- for (UInt i = 0; i < nb_quadrature_points_sub_2; ++i) {
+ for (Int i = 0; i < nb_quadrature_points_sub_2; ++i) {
J(i + nb_quadrature_points_sub_1) = J_sub_2(i);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline void IntegratorGauss<_ek_igfem, IOF>::integrate(
const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ GhostType ghost_type, const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
"No jacobians for the type "
<< jacobians.printType(type, ghost_type));
const Matrix<Real> & quads = quadrature_points(type, ghost_type);
UInt nb_points = quads.cols();
const Array<Real> & jac_loc = jacobians(type, ghost_type);
Array<Real>::const_matrix_iterator J_it;
Array<Real>::matrix_iterator inte_it;
Array<Real>::const_matrix_iterator f_it;
UInt nb_element;
Array<Real> * filtered_J = NULL;
if (filter_elements != empty_filter) {
nb_element = filter_elements.getSize();
filtered_J = new Array<Real>(0, jac_loc.getNbComponent());
FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type,
filter_elements);
const Array<Real> & cfiltered_J = *filtered_J; // \todo temporary patch
J_it = cfiltered_J.begin_reinterpret(nb_points, 1, nb_element);
} else {
nb_element = mesh.getNbElement(type, ghost_type);
J_it = jac_loc.begin_reinterpret(nb_points, 1, nb_element);
}
intf.resize(nb_element);
f_it = in_f.begin_reinterpret(nb_degree_of_freedom, nb_points, nb_element);
inte_it = intf.begin_reinterpret(nb_degree_of_freedom, 1, nb_element);
- for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) {
+ for (Int el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) {
const Matrix<Real> & f = *f_it;
const Matrix<Real> & J = *J_it;
Matrix<Real> & inte_f = *inte_it;
inte_f.mul<false, false>(f, J);
}
delete filtered_J;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline Real IntegratorGauss<_ek_igfem, IOF>::integrate(
const Array<Real> & in_f, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
"No jacobians for the type "
<< jacobians.printType(type, ghost_type));
Array<Real> intfv(0, 1);
integrate<type>(in_f, intfv, 1, ghost_type, filter_elements);
UInt nb_values = intfv.getSize();
if (nb_values == 0)
return 0.;
UInt nb_values_to_sum = nb_values >> 1;
std::sort(intfv.begin(), intfv.end());
// as long as the half is not empty
while (nb_values_to_sum) {
UInt remaining = (nb_values - 2 * nb_values_to_sum);
if (remaining)
intfv(nb_values - 2) += intfv(nb_values - 1);
// sum to consecutive values and store the sum in the first half
- for (UInt i = 0; i < nb_values_to_sum; ++i) {
+ for (Int i = 0; i < nb_values_to_sum; ++i) {
intfv(i) = intfv(2 * i) + intfv(2 * i + 1);
}
nb_values = nb_values_to_sum;
nb_values_to_sum >>= 1;
}
AKANTU_DEBUG_OUT();
return intfv(0);
}
/* -------------------------------------------------------------------------- */
template <class IOF>
template <ElementType type>
inline void IntegratorGauss<_ek_igfem, IOF>::integrateOnIntegrationPoints(
const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ GhostType ghost_type, const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
"No jacobians for the type "
<< jacobians.printType(type, ghost_type));
UInt nb_element;
const Matrix<Real> & quads = quadrature_points(type, ghost_type);
UInt nb_points = quads.cols();
const Array<Real> & jac_loc = jacobians(type, ghost_type);
Array<Real>::const_scalar_iterator J_it;
Array<Real>::vector_iterator inte_it;
Array<Real>::const_vector_iterator f_it;
Array<Real> * filtered_J = NULL;
if (filter_elements != empty_filter) {
nb_element = filter_elements.getSize();
filtered_J = new Array<Real>(0, jac_loc.getNbComponent());
FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type,
filter_elements);
J_it = filtered_J->begin();
} else {
nb_element = mesh.getNbElement(type, ghost_type);
J_it = jac_loc.begin();
}
intf.resize(nb_element * nb_points);
f_it = in_f.begin(nb_degree_of_freedom);
inte_it = intf.begin(nb_degree_of_freedom);
- for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) {
+ for (Int el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) {
const Real & J = *J_it;
const Vector<Real> & f = *f_it;
Vector<Real> & inte_f = *inte_it;
inte_f = f;
inte_f *= J;
}
delete filtered_J;
AKANTU_DEBUG_OUT();
}
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem.cc b/extra_packages/igfem/src/material_igfem/material_igfem.cc
index dceb3322f..d8ef0138e 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem.cc
+++ b/extra_packages/igfem/src/material_igfem/material_igfem.cc
@@ -1,367 +1,367 @@
/**
* @file element_class_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
*
* @brief Implementation parent material for IGFEM
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
#include "material_igfem.hh"
#include "aka_math.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
MaterialIGFEM::MaterialIGFEM(SolidMechanicsModel & model, const ID & id)
: Material(model, id), nb_sub_materials(2),
sub_material("sub_material", *this), name_sub_mat_1(""),
name_sub_mat_2("") {
AKANTU_DEBUG_IN();
this->model = dynamic_cast<SolidMechanicsModelIGFEM *>(&model);
this->fem = &(model.getFEEngineClass<MyFEEngineIGFEMType>("IGFEMFEEngine"));
this->model->getMesh().initElementTypeMapArray(
element_filter, 1, spatial_dimension, false, _ek_igfem);
this->initialize();
AKANTU_DEBUG_OUT();
};
/* -------------------------------------------------------------------------- */
MaterialIGFEM::~MaterialIGFEM() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MaterialIGFEM::initialize() {
this->gradu.setElementKind(_ek_igfem);
this->stress.setElementKind(_ek_igfem);
this->eigengradu.setElementKind(_ek_igfem);
this->gradu.setFEEngine(*fem);
this->stress.setFEEngine(*fem);
this->eigengradu.setFEEngine(*fem);
registerParam("name_sub_mat_1", name_sub_mat_1, std::string(),
_pat_parsable | _pat_readable);
registerParam("name_sub_mat_2", name_sub_mat_2, std::string(),
_pat_parsable | _pat_readable);
this->sub_material.initialize(1);
}
/* -------------------------------------------------------------------------- */
void MaterialIGFEM::computeQuadraturePointsCoordinates(
ElementTypeMapArray<Real> & quadrature_points_coordinates,
GhostType ghost_type) const {
AKANTU_DEBUG_IN();
/// compute quadrature points position in undeformed configuration
Array<Real> & nodes_coordinates = this->fem->getMesh().getNodes();
Mesh::type_iterator it =
this->element_filter.firstType(spatial_dimension, ghost_type, _ek_igfem);
Mesh::type_iterator last_type =
this->element_filter.lastType(spatial_dimension, ghost_type, _ek_igfem);
for (; it != last_type; ++it) {
- const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type);
+ const Array<Idx> & elem_filter = this->element_filter(*it, ghost_type);
UInt nb_element = elem_filter.getSize();
if (nb_element) {
UInt nb_tot_quad =
this->fem->getNbIntegrationPoints(*it, ghost_type) * nb_element;
Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
quads.resize(nb_tot_quad);
this->model->getFEEngine("IGFEMFEEngine")
.interpolateOnIntegrationPoints(nodes_coordinates, quads,
spatial_dimension, *it, ghost_type,
elem_filter);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Compute the stress from the gradu
*
* @param[in] current_position nodes postition + displacements
* @param[in] ghost_type compute the residual for _ghost or _not_ghost element
*/
void MaterialIGFEM::computeAllStresses(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model->getSpatialDimension();
+ Int spatial_dimension = model->getSpatialDimension();
Mesh::type_iterator it =
this->fem->getMesh().firstType(spatial_dimension, ghost_type, _ek_igfem);
Mesh::type_iterator last_type =
this->fem->getMesh().lastType(spatial_dimension, ghost_type, _ek_igfem);
for (; it != last_type; ++it) {
- Array<UInt> & elem_filter = element_filter(*it, ghost_type);
+ Array<Idx> & elem_filter = element_filter(*it, ghost_type);
if (elem_filter.getSize()) {
Array<Real> & gradu_vect = gradu(*it, ghost_type);
/// compute @f$\nabla u@f$
this->fem->gradientOnIntegrationPoints(model->getDisplacement(),
gradu_vect, spatial_dimension, *it,
ghost_type, elem_filter);
gradu_vect -= eigengradu(*it, ghost_type);
/// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$
computeStress(*it, ghost_type);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/// extrapolate internal values
void MaterialIGFEM::extrapolateInternal(const ID & id, const Element & element,
const Matrix<Real> & point,
Matrix<Real> & extrapolated) {
if (this->isInternal<Real>(id, element.kind)) {
UInt nb_element =
this->element_filter(element.type, element.ghost_type).getSize();
const ID name = this->getID() + ":" + id;
UInt nb_quads =
this->internal_vectors_real[name]->getFEEngine().getNbIntegrationPoints(
element.type, element.ghost_type);
const Array<Real> & internal =
this->getArray<Real>(id, element.type, element.ghost_type);
UInt nb_component = internal.getNbComponent();
Array<Real>::const_matrix_iterator internal_it =
internal.begin_reinterpret(nb_component, nb_quads, nb_element);
Element local_element = this->convertToLocalElement(element);
/// instead of really extrapolating, here the value of the first GP
/// is copied into the result vector. This works only for linear
/// elements
/// @todo extrapolate!!!!
AKANTU_DEBUG_WARNING("This is a fix, values are not truly extrapolated");
const Matrix<Real> & values = internal_it[local_element.element];
UInt index = 0;
Vector<Real> tmp(nb_component);
- for (UInt j = 0; j < values.cols(); ++j) {
+ for (Int j = 0; j < values.cols(); ++j) {
tmp = values(j);
if (tmp.norm() > Math::getTolerance()) {
index = j;
break;
}
}
- for (UInt i = 0; i < extrapolated.size(); ++i) {
+ for (Int i = 0; i < extrapolated.size(); ++i) {
extrapolated(i) = values(index);
}
} else {
Matrix<Real> default_values(extrapolated.rows(), extrapolated.cols(), 0.);
extrapolated = default_values;
}
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void MaterialIGFEM::setSubMaterial(const Array<Element> & element_list,
GhostType ghost_type) {
AKANTU_DEBUG_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
template <>
void MaterialIGFEM::setSubMaterial<_igfem_triangle_5>(
const Array<Element> & element_list, GhostType ghost_type) {
SolidMechanicsModelIGFEM * igfem_model =
static_cast<SolidMechanicsModelIGFEM *>(this->model);
Vector<UInt> sub_material_index(this->nb_sub_materials);
Array<Element>::const_iterator<Element> el_begin = element_list.begin();
Array<Element>::const_iterator<Element> el_end = element_list.end();
const Mesh & mesh = this->model->getMesh();
Array<Real> nodes_coordinates(mesh.getNodes(), true);
Array<Real>::const_vector_iterator nodes_it =
nodes_coordinates.begin(spatial_dimension);
Element el;
el.kind = _ek_igfem;
el.type = _igfem_triangle_5;
el.ghost_type = ghost_type;
UInt nb_nodes_per_el = mesh.getNbNodesPerElement(el.type);
UInt nb_parent_nodes = IGFEMHelper::getNbParentNodes(el.type);
Vector<bool> is_inside(nb_parent_nodes);
- const Array<UInt> & connectivity = mesh.getConnectivity(el.type, ghost_type);
- Array<UInt>::const_vector_iterator connec_it =
+ const Array<Idx> & connectivity = mesh.getConnectivity(el.type, ghost_type);
+ Array<Idx>::const_vector_iterator connec_it =
connectivity.begin(nb_nodes_per_el);
/// get the number of quadrature points for the two sub-elements
UInt quads_1 = IGFEMHelper::getNbQuadraturePoints(el.type, 0);
UInt quads_2 = IGFEMHelper::getNbQuadraturePoints(el.type, 1);
UInt nb_total_quads = quads_1 + quads_2;
- UInt * sub_mat_ptr = this->sub_material(el.type, ghost_type).storage();
+ UInt * sub_mat_ptr = this->sub_material(el.type, ghost_type).data();
/// loop all elements for the given type
- const Array<UInt> & filter = this->element_filter(el.type, ghost_type);
+ const Array<Idx> & filter = this->element_filter(el.type, ghost_type);
UInt nb_elements = filter.getSize();
- for (UInt e = 0; e < nb_elements; ++e, ++connec_it) {
+ for (Int e = 0; e < nb_elements; ++e, ++connec_it) {
el.element = filter(e);
if (std::find(el_begin, el_end, el) == el_end) {
sub_mat_ptr += nb_total_quads;
continue;
}
- for (UInt i = 0; i < nb_parent_nodes; ++i) {
+ for (Int i = 0; i < nb_parent_nodes; ++i) {
Vector<Real> node = nodes_it[(*connec_it)(i)];
is_inside(i) = igfem_model->isInside(node, this->name_sub_mat_1);
}
UInt orientation = IGFEMHelper::getElementOrientation(el.type, is_inside);
switch (orientation) {
case 0: {
sub_material_index(0) = 0;
sub_material_index(1) = 1;
break;
}
case 1: {
sub_material_index(0) = 1;
sub_material_index(1) = 0;
break;
}
case 2: {
sub_material_index(0) = 0;
sub_material_index(1) = 0;
break;
}
case 3: {
sub_material_index(0) = 1;
sub_material_index(0) = 1;
break;
}
}
- for (UInt q = 0; q < quads_1; ++q, ++sub_mat_ptr) {
+ for (Int q = 0; q < quads_1; ++q, ++sub_mat_ptr) {
UInt index = sub_material_index(0);
*sub_mat_ptr = index;
}
- for (UInt q = 0; q < quads_2; ++q, ++sub_mat_ptr) {
+ for (Int q = 0; q < quads_2; ++q, ++sub_mat_ptr) {
UInt index = sub_material_index(1);
*sub_mat_ptr = index;
}
}
}
/* -------------------------------------------------------------------------- */
template <>
void MaterialIGFEM::setSubMaterial<_igfem_triangle_4>(
const Array<Element> & element_list, GhostType ghost_type) {
SolidMechanicsModelIGFEM * igfem_model =
static_cast<SolidMechanicsModelIGFEM *>(this->model);
Vector<UInt> sub_material_index(this->nb_sub_materials);
Array<Element>::const_iterator<Element> el_begin = element_list.begin();
Array<Element>::const_iterator<Element> el_end = element_list.end();
const Mesh & mesh = this->model->getMesh();
Element el;
el.kind = _ek_igfem;
el.ghost_type = ghost_type;
el.type = _igfem_triangle_4;
UInt nb_nodes_per_el = mesh.getNbNodesPerElement(el.type);
Vector<Real> barycenter(spatial_dimension);
- const Array<UInt> & connectivity = mesh.getConnectivity(el.type, ghost_type);
- Array<UInt>::const_vector_iterator connec_it =
+ const Array<Idx> & connectivity = mesh.getConnectivity(el.type, ghost_type);
+ Array<Idx>::const_vector_iterator connec_it =
connectivity.begin(nb_nodes_per_el);
/// get the number of quadrature points for the two sub-elements
UInt quads_1 = IGFEMHelper::getNbQuadraturePoints(el.type, 0);
UInt quads_2 = IGFEMHelper::getNbQuadraturePoints(el.type, 1);
UInt nb_total_quads = quads_1 + quads_2;
- UInt * sub_mat_ptr = this->sub_material(el.type, ghost_type).storage();
+ UInt * sub_mat_ptr = this->sub_material(el.type, ghost_type).data();
/// loop all elements for the given type
- const Array<UInt> & filter = this->element_filter(el.type, ghost_type);
+ const Array<Idx> & filter = this->element_filter(el.type, ghost_type);
UInt nb_elements = filter.getSize();
- for (UInt e = 0; e < nb_elements; ++e, ++connec_it) {
+ for (Int e = 0; e < nb_elements; ++e, ++connec_it) {
el.element = filter(e);
if (std::find(el_begin, el_end, el) == el_end) {
sub_mat_ptr += nb_total_quads;
continue;
}
- for (UInt s = 0; s < this->nb_sub_materials; ++s) {
+ for (Int s = 0; s < this->nb_sub_materials; ++s) {
igfem_model->getSubElementBarycenter(el.element, s, el.type, barycenter,
ghost_type);
sub_material_index(s) =
1 - igfem_model->isInside(barycenter, this->name_sub_mat_1);
}
- for (UInt q = 0; q < quads_1; ++q, ++sub_mat_ptr) {
+ for (Int q = 0; q < quads_1; ++q, ++sub_mat_ptr) {
UInt index = sub_material_index(0);
*sub_mat_ptr = index;
}
- for (UInt q = 0; q < quads_2; ++q, ++sub_mat_ptr) {
+ for (Int q = 0; q < quads_2; ++q, ++sub_mat_ptr) {
UInt index = sub_material_index(1);
*sub_mat_ptr = index;
}
}
}
/* -------------------------------------------------------------------------- */
void MaterialIGFEM::applyEigenGradU(
const Matrix<Real> & prescribed_eigen_grad_u, const ID & id,
const GhostType ghost_type) {
std::map<UInt, ID>::const_iterator sub_mat_it =
this->sub_material_names.begin();
for (; sub_mat_it != sub_material_names.end(); ++sub_mat_it) {
if (sub_mat_it->second == id) {
UInt sub_element_index = sub_mat_it->first;
- ElementTypeMapArray<UInt>::type_iterator it =
+ ElementTypeMapArray<Idx>::type_iterator it =
this->element_filter.firstType(_all_dimensions, ghost_type,
_ek_not_defined);
- ElementTypeMapArray<UInt>::type_iterator end =
+ ElementTypeMapArray<Idx>::type_iterator end =
element_filter.lastType(_all_dimensions, ghost_type, _ek_not_defined);
for (; it != end; ++it) {
ElementType type = *it;
if (!element_filter(type, ghost_type).getSize())
continue;
Array<Real>::matrix_iterator eigen_it =
this->eigengradu(type, ghost_type)
.begin(spatial_dimension, spatial_dimension);
Array<Real>::matrix_iterator eigen_end =
this->eigengradu(type, ghost_type)
.end(spatial_dimension, spatial_dimension);
- UInt * sub_mat_ptr = this->sub_material(type, ghost_type).storage();
+ UInt * sub_mat_ptr = this->sub_material(type, ghost_type).data();
for (; eigen_it != eigen_end; ++eigen_it, ++sub_mat_ptr) {
if (*sub_mat_ptr == sub_element_index) {
Matrix<Real> & current_eigengradu = *eigen_it;
current_eigengradu = prescribed_eigen_grad_u;
}
}
}
}
}
}
} // namespace akantu
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem.hh b/extra_packages/igfem/src/material_igfem/material_igfem.hh
index 1d708d2ec..fe3d02c04 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem.hh
+++ b/extra_packages/igfem/src/material_igfem/material_igfem.hh
@@ -1,134 +1,134 @@
/**
* @file element_class_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
*
* @brief Parent material for IGFEM
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "igfem_internal_field.hh"
#include "material.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_IGFEM_HH_
#define AKANTU_MATERIAL_IGFEM_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class SolidMechanicsModelIGFEM;
}
namespace akantu {
class MaterialIGFEM : public virtual Material {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem>
MyFEEngineIGFEMType;
MaterialIGFEM(SolidMechanicsModel & model, const ID & id = "");
virtual ~MaterialIGFEM();
protected:
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
virtual void computeAllStresses(GhostType ghost_type = _not_ghost);
virtual void extrapolateInternal(const ID & id, const Element & element,
const Matrix<Real> & point,
Matrix<Real> & extrapolated);
/// apply a constant eigengrad_u everywhere in the material
virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
const ID & sub_mat_name,
const GhostType = _not_ghost);
/* ------------------------------------------------------------------------ */
/* MeshEventHandler inherited members */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
virtual void computeQuadraturePointsCoordinates(
ElementTypeMapArray<Real> & quadrature_points_coordinates,
GhostType ghost_type) const;
// virtual void onElementsAdded(const Array<Element> & element_list,
// const NewElementsEvent & event) {};
// virtual void onElementsRemoved(const Array<Element> & element_list,
- // const ElementTypeMapArray<UInt> &
+ // const ElementTypeMapArray<Idx> &
// new_numbering,
// const RemovedElementsEvent & event) {};
protected:
/// constitutive law
virtual void computeStress(__attribute__((unused)) ElementType el_type,
__attribute__((unused))
GhostType ghost_type = _not_ghost) {}
void initialize();
template <ElementType type>
void setSubMaterial(const Array<Element> & element_list,
GhostType ghost_type);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
virtual inline UInt getNbDataForElements(const Array<Element> & elements,
SynchronizationTag tag) const;
virtual inline void packElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) const;
virtual inline void unpackElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
const UInt nb_sub_materials;
/// pointer to the solid mechanics model for igfem elements
SolidMechanicsModelIGFEM * model;
/// internal field of bool to know to which sub-material a quad point belongs
IGFEMInternalField<UInt> sub_material;
/// material name of first sub-material
std::string name_sub_mat_1;
/// material name of first sub-material
std::string name_sub_mat_2;
/// map the index of the sub-materials to the names
std::map<UInt, ID> sub_material_names;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_igfem_inline_impl.hh"
} // namespace akantu
#include "igfem_internal_field_tmpl.hh"
#endif /* AKANTU_MATERIAL_IGFEM_HH_ */
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_elastic.cc b/extra_packages/igfem/src/material_igfem/material_igfem_elastic.cc
index 16413e09b..8e047939f 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_elastic.cc
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_elastic.cc
@@ -1,240 +1,240 @@
/**
* @file material_igfem_elastic.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Specializaton of material class for the igfem elastic material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_elastic.hh"
#include "material_elastic.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialIGFEMElastic<dim>::MaterialIGFEMElastic(SolidMechanicsModel & model,
const ID & id)
: Material(model, id), Parent(model, id), lambda("lambda", *this),
mu("mu", *this), kpa("kappa", *this) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialIGFEMElastic<dim>::initialize() {
+template <Int dim> void MaterialIGFEMElastic<dim>::initialize() {
this->lambda.initialize(1);
this->mu.initialize(1);
this->kpa.initialize(1);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialIGFEMElastic<dim>::initMaterial() {
+template <Int dim> void MaterialIGFEMElastic<dim>::initMaterial() {
AKANTU_DEBUG_IN();
Parent::initMaterial();
/// insert the sub_material names into the map
this->sub_material_names[0] = this->name_sub_mat_1;
this->sub_material_names[1] = this->name_sub_mat_2;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMElastic<spatial_dimension>::updateElasticInternals(
const Array<Element> & element_list) {
/// compute the Lamé constants for both sub-materials
Vector<Real> lambda_per_sub_mat(this->nb_sub_materials);
Vector<Real> mu_per_sub_mat(this->nb_sub_materials);
Vector<Real> kpa_per_sub_mat(this->nb_sub_materials);
- for (UInt i = 0; i < this->nb_sub_materials; ++i) {
+ for (Int i = 0; i < this->nb_sub_materials; ++i) {
ID mat_name = this->sub_material_names[i];
const MaterialElastic<spatial_dimension> & mat =
dynamic_cast<MaterialElastic<spatial_dimension> &>(
this->model->getMaterial(mat_name));
lambda_per_sub_mat(i) = mat.getLambda();
mu_per_sub_mat(i) = mat.getMu();
kpa_per_sub_mat(i) = mat.getKappa();
}
for (ghost_type_t::iterator g = ghost_type_t::begin();
g != ghost_type_t::end(); ++g) {
GhostType ghost_type = *g;
/// loop over all types in the material
- typedef ElementTypeMapArray<UInt>::type_iterator iterator;
+ typedef ElementTypeMapArray<Idx>::type_iterator iterator;
iterator it = this->element_filter.firstType(spatial_dimension, ghost_type,
_ek_igfem);
iterator last_type =
this->element_filter.lastType(spatial_dimension, ghost_type, _ek_igfem);
/// loop over all types in the filter
for (; it != last_type; ++it) {
ElementType el_type = *it;
if (el_type == _igfem_triangle_4)
this->template setSubMaterial<_igfem_triangle_4>(element_list,
ghost_type);
else if (el_type == _igfem_triangle_5)
this->template setSubMaterial<_igfem_triangle_5>(element_list,
ghost_type);
else
AKANTU_ERROR("There is currently no other IGFEM type implemented");
UInt nb_element = this->element_filter(el_type, ghost_type).getSize();
UInt nb_quads = this->fem->getNbIntegrationPoints(el_type);
/// get pointer to internals for given type
- Real * lambda_ptr = this->lambda(el_type, ghost_type).storage();
- Real * mu_ptr = this->mu(el_type, ghost_type).storage();
- Real * kpa_ptr = this->kpa(el_type, ghost_type).storage();
- UInt * sub_mat_ptr = this->sub_material(el_type, ghost_type).storage();
- for (UInt q = 0; q < nb_element * nb_quads;
+ Real * lambda_ptr = this->lambda(el_type, ghost_type).data();
+ Real * mu_ptr = this->mu(el_type, ghost_type).data();
+ Real * kpa_ptr = this->kpa(el_type, ghost_type).data();
+ UInt * sub_mat_ptr = this->sub_material(el_type, ghost_type).data();
+ for (Int q = 0; q < nb_element * nb_quads;
++q, ++lambda_ptr, ++mu_ptr, ++kpa_ptr, ++sub_mat_ptr) {
UInt index = *sub_mat_ptr;
*lambda_ptr = lambda_per_sub_mat(index);
*mu_ptr = mu_per_sub_mat(index);
*kpa_ptr = kpa_per_sub_mat(index);
}
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMElastic<spatial_dimension>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Parent::computeStress(el_type, ghost_type);
if (!this->finite_deformation) {
/// get pointer to internals
- Real * lambda_ptr = this->lambda(el_type, ghost_type).storage();
- Real * mu_ptr = this->mu(el_type, ghost_type).storage();
+ Real * lambda_ptr = this->lambda(el_type, ghost_type).data();
+ Real * mu_ptr = this->mu(el_type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
this->computeStressOnQuad(grad_u, sigma, *lambda_ptr, *mu_ptr);
++lambda_ptr;
++mu_ptr;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
} else {
AKANTU_DEBUG_TO_IMPLEMENT();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMElastic<spatial_dimension>::computeTangentModuli(
__attribute__((unused)) ElementType el_type, Array<Real> & tangent_matrix,
__attribute__((unused)) GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// get pointer to internals
- Real * lambda_ptr = this->lambda(el_type, ghost_type).storage();
- Real * mu_ptr = this->mu(el_type, ghost_type).storage();
+ Real * lambda_ptr = this->lambda(el_type, ghost_type).data();
+ Real * mu_ptr = this->mu(el_type, ghost_type).data();
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
this->computeTangentModuliOnQuad(tangent, *lambda_ptr, *mu_ptr);
++lambda_ptr;
++mu_ptr;
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMElastic<spatial_dimension>::computePotentialEnergy(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
// MaterialThermal<spatial_dimension>::computePotentialEnergy(el_type,
// ghost_type);
// if(ghost_type != _not_ghost) return;
// Array<Real>::scalar_iterator epot = this->potential_energy(el_type,
// ghost_type).begin();
// if (!this->finite_deformation) {
// MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
// this->computePotentialEnergyOnQuad(grad_u, sigma, *epot);
// ++epot;
// MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
// } else {
// Matrix<Real> E(spatial_dimension, spatial_dimension);
// MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
// this->template gradUToGreenStrain<spatial_dimension>(grad_u, E);
// this->computePotentialEnergyOnQuad(E, sigma, *epot);
// ++epot;
// MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
// }
AKANTU_DEBUG_TO_IMPLEMENT();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMElastic<spatial_dimension>::computePotentialEnergyByElement(
ElementType type, UInt index, Vector<Real> & epot_on_quad_points) {
// Array<Real>::matrix_iterator gradu_it =
// this->gradu(type).begin(spatial_dimension,
// spatial_dimension);
// Array<Real>::matrix_iterator gradu_end =
// this->gradu(type).begin(spatial_dimension,
// spatial_dimension);
// Array<Real>::matrix_iterator stress_it =
// this->stress(type).begin(spatial_dimension,
// spatial_dimension);
// if (this->finite_deformation)
// stress_it = this->piola_kirchhoff_2(type).begin(spatial_dimension,
// spatial_dimension);
// UInt nb_quadrature_points =
// this->model->getFEEngine().getNbQuadraturePoints(type);
// gradu_it += index*nb_quadrature_points;
// gradu_end += (index+1)*nb_quadrature_points;
// stress_it += index*nb_quadrature_points;
- // Real * epot_quad = epot_on_quad_points.storage();
+ // Real * epot_quad = epot_on_quad_points.data();
// Matrix<Real> grad_u(spatial_dimension, spatial_dimension);
// for(;gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) {
// if (this->finite_deformation)
// this->template gradUToGreenStrain<spatial_dimension>(*gradu_it,
// grad_u);
// else
// grad_u.copy(*gradu_it);
// this->computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad);
// }
AKANTU_DEBUG_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMElastic<spatial_dimension>::onElementsAdded(
const Array<Element> & element_list, const NewElementsEvent & event) {
Parent::onElementsAdded(element_list, event);
updateElasticInternals(element_list);
};
INSTANTIATE_MATERIAL(MaterialIGFEMElastic);
} // namespace akantu
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_elastic.hh b/extra_packages/igfem/src/material_igfem/material_igfem_elastic.hh
index 2e1497b32..222e2b4da 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_elastic.hh
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_elastic.hh
@@ -1,129 +1,129 @@
/**
* @file element_class_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
*
* @brief Material isotropic elastic for IGFEM
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_igfem.hh"
#include "plane_stress_toolbox.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_IGFEM_ELASTIC_HH_
#define AKANTU_MATERIAL_IGFEM_ELASTIC_HH_
namespace akantu {
/**
* Material elastic isotropic
*
* parameters in the material files :
* - E : Young's modulus (default: 0)
* - nu : Poisson's ratio (default: 1/2)
* - Plane_Stress : if 0: plane strain, else: plane stress (default: 0)
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialIGFEMElastic
: public PlaneStressToolbox<spatial_dimension, MaterialIGFEM> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
private:
typedef PlaneStressToolbox<spatial_dimension, MaterialIGFEM> Parent;
public:
MaterialIGFEMElastic(SolidMechanicsModel & model, const ID & id = "");
- MaterialIGFEMElastic(SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
+ MaterialIGFEMElastic(SolidMechanicsModel & model, Int dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id = "");
virtual ~MaterialIGFEMElastic() {}
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
virtual void initMaterial();
/// constitutive law for all element of a type
virtual void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
/// compute the tangent stiffness matrix for an element type
virtual void computeTangentModuli(ElementType el_type,
Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost);
/// compute the elastic potential energy
virtual void computePotentialEnergy(ElementType el_type,
GhostType ghost_type = _not_ghost);
virtual void
computePotentialEnergyByElement(ElementType type, UInt index,
Vector<Real> & epot_on_quad_points);
void updateElasticInternals(const Array<Element> & element_list);
protected:
/// constitutive law for a given quadrature point
inline void computeStressOnQuad(const Matrix<Real> & grad_u,
Matrix<Real> & sigma,
__attribute__((unused)) const Real lambda,
const Real mu) const;
/// compute the tangent stiffness matrix for an element
inline void computeTangentModuliOnQuad(Matrix<Real> & tangent,
__attribute__((unused))
const Real lambda,
const Real mu) const;
static inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u,
const Matrix<Real> & sigma,
Real & epot);
/* ------------------------------------------------------------------------ */
/* MeshEventHandler inherited members */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
virtual void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// First Lamé coefficient
IGFEMInternalField<Real> lambda;
/// Second Lamé coefficient (shear modulus)
IGFEMInternalField<Real> mu;
/// Bulk modulus
IGFEMInternalField<Real> kpa;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_igfem_elastic_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_IGFEM_ELASTIC_HH_ */
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_elastic_inline_impl.hh b/extra_packages/igfem/src/material_igfem/material_igfem_elastic_inline_impl.hh
index 54fe6cada..68cf86c4f 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_elastic_inline_impl.hh
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_elastic_inline_impl.hh
@@ -1,91 +1,91 @@
/**
* @file material_igfem_elastic_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Implementation of the inline functions of the material igfem elastic
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialIGFEMElastic<spatial_dimension>::computeStressOnQuad(
const Matrix<Real> & grad_u, Matrix<Real> & sigma, const Real lambda,
const Real mu) const {
Real trace = grad_u.trace(); // trace = (\nabla u)_{kk}
// \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla
// u_{ij} + \nabla u_{ji})
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = 0; j < spatial_dimension; ++j) {
sigma(i, j) =
(i == j) * lambda * trace + mu * (grad_u(i, j) + grad_u(j, i));
}
}
}
/* -------------------------------------------------------------------------- */
template <>
inline void MaterialIGFEMElastic<1>::computeStressOnQuad(
const Matrix<Real> & grad_u, Matrix<Real> & sigma, const Real lambda,
const Real mu) const {
sigma(0, 0) = 2 * mu * grad_u(0, 0);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void MaterialIGFEMElastic<spatial_dimension>::computeTangentModuliOnQuad(
Matrix<Real> & tangent, const Real lambda, const Real mu) const {
UInt n = tangent.cols();
// Real Ep = E/((1+nu)*(1-2*nu));
Real Miiii = lambda + 2 * mu;
Real Miijj = lambda;
Real Mijij = mu;
if (spatial_dimension == 1)
tangent(0, 0) = 3 * mu;
else
tangent(0, 0) = Miiii;
// test of dimension should by optimized out by the compiler due to the
// template
if (spatial_dimension >= 2) {
tangent(1, 1) = Miiii;
tangent(0, 1) = Miijj;
tangent(1, 0) = Miijj;
tangent(n - 1, n - 1) = Mijij;
}
if (spatial_dimension == 3) {
tangent(2, 2) = Miiii;
tangent(0, 2) = Miijj;
tangent(1, 2) = Miijj;
tangent(2, 0) = Miijj;
tangent(2, 1) = Miijj;
tangent(3, 3) = Mijij;
tangent(4, 4) = Mijij;
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
inline void MaterialIGFEMElastic<dim>::computePotentialEnergyOnQuad(
const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot) {
AKANTU_DEBUG_TO_IMPLEMENT();
/// epot = .5 * sigma.doubleDot(grad_u);
}
/* -------------------------------------------------------------------------- */
template <>
inline void MaterialIGFEMElastic<1>::computeTangentModuliOnQuad(
Matrix<Real> & tangent, const Real lambda, const Real mu) const {
tangent(0, 0) = 2 * mu;
}
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.cc b/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.cc
index fbec0e9f9..a133cecc1 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.cc
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.cc
@@ -1,288 +1,288 @@
/**
* @file material_igfem_iterative_stiffness_reduction.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Mar 10 08:37:43 2016
*
* @brief Implementation of igfem material iterative stiffness reduction
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_iterative_stiffness_reduction.hh"
#include <math.h>
namespace akantu {
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
/* -------------------------------------------------------------------------- */
MaterialIGFEMIterativeStiffnessReduction<spatial_dimension>::
MaterialIGFEMIterativeStiffnessReduction(SolidMechanicsModel & model,
const ID & id)
: Material(model, id), MaterialIGFEMSawToothDamage<spatial_dimension>(model,
id),
eps_u("ultimate_strain", *this), reduction_step("damage_step", *this),
D("tangent", *this), Gf(0.), crack_band_width(0.), max_reductions(0),
reduction_constant(0.) {
AKANTU_DEBUG_IN();
this->eps_u.initialize(1);
this->D.initialize(1);
this->reduction_step.initialize(1);
this->internals_to_transfer.push_back("ultimate_strain");
this->internals_to_transfer.push_back("tangent");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialIGFEMIterativeStiffnessReduction<dim>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialIGFEMSawToothDamage<dim>::initMaterial();
/// get the parameters for the sub-material that can be damaged
ID mat_name = this->sub_material_names[1];
const Material & mat = this->model->getMaterial(mat_name);
this->crack_band_width = mat.getParam<Real>("crack_band_width");
this->max_reductions = mat.getParam<UInt>("max_reductions");
this->reduction_constant = mat.getParam<Real>("reduction_constant");
this->Gf = mat.getParam<Real>("Gf");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMIterativeStiffnessReduction<spatial_dimension>::
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// storage for the current stress
Matrix<Real> sigma(spatial_dimension, spatial_dimension);
/// Vector to store eigenvalues of current stress tensor
Vector<Real> eigenvalues(spatial_dimension);
/// iterators on the needed internal fields
Array<Real>::const_scalar_iterator Sc_it =
this->Sc(el_type, ghost_type).begin();
Array<Real>::scalar_iterator dam_it =
this->damage(el_type, ghost_type).begin();
Array<Real>::scalar_iterator equivalent_stress_it =
this->equivalent_stress(el_type, ghost_type).begin();
Array<Real>::const_matrix_iterator grad_u_it =
grad_u.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_matrix_iterator grad_u_end =
grad_u.end(spatial_dimension, spatial_dimension);
- Real * mu_ptr = this->mu(el_type, ghost_type).storage();
- Real * lambda_ptr = this->lambda(el_type, ghost_type).storage();
+ Real * mu_ptr = this->mu(el_type, ghost_type).data();
+ Real * lambda_ptr = this->lambda(el_type, ghost_type).data();
/// loop over all the quadrature points and compute the equivalent stress
for (; grad_u_it != grad_u_end; ++grad_u_it) {
/// compute the stress
sigma.zero();
MaterialIGFEMElastic<spatial_dimension>::computeStressOnQuad(
*grad_u_it, sigma, *lambda_ptr, *mu_ptr);
MaterialIGFEMSawToothDamage<
spatial_dimension>::computeDamageAndStressOnQuad(sigma, *dam_it);
/// compute eigenvalues
sigma.eig(eigenvalues);
/// find max eigenvalue and normalize by tensile strength
*equivalent_stress_it =
- *(std::max_element(eigenvalues.storage(),
- eigenvalues.storage() + spatial_dimension)) /
+ *(std::max_element(eigenvalues.data(),
+ eigenvalues.data() + spatial_dimension)) /
(*Sc_it);
++Sc_it;
++equivalent_stress_it;
++dam_it;
++lambda_ptr;
++mu_ptr;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
UInt MaterialIGFEMIterativeStiffnessReduction<
spatial_dimension>::updateDamage() {
UInt nb_damaged_elements = 0;
if (this->norm_max_equivalent_stress >= 1.) {
AKANTU_DEBUG_IN();
/// update the damage only on non-ghosts elements! Doesn't make sense to
/// update on ghost.
GhostType ghost_type = _not_ghost;
;
Mesh::type_iterator it = this->model->getFEEngine().getMesh().firstType(
spatial_dimension, ghost_type, _ek_igfem);
Mesh::type_iterator last_type =
this->model->getFEEngine().getMesh().lastType(spatial_dimension,
ghost_type, _ek_igfem);
/// get the Young's modulus of the damageable sub-material
ID mat_name = this->sub_material_names[1];
Real E = this->model->getMaterial(mat_name).template getParam<Real>("E");
/// loop over all the elements
for (; it != last_type; ++it) {
ElementType el_type = *it;
/// get iterators on the needed internal fields
- const Array<UInt> & sub_mat = this->sub_material(el_type, ghost_type);
- Array<UInt>::const_scalar_iterator sub_mat_it = sub_mat.begin();
+ const Array<Idx> & sub_mat = this->sub_material(el_type, ghost_type);
+ Array<Idx>::const_scalar_iterator sub_mat_it = sub_mat.begin();
Array<Real>::const_scalar_iterator equivalent_stress_it =
this->equivalent_stress(el_type, ghost_type).begin();
Array<Real>::const_scalar_iterator equivalent_stress_end =
this->equivalent_stress(el_type, ghost_type).end();
Array<Real>::scalar_iterator dam_it =
this->damage(el_type, ghost_type).begin();
- Array<UInt>::scalar_iterator reduction_it =
+ Array<Idx>::scalar_iterator reduction_it =
this->reduction_step(el_type, ghost_type).begin();
Array<Real>::const_scalar_iterator eps_u_it =
this->eps_u(el_type, ghost_type).begin();
Array<Real>::scalar_iterator Sc_it =
this->Sc(el_type, ghost_type).begin();
Array<Real>::const_scalar_iterator D_it =
this->D(el_type, ghost_type).begin();
/// loop over all the elements of the given type
UInt nb_element = this->element_filter(el_type, ghost_type).getSize();
UInt nb_quads = this->fem->getNbIntegrationPoints(el_type, ghost_type);
bool damage_element = false;
- for (UInt e = 0; e < nb_element; ++e) {
+ for (Int e = 0; e < nb_element; ++e) {
damage_element = false;
/// check if damage occurs in the element
- for (UInt q = 0; q < nb_quads;
+ for (Int q = 0; q < nb_quads;
++q, ++reduction_it, ++sub_mat_it, ++equivalent_stress_it) {
if (*equivalent_stress_it >= (1 - this->dam_tolerance) *
this->norm_max_equivalent_stress &&
*sub_mat_it != 0) {
/// check if this element can still be damaged
if (*reduction_it == this->max_reductions)
continue;
damage_element = true;
}
}
if (damage_element) {
/// damage the element
nb_damaged_elements += 1;
sub_mat_it -= nb_quads;
reduction_it -= nb_quads;
- for (UInt q = 0; q < nb_quads; ++q) {
+ for (Int q = 0; q < nb_quads; ++q) {
if (*sub_mat_it) {
/// increment the counter of stiffness reduction steps
*reduction_it += 1;
if (*reduction_it == this->max_reductions)
*dam_it = this->max_damage;
else {
/// update the damage on this quad
*dam_it = 1. - (1. / std::pow(this->reduction_constant,
*reduction_it));
/// update the stiffness on this quad
*Sc_it = (*eps_u_it) * (1. - (*dam_it)) * E * (*D_it) /
((1. - (*dam_it)) * E + (*D_it));
}
}
++sub_mat_it;
++dam_it;
++reduction_it;
++eps_u_it;
++Sc_it;
++D_it;
}
} else {
dam_it += nb_quads;
eps_u_it += nb_quads;
Sc_it += nb_quads;
D_it += nb_quads;
}
}
}
}
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
comm.allReduce(&nb_damaged_elements, 1, _so_sum);
AKANTU_DEBUG_OUT();
return nb_damaged_elements;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMIterativeStiffnessReduction<
spatial_dimension>::onElementsAdded(__attribute__((unused))
const Array<Element> & element_list,
__attribute__((unused))
const NewElementsEvent & event) {
MaterialIGFEMSawToothDamage<spatial_dimension>::onElementsAdded(element_list,
event);
/// set the correct damage iteration step (is UInt->cannot be interpolated)
Real val = 0.;
for (ghost_type_t::iterator g = ghost_type_t::begin();
g != ghost_type_t::end(); ++g) {
GhostType ghost_type = *g;
/// loop over all types in the material
- typedef ElementTypeMapArray<UInt>::type_iterator iterator;
+ typedef ElementTypeMapArray<Idx>::type_iterator iterator;
iterator it = this->element_filter.firstType(spatial_dimension, ghost_type,
_ek_igfem);
iterator last_type =
this->element_filter.lastType(spatial_dimension, ghost_type, _ek_igfem);
/// loop over all types in the filter
for (; it != last_type; ++it) {
const ElementType el_type = *it;
Array<Real>::scalar_iterator dam_it =
this->damage(el_type, ghost_type).begin();
- Array<UInt>::scalar_iterator reduction_it =
+ Array<Idx>::scalar_iterator reduction_it =
this->reduction_step(el_type, ghost_type).begin();
UInt nb_element = this->element_filter(el_type, ghost_type).getSize();
UInt nb_quads = this->fem->getNbIntegrationPoints(el_type);
- UInt * sub_mat_ptr = this->sub_material(el_type, ghost_type).storage();
- for (UInt q = 0; q < nb_element * nb_quads;
+ UInt * sub_mat_ptr = this->sub_material(el_type, ghost_type).data();
+ for (Int q = 0; q < nb_element * nb_quads;
++q, ++sub_mat_ptr, ++dam_it, ++reduction_it) {
if (*sub_mat_ptr) {
if (Math::are_float_equal(*dam_it, this->max_damage))
*reduction_it = this->max_reductions;
else {
- for (UInt i = 0; i < this->max_reductions; ++i) {
+ for (Int i = 0; i < this->max_reductions; ++i) {
val = 1 - (1. / std::pow(this->reduction_constant, i));
if (Math::are_float_equal(val, *dam_it))
*reduction_it = i;
}
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(MaterialIGFEMIterativeStiffnessReduction);
} // namespace akantu
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.hh b/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.hh
index a72e4a6a4..1314fdb52 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.hh
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_iterative_stiffness_reduction.hh
@@ -1,113 +1,113 @@
/**
* @file material_igfem_iterative_stiffness_reduction.hh
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Wed Mar 9 19:44:22 2016
*
* @brief Material for iterative stiffness reduction by contant factor
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_saw_tooth_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_IGFEM_ITERATIVE_STIFFNESS_REDUCTION_HH_
#define AKANTU_MATERIAL_IGFEM_ITERATIVE_STIFFNESS_REDUCTION_HH_
namespace akantu {
/**
* Material damage iterative
*
* parameters in the material files :
* - Gfx
* - h
* - Sc
*/
/// Proposed by Rots and Invernizzi, 2004: Regularized sequentially linear
// saw-tooth softening model (section 4.2)
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialIGFEMIterativeStiffnessReduction
: public MaterialIGFEMSawToothDamage<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialIGFEMIterativeStiffnessReduction(SolidMechanicsModel & model,
const ID & id = "");
virtual ~MaterialIGFEMIterativeStiffnessReduction(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// set the material parameters
virtual void initMaterial();
/// compute the equivalent stress on each Gauss point (i.e. the max prinicpal
/// stress) and normalize it by the tensile stiffness
virtual void
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type = _not_ghost);
/// update internal field damage
virtual UInt updateDamage();
virtual void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// the ultimate strain
IGFEMInternalField<Real> eps_u;
/// the reduction
IGFEMInternalField<UInt> reduction_step;
/// the tangent of the tensile stress-strain softening
IGFEMInternalField<Real> D;
/// fracture energy
Real Gf;
/// crack band width for normalization of fracture energy
Real crack_band_width;
/// the number of total reductions steps until complete failure
UInt max_reductions;
/// the reduction constant (denoated by a in the paper of rots)
Real reduction_constant;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_IGFEM_ITERATIVE_STIFFNESS_REDUCTION_HH_ */
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.cc b/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.cc
index e95cd3dd5..6eb4f1714 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.cc
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.cc
@@ -1,466 +1,466 @@
/**
* @file material_igfem_saw_tooth_damage.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Implementation of the squentially linear saw-tooth damage model for
* IGFEM elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_saw_tooth_damage.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialIGFEMSawToothDamage<dim>::MaterialIGFEMSawToothDamage(
SolidMechanicsModel & model, const ID & id)
: Material(model, id), Parent(model, id), Sc("Sc", *this),
equivalent_stress("equivalent_stress", *this),
norm_max_equivalent_stress(0) {
AKANTU_DEBUG_IN();
this->Sc.initialize(1);
this->equivalent_stress.initialize(1);
this->damage.setElementKind(_ek_igfem);
this->damage.setFEEngine(*(this->fem));
this->internals_to_transfer.push_back("damage");
this->internals_to_transfer.push_back("Sc");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialIGFEMSawToothDamage<dim>::initMaterial() {
+template <Int dim> void MaterialIGFEMSawToothDamage<dim>::initMaterial() {
AKANTU_DEBUG_IN();
Parent::initMaterial();
/// get the parameters for the sub-material that can be damaged
ID mat_name = this->sub_material_names[1];
const Material & mat = this->model->getMaterial(mat_name);
this->prescribed_dam = mat.getParam<Real>("prescribed_dam");
this->dam_threshold = mat.getParam<Real>("dam_threshold");
this->dam_tolerance = mat.getParam<Real>("dam_tolerance");
this->max_damage = mat.getParam<Real>("max_damage");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMSawToothDamage<spatial_dimension>::
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// Vector to store eigenvalues of current stress tensor
Vector<Real> eigenvalues(spatial_dimension);
Array<Real>::const_iterator<Real> Sc_it = Sc(el_type, ghost_type).begin();
Array<Real>::iterator<Real> equivalent_stress_it =
equivalent_stress(el_type, ghost_type).begin();
Array<Real>::const_matrix_iterator grad_u_it =
grad_u.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_matrix_iterator grad_u_end =
grad_u.end(spatial_dimension, spatial_dimension);
/// get pointer to internals
- Real * lambda_ptr = this->lambda(el_type, ghost_type).storage();
- Real * mu_ptr = this->mu(el_type, ghost_type).storage();
- Real * dam = this->damage(el_type, ghost_type).storage();
+ Real * lambda_ptr = this->lambda(el_type, ghost_type).data();
+ Real * mu_ptr = this->mu(el_type, ghost_type).data();
+ Real * dam = this->damage(el_type, ghost_type).data();
Matrix<Real> sigma(spatial_dimension, spatial_dimension);
for (; grad_u_it != grad_u_end; ++grad_u_it) {
MaterialIGFEMElastic<spatial_dimension>::computeStressOnQuad(
*grad_u_it, sigma, *lambda_ptr, *mu_ptr);
computeDamageAndStressOnQuad(sigma, *dam);
/// compute eigenvalues
sigma.eig(eigenvalues);
/// find max eigenvalue and normalize by tensile strength
*equivalent_stress_it =
- *(std::max_element(eigenvalues.storage(),
- eigenvalues.storage() + spatial_dimension)) /
+ *(std::max_element(eigenvalues.data(),
+ eigenvalues.data() + spatial_dimension)) /
*(Sc_it);
++Sc_it;
++equivalent_stress_it;
++dam;
++lambda_ptr;
++mu_ptr;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMSawToothDamage<spatial_dimension>::computeAllStresses(
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// reset normalized maximum equivalent stress
if (ghost_type == _not_ghost)
norm_max_equivalent_stress = 0;
Parent::computeAllStresses(ghost_type);
/// find global Gauss point with highest stress
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
comm.allReduce(&norm_max_equivalent_stress, 1, _so_max);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMSawToothDamage<spatial_dimension>::
findMaxNormalizedEquivalentStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
if (ghost_type == _not_ghost) {
const Array<Real> & e_stress = equivalent_stress(el_type);
Array<Real>::const_iterator<Real> equivalent_stress_it = e_stress.begin();
Array<Real>::const_iterator<Real> equivalent_stress_end = e_stress.end();
Array<Real> & dam = this->damage(el_type);
Array<Real>::iterator<Real> dam_it = dam.begin();
- Array<UInt> & sub_mat = this->sub_material(el_type);
- Array<UInt>::iterator<UInt> sub_mat_it = sub_mat.begin();
+ Array<Idx> & sub_mat = this->sub_material(el_type);
+ Array<Idx>::iterator<UInt> sub_mat_it = sub_mat.begin();
for (; equivalent_stress_it != equivalent_stress_end;
++equivalent_stress_it, ++dam_it, ++sub_mat_it) {
/// check if max equivalent stress for this element type is greater than
/// the current norm_max_eq_stress and if the element is not already fully
/// damaged
if ((*equivalent_stress_it > norm_max_equivalent_stress &&
*dam_it < max_damage) &&
*sub_mat_it != 0) {
norm_max_equivalent_stress = *equivalent_stress_it;
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMSawToothDamage<spatial_dimension>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Parent::computeStress(el_type, ghost_type);
- Real * dam = this->damage(el_type, ghost_type).storage();
+ Real * dam = this->damage(el_type, ghost_type).data();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
computeDamageAndStressOnQuad(sigma, *dam);
++dam;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
computeNormalizedEquivalentStress(this->gradu(el_type, ghost_type), el_type,
ghost_type);
norm_max_equivalent_stress = 0;
findMaxNormalizedEquivalentStress(el_type, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
UInt MaterialIGFEMSawToothDamage<spatial_dimension>::updateDamage() {
UInt nb_damaged_elements = 0;
AKANTU_DEBUG_ASSERT(prescribed_dam > 0.,
"Your prescribed damage must be greater than zero");
if (norm_max_equivalent_stress >= 1.) {
AKANTU_DEBUG_IN();
GhostType ghost_type = _not_ghost;
;
Mesh::type_iterator it = this->model->getMesh().firstType(
spatial_dimension, ghost_type, _ek_igfem);
Mesh::type_iterator last_type = this->model->getMesh().lastType(
spatial_dimension, ghost_type, _ek_igfem);
for (; it != last_type; ++it) {
ElementType el_type = *it;
- Array<UInt> & sub_mat = this->sub_material(el_type);
- Array<UInt>::iterator<UInt> sub_mat_it = sub_mat.begin();
+ Array<Idx> & sub_mat = this->sub_material(el_type);
+ Array<Idx>::iterator<UInt> sub_mat_it = sub_mat.begin();
const Array<Real> & e_stress = equivalent_stress(el_type);
Array<Real>::const_iterator<Real> equivalent_stress_it = e_stress.begin();
Array<Real>::const_iterator<Real> equivalent_stress_end = e_stress.end();
Array<Real> & dam = this->damage(el_type);
Array<Real>::iterator<Real> dam_it = dam.begin();
/// loop over all the elements of the given type
UInt nb_element = this->element_filter(el_type, ghost_type).getSize();
UInt nb_quads = this->fem->getNbIntegrationPoints(el_type, ghost_type);
bool damage_element = false;
for (UInt e = 0; e < nb_element; ++e) {
damage_element = false;
/// check if damage occurs in the element
for (UInt q = 0; q < nb_quads; ++q) {
if (*equivalent_stress_it >=
(1 - dam_tolerance) * norm_max_equivalent_stress &&
*sub_mat_it != 0) {
damage_element = true;
}
++sub_mat_it;
++equivalent_stress_it;
}
if (damage_element) {
nb_damaged_elements += 1;
/// damage the element
sub_mat_it -= nb_quads;
for (UInt q = 0; q < nb_quads; ++q) {
if (*sub_mat_it) {
if (*dam_it < dam_threshold)
*dam_it += prescribed_dam;
else
*dam_it = max_damage;
}
++sub_mat_it;
++dam_it;
}
} else {
dam_it += nb_quads;
}
}
}
}
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
comm.allReduce(&nb_damaged_elements, 1, _so_sum);
AKANTU_DEBUG_OUT();
return nb_damaged_elements;
}
/* -------------------------------------------------------------------------- */
-// template<UInt spatial_dimension>
+// template<Int spatial_dimension>
// void
// MaterialIGFEMSawToothDamage<spatial_dimension>::updateEnergiesAfterDamage(ElementType
// el_type, GhostType ghost_type) {
// MaterialDamage<spatial_dimension>::updateEnergies(el_type, ghost_type);
// }
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialIGFEMSawToothDamage<spatial_dimension>::onElementsAdded(
__attribute__((unused)) const Array<Element> & element_list,
__attribute__((unused)) const NewElementsEvent & event) {
/// update elastic constants
MaterialIGFEMElastic<spatial_dimension>::onElementsAdded(element_list, event);
IGFEMInternalField<Real> quadrature_points_coordinates(
"quadrature_points_coordinates", *this);
quadrature_points_coordinates.initialize(spatial_dimension);
this->computeQuadraturePointsCoordinates(quadrature_points_coordinates,
_not_ghost);
this->computeQuadraturePointsCoordinates(quadrature_points_coordinates,
_ghost);
Array<Element>::const_iterator<Element> el_begin = element_list.begin();
Array<Element>::const_iterator<Element> el_end = element_list.end();
Element el;
el.kind = _ek_igfem;
/// loop over all the elements in the filter
for (ghost_type_t::iterator g = ghost_type_t::begin();
g != ghost_type_t::end(); ++g) {
GhostType ghost_type = *g;
/// loop over all types in the material
- typedef ElementTypeMapArray<UInt>::type_iterator iterator;
+ typedef ElementTypeMapArray<Idx>::type_iterator iterator;
iterator it = this->element_filter.firstType(spatial_dimension, ghost_type,
_ek_igfem);
iterator last_type =
this->element_filter.lastType(spatial_dimension, ghost_type, _ek_igfem);
for (; it != last_type; ++it) {
/// store the elements added to this material
std::vector<Element> new_elements;
- Array<UInt> & elem_filter = this->element_filter(*it, ghost_type);
+ Array<Idx> & elem_filter = this->element_filter(*it, ghost_type);
UInt nb_element = elem_filter.getSize();
UInt nb_quads =
quadrature_points_coordinates.getFEEngine().getNbIntegrationPoints(
*it, ghost_type);
Array<Real> added_quads(0, spatial_dimension);
const Array<Real> & quads =
quadrature_points_coordinates(*it, ghost_type);
Array<Real>::const_vector_iterator quad = quads.begin(spatial_dimension);
el.type = *it;
el.ghost_type = ghost_type;
for (UInt e = 0; e < nb_element; ++e) {
/// global number of element
el.element = elem_filter(e);
if (std::find(el_begin, el_end, el) != el_end) {
new_elements.push_back(el);
for (UInt q = 0; q < nb_quads; ++q) {
added_quads.push_back(*quad);
++quad;
}
} else
quad += nb_quads;
}
/// get the extrapolated values
for (UInt i = 0; i < this->internals_to_transfer.size(); ++i) {
if (!new_elements.size())
continue;
const ID name = this->getID() + ":" + this->internals_to_transfer[i];
Array<Real> & internal =
(*(this->internal_vectors_real[name]))(*it, ghost_type);
UInt nb_component = internal.getNbComponent();
/// Array<Real>::vector_iterator internal_it =
/// internal.begin(nb_component);
Array<Real> extrapolated_internal_values(new_elements.size() * nb_quads,
nb_component);
this->model->transferInternalValues(this->internals_to_transfer[i],
new_elements, added_quads,
extrapolated_internal_values);
- UInt * sub_mat_ptr = this->sub_material(*it, ghost_type).storage();
+ UInt * sub_mat_ptr = this->sub_material(*it, ghost_type).data();
Array<Real>::const_vector_iterator extrapolated_it =
extrapolated_internal_values.begin(nb_component);
Array<Real>::vector_iterator internal_it = internal.begin(nb_component);
/// copy back the results
for (UInt j = 0; j < new_elements.size(); ++j) {
Element element_local = this->convertToLocalElement(new_elements[j]);
for (UInt q = 0; q < nb_quads; ++q, ++extrapolated_it) {
if (sub_mat_ptr[element_local.element * nb_quads + q])
internal_it[element_local.element * nb_quads + q] =
*extrapolated_it;
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
-// template<UInt spatial_dimension>
+// template<Int spatial_dimension>
// void
// MaterialIGFEMSawToothDamage<spatial_dimension>::transferInternals(Material &
// old_mat,
// std::vector<ElementPair> & element_pairs)
// {
// Element new_el_global;
// Element new_el_local;
// Element old_el_global;
// Element old_el_local;
// /// get the fe-engine of the old material
// FEEngine & fem_old_mat = old_mat.getFEEngine();
-// for (UInt e = 0; e < element_pairs.size(); ++e) {
+// for (Int e = 0; e < element_pairs.size(); ++e) {
// new_el_global = element_pairs[e].first;
// old_el_global = element_pairs[e].second;
// /// get the number of the elements in their materials
// old_el_local = old_el_global;
-// Array<UInt> & mat_local_numbering =
+// Array<Idx> & mat_local_numbering =
// this->model->getMaterialLocalNumbering(old_el_global.type,
// old_el_global.ghost_type);
// old_el_local.element = mat_local_numbering(old_el_global.element);
// new_el_local = this->convertToLocalElement(new_el_global);
// UInt nb_old_quads = fem_old_mat.getNbIntegrationPoints(old_el_global.type,
// old_el_global.ghost_type);
// UInt nb_new_quads = this->fem->getNbIntegrationPoints(new_el_global.type,
// new_el_global.ghost_type);
// if (old_mat.isInternal("damage", Mesh::getKind(old_el_global.type))
// && old_mat.isInternal("Sc", Mesh::getKind(old_el_global.type)) ) {
// UInt quad;
// Vector<Real> el_old_damage(nb_old_quads);
// Vector<Real> el_old_Sc(nb_old_quads);
// Vector<Real> el_new_damage(nb_new_quads);
// Vector<Real> el_new_Sc(nb_new_quads);
// const Array<Real> & old_Sc = old_mat.getArray("Sc", old_el_global.type,
// old_el_global.ghost_type);
// const Array<Real> & old_damage = old_mat.getArray("damage",
// old_el_global.type, old_el_global.ghost_type);
// Array<Real> & new_Sc = this->Sc(new_el_global.type,
// new_el_global.ghost_type);
// Array<Real> & new_damage = this->damage(new_el_global.type,
// new_el_global.ghost_type);
-// for (UInt q = 0; q < nb_old_quads; ++q) {
+// for (Int q = 0; q < nb_old_quads; ++q) {
// quad = old_el_local.element * nb_old_quads + q;
// el_old_damage(q) = old_damage(quad);
// el_old_Sc(q) = old_Sc(quad);
// }
// this->interpolateInternal(new_el_global, old_el_global, el_new_damage,
// el_old_damage, nb_new_quads, nb_old_quads);
// this->interpolateInternal(new_el_global, old_el_global, el_new_Sc,
// el_old_Sc, nb_new_quads, nb_old_quads);
-// for (UInt q = 0; q < nb_new_quads; ++q) {
+// for (Int q = 0; q < nb_new_quads; ++q) {
// quad = new_el_local.element * nb_new_quads + q;
// if (this->sub_material(new_el_global.type,new_el_global.ghost_type)(quad)) {
// new_damage(quad) = el_new_damage(q);
// new_Sc(quad) = el_new_damage(q);
// }
// }
// }
// else
// AKANTU_DEBUG_ASSERT((!old_mat.isInternal("damage",
// Mesh::getKind(old_el_global.type))
// && !old_mat.isInternal("Sc", Mesh::getKind(old_el_global.type))
// ),
// "old material has damage or Sc but not both!!!!");
// }
// }
/* -------------------------------------------------------------------------- */
INSTANTIATE_MATERIAL(MaterialIGFEMSawToothDamage);
} // namespace akantu
/* /// get the material index in the model from this current material
UInt this_mat_idx = this->model->getMaterialIndex(this->name);
/// number of elements in this event
UInt nb_new_elements = element_list.getSize();
// const Array<Element> & old_elements = igfem_event->getOldElementsList();
// std::map<UInt, std::vector<ElementPair> > elements_by_old_mat;
/// store the old elements sorted by their material
- for (UInt e = 0; e < nb_new_elements; ++e) {
+ for (Int e = 0; e < nb_new_elements; ++e) {
const Element new_el = element_list(e);
- const Array<UInt> & mat_idx =
+ const Array<Idx> & mat_idx =
this->model->getMaterialByElement(new_el.type, new_el.ghost_type);
if ( mat_idx(new_el.element) != this_mat_idx )
continue; /// new element is not part of this material: nothing to be done
/// get the corresponding old element and store new and old one as pair
const Element old_el = old_elements(e);
ElementPair el_pair(new_el, old_el);
- const Array<UInt> & old_mat_idx =
+ const Array<Idx> & old_mat_idx =
this->model->getMaterialByElement(old_el.type, old_el.ghost_type);
UInt mat_old_idx = old_mat_idx(old_el.element);
elements_by_old_mat[mat_old_idx].push_back(el_pair);
}
/// loop over all the element pairs in the map
for (std::map<UInt, std::vector<ElementPair> >::iterator map_it =
elements_by_old_mat.begin();
map_it != elements_by_old_mat.end(); ++map_it) {
/// get the vector of old and new element pairs
std::vector<ElementPair > & element_pairs = map_it->second;
Material & old_mat = this->model->getMaterial(map_it->first);
this->transferInternals(old_mat, element_pairs);
}
*/
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.hh b/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.hh
index 479abdbd9..303091f40 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.hh
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage.hh
@@ -1,138 +1,138 @@
/**
* @file material_igfem_saw_tooth_damage.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Linear saw-tooth softening material model for IGFEM elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage.hh"
#include "material_igfem_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_IGFEM_SAW_TOOTH_DAMAGE_HH_
#define AKANTU_MATERIAL_IGFEM_SAW_TOOTH_DAMAGE_HH_
namespace akantu {
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialIGFEMSawToothDamage
: public MaterialDamage<spatial_dimension, MaterialIGFEMElastic> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
private:
typedef MaterialDamage<spatial_dimension, MaterialIGFEMElastic> Parent;
public:
typedef std::pair<Element, Element> ElementPair;
MaterialIGFEMSawToothDamage(SolidMechanicsModel & model, const ID & id = "");
- MaterialIGFEMSawToothDamage(SolidMechanicsModel & model, UInt dim,
+ MaterialIGFEMSawToothDamage(SolidMechanicsModel & model, Int dim,
const Mesh & mesh, FEEngine & fe_engine,
const ID & id = "");
virtual ~MaterialIGFEMSawToothDamage() {}
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
virtual void initMaterial();
/// virtual void updateInternalParameters();
virtual void computeAllStresses(GhostType ghost_type = _not_ghost);
/// update internal field damage
virtual UInt updateDamage();
UInt updateDamage(UInt quad_index, const Real eq_stress, ElementType el_type,
GhostType ghost_type);
/// update energies after damage has been updated
// virtual void updateEnergiesAfterDamage(ElementType el_type, GhostType
// ghost_typ);
virtual void onBeginningSolveStep(const AnalysisMethod & method){};
virtual void onEndSolveStep(const AnalysisMethod & method){};
protected:
/// constitutive law for all element of a type
virtual void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
/// compute the equivalent stress on each Gauss point (i.e. the max prinicpal
/// stress) and normalize it by the tensile strength
virtual void
computeNormalizedEquivalentStress(const Array<Real> & grad_u,
ElementType el_type,
GhostType ghost_type = _not_ghost);
/// find max normalized equivalent stress
void findMaxNormalizedEquivalentStress(ElementType el_type,
GhostType ghost_type = _not_ghost);
inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma, Real & dam);
protected:
/* ------------------------------------------------------------------------ */
/* MeshEventHandler inherited members */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
virtual void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get max normalized equivalent stress
AKANTU_GET_MACRO(NormMaxEquivalentStress, norm_max_equivalent_stress, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// resistance to damage
IGFEMInternalField<Real> Sc;
/// internal field to store equivalent stress on each Gauss point
IGFEMInternalField<Real> equivalent_stress;
/// damage increment
Real prescribed_dam;
/// maximum equivalent stress
Real norm_max_equivalent_stress;
/// deviation from max stress at which Gauss point will still get damaged
Real dam_tolerance;
/// define damage threshold at which damage will be set to 1
Real dam_threshold;
/// maximum damage value
Real max_damage;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_igfem_saw_tooth_damage_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_IGFEM_SAW_TOOTH_DAMAGE_HH_ */
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage_inline_impl.hh b/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage_inline_impl.hh
index 6cacd607f..4f323a413 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage_inline_impl.hh
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_saw_tooth_damage_inline_impl.hh
@@ -1,66 +1,66 @@
/**
* @file material_igfem_saw_tooth_damage_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief Implementation of inline functions of the squentially linear
* saw-tooth damage model for IGFEM elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
inline void
MaterialIGFEMSawToothDamage<spatial_dimension>::computeDamageAndStressOnQuad(
Matrix<Real> & sigma, Real & dam) {
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
UInt MaterialIGFEMSawToothDamage<spatial_dimension>::updateDamage(
UInt quad_index, const Real eq_stress, ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_ASSERT(prescribed_dam > 0.,
"Your prescribed damage must be greater than zero");
Array<Real> & dam = this->damage(el_type, ghost_type);
Real & dam_on_quad = dam(quad_index);
/// check if damage occurs
if (equivalent_stress(el_type, ghost_type)(quad_index) >=
(1 - dam_tolerance) * norm_max_equivalent_stress) {
/// damage the entire sub-element -> get the element index
UInt el_index =
quad_index / this->element_filter(el_type, ghost_type).getSize();
UInt nb_quads = this->fem->getNbIntegrationPoints(el_type, ghost_type);
UInt start_idx = el_index * nb_quads;
- Array<UInt> & sub_mat = this->sub_material(el_type, ghost_type);
+ Array<Idx> & sub_mat = this->sub_material(el_type, ghost_type);
UInt damaged_quads = 0;
if (dam_on_quad < dam_threshold) {
- for (UInt q = 0; q < nb_quads; ++q, ++start_idx) {
+ for (Int q = 0; q < nb_quads; ++q, ++start_idx) {
if (sub_mat(start_idx)) {
dam(start_idx) += prescribed_dam;
damaged_quads += 1;
}
}
} else {
- for (UInt q = 0; q < nb_quads; ++q, ++start_idx) {
+ for (Int q = 0; q < nb_quads; ++q, ++start_idx) {
if (sub_mat(start_idx)) {
dam(start_idx) += max_damage;
damaged_quads += 1;
}
}
}
return damaged_quads;
}
return 0;
}
/* -------------------------------------------------------------------------- */
diff --git a/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel.hh b/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel.hh
index 7604a0118..c052ed89e 100644
--- a/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel.hh
+++ b/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel.hh
@@ -1,220 +1,220 @@
/**
* @file mesh_igfem_spherical_growing_gel.hh
*
* @author Clement Roux-Langlois <clement.roux@epfl.ch>
*
* @date creation: Mon Jul 13 2015
*
* @brief Computation of mesh intersection with sphere(s) and growing of these
* spheres. This class handle the intersectors templated for every
* element
* types.
*
*
* Copyright (©) 2010-2015 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
//#if 0
#ifndef AKANTU_MESH_IGFEM_SPHERICAL_GROWING_GEL_HH_
#define AKANTU_MESH_IGFEM_SPHERICAL_GROWING_GEL_HH_
#include "aka_common.hh"
#include "mesh_sphere_intersector.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/* classes for new igfem elements mesh events */
/* -------------------------------------------------------------------------- */
class NewIGFEMElementsEvent : public NewElementsEvent {
public:
AKANTU_GET_MACRO_NOT_CONST(OldElementsList, old_elements, Array<Element> &);
AKANTU_GET_MACRO(OldElementsList, old_elements, const Array<Element> &);
protected:
Array<Element> old_elements;
};
class NewIGFEMNodesEvent : public NewNodesEvent {
public:
- void setNewNodePerElem(const Array<UInt> & new_node_per_elem) {
+ void setNewNodePerElem(const Array<Idx> & new_node_per_elem) {
this->new_node_per_elem = &new_node_per_elem;
}
void setType(ElementType new_type) { type = new_type; }
void setGhostType(GhostType new_type) { ghost_type = new_type; }
- AKANTU_GET_MACRO(NewNodePerElem, *new_node_per_elem, const Array<UInt> &);
+ AKANTU_GET_MACRO(NewNodePerElem, *new_node_per_elem, const Array<Idx> &);
AKANTU_GET_MACRO(ElementType, type, ElementType);
AKANTU_GET_MACRO(GhostType, ghost_type, GhostType);
protected:
ElementType type;
GhostType ghost_type;
- const Array<UInt> * new_node_per_elem;
+ const Array<Idx> * new_node_per_elem;
};
/* -------------------------------------------------------------------------- */
-template <UInt dim> class MeshIgfemSphericalGrowingGel {
+template <Int dim> class MeshIgfemSphericalGrowingGel {
// definition of the element list
#define ELEMENT_LIST (_triangle_3)(_igfem_triangle_4)(_igfem_triangle_5)
// Solution 1
/* #define INTERSECTOR_DEFINITION(type) \
MeshSphereIntersector<2, type> intersector##type(mesh);*/
// Solution 2
#define INSTANTIATOR(_type) \
intersectors(_type, ghost_type) = \
new MeshSphereIntersector<dim, _type>(this->mesh)
/* --------------------------------------------------------------------------
*/
/* Constructor/Destructor */
/* --------------------------------------------------------------------------
*/
public:
/// Construct from mesh
MeshIgfemSphericalGrowingGel(Mesh & mesh);
/// Destructor
~MeshIgfemSphericalGrowingGel() {
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it = mesh.firstType(dim, ghost_type, _ek_not_defined);
Mesh::type_iterator end = mesh.lastType(dim, ghost_type, _ek_not_defined);
for (; it != end; ++it) {
delete intersectors(*it, ghost_type);
}
}
}
/* --------------------------------------------------------------------------
*/
/* Methods */
/* --------------------------------------------------------------------------
*/
public:
void init();
/// Remove the additionnal nodes
void removeAdditionalNodes();
/// Compute the intersection points between the mesh and the query list for
/// all element types and send the NewNodeEvent
void computeMeshQueryListIntersectionPoint(
const std::list<SK::Sphere_3> & query_list);
/// increase sphere radius and build the new intersection points between the
/// mesh and the query list for all element types and send the NewNodeEvent
void computeMeshQueryListIntersectionPoint(
const std::list<SK::Sphere_3> & query_list, Real inf_fact) {
std::list<SK::Sphere_3>::const_iterator query_it = query_list.begin(),
query_end = query_list.end();
std::list<SK::Sphere_3> sphere_list;
for (; query_it != query_end; ++query_it) {
SK::Sphere_3 sphere(query_it->center(),
query_it->squared_radius() * inf_fact * inf_fact);
sphere_list.push_back(sphere);
}
computeMeshQueryListIntersectionPoint(sphere_list);
}
/// Build the IGFEM mesh from intersection points
void buildIGFEMMesh();
/// Build the IGFEM mesh from spheres
void buildIGFEMMeshFromSpheres(const std::list<SK::Sphere_3> & query_list) {
computeMeshQueryListIntersectionPoint(query_list);
buildIGFEMMesh();
}
/// Build the IGFEM mesh from spheres with increase factor
void buildIGFEMMeshFromSpheres(const std::list<SK::Sphere_3> & query_list,
Real inf_fact) {
computeMeshQueryListIntersectionPoint(query_list, inf_fact);
buildIGFEMMesh();
}
/// set the distributed synchronizer
void setDistributedSynchronizer(DistributedSynchronizer * dist) {
synchronizer = dist;
buildSegmentConnectivityToNodeType();
}
/// update node type
- void updateNodeType(const Array<UInt> & nodes_list,
- const Array<UInt> & new_node_per_elem, ElementType type,
+ void updateNodeType(const Array<Idx> & nodes_list,
+ const Array<Idx> & new_node_per_elem, ElementType type,
GhostType ghost_type);
protected:
/// Build the unordered_map needed to assign the node type to new nodes in
/// parallel
void buildSegmentConnectivityToNodeType();
/* --------------------------------------------------------------------------
*/
/* Accessors */
/* --------------------------------------------------------------------------
*/
public:
AKANTU_GET_MACRO(NbStandardNodes, nb_nodes_fem, UInt);
AKANTU_GET_MACRO(NbEnrichedNodes, nb_enriched_nodes, UInt);
/* --------------------------------------------------------------------------
*/
/* Class Members */
/* --------------------------------------------------------------------------
*/
protected:
/// Mesh used to construct the primitives
Mesh & mesh;
/// number of fem nodes in the initial mesh
UInt nb_nodes_fem;
/// number of enriched nodes before intersection
UInt nb_enriched_nodes;
// Solution 2
/// map of the elements types in the mesh and the corresponding intersectors
ElementTypeMap<MeshAbstractIntersector<SK::Sphere_3> *> intersectors;
/// Map linking pairs of nodes to a node type. The pairs of nodes
/// contain the connectivity of the primitive segments that are
/// intersected.
unordered_map<std::pair<UInt, UInt>, Int>::type segment_conn_to_node_type;
/// Pointer to the distributed synchronizer of the model
DistributedSynchronizer * synchronizer;
};
} // namespace akantu
#include "mesh_igfem_spherical_growing_gel_tmpl.hh"
#endif // AKANTU_MESH_IGFEM_SPHERICAL_GROWING_GEL_HH_
//#endif //
diff --git a/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel_tmpl.hh b/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel_tmpl.hh
index 7dc5c855e..af63c27cd 100644
--- a/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel_tmpl.hh
+++ b/extra_packages/igfem/src/mesh_igfem_spherical_growing_gel_tmpl.hh
@@ -1,531 +1,531 @@
/**
* @file mesh_igfem_spherical_growing_gel.cc
* @author Marco Vocialta <marco.vocialta@epfl.ch>
* @date Mon Sep 21 12:42:11 2015
*
* @brief Implementation of the functions of MeshIgfemSphericalGrowingGel
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_utils.hh"
#include <algorithm>
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MeshIgfemSphericalGrowingGel<dim>::MeshIgfemSphericalGrowingGel(Mesh & mesh)
: mesh(mesh), nb_nodes_fem(mesh.getNbNodes()), nb_enriched_nodes(0),
synchronizer(NULL) {}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MeshIgfemSphericalGrowingGel<dim>::init() {
+template <Int dim> void MeshIgfemSphericalGrowingGel<dim>::init() {
nb_nodes_fem = mesh.getNbNodes();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator tit = mesh.firstType(dim, ghost_type);
Mesh::type_iterator tend = mesh.lastType(dim, ghost_type);
for (; tit != tend;
++tit) { // loop to add corresponding IGFEM element types
if (*tit == _triangle_3) {
mesh.addConnectivityType(_igfem_triangle_4, ghost_type);
mesh.addConnectivityType(_igfem_triangle_5, ghost_type);
} else
AKANTU_ERROR("Not ready for mesh type " << *tit);
}
tit = mesh.firstType(dim, ghost_type, _ek_not_defined);
tend = mesh.lastType(dim, ghost_type, _ek_not_defined);
for (; tit != tend; ++tit) {
AKANTU_BOOST_LIST_SWITCH(INSTANTIATOR, ELEMENT_LIST, *tit);
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MeshIgfemSphericalGrowingGel<dim>::computeMeshQueryListIntersectionPoint(
const std::list<SK::Sphere_3> & query_list) {
/// store number of currently enriched nodes
this->nb_enriched_nodes = mesh.getNbNodes() - nb_nodes_fem;
UInt nb_old_nodes = mesh.getNbNodes();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator iit = mesh.firstType(dim, ghost_type, _ek_not_defined);
Mesh::type_iterator iend = mesh.lastType(dim, ghost_type, _ek_not_defined);
for (; iit != iend; ++iit) {
MeshAbstractIntersector<SK::Sphere_3> & intersector =
*intersectors(*iit, ghost_type);
intersector.constructData(ghost_type);
intersector.computeMeshQueryListIntersectionPoint(query_list,
nb_old_nodes);
const Array<Real> intersection_points_current_type =
*(intersector.getIntersectionPoints());
- const Array<UInt> & new_node_per_elem = intersector.getNewNodePerElem();
+ const Array<Idx> & new_node_per_elem = intersector.getNewNodePerElem();
/// Send the new node event
UInt new_points = intersection_points_current_type.getSize();
StaticCommunicator::getStaticCommunicator().allReduce(&new_points, 1,
_so_sum);
if (new_points > 0) {
Array<Real> & nodes = this->mesh.getNodes();
UInt nb_node = nodes.getSize();
Array<Real>::const_vector_iterator intersec_p_it =
intersection_points_current_type.begin(dim);
NewIGFEMNodesEvent new_nodes_event;
- for (UInt in = 0; in < intersection_points_current_type.getSize();
+ for (Int in = 0; in < intersection_points_current_type.getSize();
++in, ++intersec_p_it) {
nodes.push_back(*intersec_p_it);
new_nodes_event.getList().push_back(nb_node + in);
}
new_nodes_event.setNewNodePerElem(new_node_per_elem);
new_nodes_event.setType(*iit);
new_nodes_event.setGhostType(ghost_type);
this->mesh.sendEvent(new_nodes_event);
}
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MeshIgfemSphericalGrowingGel<dim>::removeAdditionalNodes() {
AKANTU_DEBUG_IN();
UInt total_nodes = this->mesh.getNbNodes();
UInt nb_new_enriched_nodes =
total_nodes - this->nb_enriched_nodes - this->nb_nodes_fem;
UInt old_total_nodes = this->nb_nodes_fem + this->nb_enriched_nodes;
UInt total_new_nodes = nb_new_enriched_nodes;
StaticCommunicator::getStaticCommunicator().allReduce(&total_new_nodes, 1,
_so_sum);
if (total_new_nodes == 0)
return;
RemovedNodesEvent remove_nodes(this->mesh);
- Array<UInt> & nodes_removed = remove_nodes.getList();
- Array<UInt> & new_numbering = remove_nodes.getNewNumbering();
+ Array<Idx> & nodes_removed = remove_nodes.getList();
+ Array<Idx> & new_numbering = remove_nodes.getNewNumbering();
- for (UInt nnod = 0; nnod < this->nb_nodes_fem; ++nnod) {
+ for (Int nnod = 0; nnod < this->nb_nodes_fem; ++nnod) {
new_numbering(nnod) = nnod;
}
- for (UInt nnod = nb_nodes_fem; nnod < old_total_nodes; ++nnod) {
+ for (Int nnod = nb_nodes_fem; nnod < old_total_nodes; ++nnod) {
new_numbering(nnod) = UInt(-1);
nodes_removed.push_back(nnod);
}
- for (UInt nnod = 0; nnod < nb_new_enriched_nodes; ++nnod) {
+ for (Int nnod = 0; nnod < nb_new_enriched_nodes; ++nnod) {
new_numbering(nnod + old_total_nodes) = this->nb_nodes_fem + nnod;
}
if (nb_new_enriched_nodes > 0) {
- for (UInt gt = _not_ghost; gt <= _ghost; ++gt) {
+ for (Int gt = _not_ghost; gt <= _ghost; ++gt) {
GhostType ghost_type = (GhostType)gt;
Mesh::type_iterator it =
mesh.firstType(_all_dimensions, ghost_type, _ek_not_defined);
Mesh::type_iterator end =
mesh.lastType(_all_dimensions, ghost_type, _ek_not_defined);
for (; it != end; ++it) {
ElementType type = *it;
- Array<UInt> & connectivity_array =
+ Array<Idx> & connectivity_array =
mesh.getConnectivity(type, ghost_type);
UInt nb_nodes_per_element = connectivity_array.getNbComponent();
- Array<UInt>::vector_iterator conn_it =
+ Array<Idx>::vector_iterator conn_it =
connectivity_array.begin(nb_nodes_per_element);
- Array<UInt>::vector_iterator conn_end =
+ Array<Idx>::vector_iterator conn_end =
connectivity_array.end(nb_nodes_per_element);
for (; conn_it != conn_end; ++conn_it) {
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
(*conn_it)(n) = new_numbering((*conn_it)(n));
}
}
}
}
}
this->mesh.sendEvent(remove_nodes);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MeshIgfemSphericalGrowingGel<dim>::buildIGFEMMesh() {
+template <Int dim> void MeshIgfemSphericalGrowingGel<dim>::buildIGFEMMesh() {
AKANTU_DEBUG_IN();
NewIGFEMElementsEvent new_elements_event;
UInt total_new_elements = 0;
Array<Element> & new_elements_list = new_elements_event.getList();
Array<Element> & old_elements_list = new_elements_event.getOldElementsList();
RemovedElementsEvent removed_elements_event(this->mesh);
ChangedElementsEvent changed_elements_event(this->mesh);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
mesh.initElementTypeMapArray(removed_elements_event.getNewNumbering(), 1,
dim, ghost_type, false, _ek_not_defined);
mesh.initElementTypeMapArray(changed_elements_event.getNewNumbering(), 1,
dim, ghost_type, false, _ek_not_defined);
/// loop over all types in the mesh for a given ghost type
Mesh::type_iterator iit = mesh.firstType(dim, ghost_type, _ek_not_defined);
Mesh::type_iterator iend = mesh.lastType(dim, ghost_type, _ek_not_defined);
for (; iit != iend; ++iit) {
ElementType type = *iit;
MeshAbstractIntersector<SK::Sphere_3> & intersector =
*intersectors(type, ghost_type);
- const Array<UInt> & new_node_per_elem = intersector.getNewNodePerElem();
+ const Array<Idx> & new_node_per_elem = intersector.getNewNodePerElem();
UInt n_new_el = 0;
- Array<UInt> & connectivity = this->mesh.getConnectivity(type, ghost_type);
+ Array<Idx> & connectivity = this->mesh.getConnectivity(type, ghost_type);
/// get the connectivities of all types that that may transform
- Array<UInt> & connec_igfem_tri_4 =
+ Array<Idx> & connec_igfem_tri_4 =
this->mesh.getConnectivity(_igfem_triangle_4, ghost_type);
- Array<UInt> & connec_igfem_tri_5 =
+ Array<Idx> & connec_igfem_tri_5 =
this->mesh.getConnectivity(_igfem_triangle_5, ghost_type);
- Array<UInt> & connec_tri_3 =
+ Array<Idx> & connec_tri_3 =
this->mesh.getConnectivity(_triangle_3, ghost_type);
/// create elements to store the newly generated elements
Element el_tri_3(_triangle_3, 0, ghost_type, _ek_regular);
Element el_igfem_tri_4(_igfem_triangle_4, 0, ghost_type, _ek_igfem);
Element el_igfem_tri5(_igfem_triangle_5, 0, ghost_type, _ek_igfem);
- Array<UInt> & new_numbering =
+ Array<Idx> & new_numbering =
removed_elements_event.getNewNumbering(type, ghost_type);
new_numbering.resize(connectivity.getSize());
/// container for element to be removed
Element old_element(type, 0, ghost_type, Mesh::getKind(type));
- for (UInt nel = 0; nel != new_node_per_elem.getSize(); ++nel) {
+ for (Int nel = 0; nel != new_node_per_elem.getSize(); ++nel) {
/// a former IGFEM triangle is transformed into a regular triangle
if ((type != _triangle_3) && (new_node_per_elem(nel, 0) == 0)) {
Vector<UInt> connec_new_elem(3);
connec_new_elem(0) = connectivity(nel, 0);
connec_new_elem(1) = connectivity(nel, 1);
connec_new_elem(2) = connectivity(nel, 2);
/// add the new element in the mesh
UInt nb_triangles_3 = connec_tri_3.getSize();
connec_tri_3.push_back(connec_new_elem);
el_tri_3.element = nb_triangles_3;
new_elements_list.push_back(el_tri_3);
/// the number of the old element in the mesh
old_element.element = nel;
old_elements_list.push_back(old_element);
new_numbering(nel) = UInt(-1);
++n_new_el;
}
/// element is enriched
else if (new_node_per_elem(nel, 0) != 0) {
switch (new_node_per_elem(nel, 0)) {
/// new element is of type igfem_triangle_4
case 1: {
Vector<UInt> connec_new_elem(4);
switch (new_node_per_elem(nel, 2)) {
case 0:
connec_new_elem(0) = connectivity(nel, 2);
connec_new_elem(1) = connectivity(nel, 0);
connec_new_elem(2) = connectivity(nel, 1);
break;
case 1:
connec_new_elem(0) = connectivity(nel, 0);
connec_new_elem(1) = connectivity(nel, 1);
connec_new_elem(2) = connectivity(nel, 2);
break;
case 2:
connec_new_elem(0) = connectivity(nel, 1);
connec_new_elem(1) = connectivity(nel, 2);
connec_new_elem(2) = connectivity(nel, 0);
break;
default:
AKANTU_ERROR("A triangle has only 3 segments not "
<< new_node_per_elem(nel, 2));
break;
}
connec_new_elem(3) = new_node_per_elem(nel, 1);
UInt nb_igfem_triangles_4 = connec_igfem_tri_4.getSize();
connec_igfem_tri_4.push_back(connec_new_elem);
el_igfem_tri_4.element = nb_igfem_triangles_4;
new_elements_list.push_back(el_igfem_tri_4);
break;
}
/// new element is of type igfem_triangle_5
case 2: {
Vector<UInt> connec_new_elem(5);
if ((new_node_per_elem(nel, 2) == 0) &&
(new_node_per_elem(nel, 4) == 1)) {
connec_new_elem(0) = connectivity(nel, 1);
connec_new_elem(1) = connectivity(nel, 2);
connec_new_elem(2) = connectivity(nel, 0);
connec_new_elem(3) = new_node_per_elem(nel, 3);
connec_new_elem(4) = new_node_per_elem(nel, 1);
} else if ((new_node_per_elem(nel, 2) == 0) &&
(new_node_per_elem(nel, 4) == 2)) {
connec_new_elem(0) = connectivity(nel, 0);
connec_new_elem(1) = connectivity(nel, 1);
connec_new_elem(2) = connectivity(nel, 2);
connec_new_elem(3) = new_node_per_elem(nel, 1);
connec_new_elem(4) = new_node_per_elem(nel, 3);
} else if ((new_node_per_elem(nel, 2) == 1) &&
(new_node_per_elem(nel, 4) == 2)) {
connec_new_elem(0) = connectivity(nel, 2);
connec_new_elem(1) = connectivity(nel, 0);
connec_new_elem(2) = connectivity(nel, 1);
connec_new_elem(3) = new_node_per_elem(nel, 3);
connec_new_elem(4) = new_node_per_elem(nel, 1);
} else if ((new_node_per_elem(nel, 2) == 1) &&
(new_node_per_elem(nel, 4) == 0)) {
connec_new_elem(0) = connectivity(nel, 1);
connec_new_elem(1) = connectivity(nel, 2);
connec_new_elem(2) = connectivity(nel, 0);
connec_new_elem(3) = new_node_per_elem(nel, 1);
connec_new_elem(4) = new_node_per_elem(nel, 3);
} else if ((new_node_per_elem(nel, 2) == 2) &&
(new_node_per_elem(nel, 4) == 0)) {
connec_new_elem(0) = connectivity(nel, 0);
connec_new_elem(1) = connectivity(nel, 1);
connec_new_elem(2) = connectivity(nel, 2);
connec_new_elem(3) = new_node_per_elem(nel, 3);
connec_new_elem(4) = new_node_per_elem(nel, 1);
} else if ((new_node_per_elem(nel, 2) == 2) &&
(new_node_per_elem(nel, 4) == 1)) {
connec_new_elem(0) = connectivity(nel, 2);
connec_new_elem(1) = connectivity(nel, 0);
connec_new_elem(2) = connectivity(nel, 1);
connec_new_elem(3) = new_node_per_elem(nel, 1);
connec_new_elem(4) = new_node_per_elem(nel, 3);
} else
AKANTU_ERROR("A triangle has only 3 segments (0 to 2) not "
<< new_node_per_elem(nel, 2) << "and"
<< new_node_per_elem(nel, 4));
UInt nb_igfem_triangles_5 = connec_igfem_tri_5.getSize();
connec_igfem_tri_5.push_back(connec_new_elem);
el_igfem_tri5.element = nb_igfem_triangles_5;
new_elements_list.push_back(el_igfem_tri5);
break;
}
default:
AKANTU_ERROR("IGFEM cannot add " << new_node_per_elem(nel, 0)
<< " nodes to triangles");
break;
}
old_element.element = nel;
old_elements_list.push_back(old_element);
new_numbering(nel) = UInt(-1);
++n_new_el;
}
}
total_new_elements += n_new_el;
}
}
/// update new numbering
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
/// loop over all types in the mesh for a given ghost type
Mesh::type_iterator iit = mesh.firstType(dim, ghost_type, _ek_not_defined);
Mesh::type_iterator iend = mesh.lastType(dim, ghost_type, _ek_not_defined);
for (; iit != iend; ++iit) {
ElementType type = *iit;
- Array<UInt> & new_numbering =
+ Array<Idx> & new_numbering =
removed_elements_event.getNewNumbering(type, ghost_type);
UInt el_index = 0;
UInt nb_element = this->mesh.getNbElement(type, ghost_type);
new_numbering.resize(nb_element);
- for (UInt e = 0; e < nb_element; ++e) {
+ for (Int e = 0; e < nb_element; ++e) {
if (new_numbering(e) != UInt(-1)) {
new_numbering(e) = el_index;
++el_index;
}
}
changed_elements_event.getNewNumbering(type, ghost_type)
.copy(new_numbering);
}
}
StaticCommunicator::getStaticCommunicator().allReduce(&total_new_elements, 1,
_so_sum);
if (total_new_elements > 0) {
changed_elements_event.getListOld().copy(
new_elements_event.getOldElementsList());
changed_elements_event.getListNew().copy(new_elements_event.getList());
this->mesh.sendEvent(changed_elements_event);
this->mesh.sendEvent(new_elements_event);
Array<Element> & removed_list = removed_elements_event.getList();
removed_list.copy(new_elements_event.getOldElementsList());
this->mesh.sendEvent(removed_elements_event);
}
removeAdditionalNodes();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MeshIgfemSphericalGrowingGel<dim>::buildSegmentConnectivityToNodeType() {
Mesh mesh_facets(mesh.initMeshFacets());
MeshUtils::buildSegmentToNodeType(mesh, mesh_facets, synchronizer);
// only the ghost elements are considered
- for (UInt g = _not_ghost; g <= _ghost; ++g) {
+ for (Int g = _not_ghost; g <= _ghost; ++g) {
GhostType ghost_type = (GhostType)g;
Mesh::type_iterator it = mesh_facets.firstType(1, ghost_type);
Mesh::type_iterator end = mesh_facets.lastType(1, ghost_type);
for (; it != end; ++it) {
ElementType type = *it;
const Array<Int> & segment_to_nodetype =
mesh_facets.getData<Int>("segment_to_nodetype", type, ghost_type);
- const Array<UInt> & segment_connectivity =
+ const Array<Idx> & segment_connectivity =
mesh_facets.getConnectivity(type, ghost_type);
// looping over all the segments
Array<UInt>::const_vector_iterator conn_it =
segment_connectivity.begin(segment_connectivity.getNbComponent());
Array<UInt>::const_vector_iterator conn_end =
segment_connectivity.end(segment_connectivity.getNbComponent());
UInt seg_index = 0;
UInt n[2];
for (; conn_it != conn_end; ++conn_it, ++seg_index) {
Int seg_type = segment_to_nodetype(seg_index);
n[0] = (*conn_it)(0);
n[1] = (*conn_it)(1);
if ((mesh.isMasterNode(n[0]) || mesh.isSlaveNode(n[0])) &&
(mesh.isMasterNode(n[1]) || mesh.isSlaveNode(n[1]))) {
std::sort(n, n + 2);
segment_conn_to_node_type[std::make_pair(n[0], n[1])] = seg_type;
}
}
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MeshIgfemSphericalGrowingGel<dim>::updateNodeType(
const Array<UInt> & nodes_list, const Array<UInt> & new_node_per_elem,
ElementType type, GhostType ghost_type) {
Array<Int> & nodes_type = mesh.getNodesType();
UInt old_nodes = nodes_type.getSize();
UInt new_nodes = nodes_list.getSize();
// exit this function if the simulation in run in serial
if (old_nodes == 0 || new_nodes == 0)
return;
nodes_type.resize(old_nodes + new_nodes);
Array<bool> checked_node(new_nodes, 1, false);
UInt nb_prim_by_el = 0;
if ((type == _triangle_3) || (type == _igfem_triangle_4) ||
(type == _igfem_triangle_5)) {
nb_prim_by_el = 3;
} else {
AKANTU_ERROR("Not ready for mesh type " << type);
}
// determine the node type for the local, master and slave nodes
const Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
unordered_map<std::pair<UInt, UInt>, Int>::type::iterator seg_type_it;
unordered_map<std::pair<UInt, UInt>, Int>::type::iterator seg_type_end =
segment_conn_to_node_type.end();
- for (UInt el = 0; el < new_node_per_elem.getSize(); ++el) {
+ for (Int el = 0; el < new_node_per_elem.getSize(); ++el) {
UInt nb_nodes = new_node_per_elem(el, 0);
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
UInt node_index = new_node_per_elem(el, 2 * n + 1);
if (node_index < old_nodes || checked_node(node_index - old_nodes))
continue;
// get the elemental connectivity of the segment associated to the node
UInt segment_index = new_node_per_elem(el, 2 * n + 2);
UInt extreme_nodes[2];
extreme_nodes[0] = segment_index;
extreme_nodes[1] = segment_index + 1;
if (extreme_nodes[1] == nb_prim_by_el)
extreme_nodes[1] = 0;
// get the connectivity of the segment
extreme_nodes[0] = connectivity(el, extreme_nodes[0]);
extreme_nodes[1] = connectivity(el, extreme_nodes[1]);
// if one extreme nodes is pure ghost, then also the new node is pure
// ghost
if (mesh.isPureGhostNode(extreme_nodes[0]) ||
mesh.isPureGhostNode(extreme_nodes[1]))
nodes_type(node_index) = -3;
// if on of the two extreme nodes is local, then also the new node is
// local
else if (mesh.isLocalNode(extreme_nodes[0]) ||
mesh.isLocalNode(extreme_nodes[1]))
nodes_type(node_index) = -1;
// otherwise use the value stored in the map
else {
std::sort(extreme_nodes, extreme_nodes + 2);
seg_type_it = segment_conn_to_node_type.find(
std::make_pair(extreme_nodes[0], extreme_nodes[1]));
AKANTU_DEBUG_ASSERT(seg_type_it != seg_type_end, "Segment not found");
nodes_type(node_index) = seg_type_it->second;
}
checked_node(node_index - old_nodes) = true;
}
}
AKANTU_DEBUG_ASSERT(std::accumulate(checked_node.begin(), checked_node.end(),
0) == Int(checked_node.getSize()),
"Not all new nodes were assigned a node type");
}
} // namespace akantu
diff --git a/extra_packages/igfem/src/non_local_manager_igfem.cc b/extra_packages/igfem/src/non_local_manager_igfem.cc
index 3ad164423..632d23ebf 100644
--- a/extra_packages/igfem/src/non_local_manager_igfem.cc
+++ b/extra_packages/igfem/src/non_local_manager_igfem.cc
@@ -1,306 +1,306 @@
/**
* @file non_local_manager_igfem.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Mon Sep 21 15:32:10 2015
*
* @brief Implementation of non-local manager igfem
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifdef AKANTU_DAMAGE_NON_LOCAL
#include "non_local_manager_igfem.hh"
#include "material_non_local.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NonLocalManagerIGFEM::NonLocalManagerIGFEM(SolidMechanicsModelIGFEM & model,
const ID & id)
: NonLocalManager(model, id) {
Mesh & mesh = this->model.getMesh();
/// initialize the element type map array
/// it will be resized to nb_quad * nb_element during the computation of
/// coords
mesh.initElementTypeMapArray(quad_positions, spatial_dimension,
spatial_dimension, false, _ek_igfem, true);
}
/* -------------------------------------------------------------------------- */
NonLocalManagerIGFEM::~NonLocalManagerIGFEM() = default;
/* -------------------------------------------------------------------------- */
void NonLocalManagerIGFEM::init() {
/// store the number of current ghost elements for each type in the mesh
ElementTypeMap<UInt> nb_ghost_protected;
Mesh & mesh = this->model.getMesh();
- for (UInt k = _ek_regular; k <= _ek_igfem; ++k) {
+ for (Int k = _ek_regular; k <= _ek_igfem; ++k) {
ElementKind el_kind = (ElementKind)k;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost, el_kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, _ghost, el_kind);
for (; it != last_type; ++it)
nb_ghost_protected(mesh.getNbElement(*it, _ghost), *it, _ghost);
}
/// exchange the missing ghosts for the non-local neighborhoods
this->createNeighborhoodSynchronizers();
/// insert the ghost quadrature points of the non-local materials into the
/// non-local neighborhoods
- for (UInt m = 0; m < this->non_local_materials.size(); ++m) {
+ for (Int m = 0; m < this->non_local_materials.size(); ++m) {
switch (spatial_dimension) {
case 1:
dynamic_cast<MaterialNonLocal<1> &>(*(this->non_local_materials[m]))
.insertQuadsInNeighborhoods(_ghost);
break;
case 2:
dynamic_cast<MaterialNonLocal<2> &>(*(this->non_local_materials[m]))
.insertQuadsInNeighborhoods(_ghost);
break;
case 3:
dynamic_cast<MaterialNonLocal<3> &>(*(this->non_local_materials[m]))
.insertQuadsInNeighborhoods(_ghost);
break;
}
}
FEEngine & fee_regular = this->model.getFEEngine();
FEEngine & fee_igfem = this->model.getFEEngine("IGFEMFEEngine");
this->updatePairLists();
/// cleanup the unneccessary ghost elements
this->cleanupExtraGhostElements(nb_ghost_protected);
this->initElementTypeMap(1, volumes, fee_regular, _ek_regular);
this->initElementTypeMap(1, volumes, fee_igfem, _ek_igfem);
this->setJacobians(fee_regular, _ek_regular);
this->setJacobians(fee_igfem, _ek_igfem);
this->initNonLocalVariables();
this->computeWeights();
}
/* -------------------------------------------------------------------------- */
void NonLocalManagerIGFEM::computeAllNonLocalStresses() {
/// update the flattened version of the internals
std::map<ID, NonLocalVariable *>::iterator non_local_variable_it =
non_local_variables.begin();
std::map<ID, NonLocalVariable *>::iterator non_local_variable_end =
non_local_variables.end();
for (; non_local_variable_it != non_local_variable_end;
++non_local_variable_it) {
non_local_variable_it->second->local.zero();
non_local_variable_it->second->non_local.zero();
- for (UInt gt = _not_ghost; gt <= _ghost; ++gt) {
+ for (Int gt = _not_ghost; gt <= _ghost; ++gt) {
GhostType ghost_type = (GhostType)gt;
this->flattenInternal(non_local_variable_it->second->local, ghost_type,
_ek_regular);
this->flattenInternal(non_local_variable_it->second->local, ghost_type,
_ek_igfem);
}
}
this->volumes.zero();
/// loop over all the neighborhoods and compute intiate the
/// exchange of the non-local_variables
std::set<ID>::const_iterator global_neighborhood_it =
global_neighborhoods.begin();
NeighborhoodMap::iterator it;
for (; global_neighborhood_it != global_neighborhoods.end();
++global_neighborhood_it) {
it = neighborhoods.find(*global_neighborhood_it);
if (it != neighborhoods.end())
it->second->getSynchronizerRegistry().asynchronousSynchronize(
SynchronizationTag::_mnl_for_average);
else
dummy_synchronizers[*global_neighborhood_it]->asynchronousSynchronize(
dummy_accessor, SynchronizationTag::_mnl_for_average);
}
this->averageInternals(_not_ghost);
AKANTU_DEBUG_INFO("Wait distant non local stresses");
/// loop over all the neighborhoods and block until all non-local
/// variables have been exchanged
global_neighborhood_it = global_neighborhoods.begin();
it = neighborhoods.begin();
for (; global_neighborhood_it != global_neighborhoods.end();
++global_neighborhood_it) {
it = neighborhoods.find(*global_neighborhood_it);
if (it != neighborhoods.end())
it->second->getSynchronizerRegistry().waitEndSynchronize(
SynchronizationTag::_mnl_for_average);
else
dummy_synchronizers[*global_neighborhood_it]->waitEndSynchronize(
dummy_accessor, SynchronizationTag::_mnl_for_average);
}
this->averageInternals(_ghost);
/// copy the results in the materials
this->distributeInternals(_ek_regular);
/// loop over all the materials and update the weights
- for (UInt m = 0; m < this->non_local_materials.size(); ++m) {
+ for (Int m = 0; m < this->non_local_materials.size(); ++m) {
switch (spatial_dimension) {
case 1:
dynamic_cast<MaterialNonLocal<1> &>(*(this->non_local_materials[m]))
.computeNonLocalStresses(_not_ghost);
break;
case 2:
dynamic_cast<MaterialNonLocal<2> &>(*(this->non_local_materials[m]))
.computeNonLocalStresses(_not_ghost);
break;
case 3:
dynamic_cast<MaterialNonLocal<3> &>(*(this->non_local_materials[m]))
.computeNonLocalStresses(_not_ghost);
break;
}
}
++this->compute_stress_calls;
}
/* -------------------------------------------------------------------------- */
void NonLocalManagerIGFEM::cleanupExtraGhostElements(
ElementTypeMap<UInt> & nb_ghost_protected) {
typedef std::set<Element> ElementSet;
ElementSet relevant_ghost_elements;
ElementSet to_keep_per_neighborhood;
/// loop over all the neighborhoods and get their protected ghosts
NeighborhoodMap::iterator neighborhood_it = neighborhoods.begin();
NeighborhoodMap::iterator neighborhood_end = neighborhoods.end();
for (; neighborhood_it != neighborhood_end; ++neighborhood_it) {
neighborhood_it->second->cleanupExtraGhostElements(
to_keep_per_neighborhood);
ElementSet::const_iterator it = to_keep_per_neighborhood.begin();
for (; it != to_keep_per_neighborhood.end(); ++it)
relevant_ghost_elements.insert(*it);
to_keep_per_neighborhood.zero();
}
/// remove all unneccessary ghosts from the mesh
/// Create list of element to remove and new numbering for element to keep
Mesh & mesh = this->model.getMesh();
ElementSet ghost_to_erase;
RemovedElementsEvent remove_elem(mesh);
Element element;
- for (UInt k = _ek_regular; k < _ek_igfem; ++k) {
+ for (Int k = _ek_regular; k < _ek_igfem; ++k) {
ElementKind el_kind = (ElementKind)k;
element.kind = _ek_igfem;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost, el_kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, _ghost, el_kind);
element.ghost_type = _ghost;
for (; it != last_type; ++it) {
element.type = *it;
UInt nb_ghost_elem = mesh.getNbElement(*it, _ghost);
UInt nb_ghost_elem_protected = 0;
try {
nb_ghost_elem_protected = nb_ghost_protected(*it, _ghost);
} catch (...) {
}
if (!remove_elem.getNewNumbering().exists(*it, _ghost))
remove_elem.getNewNumbering().alloc(nb_ghost_elem, 1, *it, _ghost);
else
remove_elem.getNewNumbering(*it, _ghost).resize(nb_ghost_elem);
Array<UInt> & new_numbering = remove_elem.getNewNumbering(*it, _ghost);
- for (UInt g = 0; g < nb_ghost_elem; ++g) {
+ for (Int g = 0; g < nb_ghost_elem; ++g) {
element.element = g;
if (element.element >= nb_ghost_elem_protected &&
relevant_ghost_elements.find(element) ==
relevant_ghost_elements.end()) {
remove_elem.getList().push_back(element);
new_numbering(element.element) = UInt(-1);
}
}
/// renumber remaining ghosts
UInt ng = 0;
- for (UInt g = 0; g < nb_ghost_elem; ++g) {
+ for (Int g = 0; g < nb_ghost_elem; ++g) {
if (new_numbering(g) != UInt(-1)) {
new_numbering(g) = ng;
++ng;
}
}
}
}
- for (UInt k = _ek_regular; k < _ek_igfem; ++k) {
+ for (Int k = _ek_regular; k < _ek_igfem; ++k) {
ElementKind el_kind = (ElementKind)k;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost, el_kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, _ghost, el_kind);
for (; it != last_type; ++it) {
UInt nb_elem = mesh.getNbElement(*it, _not_ghost);
if (!remove_elem.getNewNumbering().exists(*it, _not_ghost))
remove_elem.getNewNumbering().alloc(nb_elem, 1, *it, _not_ghost);
Array<UInt> & new_numbering =
remove_elem.getNewNumbering(*it, _not_ghost);
- for (UInt e = 0; e < nb_elem; ++e) {
+ for (Int e = 0; e < nb_elem; ++e) {
new_numbering(e) = e;
}
}
}
mesh.sendEvent(remove_elem);
}
/* -------------------------------------------------------------------------- */
void NonLocalManagerIGFEM::onElementsAdded(__attribute__((unused))
const Array<Element> & element_list,
__attribute__((unused))
const NewElementsEvent & event) {
FEEngine & fee = this->model.getFEEngine("IGFEMFEEngine");
this->resizeElementTypeMap(1, volumes, fee, _ek_igfem);
this->resizeElementTypeMap(spatial_dimension, quad_positions, fee, _ek_igfem);
NonLocalManager::onElementsAdded(element_list, event);
}
/* -------------------------------------------------------------------------- */
void NonLocalManagerIGFEM::onElementsRemoved(
const Array<Element> & element_list,
const ElementTypeMapArray<UInt> & new_numbering,
__attribute__((unused)) const RemovedElementsEvent & event) {
FEEngine & fee = this->model.getFEEngine("IGFEMFEEngine");
this->removeIntegrationPointsFromMap(event.getNewNumbering(),
spatial_dimension, quad_positions, fee,
_ek_igfem);
this->removeIntegrationPointsFromMap(event.getNewNumbering(), 1, volumes, fee,
_ek_igfem);
NonLocalManager::onElementsRemoved(element_list, new_numbering, event);
}
} // namespace akantu
#endif /* AKANTU_DAMAGE_NON_LOCAL */
diff --git a/extra_packages/igfem/src/shape_igfem.cc b/extra_packages/igfem/src/shape_igfem.cc
index 38fd32a18..4f1ecbd93 100644
--- a/extra_packages/igfem/src/shape_igfem.cc
+++ b/extra_packages/igfem/src/shape_igfem.cc
@@ -1,93 +1,93 @@
/**
* @file shape_igfem_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief ShapeIGFEM inline implementation
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
//#include "mesh.hh"
#include "shape_igfem.hh"
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_IGFEM)
namespace akantu {
/* -------------------------------------------------------------------------- */
ShapeLagrange<_ek_igfem>::ShapeLagrange(const Mesh & mesh, const ID & id)
: ShapeFunctions(mesh, id), shapes("shapes_generic", id),
shapes_derivatives("shapes_derivatives_generic", id),
igfem_integration_points("igfem_integration_points", id),
shapes_at_enrichments("shapes_at_enrichments", id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/*-------------------------------------------------------------------------- */
void ShapeLagrange<_ek_igfem>::extractValuesAtStandardNodes(
const Array<Real> & nodal_values, Array<Real> & extracted_values,
GhostType ghost_type) const {
AKANTU_DEBUG_ASSERT(nodal_values.getNbComponent() ==
extracted_values.getNbComponent(),
"The arrays are not of the same size!!!!!");
extracted_values.zero();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, ghost_type, _ek_igfem);
Mesh::type_iterator end =
mesh.lastType(spatial_dimension, ghost_type, _ek_igfem);
for (; it != end; ++it) {
ElementType type = *it;
UInt nb_elements = mesh.getNbElement(type, ghost_type);
UInt nb_parent_nodes = 0;
UInt nb_nodes_per_element = 0;
#define GET_NODES_INFO(type) \
const ElementType parent_type = \
ElementClassProperty<type>::parent_element_type; \
nb_parent_nodes = \
ElementClass<parent_type>::getNbNodesPerInterpolationElement(); \
nb_nodes_per_element = \
ElementClass<type>::getNbNodesPerInterpolationElement();
AKANTU_BOOST_IGFEM_ELEMENT_SWITCH(GET_NODES_INFO);
#undef GET_NODES_INFO
- UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage();
- for (UInt e = 0; e < nb_elements; ++e) {
+ UInt * conn_val = mesh.getConnectivity(type, ghost_type).data();
+ for (Int e = 0; e < nb_elements; ++e) {
/// copy the value at standard nodes
UInt offset = e * nb_nodes_per_element;
- for (UInt n = 0; n < nb_parent_nodes; ++n) {
+ for (Int n = 0; n < nb_parent_nodes; ++n) {
UInt node = conn_val[offset + n];
- for (UInt i = 0; i < nodal_values.getNbComponent(); ++i)
+ for (Int i = 0; i < nodal_values.getNbComponent(); ++i)
extracted_values(node, i) = nodal_values(node, i);
}
}
}
}
/* -------------------------------------------------------------------------- */
void ShapeLagrange<_ek_igfem>::printself(std::ostream & stream,
int indent) const {
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
;
stream << space << "Shapes Lagrange [" << std::endl;
ShapeFunctions::printself(stream, indent + 1);
shapes.printself(stream, indent + 1);
shapes_derivatives.printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
} // namespace akantu
#endif
diff --git a/extra_packages/igfem/src/shape_igfem.hh b/extra_packages/igfem/src/shape_igfem.hh
index 93dd84432..ca3c92c43 100644
--- a/extra_packages/igfem/src/shape_igfem.hh
+++ b/extra_packages/igfem/src/shape_igfem.hh
@@ -1,196 +1,196 @@
/**
* @file shape_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief shape functions for interface-enriched generalized FEM
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "shape_functions.hh"
#ifndef AKANTU_SHAPE_IGFEM_HH_
#define AKANTU_SHAPE_IGFEM_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <> class ShapeLagrange<_ek_igfem> : public ShapeFunctions {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
ShapeLagrange(const Mesh & mesh, const ID & id = "shape_igfem");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
inline void initShapeFunctions(const Array<Real> & nodes,
const Matrix<Real> & integration_points,
const Matrix<Real> & integration_points_1,
const Matrix<Real> & integration_points_2,
ElementType type, GhostType ghost_type);
inline void interpolateEnrichmentsAllTypes(const Array<Real> & src,
Array<Real> & dst,
ElementType type,
GhostType ghost_type) const;
template <ElementType type>
inline void precomputeShapesOnEnrichedNodes(const Array<Real> & nodes,
GhostType ghost_type);
template <ElementType type>
void interpolateAtEnrichedNodes(const Array<Real> & src, Array<Real> & dst,
GhostType ghost_type) const;
/// pre compute all shapes on the element integration points from natural
/// coordinates
template <ElementType type>
void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// pre compute all shape derivatives on the element integration points from
/// natural coordinates
template <ElementType type>
void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// interpolate nodal values on the integration points
template <ElementType type>
void interpolateOnIntegrationPoints(
const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Int> & filter_elements = empty_filter) const;
/// interpolate on physical point
template <ElementType type>
void interpolate(const Vector<Real> & real_coords, UInt elem,
const Matrix<Real> & nodal_values,
Vector<Real> & interpolated, GhostType ghost_type) const;
/// compute the gradient of u on the integration points
template <ElementType type>
void gradientOnIntegrationPoints(
const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Int> & filter_elements = empty_filter) const;
/// multiply a field by shape functions @f$ fts_{ij} = f_i * \varphi_j @f$
template <ElementType type>
void fieldTimesShapes(const Array<Real> & field,
Array<Real> & field_times_shapes,
GhostType ghost_type) const;
/// find natural coords in parent element from real coords provided an element
template <ElementType type>
void inverseMap(const Vector<Real> & real_coords, UInt element,
Vector<Real> & natural_coords,
GhostType ghost_type = _not_ghost) const;
/// find natural coords in sub-element from real coords provided an element
template <ElementType type>
void inverseMap(const Vector<Real> & real_coords, UInt element,
Vector<Real> & natural_coords, UInt sub_element,
GhostType ghost_type = _not_ghost) const;
/// return true if the coordinates provided are inside the element, false
/// otherwise
template <ElementType type>
bool contains(const Vector<Real> & real_coords, UInt elem,
GhostType ghost_type) const;
/// compute the shape on a provided point
template <ElementType type>
void computeShapes(const Vector<Real> & real_coords, UInt elem,
Vector<Real> & shapes, GhostType ghost_type) const;
/// compute the shape derivatives on a provided point
template <ElementType type>
void computeShapeDerivatives(const Matrix<Real> & real_coords, UInt elem,
Tensor3<Real> & shapes,
GhostType ghost_type) const;
/// interpolate a field on a given physical point
template <ElementType type>
void interpolateOnPhysicalPoint(const Vector<Real> & real_coords, UInt elem,
const Array<Real> & field,
Vector<Real> & interpolated,
GhostType ghost_type) const;
/// function to extract values at standard nodes and zero-out enriched values
/// of a nodal field
void extractValuesAtStandardNodes(const Array<Real> & nodal_values,
Array<Real> & extracted_values,
GhostType ghost_type) const;
/// function to print the containt of the class
virtual void printself(std::ostream & stream, int indent = 0) const;
protected:
/// compute the shape derivatives on integration points for a given element
template <ElementType type>
inline void
computeShapeDerivativesOnCPointsByElement(const Matrix<Real> & node_coords,
const Matrix<Real> & natural_coords,
Tensor3<Real> & shapesd) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get a the shapes vector
inline const Array<Real> & getShapes(ElementType el_type,
GhostType ghost_type = _not_ghost) const;
/// get a the shapes derivatives vector
inline const Array<Real> &
getShapesDerivatives(ElementType el_type,
GhostType ghost_type = _not_ghost) const;
/// get a the shapes vector
inline const Array<Real> &
getShapesAtEnrichedNodes(ElementType el_type,
GhostType ghost_type = _not_ghost) const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// shape functions for all elements
ElementTypeMapArray<Real, InterpolationType> shapes;
/// shape functions derivatives for all elements
ElementTypeMapArray<Real, InterpolationType> shapes_derivatives;
/// additional integration points for the IGFEM formulation
ElementTypeMapArray<Real> igfem_integration_points;
/// values of shape functions for all elements on the enriched nodes
ElementTypeMapArray<Real, InterpolationType> shapes_at_enrichments;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "shape_igfem_inline_impl.hh"
/// standard output stream operator
// template <class ShapeFunction>
// inline std::ostream & operator <<(std::ostream & stream, const
// ShapeIGFEM<ShapeFunction> & _this)
// {
// _this.printself(stream);
// return stream;
// }
#endif /* AKANTU_SHAPE_IGFEM_HH_ */
diff --git a/extra_packages/igfem/src/shape_igfem_inline_impl.hh b/extra_packages/igfem/src/shape_igfem_inline_impl.hh
index a7febdfdf..cf284da63 100644
--- a/extra_packages/igfem/src/shape_igfem_inline_impl.hh
+++ b/extra_packages/igfem/src/shape_igfem_inline_impl.hh
@@ -1,731 +1,731 @@
/**
* @file shape_igfem_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief ShapeIGFEM inline implementation
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_IGFEM_INLINE_IMPL_HH_
#define AKANTU_SHAPE_IGFEM_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline const Array<Real> &
ShapeLagrange<_ek_igfem>::getShapes(ElementType el_type,
GhostType ghost_type) const {
return shapes(FEEngine::getInterpolationType(el_type), ghost_type);
}
/* -------------------------------------------------------------------------- */
inline const Array<Real> &
ShapeLagrange<_ek_igfem>::getShapesDerivatives(ElementType el_type,
GhostType ghost_type) const {
return shapes_derivatives(FEEngine::getInterpolationType(el_type),
ghost_type);
}
/* -------------------------------------------------------------------------- */
#define INIT_SHAPE_FUNCTIONS(type) \
setIntegrationPointsByType<type>(integration_points, ghost_type); \
setIntegrationPointsByType<ElementClassProperty<type>::sub_element_type_1>( \
integration_points_1, ghost_type); \
setIntegrationPointsByType<ElementClassProperty<type>::sub_element_type_2>( \
integration_points_2, ghost_type); \
precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type); \
if (ElementClass<type>::getNaturalSpaceDimension() == \
mesh.getSpatialDimension()) \
precomputeShapeDerivativesOnIntegrationPoints<type>(nodes, ghost_type); \
precomputeShapesOnEnrichedNodes<type>(nodes, ghost_type);
inline void ShapeLagrange<_ek_igfem>::initShapeFunctions(
const Array<Real> & nodes, const Matrix<Real> & integration_points,
const Matrix<Real> & integration_points_1,
const Matrix<Real> & integration_points_2, ElementType type,
GhostType ghost_type) {
AKANTU_BOOST_IGFEM_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
}
#undef INIT_SHAPE_FUNCTIONS
/* -------------------------------------------------------------------------- */
template <ElementType type>
inline void ShapeLagrange<_ek_igfem>::computeShapeDerivativesOnCPointsByElement(
const Matrix<Real> & node_coords, const Matrix<Real> & natural_coords,
Tensor3<Real> & shapesd) const {
AKANTU_DEBUG_IN();
// compute dnds
Tensor3<Real> dnds(node_coords.rows(), node_coords.cols(),
natural_coords.cols());
ElementClass<type>::computeDNDS(natural_coords, dnds);
// compute dxds
Tensor3<Real> J(node_coords.rows(), natural_coords.rows(),
natural_coords.cols());
ElementClass<type>::computeJMat(dnds, node_coords, J);
// compute shape derivatives
ElementClass<type>::computeShapeDerivatives(J, dnds, shapesd);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::inverseMap(const Vector<Real> & real_coords,
UInt elem,
Vector<Real> & natural_coords,
UInt sub_element,
GhostType ghost_type) const {
AKANTU_DEBUG_IN();
/// typedef for the two subelement_types and the parent element type
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
UInt nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
- UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage();
+ UInt * elem_val = mesh.getConnectivity(type, ghost_type).data();
Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
- mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.storage(),
+ mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.data(),
elem_val + elem * nb_nodes_per_element,
nb_nodes_per_element, spatial_dimension);
if (!sub_element) {
UInt nb_nodes_sub_el =
ElementClass<sub_type_1>::getNbNodesPerInterpolationElement();
Matrix<Real> sub_el_coords(spatial_dimension, nb_nodes_sub_el);
ElementClass<type>::getSubElementCoords(nodes_coord, sub_el_coords,
sub_element);
ElementClass<sub_type_1>::inverseMap(real_coords, sub_el_coords,
natural_coords);
}
else {
UInt nb_nodes_sub_el =
ElementClass<sub_type_2>::getNbNodesPerInterpolationElement();
Matrix<Real> sub_el_coords(spatial_dimension, nb_nodes_sub_el);
ElementClass<type>::getSubElementCoords(nodes_coord, sub_el_coords,
sub_element);
ElementClass<sub_type_2>::inverseMap(real_coords, sub_el_coords,
natural_coords);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::inverseMap(const Vector<Real> & real_coords,
UInt elem,
Vector<Real> & natural_coords,
GhostType ghost_type) const {
/// map point into parent reference domain
AKANTU_DEBUG_IN();
const ElementType parent_type =
ElementClassProperty<type>::parent_element_type;
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
UInt nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
- UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage();
+ UInt * elem_val = mesh.getConnectivity(type, ghost_type).data();
Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
- mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.storage(),
+ mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.data(),
elem_val + elem * nb_nodes_per_element,
nb_nodes_per_element, spatial_dimension);
UInt nb_nodes_parent_el =
ElementClass<parent_type>::getNbNodesPerInterpolationElement();
Matrix<Real> parent_coords(spatial_dimension, nb_nodes_parent_el);
ElementClass<type>::getParentCoords(nodes_coord, parent_coords);
ElementClass<parent_type>::inverseMap(real_coords, parent_coords,
natural_coords);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
bool ShapeLagrange<_ek_igfem>::contains(const Vector<Real> & real_coords,
UInt elem, GhostType ghost_type) const {
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
Vector<Real> natural_coords(spatial_dimension);
inverseMap<type>(real_coords, elem, natural_coords, ghost_type);
return ElementClass<type>::contains(natural_coords);
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::interpolate(const Vector<Real> & real_coords,
UInt elem,
const Matrix<Real> & nodal_values,
Vector<Real> & interpolated,
GhostType ghost_type) const {
UInt nb_shapes = ElementClass<type>::getShapeSize();
Vector<Real> shapes(nb_shapes);
computeShapes<type>(real_coords, elem, shapes, ghost_type);
ElementClass<type>::interpolate(nodal_values, shapes, interpolated);
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::computeShapes(const Vector<Real> & real_coords,
UInt elem, Vector<Real> & shapes,
GhostType ghost_type) const {
AKANTU_DEBUG_IN();
/// typedef for the two subelement_types and the parent element type
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
const ElementType parent_type =
ElementClassProperty<type>::parent_element_type;
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
/// parent contribution
/// get the size of the parent shapes
UInt size_of_parent_shapes = ElementClass<parent_type>::getShapeSize();
Vector<Real> parent_shapes(size_of_parent_shapes);
/// compute parent shapes -> map shapes in the physical domain of the parent
Vector<Real> natural_coords(spatial_dimension);
Real tol = Math::getTolerance();
Math::setTolerance(1e-14);
inverseMap<type>(real_coords, elem, natural_coords, ghost_type);
ElementClass<parent_type>::computeShapes(natural_coords, parent_shapes);
natural_coords.zero();
/// sub-element contribution
/// check which sub-element contains the physical point
/// check if point is in sub-element 1
inverseMap<type>(real_coords, elem, natural_coords, 0, ghost_type);
if (ElementClass<sub_type_1>::contains(natural_coords)) {
UInt size_of_sub_shapes = ElementClass<sub_type_1>::getShapeSize();
Vector<Real> sub_shapes(size_of_sub_shapes);
ElementClass<sub_type_1>::computeShapes(natural_coords, sub_shapes);
/// assemble shape functions
ElementClass<type>::assembleShapes(parent_shapes, sub_shapes, shapes, 0);
} else {
natural_coords.zero();
inverseMap<type>(real_coords, elem, natural_coords, 1, ghost_type);
AKANTU_DEBUG_ASSERT(ElementClass<sub_type_2>::contains(natural_coords),
"Physical point not contained in any element");
UInt size_of_sub_shapes = ElementClass<sub_type_2>::getShapeSize();
Vector<Real> sub_shapes(size_of_sub_shapes);
ElementClass<sub_type_2>::computeShapes(natural_coords, sub_shapes);
/// assemble shape functions
ElementClass<type>::assembleShapes(parent_shapes, sub_shapes, shapes, 1);
}
Math::setTolerance(tol);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::computeShapeDerivatives(
const Matrix<Real> & real_coords, UInt elem, Tensor3<Real> & shapesd,
GhostType ghost_type) const {
AKANTU_DEBUG_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::precomputeShapesOnIntegrationPoints(
__attribute__((unused)) const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
/// typedef for the two subelement_types and the parent element type
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
const ElementType parent_type =
ElementClassProperty<type>::parent_element_type;
/// get the spatial dimension for the given element type
- UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
+ Int spatial_dimension = ElementClass<type>::getSpatialDimension();
/// get the integration points for the subelements
Matrix<Real> & natural_coords_sub_1 =
integration_points(sub_type_1, ghost_type);
Matrix<Real> & natural_coords_sub_2 =
integration_points(sub_type_2, ghost_type);
/// store the number of quadrature points on each subelement and the toal
/// number
UInt nb_points_sub_1 = natural_coords_sub_1.cols();
UInt nb_points_sub_2 = natural_coords_sub_2.cols();
UInt nb_total_points = nb_points_sub_1 + nb_points_sub_2;
// get the integration points for the parent element
UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize();
Array<Real> & natural_coords_parent = igfem_integration_points.alloc(
nb_element * nb_total_points, spatial_dimension, type, ghost_type);
Array<Real>::matrix_iterator natural_coords_parent_it =
natural_coords_parent.begin_reinterpret(spatial_dimension,
nb_total_points, nb_element);
/// get the size of the shapes
UInt size_of_shapes = ElementClass<type>::getShapeSize();
UInt size_of_parent_shapes = ElementClass<parent_type>::getShapeSize();
UInt size_of_sub_1_shapes = ElementClass<sub_type_1>::getShapeSize();
UInt size_of_sub_2_shapes = ElementClass<sub_type_2>::getShapeSize();
/// initialize the matrices to store the shape functions of the subelements
/// and the parent
Matrix<Real> sub_1_shapes(size_of_sub_1_shapes, nb_points_sub_1);
Matrix<Real> sub_2_shapes(size_of_sub_2_shapes, nb_points_sub_2);
Matrix<Real> parent_1_shapes(size_of_parent_shapes, nb_points_sub_1);
Matrix<Real> parent_2_shapes(size_of_parent_shapes, nb_points_sub_2);
/// compute the shape functions of the subelements
ElementClass<sub_type_1>::computeShapes(natural_coords_sub_1, sub_1_shapes);
ElementClass<sub_type_2>::computeShapes(natural_coords_sub_2, sub_2_shapes);
/// get the nodal coordinates per element
UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
Array<Real>::matrix_iterator x_it =
x_el.begin(spatial_dimension, nb_nodes_per_element);
/// allocate the shapes for the given element type
Array<Real> & shapes_tmp = shapes.alloc(nb_element * nb_total_points,
size_of_shapes, itp_type, ghost_type);
Array<Real>::matrix_iterator shapes_it = shapes_tmp.begin_reinterpret(
ElementClass<type>::getNbNodesPerInterpolationElement(), nb_total_points,
nb_element);
Matrix<Real> physical_points_1(spatial_dimension, nb_points_sub_1);
Matrix<Real> physical_points_2(spatial_dimension, nb_points_sub_2);
Matrix<Real> parent_natural_coords_1(spatial_dimension, nb_points_sub_1);
Matrix<Real> parent_natural_coords_2(spatial_dimension, nb_points_sub_2);
/// intialize the matrices for the parent and subelement coordinates
UInt nb_nodes_parent_el =
ElementClass<parent_type>::getNbNodesPerInterpolationElement();
UInt nb_nodes_sub_el_1 =
ElementClass<sub_type_1>::getNbNodesPerInterpolationElement();
UInt nb_nodes_sub_el_2 =
ElementClass<sub_type_2>::getNbNodesPerInterpolationElement();
Matrix<Real> parent_coords(spatial_dimension, nb_nodes_parent_el);
Matrix<Real> sub_el_1_coords(spatial_dimension, nb_nodes_sub_el_1);
Matrix<Real> sub_el_2_coords(spatial_dimension, nb_nodes_sub_el_2);
/// loop over all elements of the given type and compute the shape functions
Vector<Real> all_shapes(size_of_shapes);
for (UInt elem = 0; elem < nb_element;
++elem, ++shapes_it, ++x_it, ++natural_coords_parent_it) {
Matrix<Real> & N = *shapes_it;
const Matrix<Real> & X = *x_it;
Matrix<Real> & nc_parent = *natural_coords_parent_it;
/// map the sub element integration points into the parent reference domain
ElementClass<type>::mapFromSubRefToParentRef(
X, sub_el_1_coords, parent_coords, sub_1_shapes, physical_points_1,
parent_natural_coords_1, 0);
ElementClass<type>::mapFromSubRefToParentRef(
X, sub_el_2_coords, parent_coords, sub_2_shapes, physical_points_2,
parent_natural_coords_2, 1);
/// compute the parent shape functions on all integration points
ElementClass<sub_type_1>::computeShapes(parent_natural_coords_1,
parent_1_shapes);
ElementClass<sub_type_1>::computeShapes(parent_natural_coords_2,
parent_2_shapes);
/// copy the results into the shape functions iterator and natural coords
/// iterator
for (UInt i = 0; i < nb_points_sub_1; ++i) {
ElementClass<type>::assembleShapes(parent_1_shapes(i), sub_1_shapes(i),
all_shapes, 0);
N(i) = all_shapes;
nc_parent(i) = parent_natural_coords_1(i);
}
for (UInt i = 0; i < nb_points_sub_2; ++i) {
ElementClass<type>::assembleShapes(parent_2_shapes(i), sub_2_shapes(i),
all_shapes, 1);
N(i + nb_points_sub_1) = all_shapes;
/// N(i + nb_points_sub_2) = all_shapes;
nc_parent(i + nb_points_sub_1) = parent_natural_coords_2(i);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::precomputeShapeDerivativesOnIntegrationPoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// typedef for the two subelement_types and the parent element type
const ElementType sub_type_1 = ElementClassProperty<type>::sub_element_type_1;
const ElementType sub_type_2 = ElementClassProperty<type>::sub_element_type_2;
const ElementType parent_type =
ElementClassProperty<type>::parent_element_type;
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
/// get the integration points for the subelements
Matrix<Real> & natural_coords_sub_1 =
integration_points(sub_type_1, ghost_type);
Matrix<Real> & natural_coords_sub_2 =
integration_points(sub_type_2, ghost_type);
/// store the number of quadrature points on each subelement and the toal
/// number
UInt nb_points_sub_1 = natural_coords_sub_1.cols();
UInt nb_points_sub_2 = natural_coords_sub_2.cols();
UInt nb_points_total = nb_points_sub_1 + nb_points_sub_2;
UInt nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
/// intialize the matrices for the parent and subelement coordinates
UInt nb_nodes_parent_el =
ElementClass<parent_type>::getNbNodesPerInterpolationElement();
UInt nb_nodes_sub_el_1 =
ElementClass<sub_type_1>::getNbNodesPerInterpolationElement();
UInt nb_nodes_sub_el_2 =
ElementClass<sub_type_2>::getNbNodesPerInterpolationElement();
Matrix<Real> parent_coords(spatial_dimension, nb_nodes_parent_el);
Matrix<Real> sub_el_1_coords(spatial_dimension, nb_nodes_sub_el_1);
Matrix<Real> sub_el_2_coords(spatial_dimension, nb_nodes_sub_el_2);
UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize();
Array<Real> & shapes_derivatives_tmp = shapes_derivatives.alloc(
nb_element * nb_points_total, size_of_shapesd, itp_type, ghost_type);
/// get an iterator to the coordiantes of the elements
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
- Real * shapesd_val = shapes_derivatives_tmp.storage();
+ Real * shapesd_val = shapes_derivatives_tmp.data();
Array<Real>::matrix_iterator x_it =
x_el.begin(spatial_dimension, nb_nodes_per_element);
/// get an iterator to the integration points of the parent element
Array<Real> & natural_coords_parent =
igfem_integration_points(type, ghost_type);
Array<Real>::matrix_iterator natural_coords_parent_it =
natural_coords_parent.begin_reinterpret(spatial_dimension,
nb_points_total, nb_element);
Tensor3<Real> B_sub_1(spatial_dimension, nb_nodes_sub_el_1, nb_points_sub_1);
Tensor3<Real> B_sub_2(spatial_dimension, nb_nodes_sub_el_2, nb_points_sub_2);
Tensor3<Real> B_parent(spatial_dimension, nb_nodes_parent_el,
nb_points_total);
/// assemble the shape derivatives
Matrix<Real> all_shapes(spatial_dimension, nb_nodes_per_element);
for (UInt elem = 0; elem < nb_element;
++elem, ++x_it, ++natural_coords_parent_it) {
Matrix<Real> & X = *x_it;
Matrix<Real> & nc_parent = *natural_coords_parent_it;
Tensor3<Real> B(shapesd_val, spatial_dimension, nb_nodes_per_element,
nb_points_total);
/// get the coordinates of the two sub elements and the parent element
ElementClass<type>::getSubElementCoords(X, sub_el_1_coords, 0);
ElementClass<type>::getSubElementCoords(X, sub_el_2_coords, 1);
ElementClass<type>::getParentCoords(X, parent_coords);
/// compute the subelements' shape derivatives and the parent shape
/// derivatives
computeShapeDerivativesOnCPointsByElement<sub_type_1>(
sub_el_1_coords, natural_coords_sub_1, B_sub_1);
computeShapeDerivativesOnCPointsByElement<sub_type_2>(
sub_el_2_coords, natural_coords_sub_2, B_sub_2);
computeShapeDerivativesOnCPointsByElement<parent_type>(parent_coords,
nc_parent, B_parent);
for (UInt i = 0; i < nb_points_sub_1; ++i) {
ElementClass<type>::assembleShapeDerivatives(B_parent(i), B_sub_1(i),
all_shapes, 0);
B(i) = all_shapes;
}
for (UInt i = 0; i < nb_points_sub_2; ++i) {
ElementClass<type>::assembleShapeDerivatives(B_parent(i), B_sub_2(i),
all_shapes, 1);
B(i + nb_points_sub_1) = all_shapes;
}
shapesd_val += size_of_shapesd * nb_points_total;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::interpolateOnIntegrationPoints(
const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ GhostType ghost_type, const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
AKANTU_DEBUG_ASSERT(shapes.exists(itp_type, ghost_type),
"No shapes for the type "
<< shapes.printType(itp_type, ghost_type));
UInt nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type,
filter_elements);
this->interpolateElementalFieldOnIntegrationPoints<type>(
u_el, out_uq, ghost_type, shapes(itp_type, ghost_type), filter_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::gradientOnIntegrationPoints(
const Array<Real> & in_u, Array<Real> & out_nablauq,
UInt nb_degree_of_freedom, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
AKANTU_DEBUG_ASSERT(
shapes_derivatives.exists(itp_type, ghost_type),
"No shapes derivatives for the type "
<< shapes_derivatives.printType(itp_type, ghost_type));
UInt nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type,
filter_elements);
this->gradientElementalFieldOnIntegrationPoints<type>(
u_el, out_nablauq, ghost_type, shapes_derivatives(itp_type, ghost_type),
filter_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::fieldTimesShapes(
const Array<Real> & field, Array<Real> & field_times_shapes,
GhostType ghost_type) const {
AKANTU_DEBUG_IN();
field_times_shapes.resize(field.getSize());
UInt size_of_shapes = ElementClass<type>::getShapeSize();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
UInt nb_degree_of_freedom = field.getNbComponent();
const Array<Real> & shape = shapes(itp_type, ghost_type);
Array<Real>::const_matrix_iterator field_it =
field.begin(nb_degree_of_freedom, 1);
Array<Real>::const_matrix_iterator shapes_it = shape.begin(1, size_of_shapes);
Array<Real>::matrix_iterator it =
field_times_shapes.begin(nb_degree_of_freedom, size_of_shapes);
Array<Real>::matrix_iterator end =
field_times_shapes.end(nb_degree_of_freedom, size_of_shapes);
for (; it != end; ++it, ++field_it, ++shapes_it) {
it->mul<false, false>(*field_it, *shapes_it);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::interpolateOnPhysicalPoint(
const Vector<Real> & real_coords, UInt elem, const Array<Real> & field,
Vector<Real> & interpolated, GhostType ghost_type) const {
AKANTU_DEBUG_IN();
Vector<Real> shapes(ElementClass<type>::getShapeSize());
computeShapes<type>(real_coords, elem, shapes, ghost_type);
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
UInt nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
- UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage();
+ UInt * elem_val = mesh.getConnectivity(type, ghost_type).data();
Matrix<Real> nodes_val(spatial_dimension, nb_nodes_per_element);
- mesh.extractNodalValuesFromElement(field, nodes_val.storage(),
+ mesh.extractNodalValuesFromElement(field, nodes_val.data(),
elem_val + elem * nb_nodes_per_element,
nb_nodes_per_element, spatial_dimension);
ElementClass<type>::interpolate(nodes_val, shapes, interpolated);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::precomputeShapesOnEnrichedNodes(
__attribute__((unused)) const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
const ElementType parent_type =
ElementClassProperty<type>::parent_element_type;
const ElementType sub_type = ElementClassProperty<type>::sub_element_type_1;
/// get the spatial dimension for the given element type
- UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
+ Int spatial_dimension = ElementClass<type>::getSpatialDimension();
// get the integration points for the parent element
UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize();
/// get the size of the shapes
UInt nb_enriched_nodes = ElementClass<type>::getNbEnrichments();
UInt nb_parent_nodes =
ElementClass<parent_type>::getNbNodesPerInterpolationElement();
UInt size_of_shapes = ElementClass<type>::getShapeSize();
UInt size_of_parent_shapes = ElementClass<parent_type>::getShapeSize();
UInt size_of_sub_shapes = ElementClass<sub_type>::getShapeSize();
Vector<Real> parent_shapes(size_of_parent_shapes);
Vector<Real> sub_shapes(size_of_sub_shapes);
Vector<Real> shapes(size_of_shapes);
/// get the nodal coordinates per element
UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
Array<Real>::matrix_iterator x_it =
x_el.begin(spatial_dimension, nb_nodes_per_element);
/// allocate the shapes for the given element type
Array<Real> & shapes_tmp = shapes_at_enrichments.alloc(
nb_element * nb_enriched_nodes, size_of_shapes, itp_type, ghost_type);
Array<Real>::matrix_iterator shapes_it = shapes_tmp.begin_reinterpret(
ElementClass<type>::getNbNodesPerInterpolationElement(),
nb_enriched_nodes, nb_element);
Vector<Real> real_coords(spatial_dimension);
Vector<Real> natural_coords(spatial_dimension);
Matrix<Real> parent_coords(spatial_dimension, nb_parent_nodes);
UInt * sub_element_enrichments =
ElementClass<type>::getSubElementEnrichments();
/// loop over all elements
for (UInt elem = 0; elem < nb_element; ++elem, ++shapes_it, ++x_it) {
Matrix<Real> & N = *shapes_it;
const Matrix<Real> & X = *x_it;
for (UInt i = 0; i < nb_enriched_nodes; ++i) {
/// get the parent element coordinates
ElementClass<type>::getParentCoords(X, parent_coords);
/// get the physical coords of the enriched node
real_coords = X(nb_parent_nodes + i);
/// map the physical point into the parent ref domain
ElementClass<parent_type>::inverseMap(real_coords, parent_coords,
natural_coords);
/// compute the parent shape functions
ElementClass<parent_type>::computeShapes(natural_coords, parent_shapes);
/// Sub-element contribution
sub_shapes.zero();
sub_shapes(sub_element_enrichments[i]) = 1.;
ElementClass<type>::assembleShapes(parent_shapes, sub_shapes, shapes, 0);
N(i) = shapes;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_igfem>::interpolateAtEnrichedNodes(
const Array<Real> & src, Array<Real> & dst, GhostType ghost_type) const {
AKANTU_DEBUG_IN();
const ElementType parent_type =
ElementClassProperty<type>::parent_element_type;
UInt nb_element = mesh.getNbElement(type, ghost_type);
UInt nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
UInt nb_parent_nodes =
ElementClass<parent_type>::getNbNodesPerInterpolationElement();
UInt nb_enrichments = ElementClass<type>::getNbEnrichments();
- UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ UInt * elem_val = mesh.getConnectivity(type, ghost_type).data();
+ Int spatial_dimension = mesh.getSpatialDimension();
Matrix<Real> nodes_val(spatial_dimension, nb_nodes_per_element);
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
const Array<Real> & shapes = shapes_at_enrichments(itp_type, ghost_type);
Array<Real>::const_matrix_iterator shapes_it = shapes.begin_reinterpret(
nb_nodes_per_element, nb_enrichments, nb_element);
Array<Real>::vector_iterator dst_vect = dst.begin(spatial_dimension);
Vector<Real> interpolated(spatial_dimension);
- for (UInt e = 0; e < nb_element; ++e, ++shapes_it) {
+ for (Int e = 0; e < nb_element; ++e, ++shapes_it) {
const Matrix<Real> & el_shapes = *shapes_it;
- mesh.extractNodalValuesFromElement(src, nodes_val.storage(),
+ mesh.extractNodalValuesFromElement(src, nodes_val.data(),
elem_val + e * nb_nodes_per_element,
nb_nodes_per_element, spatial_dimension);
;
- for (UInt i = 0; i < nb_enrichments; ++i) {
+ for (Int i = 0; i < nb_enrichments; ++i) {
ElementClass<type>::interpolate(nodes_val, el_shapes(i), interpolated);
UInt enr_node_idx =
elem_val[e * nb_nodes_per_element + nb_parent_nodes + i];
dst_vect[enr_node_idx] = interpolated;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
#define COMPUTE_ENRICHED_VALUES(type) \
interpolateAtEnrichedNodes<type>(src, dst, ghost_type);
inline void ShapeLagrange<_ek_igfem>::interpolateEnrichmentsAllTypes(
const Array<Real> & src, Array<Real> & dst, ElementType type,
GhostType ghost_type) const {
AKANTU_BOOST_IGFEM_ELEMENT_SWITCH(COMPUTE_ENRICHED_VALUES);
}
#undef COMPUTE_ENRICHED_VALUES
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_SHAPE_IGFEM_INLINE_IMPL_HH_ */
diff --git a/extra_packages/igfem/src/solid_mechanics_model_igfem.cc b/extra_packages/igfem/src/solid_mechanics_model_igfem.cc
index e6d1c34f1..4bc35a00f 100644
--- a/extra_packages/igfem/src/solid_mechanics_model_igfem.cc
+++ b/extra_packages/igfem/src/solid_mechanics_model_igfem.cc
@@ -1,573 +1,573 @@
/**
* @file solid_mechanics_model_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief solid mechanics model for IGFEM analysis
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_igfem.hh"
#include "dumpable_inline_impl.hh"
#include "group_manager_inline_impl.hh"
#include "igfem_helper.hh"
#include "material_igfem.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_igfem_element_partition.hh"
#include "dumper_igfem_elemental_field.hh"
#include "dumper_igfem_material_internal_field.hh"
#include "dumper_material_padders.hh"
#include "dumper_paraview.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
const SolidMechanicsModelIGFEMOptions
default_solid_mechanics_model_igfem_options(_static, false);
-SolidMechanicsModelIGFEM::SolidMechanicsModelIGFEM(Mesh & mesh, UInt dim,
+SolidMechanicsModelIGFEM::SolidMechanicsModelIGFEM(Mesh & mesh, Int dim,
const ID & id)
: SolidMechanicsModel(mesh, dim, id), IGFEMEnrichment(mesh),
global_ids_updater(NULL) {
AKANTU_DEBUG_IN();
delete material_selector;
material_selector = new DefaultMaterialIGFEMSelector(*this);
this->registerEventHandler(*this);
this->mesh.registerDumper<DumperParaview>("igfem elements", id);
this->mesh.addDumpMeshToDumper("igfem elements", mesh, spatial_dimension,
_not_ghost, _ek_igfem);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
SolidMechanicsModelIGFEM::~SolidMechanicsModelIGFEM() {
AKANTU_DEBUG_IN();
if (global_ids_updater)
delete global_ids_updater;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::initFull(const ModelOptions & options) {
AKANTU_DEBUG_IN();
/// intialize the IGFEM enrichment
this->initialize();
SolidMechanicsModel::initFull(options);
// set the initial condition to 0
real_force->clear();
real_displacement->clear();
real_residual->clear();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Allocate all the needed vectors. By default their are not necessarily set to
* 0
*
*/
void SolidMechanicsModelIGFEM::initArrays() {
AKANTU_DEBUG_IN();
UInt nb_nodes = mesh.getNbNodes();
std::stringstream sstr_rdisp;
sstr_rdisp << id << ":real_displacement";
std::stringstream sstr_rforc;
sstr_rforc << id << ":real_force";
std::stringstream sstr_rresi;
sstr_rresi << id << ":real_residual";
real_displacement = &(alloc<Real>(sstr_rdisp.str(), nb_nodes,
spatial_dimension, REAL_INIT_VALUE));
real_force = &(alloc<Real>(sstr_rforc.str(), nb_nodes, spatial_dimension,
REAL_INIT_VALUE));
real_residual = &(alloc<Real>(sstr_rresi.str(), nb_nodes, spatial_dimension,
REAL_INIT_VALUE));
SolidMechanicsModel::initArrays();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::initParallel(MeshPartition * partition,
DataAccessor * data_accessor) {
SolidMechanicsModel::initParallel(partition, data_accessor);
this->intersector_sphere.setDistributedSynchronizer(synch_parallel);
if (mesh.isDistributed())
global_ids_updater = new GlobalIdsUpdater(mesh, synch_parallel);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::initMaterials() {
AKANTU_DEBUG_IN();
// make sure the material are instantiated
if (!are_materials_instantiated)
instantiateMaterials();
/// find the first igfem material
UInt igfem_index = 0;
while ((dynamic_cast<MaterialIGFEM *>(materials[igfem_index]) == NULL) &&
igfem_index <= materials.size())
++igfem_index;
AKANTU_DEBUG_ASSERT(igfem_index != materials.size(),
"No igfem materials in the material input file");
DefaultMaterialIGFEMSelector * igfem_mat_selector =
dynamic_cast<DefaultMaterialIGFEMSelector *>(material_selector);
if (igfem_mat_selector != NULL)
igfem_mat_selector->setIGFEMFallback(igfem_index);
SolidMechanicsModel::initMaterials();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Initialize the model, basically pre-compute the shapes, shapes derivatives
* and jacobian
*
*/
void SolidMechanicsModelIGFEM::initModel() {
AKANTU_DEBUG_IN();
SolidMechanicsModel::initModel();
registerFEEngineObject<MyFEEngineIGFEMType>("IGFEMFEEngine", mesh,
spatial_dimension);
/// insert the two feengines associated with the model in the map
this->fe_engines_per_kind[_ek_regular] = &(this->getFEEngine());
this->fe_engines_per_kind[_ek_igfem] = &(this->getFEEngine("IGFEMFEEngine"));
/// add the igfem type connectivities
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType type_ghost = *gt;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, type_ghost);
Mesh::type_iterator last = mesh.lastType(spatial_dimension, type_ghost);
for (; it != last; ++it) {
const Array<UInt> & connectivity = mesh.getConnectivity(*it, type_ghost);
if (connectivity.getSize() != 0) {
ElementType type = *it;
Vector<ElementType> types_igfem = FEEngine::getIGFEMElementTypes(type);
- for (UInt i = 0; i < types_igfem.size(); ++i)
+ for (Int i = 0; i < types_igfem.size(); ++i)
mesh.addConnectivityType(types_igfem(i), type_ghost);
}
}
}
getFEEngine("IGFEMFEEngine").initShapeFunctions(_not_ghost);
getFEEngine("IGFEMFEEngine").initShapeFunctions(_ghost);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::onElementsAdded(const Array<Element> & elements,
const NewElementsEvent & event) {
AKANTU_DEBUG_IN();
const NewIGFEMElementsEvent * igfem_event =
dynamic_cast<const NewIGFEMElementsEvent *>(&event);
/// insert the new and old elements in the map
if (igfem_event != NULL) {
this->element_map.zero();
const Array<Element> & old_elements = igfem_event->getOldElementsList();
- for (UInt e = 0; e < elements.getSize(); ++e) {
+ for (Int e = 0; e < elements.getSize(); ++e) {
this->element_map[elements(e)] = old_elements(e);
}
}
/// update shape functions
getFEEngine("IGFEMFEEngine").initShapeFunctions(_not_ghost);
getFEEngine("IGFEMFEEngine").initShapeFunctions(_ghost);
SolidMechanicsModel::onElementsAdded(elements, event);
this->reassignMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::onElementsRemoved(
const Array<Element> & element_list,
const ElementTypeMapArray<UInt> & new_numbering,
const RemovedElementsEvent & event) {
this->getFEEngine("IGFEMFEEngine").initShapeFunctions(_not_ghost);
this->getFEEngine("IGFEMFEEngine").initShapeFunctions(_ghost);
SolidMechanicsModel::onElementsRemoved(element_list, new_numbering, event);
if (synch_parallel)
synch_parallel->computeAllBufferSizes(*this);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::onNodesAdded(const Array<UInt> & nodes_list,
const NewNodesEvent & event) {
AKANTU_DEBUG_IN();
const NewIGFEMNodesEvent * igfem_event =
dynamic_cast<const NewIGFEMNodesEvent *>(&event);
// update the node type
if (igfem_event != NULL) {
intersector_sphere.updateNodeType(
nodes_list, igfem_event->getNewNodePerElem(),
igfem_event->getElementType(), igfem_event->getGhostType());
}
UInt nb_nodes = mesh.getNbNodes();
if (real_displacement)
real_displacement->resize(nb_nodes);
if (real_force)
real_force->resize(nb_nodes);
if (real_residual)
real_residual->resize(nb_nodes);
if (mesh.isDistributed())
mesh.getGlobalNodesIds().resize(mesh.getNbNodes());
if (displacement)
displacement->resize(nb_nodes);
if (mass)
mass->resize(nb_nodes);
if (velocity)
velocity->resize(nb_nodes);
if (acceleration)
acceleration->resize(nb_nodes);
if (force)
force->resize(nb_nodes);
if (residual)
residual->resize(nb_nodes);
if (blocked_dofs)
blocked_dofs->resize(nb_nodes);
if (previous_displacement)
previous_displacement->resize(nb_nodes);
if (increment_acceleration)
increment_acceleration->resize(nb_nodes);
if (increment)
increment->resize(nb_nodes);
if (current_position)
current_position->resize(nb_nodes);
std::vector<Material *>::iterator mat_it;
for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
(*mat_it)->onNodesAdded(nodes_list, event);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::onNodesRemoved(const Array<UInt> & nodes_list,
const Array<UInt> & new_numbering,
const RemovedNodesEvent & event) {
if (real_displacement)
mesh.removeNodesFromArray(*real_displacement, new_numbering);
if (real_force)
mesh.removeNodesFromArray(*real_force, new_numbering);
if (real_residual)
mesh.removeNodesFromArray(*real_residual, new_numbering);
// communicate global connectivity for slave nodes
if (global_ids_updater)
global_ids_updater->updateGlobalIDs(
mesh.getNbNodes() - intersector_sphere.getNbStandardNodes());
SolidMechanicsModel::onNodesRemoved(nodes_list, new_numbering, event);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::addDumpGroupFieldToDumper(
const std::string & dumper_name, const std::string & field_id,
const std::string & group_name, ElementKind element_kind,
bool padding_flag) {
AKANTU_DEBUG_IN();
ElementKind _element_kind = element_kind;
if (dumper_name == "igfem elements") {
_element_kind = _ek_igfem;
}
SolidMechanicsModel::addDumpGroupFieldToDumper(
dumper_name, field_id, group_name, _element_kind, padding_flag);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::onDump() {
this->computeValuesOnEnrichedNodes();
this->flattenAllRegisteredInternals(_ek_igfem);
SolidMechanicsModel::onDump();
}
/* -------------------------------------------------------------------------- */
dumpers::Field * SolidMechanicsModelIGFEM::createElementalField(
const std::string & field_name, const std::string & group_name,
bool padding_flag, const UInt & spatial_dimension, ElementKind kind) {
dumpers::Field * field = NULL;
if (kind != _ek_igfem)
field = SolidMechanicsModel::createElementalField(
field_name, group_name, padding_flag, spatial_dimension, kind);
else {
if (field_name == "partitions")
field =
mesh.createElementalField<UInt, dumpers::IGFEMElementPartitionField>(
mesh.getConnectivities(), group_name, spatial_dimension, kind);
else if (field_name == "material_index")
field =
mesh.createElementalField<UInt, Vector, dumpers::IGFEMElementalField>(
material_index, group_name, spatial_dimension, kind);
else {
// this copy of field_name is used to compute derivated data such as
// strain and von mises stress that are based on grad_u and stress
std::string field_name_copy(field_name);
if (field_name == "strain" || field_name == "Green strain" ||
field_name == "principal strain" ||
field_name == "principal Green strain")
field_name_copy = "grad_u";
else if (field_name == "Von Mises stress")
field_name_copy = "stress";
bool is_internal = this->isInternal(field_name_copy, kind);
if (is_internal) {
ElementTypeMap<UInt> nb_data_per_elem =
this->getInternalDataPerElem(field_name_copy, kind);
ElementTypeMapArray<Real> & internal_flat =
this->flattenInternal(field_name_copy, kind);
field = mesh.createElementalField<Real,
dumpers::IGFEMInternalMaterialField>(
internal_flat, group_name, spatial_dimension, kind,
nb_data_per_elem);
if (field_name == "strain") {
dumpers::ComputeStrain<false> * foo =
new dumpers::ComputeStrain<false>(*this);
field = dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
} else if (field_name == "Von Mises stress") {
dumpers::ComputeVonMisesStress * foo =
new dumpers::ComputeVonMisesStress(*this);
field = dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
} else if (field_name == "Green strain") {
dumpers::ComputeStrain<true> * foo =
new dumpers::ComputeStrain<true>(*this);
field = dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
} else if (field_name == "principal strain") {
dumpers::ComputePrincipalStrain<false> * foo =
new dumpers::ComputePrincipalStrain<false>(*this);
field = dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
} else if (field_name == "principal Green strain") {
dumpers::ComputePrincipalStrain<true> * foo =
new dumpers::ComputePrincipalStrain<true>(*this);
field = dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
}
/// treat the paddings
if (padding_flag) {
if (field_name == "stress") {
if (spatial_dimension == 2) {
dumpers::StressPadder<2> * foo =
new dumpers::StressPadder<2>(*this);
field =
dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
}
} else if (field_name == "strain" || field_name == "Green strain") {
if (spatial_dimension == 2) {
dumpers::StrainPadder<2> * foo =
new dumpers::StrainPadder<2>(*this);
field =
dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
}
}
}
// homogenize the field
dumpers::ComputeFunctorInterface * foo =
dumpers::HomogenizerProxy::createHomogenizer(*field);
field = dumpers::FieldComputeProxy::createFieldCompute(field, *foo);
}
}
}
// }
return field;
}
/* -------------------------------------------------------------------------- */
dumpers::Field *
SolidMechanicsModelIGFEM::createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) {
std::map<std::string, Array<Real> *> real_nodal_fields;
real_nodal_fields["real_displacement"] = real_displacement;
dumpers::Field * field = NULL;
if (padding_flag)
field = mesh.createNodalField(real_nodal_fields[field_name], group_name, 3);
else
field = mesh.createNodalField(real_nodal_fields[field_name], group_name);
if (field == NULL)
return SolidMechanicsModel::createNodalFieldReal(field_name, group_name,
padding_flag);
return field;
}
#else
/* -------------------------------------------------------------------------- */
dumpers::Field * SolidMechanicsModelIGFEM::createElementalField(
const std::string & field_name, const std::string & group_name,
bool padding_flag, const UInt & spatial_dimension, ElementKind kind) {
return NULL;
}
/* -------------------------------------------------------------------------- */
dumpers::Field *
SolidMechanicsModelIGFEM::createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) {
return NULL;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::computeValuesOnEnrichedNodes() {
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
- for (UInt s = 0; s < spatial_dimension; ++s)
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int s = 0; s < spatial_dimension; ++s)
(*real_displacement)(n, s) = (*displacement)(n, s);
}
Element element;
Vector<Real> real_coords(spatial_dimension);
Vector<Real> interpolated(spatial_dimension);
Array<Real>::const_vector_iterator r_displ_it =
this->real_displacement->begin(spatial_dimension);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
element.ghost_type = *gt;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, *gt, _ek_igfem);
Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_igfem);
for (; it != last; ++it) {
element.type = *it;
UInt nb_element = mesh.getNbElement(*it, *gt);
if (!nb_element)
continue;
- UInt * elem_val = mesh.getConnectivity(*it, *gt).storage();
+ UInt * elem_val = mesh.getConnectivity(*it, *gt).data();
UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it);
Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
Matrix<Real> displ_val(spatial_dimension, nb_nodes_per_element);
UInt nb_enriched_nodes = IGFEMHelper::getNbEnrichedNodes(*it);
UInt nb_parent_nodes = IGFEMHelper::getNbParentNodes(*it);
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
element.element = el;
/// get the node coordinates of the element
- mesh.extractNodalValuesFromElement(
- mesh.getNodes(), nodes_coord.storage(),
- elem_val + el * nb_nodes_per_element, nb_nodes_per_element,
- spatial_dimension);
+ mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.data(),
+ elem_val + el * nb_nodes_per_element,
+ nb_nodes_per_element,
+ spatial_dimension);
/// get the displacement values at the nodes of the element
mesh.extractNodalValuesFromElement(
- *(this->displacement), displ_val.storage(),
+ *(this->displacement), displ_val.data(),
elem_val + el * nb_nodes_per_element, nb_nodes_per_element,
spatial_dimension);
- for (UInt i = 0; i < nb_enriched_nodes; ++i) {
+ for (Int i = 0; i < nb_enriched_nodes; ++i) {
/// coordinates of enriched node
real_coords = nodes_coord(nb_parent_nodes + i);
/// global index of the enriched node
UInt idx = elem_val[el * nb_nodes_per_element + nb_parent_nodes + i];
/// compute the real displacement value
this->getFEEngine("IGFEMFEEngine")
.interpolate(real_coords, displ_val, interpolated, element);
r_displ_it[idx] = interpolated;
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::transferInternalValues(
const ID & internal, std::vector<Element> & new_elements,
Array<Real> & added_quads, Array<Real> & internal_values) {
/// @todo sort the new elements by their corresponding old element type and
/// old material!!!
/// get the number of elements for which iternals need to be transfered
UInt nb_new_elements = new_elements.size();
UInt nb_new_quads = added_quads.getSize() / nb_new_elements;
Array<Real>::const_matrix_iterator quad_coords =
added_quads.begin_reinterpret(this->spatial_dimension, nb_new_quads,
nb_new_elements);
UInt nb_internal_component = internal_values.getNbComponent();
Array<Real>::matrix_iterator internal_val = internal_values.begin_reinterpret(
nb_internal_component, nb_new_quads, nb_new_elements);
Vector<Real> default_values(nb_internal_component, 0.);
- for (UInt e = 0; e < nb_new_elements; ++e, ++quad_coords, ++internal_val) {
+ for (Int e = 0; e < nb_new_elements; ++e, ++quad_coords, ++internal_val) {
Element new_element = new_elements[e];
Element old_element = this->element_map[new_element];
UInt mat_idx = (this->material_index(
old_element.type, old_element.ghost_type))(old_element.element);
Material & old_material = *(this->materials[mat_idx]);
old_material.extrapolateInternal(internal, old_element, *quad_coords,
*internal_val);
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelIGFEM::applyEigenGradU(
const Matrix<Real> & prescribed_eigen_grad_u, const ID & material_name,
const GhostType ghost_type) {
AKANTU_DEBUG_ASSERT(prescribed_eigen_grad_u.size() ==
spatial_dimension * spatial_dimension,
"The prescribed grad_u is not of the good size");
std::vector<Material *>::iterator mat_it;
for (mat_it = this->materials.begin(); mat_it != this->materials.end();
++mat_it) {
MaterialIGFEM * mat_igfem = dynamic_cast<MaterialIGFEM *>(*mat_it);
if (mat_igfem != NULL)
mat_igfem->applyEigenGradU(prescribed_eigen_grad_u, material_name,
ghost_type);
else if ((*mat_it)->getName() == material_name)
(*mat_it)->applyEigenGradU(prescribed_eigen_grad_u, ghost_type);
}
}
} // namespace akantu
diff --git a/extra_packages/igfem/src/solid_mechanics_model_igfem.hh b/extra_packages/igfem/src/solid_mechanics_model_igfem.hh
index c9f893958..aa875b2d5 100644
--- a/extra_packages/igfem/src/solid_mechanics_model_igfem.hh
+++ b/extra_packages/igfem/src/solid_mechanics_model_igfem.hh
@@ -1,196 +1,195 @@
/**
* @file solid_mechanics_model_igfem.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief solid mechanics model for IGFEM analysis
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLID_MECHANICS_MODEL_IGFEM_HH_
#define AKANTU_SOLID_MECHANICS_MODEL_IGFEM_HH_
#include "global_ids_updater.hh"
#include "igfem_enrichment.hh"
#include "solid_mechanics_model.hh"
#include "solid_mechanics_model_event_handler.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
struct SolidMechanicsModelIGFEMOptions : public SolidMechanicsModelOptions {
SolidMechanicsModelIGFEMOptions(AnalysisMethod analysis_method = _static,
bool no_init_materials = false)
: SolidMechanicsModelOptions(analysis_method, no_init_materials) {}
};
extern const SolidMechanicsModelIGFEMOptions
default_solid_mechanics_model_igfem_options;
/* -------------------------------------------------------------------------- */
/* Solid Mechanics Model for IGFEM analysis */
/* -------------------------------------------------------------------------- */
class SolidMechanicsModelIGFEM : public SolidMechanicsModel,
public SolidMechanicsModelEventHandler,
public IGFEMEnrichment {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem>
MyFEEngineIGFEMType;
typedef std::map<Element, Element> ElementMap;
typedef std::map<ElementKind, FEEngine *> FEEnginesPerKindMap;
- SolidMechanicsModelIGFEM(Mesh & mesh,
- UInt spatial_dimension = _all_dimensions,
+ SolidMechanicsModelIGFEM(Mesh & mesh, Int spatial_dimension = _all_dimensions,
const ID & id = "solid_mechanics_model_igfem");
virtual ~SolidMechanicsModelIGFEM();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the cohesive model
virtual void initFull(const ModelOptions & options =
default_solid_mechanics_model_igfem_options);
/// initialize the model
virtual void initModel();
/// initialize igfem material
virtual void initMaterials();
/// register the tags associated with the parallel synchronizer
virtual void initParallel(MeshPartition * partition,
DataAccessor * data_accessor = NULL);
/// allocate all vectors
virtual void initArrays();
/// transfer internals from old to new elements
void transferInternalValues(const ID & internal,
std::vector<Element> & new_elements,
Array<Real> & added_quads,
Array<Real> & internal_values);
/// compute the barycenter for a sub-element
inline void getSubElementBarycenter(UInt element, UInt sub_element,
ElementType type,
Vector<Real> & barycenter,
GhostType ghost_type) const;
/// apply a constant eigen_grad_u on all quadrature points of a given material
virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
const ID & material_name,
const GhostType ghost_type = _not_ghost);
private:
/// compute the real values of displacement, force, etc. on the enriched nodes
void computeValuesOnEnrichedNodes();
/* ------------------------------------------------------------------------ */
/* Mesh Event Handler inherited members */
/* ------------------------------------------------------------------------ */
protected:
virtual void onNodesAdded(const Array<UInt> & nodes_list,
const NewNodesEvent & event);
virtual void onNodesRemoved(const Array<UInt> & element_list,
const Array<UInt> & new_numbering,
const RemovedNodesEvent & event);
virtual void onElementsAdded(const Array<Element> & nodes_list,
const NewElementsEvent & event);
virtual void
onElementsRemoved(const Array<Element> & element_list,
const ElementTypeMapArray<UInt> & new_numbering,
const RemovedElementsEvent & event);
/* ------------------------------------------------------------------------ */
/* Dumpable interface */
/* ------------------------------------------------------------------------ */
public:
virtual void onDump();
virtual void addDumpGroupFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name,
ElementKind element_kind,
bool padding_flag);
virtual dumpers::Field * createElementalField(const std::string & field_name,
const std::string & group_name,
bool padding_flag,
const UInt & spatial_dimension,
ElementKind kind);
virtual dumpers::Field * createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag);
/* --------------------------------------------------------------------------
*/
/* Accessors */
/* --------------------------------------------------------------------------
*/
public:
/// get the fe-engines per kind
AKANTU_GET_MACRO(FEEnginesPerKind, fe_engines_per_kind,
const FEEnginesPerKindMap &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// real displacements array
Array<Real> * real_displacement;
/// real forces array
Array<Real> * real_force;
/// real residuals array
Array<Real> * real_residual;
/// map between and new elements (needed when the interface is moving)
ElementMap element_map;
/// global connectivity ids updater
GlobalIdsUpdater * global_ids_updater;
/// map between element kind and corresponding FEEngine object
FEEnginesPerKindMap fe_engines_per_kind;
};
/* -------------------------------------------------------------------------- */
/* IGFEMMaterialSelector */
/* -------------------------------------------------------------------------- */
class DefaultMaterialIGFEMSelector : public DefaultMaterialSelector {
public:
DefaultMaterialIGFEMSelector(const SolidMechanicsModelIGFEM & model)
: DefaultMaterialSelector(model.getMaterialByElement()),
fallback_value_igfem(0) {}
virtual UInt operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_igfem)
return fallback_value_igfem;
else
return DefaultMaterialSelector::operator()(element);
}
void setIGFEMFallback(UInt f) { this->fallback_value_igfem = f; }
protected:
UInt fallback_value_igfem;
};
} // namespace akantu
#if defined(AKANTU_INCLUDE_INLINE_IMPL)
#include "solid_mechanics_model_igfem_inline_impl.hh"
#endif
#endif /* AKANTU_SOLID_MECHANICS_MODEL_IGFEM_HH_ */
diff --git a/extra_packages/igfem/src/solid_mechanics_model_igfem_inline_impl.hh b/extra_packages/igfem/src/solid_mechanics_model_igfem_inline_impl.hh
index 3158409f9..5dcd3e2a7 100644
--- a/extra_packages/igfem/src/solid_mechanics_model_igfem_inline_impl.hh
+++ b/extra_packages/igfem/src/solid_mechanics_model_igfem_inline_impl.hh
@@ -1,59 +1,59 @@
/**
* @file solid_mechanics_model_igfem_inline_impl.hh
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Wed Nov 4 15:53:52 2015
*
* @brief Implementation on inline functions for SMMIGFEM
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLID_MECHANICS_MODEL_IGFEM_INLINE_IMPL_HH_
#define AKANTU_SOLID_MECHANICS_MODEL_IGFEM_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline void SolidMechanicsModelIGFEM::getSubElementBarycenter(
UInt element, UInt sub_element, ElementType type, Vector<Real> & barycenter,
GhostType ghost_type) const {
- UInt * conn_val = this->mesh.getConnectivity(type, ghost_type).storage();
+ UInt * conn_val = this->mesh.getConnectivity(type, ghost_type).data();
UInt nb_sub_element_nodes =
IGFEMHelper::getNbNodesPerSubElement(type, sub_element);
UInt * sub_el_conn =
IGFEMHelper::getSubElementConnectivity(type, sub_element);
UInt nb_nodes_per_element = this->mesh.getNbNodesPerElement(type);
const Array<Real> & node_coords = this->mesh.getNodes();
Real local_coord[spatial_dimension * nb_sub_element_nodes];
UInt offset = element * nb_nodes_per_element;
- for (UInt n = 0; n < nb_sub_element_nodes; ++n) {
+ for (Int n = 0; n < nb_sub_element_nodes; ++n) {
UInt index = conn_val[offset + sub_el_conn[n]];
memcpy(local_coord + n * spatial_dimension,
- node_coords.storage() + index * spatial_dimension,
+ node_coords.data() + index * spatial_dimension,
spatial_dimension * sizeof(Real));
}
Math::barycenter(local_coord, nb_sub_element_nodes, spatial_dimension,
- barycenter.storage());
+ barycenter.data());
}
} // namespace akantu
#endif /* AKANTU_SOLID_MECHANICS_MODEL_IGFEM_INLINE_IMPL_HH_ */
diff --git a/extra_packages/igfem/test/patch_tests/test_igfem_triangle_4.cc b/extra_packages/igfem/test/patch_tests/test_igfem_triangle_4.cc
index 14a3c6ca6..4cc51dc2b 100644
--- a/extra_packages/igfem/test/patch_tests/test_igfem_triangle_4.cc
+++ b/extra_packages/igfem/test/patch_tests/test_igfem_triangle_4.cc
@@ -1,265 +1,265 @@
/**
* @file test_igfem_triangle_4.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief patch tests with elements of type _igfem_triangle_4
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class StraightInterfaceMatSelector
: public MeshDataMaterialSelector<std::string> {
public:
StraightInterfaceMatSelector(const ID & id, SolidMechanicsModelIGFEM & model)
: MeshDataMaterialSelector<std::string>(id, model) {}
UInt operator()(const Element & elem) {
if (Mesh::getKind(elem.type) == _ek_igfem)
/// choose IGFEM material
return 2;
return MeshDataMaterialSelector<std::string>::operator()(elem);
}
};
Real computeL2Error(SolidMechanicsModelIGFEM & model);
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
/// create a mesh and read the regular elements from the mesh file
/// mesh creation
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("test_mesh.msh");
/// model creation
SolidMechanicsModelIGFEM model(mesh);
/// creation of material selector
MeshDataMaterialSelector<std::string> * mat_selector;
mat_selector = new StraightInterfaceMatSelector("physical_names", model);
model.setMaterialSelector(*mat_selector);
model.initFull();
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
model.addDumpField("blocked_dofs");
model.addDumpField("stress");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
model.addDumpFieldVectorToDumper("igfem elements", "real_displacement");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "stress");
/// dump mesh before the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// create the interace: the bi-material interface is a straight line
/// since the SMMIGFEM has only a sphere intersector we generate a large
/// sphere so that the intersection points with the mesh lie almost along
/// the straight line x = 0.25. We then move the interface nodes to correct
/// their position and make them lie exactly along the line. This is a
/// workaround to generate a straight line with the sphere intersector.
/// Ideally, there should be a new type of IGFEM enrichment implemented to
/// generate straight lines
std::list<SK::Sphere_3> sphere_list;
SK::Sphere_3 sphere_1(SK::Point_3(1000000000.5, 0., 0.),
1000000000. * 1000000000);
sphere_list.push_back(sphere_1);
model.registerGeometryObject(sphere_list, "inside");
model.update();
if ((mesh.getNbElement(_igfem_triangle_4) != 4) ||
(mesh.getNbElement(_igfem_triangle_5) != 0)) {
std::cout << "something went wrong in the interface creation" << std::endl;
finalize();
return EXIT_FAILURE;
}
/// dump mesh after the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// apply the boundary conditions: left and bottom side on rollers
/// imposed displacement along right side
mesh.computeBoundingBox();
const Vector<Real> & lower_bounds = mesh.getLowerBounds();
const Vector<Real> & upper_bounds = mesh.getUpperBounds();
Real bottom = lower_bounds(1);
Real left = lower_bounds(0);
Real right = upper_bounds(0);
Real eps = std::abs((right - left) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & boun = model.getBlockedDOFs();
for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
if (std::abs(pos(i, 1) - bottom) < eps) {
boun(i, 1) = true;
disp(i, 1) = 0.0;
}
if (std::abs(pos(i, 0) - left) < eps) {
boun(i, 0) = true;
disp(i, 0) = 0.0;
}
if (std::abs(pos(i, 0) - right) < eps) {
boun(i, 0) = true;
disp(i, 0) = 1.0;
}
}
/// compute the volume of the mesh
Real int_volume = 0.;
std::map<ElementKind, FEEngine *> fe_engines = model.getFEEnginesPerKind();
std::map<ElementKind, FEEngine *>::const_iterator fe_it = fe_engines.begin();
for (; fe_it != fe_engines.end(); ++fe_it) {
ElementKind kind = fe_it->first;
FEEngine & fe_engine = *(fe_it->second);
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, _not_ghost, kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, _not_ghost, kind);
for (; it != last_type; ++it) {
ElementType type = *it;
Array<Real> Volume(mesh.getNbElement(type) *
fe_engine.getNbIntegrationPoints(type),
1, 1.);
int_volume += fe_engine.integrate(Volume, type);
}
}
if (!Math::are_float_equal(int_volume, 4)) {
std::cout << "Error in area computation of the 2D mesh" << std::endl;
return EXIT_FAILURE;
}
std::cout << "the area of the mesh is: " << int_volume << std::endl;
/// solve the system
model.assembleStiffnessMatrix();
Real error = 0;
bool converged = false;
bool factorize = false;
converged = model.solveStep<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
1e-12, error, 2, factorize);
if (!converged) {
std::cout << "The solver did not converge!!! The error is: " << error
<< std::endl;
finalize();
return EXIT_FAILURE;
}
/// dump the deformed mesh
model.dump();
model.dump("igfem elements");
Real L2_error = computeL2Error(model);
std::cout << "Error: " << L2_error << std::endl;
if (L2_error > 1e-14) {
finalize();
std::cout << "The patch test did not pass!!!!" << std::endl;
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
Real computeL2Error(SolidMechanicsModelIGFEM & model) {
/// store the error on each element for visualization
ElementTypeMapReal error_per_element("error_per_element");
Real error = 0;
Real normalization = 0;
/// Young's moduli for the two materials
Real E_1 = 10.;
Real E_2 = 1.;
Mesh & mesh = model.getMesh();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
mesh.addDumpFieldExternal("error_per_element", error_per_element,
spatial_dimension, _not_ghost, _ek_regular);
mesh.addDumpFieldExternalToDumper("igfem elements", "error_per_element",
error_per_element, spatial_dimension,
_not_ghost, _ek_igfem);
ElementTypeMapReal quad_coords("quad_coords");
GhostType ghost_type = _not_ghost;
const std::map<ElementKind, FEEngine *> & fe_engines =
model.getFEEnginesPerKind();
std::map<ElementKind, FEEngine *>::const_iterator fe_it = fe_engines.begin();
for (; fe_it != fe_engines.end(); ++fe_it) {
ElementKind kind = fe_it->first;
FEEngine & fe_engine = *(fe_it->second);
mesh.initElementTypeMapArray(quad_coords, spatial_dimension,
spatial_dimension, false, kind, true);
mesh.initElementTypeMapArray(error_per_element, 1, spatial_dimension, false,
kind, true);
fe_engine.computeIntegrationPointsCoordinates(quad_coords);
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, ghost_type, kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, ghost_type, kind);
for (; it != last_type; ++it) {
ElementType type = *it;
UInt nb_elements = mesh.getNbElement(type, ghost_type);
UInt nb_quads = fe_engine.getNbIntegrationPoints(type);
/// interpolate the displacement at the quadrature points
Array<Real> displ_on_quads(nb_quads * nb_elements, spatial_dimension,
"displ_on_quads");
Array<Real> quad_coords(nb_quads * nb_elements, spatial_dimension,
"quad_coords");
fe_engine.interpolateOnIntegrationPoints(
model.getDisplacement(), displ_on_quads, spatial_dimension, type);
fe_engine.computeIntegrationPointsCoordinates(quad_coords, type,
ghost_type);
Array<Real> & el_error = error_per_element(type, ghost_type);
Array<Real>::const_vector_iterator displ_it =
displ_on_quads.begin(spatial_dimension);
Array<Real>::const_vector_iterator coord_it =
quad_coords.begin(spatial_dimension);
Vector<Real> error_vec(spatial_dimension);
- for (UInt e = 0; e < nb_elements; ++e) {
+ for (Int e = 0; e < nb_elements; ++e) {
Vector<Real> error_per_quad(nb_quads);
Vector<Real> normalization_per_quad(nb_quads);
- for (UInt q = 0; q < nb_quads; ++q, ++displ_it, ++coord_it) {
+ for (Int q = 0; q < nb_quads; ++q, ++displ_it, ++coord_it) {
Real exact = 0.;
Real x = (*coord_it)(0);
if (x < 0.5)
exact = (2. * x * E_2) / (E_1 + 3. * E_2) +
(2. * E_2) / (E_1 + 3. * E_2);
else
exact = 2. * x * E_1 / (E_1 + 3. * E_2) -
(E_1 - 3. * E_2) / (E_1 + 3. * E_2);
error_vec = *displ_it;
error_vec(0) -= exact;
error_per_quad(q) = error_vec.dot(error_vec);
normalization_per_quad(q) = std::abs(exact) * std::abs(exact);
std::cout << error_vec << std::endl;
}
/// integrate the error in the element and the corresponding
/// normalization
Real int_error =
fe_engine.integrate(error_per_quad, type, e, ghost_type);
error += int_error;
el_error(e) = std::sqrt(int_error);
normalization +=
fe_engine.integrate(normalization_per_quad, type, e, ghost_type);
}
}
}
model.dump();
model.dump("igfem elements");
return (std::sqrt(error) / std::sqrt(normalization));
}
diff --git a/extra_packages/igfem/test/patch_tests/test_igfem_triangle_5.cc b/extra_packages/igfem/test/patch_tests/test_igfem_triangle_5.cc
index fccb2736a..bd26e2948 100644
--- a/extra_packages/igfem/test/patch_tests/test_igfem_triangle_5.cc
+++ b/extra_packages/igfem/test/patch_tests/test_igfem_triangle_5.cc
@@ -1,275 +1,275 @@
/**
* @file test_igfem_triangle_5.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief patch tests with elements of type _igfem_triangle_5
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class StraightInterfaceMatSelector
: public MeshDataMaterialSelector<std::string> {
public:
StraightInterfaceMatSelector(const ID & id, SolidMechanicsModelIGFEM & model)
: MeshDataMaterialSelector<std::string>(id, model) {}
UInt operator()(const Element & elem) {
if (Mesh::getKind(elem.type) == _ek_igfem)
/// choose IGFEM material
return 2;
return MeshDataMaterialSelector<std::string>::operator()(elem);
}
};
Real computeL2Error(SolidMechanicsModelIGFEM & model);
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
/// create a mesh and read the regular elements from the mesh file
/// mesh creation
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("plate.msh");
/// model creation
SolidMechanicsModelIGFEM model(mesh);
/// creation of material selector
MeshDataMaterialSelector<std::string> * mat_selector;
mat_selector = new StraightInterfaceMatSelector("physical_names", model);
model.setMaterialSelector(*mat_selector);
model.initFull();
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
model.addDumpField("blocked_dofs");
model.addDumpField("stress");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
model.addDumpFieldVectorToDumper("igfem elements", "real_displacement");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "stress");
/// dump mesh before the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// create the interace: the bi-material interface is a straight line
/// since the SMMIGFEM has only a sphere intersector we generate a large
/// sphere so that the intersection points with the mesh lie almost along
/// the straight line x = 0.25. We then move the interface nodes to correct
/// their position and make them lie exactly along the line. This is a
/// workaround to generate a straight line with the sphere intersector.
/// Ideally, there should be a new type of IGFEM enrichment implemented to
/// generate straight lines
std::list<SK::Sphere_3> sphere_list;
SK::Sphere_3 sphere_1(SK::Point_3(6.57, 0., 0.), 6.32 * 6.32);
sphere_list.push_back(sphere_1);
model.registerGeometryObject(sphere_list, "inside");
UInt nb_regular_nodes = mesh.getNbNodes();
model.update();
UInt nb_igfem_nodes = mesh.getNbNodes() - nb_regular_nodes;
/// adjust the positions of the node to have an exact straight line
Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes());
Array<Real>::vector_iterator nodes_it = nodes.begin(spatial_dimension);
nodes_it += nb_regular_nodes;
for (UInt i = 0; i < nb_igfem_nodes; ++i, ++nodes_it) {
Vector<Real> & node_coords = *nodes_it;
node_coords(0) = 0.25;
Int multiplier = std::round(node_coords(1) / 0.25);
node_coords(1) = 0.25 * multiplier;
}
/// reinitialize the shape functions because node coordinates have changed
model.getFEEngine("IGFEMFEEngine").initShapeFunctions(_not_ghost);
model.getFEEngine("IGFEMFEEngine").initShapeFunctions(_ghost);
/// dump mesh after the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// apply the boundary conditions: left and bottom side on rollers
/// imposed displacement along right side
mesh.computeBoundingBox();
const Vector<Real> & lower_bounds = mesh.getLowerBounds();
const Vector<Real> & upper_bounds = mesh.getUpperBounds();
Real bottom = lower_bounds(1);
Real left = lower_bounds(0);
Real right = upper_bounds(0);
Real eps = std::abs((right - left) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & boun = model.getBlockedDOFs();
for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
if (std::abs(pos(i, 1) - bottom) < eps) {
boun(i, 1) = true;
disp(i, 1) = 0.0;
}
if (std::abs(pos(i, 0) - left) < eps) {
boun(i, 0) = true;
disp(i, 0) = 0.0;
}
if (std::abs(pos(i, 0) - right) < eps) {
boun(i, 0) = true;
disp(i, 0) = 1.0;
}
}
/// compute the volume of the mesh
Real int_volume = 0.;
std::map<ElementKind, FEEngine *> fe_engines = model.getFEEnginesPerKind();
std::map<ElementKind, FEEngine *>::const_iterator fe_it = fe_engines.begin();
for (; fe_it != fe_engines.end(); ++fe_it) {
ElementKind kind = fe_it->first;
FEEngine & fe_engine = *(fe_it->second);
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, _not_ghost, kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, _not_ghost, kind);
for (; it != last_type; ++it) {
ElementType type = *it;
Array<Real> Volume(mesh.getNbElement(type) *
fe_engine.getNbIntegrationPoints(type),
1, 1.);
int_volume += fe_engine.integrate(Volume, type);
}
}
if (!Math::are_float_equal(int_volume, 4)) {
std::cout << "Error in area computation of the 2D mesh" << std::endl;
return EXIT_FAILURE;
}
std::cout << "the area of the mesh is: " << int_volume << std::endl;
/// solve the system
model.assembleStiffnessMatrix();
Real error = 0;
bool converged = false;
bool factorize = false;
converged = model.solveStep<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
1e-12, error, 2, factorize);
if (!converged) {
std::cout << "The solver did not converge!!! The error is: " << error
<< std::endl;
finalize();
return EXIT_FAILURE;
}
/// dump the deformed mesh
model.dump();
model.dump("igfem elements");
Real L2_error = computeL2Error(model);
std::cout << "Error: " << L2_error << std::endl;
if (L2_error > 1e-12) {
finalize();
std::cout << "The patch test did not pass!!!!" << std::endl;
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
Real computeL2Error(SolidMechanicsModelIGFEM & model) {
/// store the error on each element for visualization
ElementTypeMapReal error_per_element("error_per_element");
Real error = 0;
Real normalization = 0;
/// Young's moduli for the two materials
Real E_1 = 10.;
Real E_2 = 1.;
Mesh & mesh = model.getMesh();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
mesh.addDumpFieldExternal("error_per_element", error_per_element,
spatial_dimension, _not_ghost, _ek_regular);
mesh.addDumpFieldExternalToDumper("igfem elements", "error_per_element",
error_per_element, spatial_dimension,
_not_ghost, _ek_igfem);
ElementTypeMapReal quad_coords("quad_coords");
GhostType ghost_type = _not_ghost;
const std::map<ElementKind, FEEngine *> & fe_engines =
model.getFEEnginesPerKind();
std::map<ElementKind, FEEngine *>::const_iterator fe_it = fe_engines.begin();
for (; fe_it != fe_engines.end(); ++fe_it) {
ElementKind kind = fe_it->first;
FEEngine & fe_engine = *(fe_it->second);
mesh.initElementTypeMapArray(quad_coords, spatial_dimension,
spatial_dimension, false, kind, true);
mesh.initElementTypeMapArray(error_per_element, 1, spatial_dimension, false,
kind, true);
fe_engine.computeIntegrationPointsCoordinates(quad_coords);
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, ghost_type, kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, ghost_type, kind);
for (; it != last_type; ++it) {
ElementType type = *it;
UInt nb_elements = mesh.getNbElement(type, ghost_type);
UInt nb_quads = fe_engine.getNbIntegrationPoints(type);
/// interpolate the displacement at the quadrature points
Array<Real> displ_on_quads(nb_quads * nb_elements, spatial_dimension,
"displ_on_quads");
Array<Real> quad_coords(nb_quads * nb_elements, spatial_dimension,
"quad_coords");
fe_engine.interpolateOnIntegrationPoints(
model.getDisplacement(), displ_on_quads, spatial_dimension, type);
fe_engine.computeIntegrationPointsCoordinates(quad_coords, type,
ghost_type);
Array<Real> & el_error = error_per_element(type, ghost_type);
Array<Real>::const_vector_iterator displ_it =
displ_on_quads.begin(spatial_dimension);
Array<Real>::const_vector_iterator coord_it =
quad_coords.begin(spatial_dimension);
Vector<Real> error_vec(spatial_dimension);
- for (UInt e = 0; e < nb_elements; ++e) {
+ for (Int e = 0; e < nb_elements; ++e) {
Vector<Real> error_per_quad(nb_quads);
Vector<Real> normalization_per_quad(nb_quads);
- for (UInt q = 0; q < nb_quads; ++q, ++displ_it, ++coord_it) {
+ for (Int q = 0; q < nb_quads; ++q, ++displ_it, ++coord_it) {
Real exact = 0.;
Real x = (*coord_it)(0);
if (x < 0.25)
exact = (4. * x * E_2) / (3. * E_1 + 5. * E_2) +
(4. * E_2) / (3. * E_1 + 5. * E_2);
else
exact = 4. * x * E_1 / (3. * E_1 + 5. * E_2) -
(E_1 - 5. * E_2) / (3. * E_1 + 5. * E_2);
error_vec = *displ_it;
error_vec(0) -= exact;
error_per_quad(q) = error_vec.dot(error_vec);
normalization_per_quad(q) = std::abs(exact) * std::abs(exact);
std::cout << error_vec << std::endl;
}
/// integrate the error in the element and the corresponding
/// normalization
Real int_error =
fe_engine.integrate(error_per_quad, type, e, ghost_type);
error += int_error;
el_error(e) = std::sqrt(int_error);
normalization +=
fe_engine.integrate(normalization_per_quad, type, e, ghost_type);
}
}
}
model.dump();
model.dump("igfem elements");
return (std::sqrt(error) / std::sqrt(normalization));
}
diff --git a/extra_packages/igfem/test/patch_tests/test_interface_position.cc b/extra_packages/igfem/test/patch_tests/test_interface_position.cc
index b7f12cd8e..63af8feb9 100644
--- a/extra_packages/igfem/test/patch_tests/test_interface_position.cc
+++ b/extra_packages/igfem/test/patch_tests/test_interface_position.cc
@@ -1,350 +1,350 @@
/**
* @file test_interface_position.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief patch test for interface close to standard nodes
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
Real computeL2Error(SolidMechanicsModelIGFEM & model,
ElementTypeMapReal & error_per_element);
int main(int argc, char * argv[]) {
initialize("material_test_interface_position.dat", argc, argv);
StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// create a mesh and read the regular elements from the mesh file
/// mesh creation
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("test_interface_position.msh");
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
model.initFull();
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
model.addDumpField("blocked_dofs");
model.addDumpField("stress");
model.addDumpField("partitions");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
model.addDumpFieldVectorToDumper("igfem elements", "real_displacement");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "stress");
model.addDumpFieldToDumper("igfem elements", "partitions");
/// dump mesh before the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// create the interace:
UInt nb_standard_nodes = mesh.getNbNodes();
std::list<SK::Sphere_3> sphere_list;
SK::Sphere_3 sphere_1(SK::Point_3(0., 0., 0.), 0.25 * 0.25);
sphere_list.push_back(sphere_1);
model.registerGeometryObject(sphere_list, "inside");
model.update();
/// dump mesh after the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// apply the boundary conditions: left and bottom side on rollers
/// imposed displacement along right side
mesh.computeBoundingBox();
const Vector<Real> & lower_bounds = mesh.getLowerBounds();
const Vector<Real> & upper_bounds = mesh.getUpperBounds();
Real bottom = lower_bounds(1);
Real left = lower_bounds(0);
Real right = upper_bounds(0);
Real eps = std::abs((right - left) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & boun = model.getBlockedDOFs();
for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
if (std::abs(pos(i, 1) - bottom) < eps) {
boun(i, 1) = true;
disp(i, 1) = 0.0;
}
if (std::abs(pos(i, 0) - left) < eps) {
boun(i, 0) = true;
disp(i, 0) = 0.0;
}
if (std::abs(pos(i, 0) - right) < eps) {
boun(i, 0) = true;
disp(i, 0) = 1.0;
}
}
/// compute the volume of the mesh
Real int_volume = 0.;
std::map<ElementKind, FEEngine *> fe_engines = model.getFEEnginesPerKind();
std::map<ElementKind, FEEngine *>::const_iterator fe_it = fe_engines.begin();
for (; fe_it != fe_engines.end(); ++fe_it) {
ElementKind kind = fe_it->first;
FEEngine & fe_engine = *(fe_it->second);
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, _not_ghost, kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, _not_ghost, kind);
for (; it != last_type; ++it) {
ElementType type = *it;
Array<Real> Volume(mesh.getNbElement(type) *
fe_engine.getNbIntegrationPoints(type),
1, 1.);
int_volume += fe_engine.integrate(Volume, type);
}
}
comm.allReduce(&int_volume, 1, _so_sum);
if (prank == 0)
if (!Math::are_float_equal(int_volume, 4)) {
finalize();
std::cout << "Error in area computation of the 2D mesh" << std::endl;
return EXIT_FAILURE;
}
/// solve the system
model.assembleStiffnessMatrix();
Real error = 0;
bool converged = false;
bool factorize = false;
converged = model.solveStep<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
1e-12, error, 2, factorize);
if (!converged) {
std::cout << "The solver did not converge!!! The error is: " << error
<< std::endl;
finalize();
return EXIT_FAILURE;
}
/// store the error on each element for visualization
ElementTypeMapReal error_per_element("error_per_element");
mesh.addDumpFieldExternal("error_per_element", error_per_element,
spatial_dimension, _not_ghost, _ek_regular);
mesh.addDumpFieldExternalToDumper("igfem elements", "error_per_element",
error_per_element, spatial_dimension,
_not_ghost, _ek_igfem);
mesh.initElementTypeMapArray(error_per_element, 1, spatial_dimension, false,
_ek_regular, true);
mesh.initElementTypeMapArray(error_per_element, 1, spatial_dimension, false,
_ek_igfem, true);
Real L2_error = computeL2Error(model, error_per_element);
comm.allReduce(&L2_error, 1, _so_sum);
if (prank == 0) {
std::cout << "Error: " << L2_error << std::endl;
if (L2_error > 1e-13) {
finalize();
std::cout << "The patch test did not pass!!!!" << std::endl;
return EXIT_FAILURE;
}
}
/// dump the deformed mesh
model.dump();
model.dump("igfem elements");
/* --------------------------------------------------------------------------
*/
/// move the interface very close the standard nodes, but far enough
/// to not cut trough the standard nodes
model.moveInterface(0.5 * (1 - 1e-9));
model.dump();
model.dump("igfem elements");
UInt nb_igfem_triangle_4 = mesh.getNbElement(_igfem_triangle_4, _not_ghost);
UInt nb_igfem_triangle_5 = mesh.getNbElement(_igfem_triangle_5, _not_ghost);
comm.allReduce(&nb_igfem_triangle_4, 1, _so_sum);
comm.allReduce(&nb_igfem_triangle_5, 1, _so_sum);
if (prank == 0) {
if ((nb_igfem_triangle_4 != 0) || (nb_igfem_triangle_5 != 8)) {
std::cout << "something went wrong in the interface creation"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
}
if ((psize == 0) && (mesh.getNbNodes() - nb_standard_nodes != 8)) {
std::cout << "something went wrong in the interface node creation"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
converged = model.solveStep<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
1e-12, error, 2, factorize);
if (!converged) {
std::cout << "The solver did not converge!!! The error is: " << error
<< std::endl;
finalize();
return EXIT_FAILURE;
}
L2_error = computeL2Error(model, error_per_element);
comm.allReduce(&L2_error, 1, _so_sum);
if (prank == 0) {
std::cout << "Error: " << L2_error << std::endl;
if (L2_error > 1e-13) {
finalize();
std::cout << "The patch test did not pass!!!!" << std::endl;
return EXIT_FAILURE;
}
}
/// dump the new interface
model.dump();
model.dump("igfem elements");
/* --------------------------------------------------------------------------
*/
/// move the interface so that it cuts through the standard nodes
model.moveInterface((0.5 * (1 - 1e-10)));
nb_igfem_triangle_4 = mesh.getNbElement(_igfem_triangle_4, _not_ghost);
nb_igfem_triangle_5 = mesh.getNbElement(_igfem_triangle_5, _not_ghost);
comm.allReduce(&nb_igfem_triangle_4, 1, _so_sum);
comm.allReduce(&nb_igfem_triangle_5, 1, _so_sum);
if (prank == 0) {
if ((nb_igfem_triangle_4 != 8) || (nb_igfem_triangle_5 != 0)) {
std::cout << "something went wrong in the interface creation"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
}
if ((psize == 0) && (mesh.getNbNodes() - nb_standard_nodes != 4)) {
std::cout << "something went wrong in the interface node creation"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
converged = model.solveStep<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
1e-12, error, 2, factorize);
if (!converged) {
std::cout << "The solver did not converge!!! The error is: " << error
<< std::endl;
finalize();
return EXIT_FAILURE;
}
L2_error = computeL2Error(model, error_per_element);
comm.allReduce(&L2_error, 1, _so_sum);
if (prank == 0) {
std::cout << "Error: " << L2_error << std::endl;
if (L2_error > 1e-13) {
finalize();
std::cout << "The patch test did not pass!!!!" << std::endl;
return EXIT_FAILURE;
}
}
/// dump the new interface
model.dump();
model.dump("igfem elements");
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
Real computeL2Error(SolidMechanicsModelIGFEM & model,
ElementTypeMapReal & error_per_element) {
Real error = 0;
Real normalization = 0;
Mesh & mesh = model.getMesh();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
ElementTypeMapReal quad_coords("quad_coords");
GhostType ghost_type = _not_ghost;
const std::map<ElementKind, FEEngine *> & fe_engines =
model.getFEEnginesPerKind();
std::map<ElementKind, FEEngine *>::const_iterator fe_it = fe_engines.begin();
for (; fe_it != fe_engines.end(); ++fe_it) {
ElementKind kind = fe_it->first;
FEEngine & fe_engine = *(fe_it->second);
mesh.initElementTypeMapArray(quad_coords, spatial_dimension,
spatial_dimension, false, kind, true);
fe_engine.computeIntegrationPointsCoordinates(quad_coords);
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, ghost_type, kind);
Mesh::type_iterator last_type =
mesh.lastType(spatial_dimension, ghost_type, kind);
for (; it != last_type; ++it) {
ElementType type = *it;
UInt nb_elements = mesh.getNbElement(type, ghost_type);
UInt nb_quads = fe_engine.getNbIntegrationPoints(type);
/// interpolate the displacement at the quadrature points
Array<Real> displ_on_quads(nb_quads * nb_elements, spatial_dimension,
"displ_on_quads");
Array<Real> quad_coords(nb_quads * nb_elements, spatial_dimension,
"quad_coords");
fe_engine.interpolateOnIntegrationPoints(
model.getDisplacement(), displ_on_quads, spatial_dimension, type);
fe_engine.computeIntegrationPointsCoordinates(quad_coords, type,
ghost_type);
Array<Real> & el_error = error_per_element(type, ghost_type);
el_error.resize(nb_elements);
Array<Real>::const_vector_iterator displ_it =
displ_on_quads.begin(spatial_dimension);
Array<Real>::const_vector_iterator coord_it =
quad_coords.begin(spatial_dimension);
Vector<Real> error_vec(spatial_dimension);
- for (UInt e = 0; e < nb_elements; ++e) {
+ for (Int e = 0; e < nb_elements; ++e) {
Vector<Real> error_per_quad(nb_quads);
Vector<Real> normalization_per_quad(nb_quads);
- for (UInt q = 0; q < nb_quads; ++q, ++displ_it, ++coord_it) {
+ for (Int q = 0; q < nb_quads; ++q, ++displ_it, ++coord_it) {
Real exact = 0.5 * (*coord_it)(0) + 0.5;
error_vec = *displ_it;
error_vec(0) -= exact;
error_per_quad(q) = error_vec.dot(error_vec);
normalization_per_quad(q) = std::abs(exact) * std::abs(exact);
/// std::cout << error_vec << std::endl;
}
/// integrate the error in the element and the corresponding
/// normalization
Real int_error =
fe_engine.integrate(error_per_quad, type, e, ghost_type);
error += int_error;
el_error(e) = std::sqrt(int_error);
normalization +=
fe_engine.integrate(normalization_per_quad, type, e, ghost_type);
}
}
}
return (std::sqrt(error) / std::sqrt(normalization));
}
diff --git a/extra_packages/igfem/test/test_fe_engine/igfem_mesh_generation.cc b/extra_packages/igfem/test/test_fe_engine/igfem_mesh_generation.cc
index 53d9a09d8..fe21f8c63 100644
--- a/extra_packages/igfem/test/test_fe_engine/igfem_mesh_generation.cc
+++ b/extra_packages/igfem/test/test_fe_engine/igfem_mesh_generation.cc
@@ -1,114 +1,114 @@
/**
* @file igfem_mesh_generation.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Fri Oct 30 14:55:51 2015
*
* @brief function to generate a IGFEM mesh for fe_engine tests
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh.hh"
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
void generateIGFEMMesh(const ElementType type, Mesh & mesh,
const std::string & filename) {
std::ifstream infile;
infile.open(filename.c_str());
if (!infile.good()) {
AKANTU_ERROR("Cannot open file " << filename);
}
UInt current_line = 0;
std::string line;
UInt first_node_number = std::numeric_limits<UInt>::max();
UInt last_node_number = 0;
while (infile.good()) {
std::getline(infile, line);
current_line++;
/// read all nodes
if (line == "$Nodes" || line == "$NOD") {
UInt nb_nodes;
std::getline(infile, line);
std::stringstream sstr(line);
sstr >> nb_nodes;
current_line++;
Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes());
nodes.resize(nb_nodes);
UInt index;
Real coord[3];
- UInt spatial_dimension = nodes.getNbComponent();
+ Int spatial_dimension = nodes.getNbComponent();
/// for each node, read the coordinates
- for (UInt i = 0; i < nb_nodes; ++i) {
+ for (Int i = 0; i < nb_nodes; ++i) {
UInt offset = i * spatial_dimension;
std::getline(infile, line);
std::stringstream sstr_node(line);
sstr_node >> index >> coord[0] >> coord[1] >> coord[2];
current_line++;
first_node_number = std::min(first_node_number, index);
last_node_number = std::max(last_node_number, index);
/// read the coordinates
- for (UInt j = 0; j < spatial_dimension; ++j)
- nodes.storage()[offset + j] = coord[j];
+ for (Int j = 0; j < spatial_dimension; ++j)
+ nodes.data()[offset + j] = coord[j];
}
std::getline(infile, line); /// the end of block line
}
/// read all elements
if (line == "$Elements" || line == "$ELM") {
mesh.addConnectivityType(type);
Array<UInt> & connectivity =
const_cast<Array<UInt> &>(mesh.getConnectivity(type));
UInt node_per_element = connectivity.getNbComponent();
UInt nb_elements = 0;
std::getline(infile, line);
std::stringstream sstr(line);
sstr >> nb_elements;
current_line++;
- for (UInt i = 0; i < nb_elements; ++i) {
+ for (Int i = 0; i < nb_elements; ++i) {
std::getline(infile, line);
std::stringstream sstr_elem(line);
current_line++;
Vector<UInt> local_connect(node_per_element);
- for (UInt j = 0; j < node_per_element; ++j) {
+ for (Int j = 0; j < node_per_element; ++j) {
UInt node_index;
sstr_elem >> node_index;
AKANTU_DEBUG_ASSERT(node_index <= last_node_number,
"Node number not in range : line "
<< current_line);
node_index -= first_node_number;
local_connect(j) = node_index;
}
connectivity.push_back(local_connect);
}
std::getline(infile, line); /// the end of block line
}
}
}
diff --git a/extra_packages/igfem/test/test_fe_engine/test_fe_engine_precomputation.cc b/extra_packages/igfem/test/test_fe_engine/test_fe_engine_precomputation.cc
index 28a2460cd..26bb3d0d4 100644
--- a/extra_packages/igfem/test/test_fe_engine/test_fe_engine_precomputation.cc
+++ b/extra_packages/igfem/test/test_fe_engine/test_fe_engine_precomputation.cc
@@ -1,79 +1,79 @@
/**
* @file test_fe_engine_percompuation.cc
*
* @author Aurelia Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Fri Oct 30 2015
* @date last modification: Fri Oct 30 2015
*
* @brief test the fe-engine precomputations for IGFEM elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "integrator_gauss_igfem.hh"
#include "shape_igfem.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
void precompute(const ElementType type);
void generateIGFEMMesh(const ElementType type, Mesh & mesh,
const std::string & filename);
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
debug::setDebugLevel(dblTest);
/// precompuation for _igfem_triangle_4
AKANTU_DEBUG_INFO("precomputation for _igfem_triangle_4...");
precompute(_igfem_triangle_4);
/// precompuation for _igfem_triangle_5
AKANTU_DEBUG_INFO("precomputation for _igfem_triangle_5...");
precompute(_igfem_triangle_5);
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void precompute(const ElementType type) {
- UInt dim = 2;
+ Int dim = 2;
std::stringstream mesh_info;
mesh_info << "mesh_info" << type << ".txt";
Mesh my_mesh(dim);
generateIGFEMMesh(type, my_mesh, mesh_info.str());
FEEngine * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem>(
my_mesh, dim, "my_fem");
fem->initShapeFunctions();
std::cout << *fem << std::endl;
delete fem;
}
diff --git a/extra_packages/igfem/test/test_fe_engine/test_gradient.cc b/extra_packages/igfem/test/test_fe_engine/test_gradient.cc
index d31fc1499..08b6f5219 100644
--- a/extra_packages/igfem/test/test_fe_engine/test_gradient.cc
+++ b/extra_packages/igfem/test/test_fe_engine/test_gradient.cc
@@ -1,165 +1,165 @@
/**
* @file test_gradient.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief test the gradient computation for the igfem elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "integrator_gauss_igfem.hh"
#include "shape_igfem.hh"
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
bool gradient(const ElementType type);
void generateIGFEMMesh(const ElementType type, Mesh & mesh,
const std::string & filename);
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
debug::setDebugLevel(dblTest);
bool test_passed = false;
/// integrate test of _igfem_triangle_4
AKANTU_DEBUG_INFO("integrating _igfem_triangle_4...");
test_passed = gradient(_igfem_triangle_4);
if (!test_passed) {
finalize();
return EXIT_FAILURE;
}
/// integrate test of _igfem_triangle_5
AKANTU_DEBUG_INFO("integrating _igfem_triangle_5...");
test_passed = gradient(_igfem_triangle_5);
if (!test_passed) {
finalize();
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
bool gradient(const ElementType type) {
bool correct_result = true;
- UInt dim = 2;
+ Int dim = 2;
std::stringstream mesh_info;
mesh_info << "mesh_info" << type << ".txt";
Mesh my_mesh(dim);
generateIGFEMMesh(type, my_mesh, mesh_info.str());
Real eps = 3e-13;
std::cout << "Epsilon : " << eps << std::endl;
FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem> * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem>(
my_mesh, dim, "my_fem");
fem->initShapeFunctions();
Real alpha[2][3] = {{13, 23, 31}, {11, 7, 5}};
/// create the 2 component field
/// for field to be constant the enriched values need to be zero!! Therefore
/// non-zero values
/// are only imposed on standard nodes
UInt nb_standard_nodes = 9;
const Array<Real> & position = fem->getMesh().getNodes();
Array<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val");
UInt nb_element = my_mesh.getNbElement(type);
UInt nb_quadrature_points = fem->getNbIntegrationPoints(type) * nb_element;
Array<Real> grad_on_quad(nb_quadrature_points, 2 * dim, "grad_on_quad");
- for (UInt i = 0; i < nb_standard_nodes; ++i) {
+ for (Int i = 0; i < nb_standard_nodes; ++i) {
const_val(i, 0) = 0;
const_val(i, 1) = 0;
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
const_val(i, 0) += alpha[0][d] * position(i, d);
const_val(i, 1) += alpha[1][d] * position(i, d);
}
}
/// impose zero at enriched nodes
- for (UInt i = nb_standard_nodes; i < const_val.getSize(); ++i) {
+ for (Int i = nb_standard_nodes; i < const_val.getSize(); ++i) {
const_val(i, 0) = 0;
const_val(i, 1) = 0;
}
/// compute the gradient
fem->gradientOnIntegrationPoints(const_val, grad_on_quad, 2, type);
std::cout << "Linear array on nodes : " << const_val << std::endl;
std::cout << "Gradient on quad : " << grad_on_quad << std::endl;
/// check the results
Array<Real>::matrix_iterator it = grad_on_quad.begin(2, dim);
Array<Real>::matrix_iterator it_end = grad_on_quad.end(2, dim);
for (; it != it_end; ++it) {
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
Matrix<Real> & grad = *it;
if (!(std::abs(grad(0, d) - alpha[0][d]) < eps) ||
!(std::abs(grad(1, d) - alpha[1][d]) < eps)) {
std::cout << "Error gradient is not correct " << (*it)(0, d) << " "
<< alpha[0][d] << " (" << std::abs((*it)(0, d) - alpha[0][d])
<< ")"
<< " - " << (*it)(1, d) << " " << alpha[1][d] << " ("
<< std::abs((*it)(1, d) - alpha[1][d]) << ")"
<< " - " << d << std::endl;
std::cout << *it << std::endl;
correct_result = false;
return correct_result;
}
}
}
// compute gradient of coordinates
Array<Real> grad_coord_on_quad(nb_quadrature_points, dim * dim,
"grad_coord_on_quad");
/// create an array with the nodal coordinates that need to be
/// interpolated. The nodal coordinates of the enriched nodes need
/// to be set to zero, because they represent the enrichment of the
/// position field, and the enrichments for this field are all zero!
/// There is no gap in the mesh!
Array<Real> igfem_nodes(my_mesh.getNbNodes(), dim);
const ShapeLagrange<_ek_igfem> & shapes = fem->getShapeFunctions();
shapes.extractValuesAtStandardNodes(my_mesh.getNodes(), igfem_nodes,
_not_ghost);
fem->gradientOnIntegrationPoints(igfem_nodes, grad_coord_on_quad,
my_mesh.getSpatialDimension(), type);
std::cout << "Node positions : " << my_mesh.getNodes() << std::endl;
std::cout << "Gradient of nodes : " << grad_coord_on_quad << std::endl;
Array<Real>::matrix_iterator itp = grad_coord_on_quad.begin(dim, dim);
Array<Real>::matrix_iterator itp_end = grad_coord_on_quad.end(dim, dim);
for (; itp != itp_end; ++itp) {
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
+ for (Int i = 0; i < dim; ++i) {
+ for (Int j = 0; j < dim; ++j) {
if (!(std::abs((*itp)(i, j) - (i == j)) < eps)) {
std::cout << *itp << std::endl;
correct_result = false;
return correct_result;
}
}
}
}
delete fem;
return correct_result;
}
diff --git a/extra_packages/igfem/test/test_fe_engine/test_integrate.cc b/extra_packages/igfem/test/test_fe_engine/test_integrate.cc
index 9c25fda98..1bbda763e 100644
--- a/extra_packages/igfem/test/test_fe_engine/test_integrate.cc
+++ b/extra_packages/igfem/test/test_fe_engine/test_integrate.cc
@@ -1,135 +1,135 @@
/**
* @file test_integrate.cc
*
* @author Aurelia Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Fri Oct 30 2015
* @date last modification: Fri Oct 30 2015
*
* @brief test the integration of IGFEM elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "integrator_gauss_igfem.hh"
#include "shape_igfem.hh"
///#include "dumper_paraview.hh"
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
bool integrate(const ElementType type);
void generateIGFEMMesh(const ElementType type, Mesh & mesh,
const std::string & filename);
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
debug::setDebugLevel(dblTest);
bool test_passed = false;
/// integrate test of _igfem_triangle_4
AKANTU_DEBUG_INFO("integrating _igfem_triangle_4...");
test_passed = integrate(_igfem_triangle_4);
if (!test_passed) {
finalize();
return EXIT_FAILURE;
}
/// integrate test of _igfem_triangle_5
AKANTU_DEBUG_INFO("integrating _igfem_triangle_5...");
test_passed = integrate(_igfem_triangle_5);
if (!test_passed) {
finalize();
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
bool integrate(const ElementType type) {
bool correct_result = true;
- UInt dim = 2;
+ Int dim = 2;
std::stringstream mesh_info;
mesh_info << "mesh_info" << type << ".txt";
Mesh my_mesh(dim);
generateIGFEMMesh(type, my_mesh, mesh_info.str());
// DumperParaview dumper_igfem("mesh_igfem");
// dumper_igfem.registerMesh(my_mesh, dim, _not_ghost, _ek_igfem);
// dumper_igfem.dump();
Real eps = 3e-13;
std::cout << "Epsilon : " << eps << std::endl;
FEEngine * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem>(
my_mesh, dim, "my_fem");
fem->initShapeFunctions();
UInt nb_element = my_mesh.getNbElement(type);
UInt nb_quadrature_points = fem->getNbIntegrationPoints(type) * nb_element;
/// impose a constant field on the quadrature points with x = 1 and y = 2
Array<Real> val_on_quad(nb_quadrature_points, dim, "val_on_quad");
Array<Real>::vector_iterator val_it = val_on_quad.begin(dim);
Vector<Real> values(dim);
values(0) = 1.;
values(1) = 2;
- for (UInt i = 0; i < val_on_quad.getSize(); ++i, ++val_it)
+ for (Int i = 0; i < val_on_quad.getSize(); ++i, ++val_it)
*val_it = values;
// integrate function on elements
akantu::Array<akantu::Real> int_val_on_elem(nb_element, dim,
"int_val_on_elem");
fem->integrate(val_on_quad, int_val_on_elem, dim, type);
// get global integration value
Real value[2] = {0, 0};
std::cout << "Val on quads : " << val_on_quad << std::endl;
std::cout << "Integral on elements : " << int_val_on_elem << std::endl;
- for (UInt i = 0; i < fem->getMesh().getNbElement(type); ++i) {
- value[0] += int_val_on_elem.storage()[2 * i];
- value[1] += int_val_on_elem.storage()[2 * i + 1];
+ for (Int i = 0; i < fem->getMesh().getNbElement(type); ++i) {
+ value[0] += int_val_on_elem.data()[2 * i];
+ value[1] += int_val_on_elem.data()[2 * i + 1];
}
std::cout << "integral on the mesh of 1 is " << value[0] << " and of 2 is "
<< value[1] << std::endl;
delete fem;
if (!(std::abs(value[0] - 1.) < eps && std::abs(value[1] - 2.) < eps)) {
std::cout << "|1 - " << value[0] << "| = " << std::abs(value[0] - 1.)
<< std::endl
<< "|2 - " << value[1] << "| = " << std::abs(value[1] - 2.)
<< std::endl;
correct_result = false;
}
return correct_result;
}
diff --git a/extra_packages/igfem/test/test_fe_engine/test_interpolate.cc b/extra_packages/igfem/test/test_fe_engine/test_interpolate.cc
index ca46c1630..4ef2931fd 100644
--- a/extra_packages/igfem/test/test_fe_engine/test_interpolate.cc
+++ b/extra_packages/igfem/test/test_fe_engine/test_interpolate.cc
@@ -1,113 +1,113 @@
/**
* @file test_interpolate.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief test the interpolation function of the igfem elements
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "integrator_gauss_igfem.hh"
#include "shape_igfem.hh"
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
void interpolate(const ElementType type);
void generateIGFEMMesh(const ElementType type, Mesh & mesh,
const std::string & filename);
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
debug::setDebugLevel(dblTest);
/// interpolate test of _igfem_triangle_4
AKANTU_DEBUG_INFO("integrating _igfem_triangle_4...");
interpolate(_igfem_triangle_4);
/// interpolate test of _igfem_triangle_5
AKANTU_DEBUG_INFO("integrating _igfem_triangle_5...");
interpolate(_igfem_triangle_5);
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void interpolate(const ElementType type) {
- UInt dim = 2;
+ Int dim = 2;
std::stringstream mesh_info;
mesh_info << "mesh_info" << type << ".txt";
Mesh my_mesh(dim);
generateIGFEMMesh(type, my_mesh, mesh_info.str());
Real eps = 3e-13;
std::cout << "Epsilon : " << eps << std::endl;
FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem> * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_igfem>(
my_mesh, dim, "my_fem");
fem->initShapeFunctions();
Array<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val");
UInt nb_element = my_mesh.getNbElement(type);
UInt nb_quadrature_points = fem->getNbIntegrationPoints(type) * nb_element;
Array<Real> val_on_quad(nb_quadrature_points, 2, "val_on_quad");
/// the number of standard nodes in the mesh, i.e. not interface nodes
UInt nb_standard_nodes = 9;
/// impose constant value at standard nodes
- for (UInt i = 0; i < nb_standard_nodes; ++i) {
- const_val.storage()[i * 2 + 0] = 1.;
- const_val.storage()[i * 2 + 1] = 2.;
+ for (Int i = 0; i < nb_standard_nodes; ++i) {
+ const_val.data()[i * 2 + 0] = 1.;
+ const_val.data()[i * 2 + 1] = 2.;
}
/// for field to be constant the enriched values need to be zero,
/// because enrichment is not needed since there is no kink in the
/// applied field
- for (UInt i = nb_standard_nodes; i < const_val.getSize(); ++i) {
- const_val.storage()[i * 2 + 0] = 0.;
- const_val.storage()[i * 2 + 1] = 0.;
+ for (Int i = nb_standard_nodes; i < const_val.getSize(); ++i) {
+ const_val.data()[i * 2 + 0] = 0.;
+ const_val.data()[i * 2 + 1] = 0.;
}
fem->interpolateOnIntegrationPoints(const_val, val_on_quad, 2, type);
std::cout << "Interpolation of array : " << const_val << std::endl;
std::cout << "Gives on quads : " << val_on_quad << std::endl;
/// interpolate coordinates
Array<Real> coord_on_quad(nb_quadrature_points, my_mesh.getSpatialDimension(),
"coord_on_quad");
/// create an array with the nodal coordinates that need to be
/// interpolated. The nodal coordinates of the enriched nodes need
/// to be set to zero, because they represent the enrichment of the
/// position field, and the enrichments for this field are all zero!
/// There is no gap in the mesh!
Array<Real> igfem_nodes(my_mesh.getNbNodes(), dim);
const ShapeLagrange<_ek_igfem> & shapes = fem->getShapeFunctions();
shapes.extractValuesAtStandardNodes(my_mesh.getNodes(), igfem_nodes,
_not_ghost);
fem->interpolateOnIntegrationPoints(igfem_nodes, coord_on_quad,
my_mesh.getSpatialDimension(), type);
std::cout << "Interpolations of node coordinates : " << my_mesh.getNodes()
<< std::endl;
std::cout << "Gives : " << coord_on_quad << std::endl;
delete fem;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_ASR_damage.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_ASR_damage.cc
index 8f6dd15d0..fad01b60a 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_ASR_damage.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_ASR_damage.cc
@@ -1,210 +1,210 @@
/**
* @file test_ASR_damage.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief test the solidmechancis model for IGFEM analysis
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative.hh"
#include "material_igfem_saw_tooth_damage.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/// function declaration
void applyBoundaryConditions(SolidMechanicsModelIGFEM & model);
class ASRMaterialSelector : public MaterialSelector {
public:
ASRMaterialSelector(SolidMechanicsModelIGFEM & model) : model(model) {}
UInt operator()(const Element & elem) {
if (Mesh::getKind(elem.type) == _ek_igfem)
/// choose IGFEM material
return 2;
const Mesh & mesh = model.getMesh();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Vector<Real> barycenter(spatial_dimension);
mesh.getBarycenter(elem, barycenter);
if (model.isInside(barycenter))
return 1;
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
};
typedef Spherical SK;
int main(int argc, char * argv[]) {
initialize("material_ASR.dat", argc, argv);
/// problem dimension
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// mesh creation
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("one_inclusion.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
/// register the gel pocket list in the model
std::list<SK::Sphere_3> gel_pocket_list;
model.registerGeometryObject(gel_pocket_list, "gel");
ASRMaterialSelector * mat_selector;
mat_selector = new ASRMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
model.initFull();
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.addDumpField("material_index");
model.addDumpField("damage");
model.addDumpField("Sc");
model.addDumpField("partitions");
model.addDumpField("eigen_grad_u");
model.addDumpField("blocked_dofs");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "damage");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldToDumper("igfem elements", "eigen_grad_u");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
/// dump before the interface generation
model.dump();
model.dump("igfem elements");
/// weaken one element to enforce damage there
Array<Real> & Sc =
model.getMaterial(0).getInternal<Real>("Sc")(_triangle_3, _not_ghost);
Sc(11) = 1;
/// create the gel pocket
Real initial_gel_radius = 0.1;
SK::Sphere_3 sphere_1(SK::Point_3(0., 0., 0.),
initial_gel_radius * initial_gel_radius);
gel_pocket_list.push_back(sphere_1);
/// create the interface
model.update("gel");
/// apply eigenstrain the eigenstrain in the inclusions
Matrix<Real> prestrain(spatial_dimension, spatial_dimension, 0.);
- for (UInt i = 0; i < spatial_dimension; ++i)
+ for (Int i = 0; i < spatial_dimension; ++i)
prestrain(i, i) = 0.05;
model.applyEigenGradU(prestrain, "gel", _not_ghost);
applyBoundaryConditions(model);
/// dump
model.dump("igfem elements");
model.dump();
/// Instantiate objects of class MyDamageso
MaterialDamageIterative<spatial_dimension> & mat_aggregate =
dynamic_cast<MaterialDamageIterative<spatial_dimension> &>(
model.getMaterial(0));
MaterialIGFEMSawToothDamage<spatial_dimension> & mat_igfem =
dynamic_cast<MaterialIGFEMSawToothDamage<spatial_dimension> &>(
model.getMaterial(2));
bool factorize = false;
bool converged = false;
Real error;
UInt nb_damaged_elements = 0;
Real max_eq_stress_aggregate = 0;
Real max_igfem = 0;
const Array<Real> & stress =
model.getMaterial(2).getStress(_igfem_triangle_5, _not_ghost);
Array<Real>::const_matrix_iterator stress_it =
stress.begin(spatial_dimension, spatial_dimension);
do {
converged = model.solveStep<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
1e-6, error, 2, factorize);
/// compute damage
max_eq_stress_aggregate = mat_aggregate.getNormMaxEquivalentStress();
max_igfem = mat_igfem.getNormMaxEquivalentStress();
if (max_eq_stress_aggregate > max_igfem)
nb_damaged_elements = mat_aggregate.updateDamage();
else
nb_damaged_elements = mat_igfem.updateDamage();
std::cout << "damaged elements: " << nb_damaged_elements << std::endl;
- for (UInt i = 0; i < 5; ++i) {
+ for (Int i = 0; i < 5; ++i) {
std::cout << *stress_it << std::endl;
++stress_it;
}
model.dump();
model.dump("igfem elements");
} while (nb_damaged_elements);
model.dump();
model.dump("igfem elements");
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void applyBoundaryConditions(SolidMechanicsModelIGFEM & model) {
/// boundary conditions
Mesh & mesh = model.getMesh();
mesh.computeBoundingBox();
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real left = lowerBounds(0);
// Real right = upperBounds(0);
Real eps = std::abs((top - bottom) * 1e-12);
const Array<Real> & pos = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & boun = model.getBlockedDOFs();
disp.zero();
boun.zero();
/// free expansion
- for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
+ for (Int i = 0; i < mesh.getNbNodes(); ++i) {
if (std::abs(pos(i, 1) - bottom) < eps) {
boun(i, 1) = true;
disp(i, 1) = 0.0;
}
if (std::abs(pos(i, 0) - left) < eps) {
boun(i, 0) = true;
disp(i, 0) = 0.0;
}
}
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_eigenstrain.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_eigenstrain.cc
index 06733b5f3..f068003b4 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_eigenstrain.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_eigenstrain.cc
@@ -1,183 +1,183 @@
/**
* @file test_eigenstrain.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief test to that eigenstrain is only applied on one sub-material
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dumper_paraview.hh"
#include "material_igfem.hh"
#include "mesh_geom_common.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class ASRMaterialSelector : public DefaultMaterialIGFEMSelector {
public:
ASRMaterialSelector(SolidMechanicsModelIGFEM & model)
: DefaultMaterialIGFEMSelector(model), model(model) {}
UInt operator()(const Element & elem) {
if (Mesh::getKind(elem.type) == _ek_igfem)
/// choose IGFEM material
return this->fallback_value_igfem;
const Mesh & mesh = model.getMesh();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Vector<Real> barycenter(spatial_dimension);
mesh.getBarycenter(elem, barycenter);
if (model.isInside(barycenter))
return 1;
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
};
typedef Spherical SK;
int main(int argc, char * argv[]) {
initialize("material_damage.dat", argc, argv);
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// problem dimension
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
/// mesh creation and partioning
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("fine_mesh.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation and initialization
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
/// create the list to store the gel pockets
std::list<SK::Sphere_3> gel_pocket_list;
model.registerGeometryObject(gel_pocket_list, "mat_1");
/// set the material selector
ASRMaterialSelector * mat_selector = new ASRMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
model.initFull();
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.addDumpField("material_index");
model.addDumpField("damage");
model.addDumpField("Sc");
model.addDumpField("partitions");
model.addDumpField("eigen_grad_u");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldToDumper("igfem elements", "partitions");
model.addDumpFieldToDumper("igfem elements", "eigen_grad_u");
/// dump
model.dump("igfem elements");
model.dump();
/// create the inclusions
SK::Sphere_3 sphere_1(SK::Point_3(0., 0., 0.), 0.13 * 0.13);
SK::Sphere_3 sphere_2(SK::Point_3(0.5, 0.5, 0.), 0.4 * 0.4);
SK::Sphere_3 sphere_3(SK::Point_3(-0.75, -0.75, 0.), 0.12 * 0.12);
SK::Sphere_3 sphere_4(SK::Point_3(0.625, -0.625, 0.), 0.25 * 0.25);
gel_pocket_list.push_back(sphere_1);
gel_pocket_list.push_back(sphere_2);
gel_pocket_list.push_back(sphere_3);
gel_pocket_list.push_back(sphere_4);
/// create the interface
model.update("mat_1");
if (mesh.getNbElement(_igfem_triangle_4, _not_ghost)) {
/// something went wrong in the interface creation
finalize();
return EXIT_FAILURE;
}
/// apply eigenstrain the eigenstrain in the inclusions
Matrix<Real> prestrain(spatial_dimension, spatial_dimension, 0.);
- for (UInt i = 0; i < spatial_dimension; ++i)
+ for (Int i = 0; i < spatial_dimension; ++i)
prestrain(i, i) = 0.07;
model.applyEigenGradU(prestrain, "mat_1", _not_ghost);
/// check that eigenstrain has been applied correctly
/// check first the regular materials (the first two in the mat file)
Real error = 0;
Material & mat_1 = model.getMaterial(0);
const Array<Real> & eigen_grad_u_1 =
mat_1.getArray<Real>("eigen_grad_u", _triangle_3, _not_ghost);
Array<Real>::const_matrix_iterator eigen_it =
eigen_grad_u_1.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_matrix_iterator eigen_end =
eigen_grad_u_1.end(spatial_dimension, spatial_dimension);
for (; eigen_it != eigen_end; ++eigen_it) {
const Matrix<Real> & eigen_grad_u = *eigen_it;
error += eigen_grad_u.norm<L_2>();
}
Material & mat_2 = model.getMaterial(1);
const Array<Real> & eigen_grad_u_2 =
mat_2.getArray<Real>("eigen_grad_u", _triangle_3, _not_ghost);
eigen_it = eigen_grad_u_2.begin(spatial_dimension, spatial_dimension);
eigen_end = eigen_grad_u_2.end(spatial_dimension, spatial_dimension);
for (; eigen_it != eigen_end; ++eigen_it) {
const Matrix<Real> & eigen_grad_u = *eigen_it;
Matrix<Real> diff = (prestrain - eigen_grad_u);
error += diff.norm<L_2>();
}
MaterialIGFEM & mat_3 = dynamic_cast<MaterialIGFEM &>(model.getMaterial(2));
const Array<Real> & eigen_grad_u_3 =
mat_3.getArray<Real>("eigen_grad_u", _igfem_triangle_5, _not_ghost);
UInt * sub_mat_ptr =
mat_3.getArray<UInt>("sub_material", _igfem_triangle_5, _not_ghost)
- .storage();
+ .data();
eigen_it = eigen_grad_u_3.begin(spatial_dimension, spatial_dimension);
eigen_end = eigen_grad_u_3.end(spatial_dimension, spatial_dimension);
for (; eigen_it != eigen_end; ++eigen_it, ++sub_mat_ptr) {
const Matrix<Real> & eigen_grad_u = *eigen_it;
if (!(*sub_mat_ptr)) {
Matrix<Real> diff = (prestrain - eigen_grad_u);
error += diff.norm<L_2>();
} else
error += eigen_grad_u.norm<L_2>();
}
std::cout << "The error in the prestrain is: " << error << std::endl;
if (std::abs(error) > Math::getTolerance()) {
std::cout << "The test failed!!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
/// dump
model.dump("igfem elements");
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_igfem_element_orientation.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_igfem_element_orientation.cc
index f8a3d2bde..57b258ded 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_igfem_element_orientation.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_igfem_element_orientation.cc
@@ -1,147 +1,147 @@
/**
* @file test_interface_position.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief patch test for interface close to standard nodes
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// create a mesh and read the regular elements from the mesh file
/// mesh creation
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("test_igfem_element_orientation.msh");
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
model.initFull();
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpField("material_index");
model.addDumpField("partitions");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "partitions");
/// dump mesh before the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// create the interace:
std::list<SK::Sphere_3> sphere_list;
Real radius = std::sqrt(0.2 * 0.2 + 0.2 * 0.2);
Real tol = std::sqrt(2.) * 1e-11;
radius += tol;
SK::Sphere_3 sphere_1(SK::Point_3(-0.2, 0.3, 0.), radius * radius);
sphere_list.push_back(sphere_1);
model.registerGeometryObject(sphere_list, "gel");
model.update();
/// check that the igfem elements have been created correctly
UInt nb_igfem_triangle_4 = mesh.getNbElement(_igfem_triangle_4, _not_ghost);
UInt nb_igfem_triangle_5 = mesh.getNbElement(_igfem_triangle_5, _not_ghost);
comm.allReduce(&nb_igfem_triangle_4, 1, _so_sum);
comm.allReduce(&nb_igfem_triangle_5, 1, _so_sum);
if (prank == 0) {
if ((nb_igfem_triangle_4 != 2) || (nb_igfem_triangle_5 != 1)) {
std::cout << "something went wrong in the interface creation"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
}
/// check that the igfem nodes have been created correctly
UInt nb_global_nodes = 0;
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (mesh.isLocalOrMasterNode(n))
nb_global_nodes += 1;
}
comm.allReduce(&nb_global_nodes, 1, _so_sum);
if (prank == 0 && nb_global_nodes != 27) {
std::cout << "something went wrong in the interface creation" << std::endl;
finalize();
return EXIT_FAILURE;
}
/// in this test the sphere interface is positioned in a way that it
/// genereates two IGFEM elements (of type _igfem_triangle_4), that are
/// enriched for
/// compatibilty with their neighboring elements but they don't
/// contain a material interface. Therefore, the same material has
/// to be assigned to both sub-elements.
/// this is to check that both sub-elements have the same material
/// properties Note: This check works because all _igfem_triangle_4s
/// in the mesh do not contain a material interface
MaterialElastic<spatial_dimension> & aggregate_mat =
dynamic_cast<MaterialElastic<spatial_dimension> &>(
model.getMaterial("aggregate"));
Real lambda_1 = aggregate_mat.getLambda();
Real mu_1 = aggregate_mat.getMu();
ElementType type = _igfem_triangle_4;
GhostType ghost_type = _not_ghost;
UInt nb_element = mesh.getNbElement(type, ghost_type);
UInt nb_quads =
model.getFEEngine("IGFEMFEEngine").getNbIntegrationPoints(type);
Real * lambda = model.getMaterial("igfem_elastic")
.getArray<Real>("lambda", type, ghost_type)
- .storage();
+ .data();
Real * mu = model.getMaterial("igfem_elastic")
.getArray<Real>("mu", type, ghost_type)
- .storage();
+ .data();
Real error = 0;
- for (UInt e = 0; e < nb_element; ++e) {
- for (UInt q = 0; q < nb_quads; ++q, ++lambda, ++mu) {
+ for (Int e = 0; e < nb_element; ++e) {
+ for (Int q = 0; q < nb_quads; ++q, ++lambda, ++mu) {
error += std::abs(lambda_1 - *lambda);
error += std::abs(mu_1 - *mu);
}
}
comm.allReduce(&error, 1, _so_sum);
if (prank == 0) {
std::cout << "The error is: " << error << std::endl;
if (error > 1e-14) {
std::cout << "The test failed!!!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
/// dump mesh after the IGFEM interface is created
model.dump();
model.dump("igfem elements");
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction.cc
index 033063cdf..9ea53b6f4 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction.cc
@@ -1,411 +1,410 @@
/**
* @file test_material_igfem_iterative_strength_reduction.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the material iterative stiffness reduction
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage_iterative.hh"
#include "material_igfem_saw_tooth_damage.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/// function declaration
bool checkDamageState(UInt step, const SolidMechanicsModelIGFEM & model,
bool igfem_analysis);
class TestMaterialSelector : public MaterialSelector {
public:
TestMaterialSelector(SolidMechanicsModelIGFEM & model)
: MaterialSelector(), model(model),
spatial_dimension(model.getSpatialDimension()) {}
UInt operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_igfem)
return 2;
else {
/// regular elements
const Mesh & mesh = model.getMesh();
Vector<Real> barycenter(this->spatial_dimension);
mesh.getBarycenter(element, barycenter);
/// check if element belongs to ASR gel
if (model.isInside(barycenter))
return 1;
}
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
- UInt spatial_dimension;
+ Int spatial_dimension;
};
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material_stiffness_reduction.dat", argc, argv);
bool igfem_analysis;
std::string action(argv[1]);
if (action == "igfem") {
igfem_analysis = true;
} else if (action == "standard_fem") {
igfem_analysis = false;
} else {
std::cerr << "invalid option" << std::endl;
}
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
if (igfem_analysis)
mesh.read("igfem_mesh.msh");
else
mesh.read("regular_mesh.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
Math::setTolerance(1.e-14);
/// intialize the geometry and set the material selector
std::list<SK::Sphere_3> inclusions_list;
model.registerGeometryObject(inclusions_list, "inclusion");
Real val = 1000000000;
Real radius_squared = val * val;
Vector<Real> center(spatial_dimension);
center(0) = 0;
center(1) = val;
SK::Sphere_3 sphere(SK::Point_3(center(0), center(1), 0.), radius_squared);
inclusions_list.push_back(sphere);
TestMaterialSelector * mat_selector = new TestMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
/// initialization of the model
model.initFull();
/// create the interface
if (igfem_analysis)
model.update("inclusion");
/// boundary conditions
mesh.computeBoundingBox();
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real left = lowerBounds(0);
Real eps = std::abs((top - bottom) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<bool> & boun = model.getBlockedDOFs();
Array<Real> & disp = model.getDisplacement();
for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
if (std::abs(pos(n, 1) - bottom) < eps) {
boun(n, 1) = true;
disp(n, 1) = 0.;
}
if (std::abs(pos(n, 1) - top) < eps) {
boun(n, 1) = true;
disp(n, 1) = 1.e-3;
}
if (std::abs(pos(n, 0) - left) < eps) {
boun(n, 0) = true;
disp(n, 0) = 0.;
}
}
/// add fields that should be dumped
model.setBaseName("regular");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.addDumpField("ultimate_strain");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
;
model.addDumpFieldToDumper("igfem elements", "stress");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "residual");
model.addDumpFieldToDumper("igfem elements", "grad_u");
model.addDumpFieldToDumper("igfem elements", "damage");
model.addDumpFieldToDumper("igfem elements", "partitions");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "force");
model.addDumpFieldToDumper("igfem elements", "equivalent_stress");
model.addDumpFieldToDumper("igfem elements", "ultimate_strain");
model.dump();
model.dump("igfem elements");
/// get a reference to the damage materials
MaterialDamageIterative<spatial_dimension> & material =
dynamic_cast<MaterialDamageIterative<spatial_dimension> &>(
model.getMaterial(0));
MaterialIGFEMSawToothDamage<spatial_dimension> & igfem_material =
dynamic_cast<MaterialIGFEMSawToothDamage<spatial_dimension> &>(
model.getMaterial(2));
Real error;
bool converged = false;
UInt nb_damaged_elements = 0;
Real max_eq_stress_regular = 0;
Real max_eq_stress_igfem = 0;
/// solve the system
// counter for the damage steps
UInt s = 0;
do {
converged =
model.solveStep<_scm_newton_raphson_tangent_modified,
SolveConvergenceCriteria::_increment>(1e-12, error, 2);
if (converged == false) {
std::cout << "The error is: " << error << std::endl;
AKANTU_DEBUG_ASSERT(converged, "Did not converge");
}
/// compute damage
max_eq_stress_regular = material.getNormMaxEquivalentStress();
max_eq_stress_igfem = igfem_material.getNormMaxEquivalentStress();
if (max_eq_stress_regular > max_eq_stress_igfem)
nb_damaged_elements = material.updateDamage();
else if (max_eq_stress_regular == max_eq_stress_igfem) {
nb_damaged_elements = material.updateDamage();
nb_damaged_elements += igfem_material.updateDamage();
} else
nb_damaged_elements = igfem_material.updateDamage();
model.dump();
model.dump("igfem elements");
/// check the current damage state
if (!checkDamageState(s, model, igfem_analysis)) {
std::cout << "error in the damage compuation" << std::endl;
finalize();
return EXIT_FAILURE;
}
s++;
} while (nb_damaged_elements);
std::cout << action << " passed!!" << std::endl;
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
bool checkDamageState(UInt step, const SolidMechanicsModelIGFEM & model,
bool igfem_analysis) {
bool test_result = true;
- const UInt spatial_dimension = model.getSpatialDimension();
+ const Int spatial_dimension = model.getSpatialDimension();
const Mesh & mesh = model.getMesh();
if (!igfem_analysis) {
const ElementType element_type = _triangle_3;
/// prepare output: compute barycenters for elements that can be damaged
- const Array<UInt> & element_filter =
+ const Array<Int> & element_filter =
model.getMaterial(0).getElementFilter(element_type, _not_ghost);
Array<Real> barycenters(element_filter.getSize(), spatial_dimension);
Array<Real>::vector_iterator bary_it = barycenters.begin(spatial_dimension);
- for (UInt e = 0; e < element_filter.getSize(); ++e, ++bary_it) {
+ for (Int e = 0; e < element_filter.getSize(); ++e, ++bary_it) {
UInt global_el_idx = element_filter(e);
mesh.getBarycenter(global_el_idx, element_type, bary_it->storage(),
_not_ghost);
}
const Array<Real> & damage = model.getMaterial(0).getInternal<Real>(
"damage")(element_type, _not_ghost);
const Array<Real> & Sc =
model.getMaterial(0).getInternal<Real>("Sc")(element_type, _not_ghost);
std::ostringstream file_name;
file_name << "step_" << std::setfill('0') << std::setw(3) << step << ".txt";
std::ofstream file_output;
file_output.open(file_name.str());
file_output << std::setprecision(14);
- for (UInt e = 0; e < barycenters.getSize(); ++e)
+ for (Int e = 0; e < barycenters.getSize(); ++e)
file_output << barycenters(e, 0) << " " << barycenters(e, 1) << " "
<< damage(e) << " " << Sc(e) << std::endl;
}
else {
/// read data
Real default_tolerance = Math::getTolerance();
Math::setTolerance(1.e-10);
std::stringstream results_file;
results_file << "step_" << std::setfill('0') << std::setw(3) << step
<< ".txt";
std::ifstream damage_input;
damage_input.open(results_file.str().c_str());
Array<Real> damage_result(0, 1);
Array<Real> Sc_result(0, 1);
Array<Real> bary_regular(0, spatial_dimension);
Vector<Real> bary(spatial_dimension);
Real dam = 0.;
Real strength = 0;
while (damage_input.good()) {
damage_input >> bary(0) >> bary(1) >> dam >> strength;
bary_regular.push_back(bary);
damage_result.push_back(dam);
Sc_result.push_back(strength);
}
/// compare the results
Array<Real>::const_vector_iterator bary_it;
Array<Real>::const_vector_iterator bary_begin =
bary_regular.begin(spatial_dimension);
Array<Real>::const_vector_iterator bary_end =
bary_regular.end(spatial_dimension);
/// compare the regular elements
ElementType element_type = _triangle_3;
- const Array<UInt> & element_filter =
+ const Array<Int> & element_filter =
model.getMaterial(0).getElementFilter(element_type, _not_ghost);
const Array<Real> & damage_regular_el =
model.getMaterial(0).getInternal<Real>("damage")(element_type,
_not_ghost);
const Array<Real> & Sc_regular_el =
model.getMaterial(0).getInternal<Real>("Sc")(element_type, _not_ghost);
- for (UInt e = 0; e < element_filter.getSize(); ++e) {
+ for (Int e = 0; e < element_filter.getSize(); ++e) {
UInt global_el_idx = element_filter(e);
- mesh.getBarycenter(global_el_idx, element_type, bary.storage(),
- _not_ghost);
+ mesh.getBarycenter(global_el_idx, element_type, bary.data(), _not_ghost);
/// find element
for (bary_it = bary_begin; bary_it != bary_end; ++bary_it) {
UInt matched_dim = 0;
while (
matched_dim < spatial_dimension &&
Math::are_float_equal(bary(matched_dim), (*bary_it)(matched_dim)))
++matched_dim;
if (matched_dim == spatial_dimension)
break;
}
if (bary_it == bary_end) {
std::cout << "Element barycenter not found!" << std::endl;
return false;
}
UInt matched_el = bary_it - bary_begin;
if (std::abs(damage_result(matched_el) - damage_regular_el(e)) > 1.e-12 ||
std::abs(Sc_result(matched_el) - Sc_regular_el(e)) > 1.e-4) {
test_result = false;
break;
}
}
/// compare the IGFEM elements
UInt nb_sub_elements = 2;
element_type = _igfem_triangle_4;
- const Array<UInt> & element_filter_igfem =
+ const Array<Int> & element_filter_igfem =
model.getMaterial(2).getElementFilter(element_type, _not_ghost);
const Array<Real> & damage_regular_el_igfem =
model.getMaterial(2).getInternal<Real>("damage")(element_type,
_not_ghost);
const Array<Real> & Sc_regular_el_igfem =
model.getMaterial(2).getInternal<Real>("Sc")(element_type, _not_ghost);
UInt * sub_el_ptr =
model.getMaterial(2)
.getInternal<UInt>("sub_material")(element_type, _not_ghost)
- .storage();
+ .data();
- for (UInt e = 0; e < element_filter_igfem.getSize(); ++e) {
+ for (Int e = 0; e < element_filter_igfem.getSize(); ++e) {
UInt global_el_idx = element_filter_igfem(e);
- for (UInt s = 0; s < nb_sub_elements; ++s, ++sub_el_ptr) {
+ for (Int s = 0; s < nb_sub_elements; ++s, ++sub_el_ptr) {
if (*sub_el_ptr)
model.getSubElementBarycenter(global_el_idx, s, element_type, bary,
_not_ghost);
else
continue;
/// find element
for (bary_it = bary_begin; bary_it != bary_end; ++bary_it) {
UInt matched_dim = 0;
while (
matched_dim < spatial_dimension &&
Math::are_float_equal(bary(matched_dim), (*bary_it)(matched_dim)))
++matched_dim;
if (matched_dim == spatial_dimension)
break;
}
if (bary_it == bary_end) {
std::cout << "Element barycenter not found!" << std::endl;
return false;
}
UInt matched_el = bary_it - bary_begin;
if (std::abs(damage_result(matched_el) -
damage_regular_el_igfem(e * nb_sub_elements + s)) >
1.e-12 ||
std::abs(Sc_result(matched_el) -
Sc_regular_el_igfem(e * nb_sub_elements + s)) > 1.e-4) {
test_result = false;
break;
}
}
}
Math::setTolerance(default_tolerance);
}
return test_result;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_damage_step_transfer.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_damage_step_transfer.cc
index 0921d7228..71ac629c4 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_damage_step_transfer.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_damage_step_transfer.cc
@@ -1,362 +1,362 @@
/**
* @file
* test_material_igfem_iterative_stiffness_reduction_damage_step_transfer.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the damage step transfer for the material iterative
* stiffness reduction
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_saw_tooth_damage.hh"
#include "material_iterative_stiffness_reduction.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class TestMaterialSelector : public MaterialSelector {
public:
TestMaterialSelector(SolidMechanicsModelIGFEM & model)
: MaterialSelector(), model(model),
spatial_dimension(model.getSpatialDimension()) {}
UInt operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_igfem)
return 2;
else {
/// regular elements
const Mesh & mesh = model.getMesh();
Vector<Real> barycenter(this->spatial_dimension);
mesh.getBarycenter(element, barycenter);
/// check if element belongs to ASR gel
if (model.isInside(barycenter))
return 1;
}
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
- UInt spatial_dimension;
+ Int spatial_dimension;
};
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material_stiffness_reduction_2.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("test_damage_transfer.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
Math::setTolerance(1.e-14);
/// intialize the geometry and set the material selector
std::list<SK::Sphere_3> inclusions_list;
model.registerGeometryObject(inclusions_list, "inclusion");
Real val = 1000000000;
Real radius_squared = (val - 0.6) * (val - 0.6);
Vector<Real> center(spatial_dimension);
center(0) = 0;
center(1) = val;
SK::Sphere_3 sphere(SK::Point_3(center(0), center(1), 0.), radius_squared);
inclusions_list.push_back(sphere);
TestMaterialSelector * mat_selector = new TestMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
/// initialization of the model
model.initFull();
/// boundary conditions
mesh.computeBoundingBox();
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real left = lowerBounds(0);
Real eps = std::abs((top - bottom) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<bool> & boun = model.getBlockedDOFs();
Array<Real> & disp = model.getDisplacement();
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (std::abs(pos(n, 1) - bottom) < eps) {
boun(n, 1) = true;
disp(n, 1) = 0.;
}
if (std::abs(pos(n, 1) - top) < eps) {
boun(n, 1) = true;
disp(n, 1) = 1.e-3;
}
if (std::abs(pos(n, 0) - left) < eps) {
boun(n, 0) = true;
disp(n, 0) = 0.;
}
}
/// add fields that should be dumped
model.setBaseName("regular");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.addDumpField("ultimate_strain");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
;
model.addDumpFieldToDumper("igfem elements", "stress");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "residual");
model.addDumpFieldToDumper("igfem elements", "grad_u");
model.addDumpFieldToDumper("igfem elements", "damage");
model.addDumpFieldToDumper("igfem elements", "partitions");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "force");
model.addDumpFieldToDumper("igfem elements", "equivalent_stress");
model.addDumpFieldToDumper("igfem elements", "ultimate_strain");
model.dump();
model.dump("igfem elements");
/// get a reference to the damage materials
MaterialIterativeStiffnessReduction<spatial_dimension> & material =
dynamic_cast<MaterialIterativeStiffnessReduction<spatial_dimension> &>(
model.getMaterial(0));
MaterialIGFEMSawToothDamage<spatial_dimension> & igfem_material =
dynamic_cast<MaterialIGFEMSawToothDamage<spatial_dimension> &>(
model.getMaterial(2));
Real error;
bool converged = false;
UInt nb_damaged_elements = 0;
Real max_eq_stress_regular = 0;
Real max_eq_stress_igfem = 0;
/// solve the system
// counter for the damage steps
UInt regular_steps = 15;
- for (UInt s = 0; s < regular_steps; ++s) {
+ for (Int s = 0; s < regular_steps; ++s) {
converged =
model.solveStep<_scm_newton_raphson_tangent_modified,
SolveConvergenceCriteria::_increment>(1e-12, error, 2);
if (converged == false) {
std::cout << "The error is: " << error << std::endl;
AKANTU_DEBUG_ASSERT(converged, "Did not converge");
}
/// compute damage
max_eq_stress_regular = material.getNormMaxEquivalentStress();
max_eq_stress_igfem = igfem_material.getNormMaxEquivalentStress();
if (max_eq_stress_regular > max_eq_stress_igfem)
nb_damaged_elements = material.updateDamage();
else if (max_eq_stress_regular == max_eq_stress_igfem) {
nb_damaged_elements = material.updateDamage();
nb_damaged_elements += igfem_material.updateDamage();
} else
nb_damaged_elements = igfem_material.updateDamage();
if (!nb_damaged_elements)
break;
model.dump();
model.dump("igfem elements");
}
const Array<UInt> & reduction_step_regular =
material.getInternal<UInt>("damage_step")(_triangle_3, _not_ghost);
UInt reduction_step_el_27 = reduction_step_regular(27);
UInt reduction_step_el_19 = reduction_step_regular(19);
/// create the interface
Real new_radius = (val - 0.1);
model.moveInterface(new_radius);
model.dump();
model.dump("igfem elements");
/// check that the damage reduction step has been correctly computed
/// regular element id -> igfem element id
/// 27 -> 7; 19 -> 5
const Array<UInt> & reduction_step_igfem = igfem_material.getInternal<UInt>(
"damage_step")(_igfem_triangle_5, _not_ghost);
Array<UInt>::const_scalar_iterator step_it = reduction_step_igfem.begin();
/// check the igfem elements
UInt nb_igfem_elements = mesh.getNbElement(_igfem_triangle_5, _not_ghost);
UInt nb_quads = model.getFEEngine("IGFEMFEEngine")
.getNbIntegrationPoints(_igfem_triangle_5, _not_ghost);
const Array<UInt> & sub_material = igfem_material.getInternal<UInt>(
"sub_material")(_igfem_triangle_5, _not_ghost);
Array<UInt>::const_scalar_iterator sub_it = sub_material.begin();
- for (UInt e = 0; e < nb_igfem_elements; ++e) {
- for (UInt q = 0; q < nb_quads; ++q, ++sub_it, ++step_it) {
+ for (Int e = 0; e < nb_igfem_elements; ++e) {
+ for (Int q = 0; q < nb_quads; ++q, ++sub_it, ++step_it) {
if (!*sub_it) {
if (!Math::are_float_equal(*step_it, 0.)) {
std::cout
<< "the reduction step for an elastic sub-element must be zero!!"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
} else {
if (e == 7) {
if (!Math::are_float_equal(*step_it, reduction_step_el_27)) {
std::cout << "error in computation of damage step!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
} else if (e == 5) {
if (!Math::are_float_equal(*step_it, reduction_step_el_19)) {
std::cout << "error in computation of damage step!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
} else {
if (!Math::are_float_equal(*step_it, 0.)) {
std::cout << "error in computation of damage step!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
}
}
}
//// force the next damage event
const Array<Real> & dam_igfem =
igfem_material.getInternal<Real>("damage")(_igfem_triangle_5, _not_ghost);
Array<Real> old_damage(dam_igfem);
- for (UInt s = 0; s < 1; ++s) {
+ for (Int s = 0; s < 1; ++s) {
converged =
model.solveStep<_scm_newton_raphson_tangent_modified,
SolveConvergenceCriteria::_increment>(1e-12, error, 2);
if (converged == false) {
std::cout << "The error is: " << error << std::endl;
AKANTU_DEBUG_ASSERT(converged, "Did not converge");
}
/// compute damage
max_eq_stress_regular = material.getNormMaxEquivalentStress();
max_eq_stress_igfem = igfem_material.getNormMaxEquivalentStress();
if (max_eq_stress_regular > max_eq_stress_igfem)
nb_damaged_elements = material.updateDamage();
else if (max_eq_stress_regular == max_eq_stress_igfem) {
nb_damaged_elements = material.updateDamage();
nb_damaged_elements += igfem_material.updateDamage();
} else
nb_damaged_elements = igfem_material.updateDamage();
if (!nb_damaged_elements)
break;
model.dump();
model.dump("igfem elements");
}
/// check that damage has been simultanously been updated on all the
/// the integration points of one sub-element
const Array<Real> & new_dam_igfem =
igfem_material.getInternal<Real>("damage")(_igfem_triangle_5, _not_ghost);
sub_it = sub_material.begin();
Array<Real>::const_scalar_iterator new_dam_it = new_dam_igfem.begin();
Array<Real>::const_scalar_iterator old_dam_it = old_damage.begin();
step_it = reduction_step_igfem.begin();
UInt reduction_constant = material.getParam<Real>("reduction_constant");
- for (UInt e = 0; e < nb_igfem_elements; ++e) {
- for (UInt q = 0; q < nb_quads;
+ for (Int e = 0; e < nb_igfem_elements; ++e) {
+ for (Int q = 0; q < nb_quads;
++q, ++sub_it, ++step_it, ++new_dam_it, ++old_dam_it) {
if (!*sub_it) {
if (!Math::are_float_equal(*step_it, 0.) ||
!Math::are_float_equal(*new_dam_it, 0.)) {
std::cout << "the reduction step and damagefor an elastic "
"sub-element must be zero!!"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
} else {
if (e == 7) {
if (!Math::are_float_equal(*step_it, reduction_step_el_27 + 1) ||
!Math::are_float_equal(
*new_dam_it, 1 - (1. / std::pow(reduction_constant,
reduction_step_el_27 + 1)))) {
std::cout << "error in computation of damage step!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
} else if (e == 5) {
if (!Math::are_float_equal(*step_it, reduction_step_el_19) ||
!Math::are_float_equal(*new_dam_it, *old_dam_it)) {
std::cout << "error in computation of damage step!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
} else {
if (!Math::are_float_equal(*step_it, 0.) ||
!Math::are_float_equal(*new_dam_it, 0.)) {
std::cout << "error in computation of damage step!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
}
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_parallel.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_parallel.cc
index 365259bce..3065a830c 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_parallel.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_parallel.cc
@@ -1,436 +1,435 @@
/**
* @file test_material_igfem_iterative_stiffness_reduction_parallel.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the material iterative stiffness reduction in parallel
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_saw_tooth_damage.hh"
#include "material_iterative_stiffness_reduction.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/// function declaration
bool checkDamageState(UInt step, const SolidMechanicsModelIGFEM & model);
class TestMaterialSelector : public MaterialSelector {
public:
TestMaterialSelector(SolidMechanicsModelIGFEM & model)
: MaterialSelector(), model(model),
spatial_dimension(model.getSpatialDimension()) {}
UInt operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_igfem)
return 2;
else {
/// regular elements
const Mesh & mesh = model.getMesh();
Vector<Real> barycenter(this->spatial_dimension);
mesh.getBarycenter(element, barycenter);
/// check if element belongs to ASR gel
if (model.isInside(barycenter))
return 1;
}
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
- UInt spatial_dimension;
+ Int spatial_dimension;
};
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material_stiffness_reduction_2.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("test_damage_transfer.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
Math::setTolerance(1.e-14);
/// intialize the geometry and set the material selector
std::list<SK::Sphere_3> inclusions_list;
model.registerGeometryObject(inclusions_list, "inclusion");
Real radius = 0.125;
;
Vector<Real> center(spatial_dimension);
center(0) = 0.;
center(1) = 0.;
SK::Sphere_3 sphere(SK::Point_3(center(0), center(1), 0.), radius * radius);
inclusions_list.push_back(sphere);
TestMaterialSelector * mat_selector = new TestMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
/// initialization of the model
model.initFull();
/// boundary conditions
mesh.computeBoundingBox();
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real left = lowerBounds(0);
Real eps = std::abs((top - bottom) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<bool> & boun = model.getBlockedDOFs();
Array<Real> & disp = model.getDisplacement();
for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
if (std::abs(pos(n, 1) - bottom) < eps) {
boun(n, 1) = true;
disp(n, 1) = 0.;
}
if (std::abs(pos(n, 1) - top) < eps) {
boun(n, 1) = true;
disp(n, 1) = 1.e-3;
}
if (std::abs(pos(n, 0) - left) < eps) {
boun(n, 0) = true;
disp(n, 0) = 0.;
}
}
/// add fields that should be dumped
model.setBaseName("regular");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.addDumpField("ultimate_strain");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
;
model.addDumpFieldToDumper("igfem elements", "stress");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "residual");
model.addDumpFieldToDumper("igfem elements", "grad_u");
model.addDumpFieldToDumper("igfem elements", "damage");
model.addDumpFieldToDumper("igfem elements", "partitions");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "force");
model.addDumpFieldToDumper("igfem elements", "equivalent_stress");
model.addDumpFieldToDumper("igfem elements", "ultimate_strain");
model.dump();
model.dump("igfem elements");
/// create the interface
model.update("inclusion");
/// get a reference to the damage materials
MaterialIterativeStiffnessReduction<spatial_dimension> & material =
dynamic_cast<MaterialIterativeStiffnessReduction<spatial_dimension> &>(
model.getMaterial(0));
MaterialIGFEMSawToothDamage<spatial_dimension> & igfem_material =
dynamic_cast<MaterialIGFEMSawToothDamage<spatial_dimension> &>(
model.getMaterial(2));
Real error;
bool converged = false;
UInt nb_damaged_elements = 0;
Real max_eq_stress_regular = 0;
Real max_eq_stress_igfem = 0;
/// solve the system
UInt s = 0;
do {
converged =
model.solveStep<_scm_newton_raphson_tangent_modified,
SolveConvergenceCriteria::_increment>(1e-12, error, 2);
if (converged == false) {
std::cout << "The error is: " << error << std::endl;
AKANTU_DEBUG_ASSERT(converged, "Did not converge");
}
/// compute damage
max_eq_stress_regular = material.getNormMaxEquivalentStress();
max_eq_stress_igfem = igfem_material.getNormMaxEquivalentStress();
if (max_eq_stress_regular > max_eq_stress_igfem)
nb_damaged_elements = material.updateDamage();
else if (max_eq_stress_regular == max_eq_stress_igfem) {
nb_damaged_elements = material.updateDamage();
nb_damaged_elements += igfem_material.updateDamage();
} else
nb_damaged_elements = igfem_material.updateDamage();
model.dump();
model.dump("igfem elements");
/// check the current damage state
if (!checkDamageState(s, model)) {
std::cout << "error in the damage compuation" << std::endl;
finalize();
return EXIT_FAILURE;
}
s++;
} while (nb_damaged_elements);
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
bool checkDamageState(UInt step, const SolidMechanicsModelIGFEM & model) {
bool test_result = true;
- const UInt spatial_dimension = model.getSpatialDimension();
+ const Int spatial_dimension = model.getSpatialDimension();
const Mesh & mesh = model.getMesh();
StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
if (psize == 1) {
const ElementType element_type = _triangle_3;
/// prepare output: compute barycenters for elements that can be damaged
- const Array<UInt> & element_filter =
+ const Array<Int> & element_filter =
model.getMaterial(0).getElementFilter(element_type, _not_ghost);
Array<Real> barycenters(element_filter.getSize(), spatial_dimension);
Array<Real>::vector_iterator bary_it = barycenters.begin(spatial_dimension);
- for (UInt e = 0; e < element_filter.getSize(); ++e, ++bary_it) {
+ for (Int e = 0; e < element_filter.getSize(); ++e, ++bary_it) {
UInt global_el_idx = element_filter(e);
mesh.getBarycenter(global_el_idx, element_type, bary_it->storage(),
_not_ghost);
}
const Array<Real> & damage = model.getMaterial(0).getInternal<Real>(
"damage")(element_type, _not_ghost);
const Array<Real> & Sc =
model.getMaterial(0).getInternal<Real>("Sc")(element_type, _not_ghost);
std::ostringstream file_name;
file_name << "step_" << std::setfill('0') << std::setw(3) << step << ".txt";
std::ofstream file_output;
file_output.open(file_name.str());
file_output << std::setprecision(14);
- for (UInt e = 0; e < barycenters.getSize(); ++e)
+ for (Int e = 0; e < barycenters.getSize(); ++e)
file_output << barycenters(e, 0) << " " << barycenters(e, 1) << " "
<< damage(e) << " " << Sc(e) << std::endl;
/// igfem elements
const ElementType element_type_igfem = _igfem_triangle_5;
/// prepare output: compute barycenters for elements that can be damaged
UInt nb_igfem_elements = mesh.getNbElement(_igfem_triangle_5, _not_ghost);
UInt nb_sub_elements = 2;
Array<Real> barycenters_igfem(nb_sub_elements * nb_igfem_elements,
spatial_dimension);
bary_it = barycenters_igfem.begin(spatial_dimension);
- for (UInt e = 0; e < nb_igfem_elements; ++e) {
+ for (Int e = 0; e < nb_igfem_elements; ++e) {
/// note global index is local index because there is only one igfem
/// material
- for (UInt s = 0; s < nb_sub_elements; ++s, ++bary_it)
+ for (Int s = 0; s < nb_sub_elements; ++s, ++bary_it)
model.getSubElementBarycenter(e, s, element_type_igfem, *bary_it,
_not_ghost);
}
const Array<Real> & damage_igfem = model.getMaterial(2).getInternal<Real>(
"damage")(element_type_igfem, _not_ghost);
Array<Real>::const_scalar_iterator dam_it = damage_igfem.begin();
const Array<Real> & Sc_igfem = model.getMaterial(2).getInternal<Real>("Sc")(
element_type_igfem, _not_ghost);
Array<Real>::const_scalar_iterator Sc_it = Sc_igfem.begin();
- for (UInt e = 0; e < nb_igfem_elements; ++e) {
- for (UInt s = 0; s < nb_sub_elements; ++s)
+ for (Int e = 0; e < nb_igfem_elements; ++e) {
+ for (Int s = 0; s < nb_sub_elements; ++s)
if (IGFEMHelper::getSubElementType(element_type_igfem, s) ==
_triangle_3) {
file_output << barycenters_igfem(e * nb_sub_elements + s, 0) << " "
<< barycenters_igfem(e * nb_sub_elements + s, 1) << " "
<< *dam_it << " " << *Sc_it << std::endl;
++dam_it;
++Sc_it;
} else if (IGFEMHelper::getSubElementType(element_type_igfem, s) ==
_quadrangle_4) {
file_output << barycenters_igfem(e * nb_sub_elements + s, 0) << " "
<< barycenters_igfem(e * nb_sub_elements + s, 1) << " "
<< *dam_it << " " << *Sc_it << std::endl;
dam_it += 4;
Sc_it += 4;
}
}
}
else {
/// read data
Real default_tolerance = Math::getTolerance();
Math::setTolerance(1.e-10);
std::stringstream results_file;
results_file << "step_" << std::setfill('0') << std::setw(3) << step
<< ".txt";
std::ifstream damage_input;
damage_input.open(results_file.str().c_str());
Array<Real> damage_result(0, 1);
Array<Real> Sc_result(0, 1);
Array<Real> bary_regular(0, spatial_dimension);
Vector<Real> bary(spatial_dimension);
Real dam = 0.;
Real strength = 0;
while (damage_input.good()) {
damage_input >> bary(0) >> bary(1) >> dam >> strength;
bary_regular.push_back(bary);
damage_result.push_back(dam);
Sc_result.push_back(strength);
}
/// compare the results
Array<Real>::const_vector_iterator bary_it;
Array<Real>::const_vector_iterator bary_begin =
bary_regular.begin(spatial_dimension);
Array<Real>::const_vector_iterator bary_end =
bary_regular.end(spatial_dimension);
/// compare the regular elements
ElementType element_type = _triangle_3;
- const Array<UInt> & element_filter =
+ const Array<Int> & element_filter =
model.getMaterial(0).getElementFilter(element_type, _not_ghost);
const Array<Real> & damage_regular_el =
model.getMaterial(0).getInternal<Real>("damage")(element_type,
_not_ghost);
const Array<Real> & Sc_regular_el =
model.getMaterial(0).getInternal<Real>("Sc")(element_type, _not_ghost);
- for (UInt e = 0; e < element_filter.getSize(); ++e) {
+ for (Int e = 0; e < element_filter.getSize(); ++e) {
UInt global_el_idx = element_filter(e);
- mesh.getBarycenter(global_el_idx, element_type, bary.storage(),
- _not_ghost);
+ mesh.getBarycenter(global_el_idx, element_type, bary.data(), _not_ghost);
/// find element
for (bary_it = bary_begin; bary_it != bary_end; ++bary_it) {
UInt matched_dim = 0;
while (
matched_dim < spatial_dimension &&
Math::are_float_equal(bary(matched_dim), (*bary_it)(matched_dim)))
++matched_dim;
if (matched_dim == spatial_dimension)
break;
}
if (bary_it == bary_end) {
std::cout << "Element barycenter not found!" << std::endl;
return false;
}
UInt matched_el = bary_it - bary_begin;
if (std::abs(damage_result(matched_el) - damage_regular_el(e)) > 1.e-12 ||
std::abs(Sc_result(matched_el) - Sc_regular_el(e)) > 1.e-4) {
test_result = false;
break;
}
}
/// compare the IGFEM elements
UInt nb_sub_elements = 2;
element_type = _igfem_triangle_5;
- const Array<UInt> & element_filter_igfem =
+ const Array<Int> & element_filter_igfem =
model.getMaterial(2).getElementFilter(element_type, _not_ghost);
const Array<Real> & damage_regular_el_igfem =
model.getMaterial(2).getInternal<Real>("damage")(element_type,
_not_ghost);
Array<Real>::const_scalar_iterator dam_igfem_it =
damage_regular_el_igfem.begin();
const Array<Real> & Sc_regular_el_igfem =
model.getMaterial(2).getInternal<Real>("Sc")(element_type, _not_ghost);
Array<Real>::const_scalar_iterator Sc_igfem_it =
Sc_regular_el_igfem.begin();
- for (UInt e = 0; e < element_filter_igfem.getSize(); ++e) {
+ for (Int e = 0; e < element_filter_igfem.getSize(); ++e) {
UInt global_el_idx = element_filter_igfem(e);
- for (UInt s = 0; s < nb_sub_elements; ++s) {
+ for (Int s = 0; s < nb_sub_elements; ++s) {
model.getSubElementBarycenter(global_el_idx, s, element_type, bary,
_not_ghost);
/// find element
for (bary_it = bary_begin; bary_it != bary_end; ++bary_it) {
UInt matched_dim = 0;
while (
matched_dim < spatial_dimension &&
Math::are_float_equal(bary(matched_dim), (*bary_it)(matched_dim)))
++matched_dim;
if (matched_dim == spatial_dimension)
break;
}
if (bary_it == bary_end) {
std::cout << "Sub-element barycenter not found!" << std::endl;
return false;
}
UInt matched_el = bary_it - bary_begin;
if (std::abs(damage_result(matched_el) - *dam_igfem_it) > 1.e-12 ||
std::abs(Sc_result(matched_el) - *Sc_igfem_it) > 1.e-4) {
test_result = false;
break;
}
if (IGFEMHelper::getSubElementType(element_type, s) == _triangle_3) {
++Sc_igfem_it;
++dam_igfem_it;
} else if (IGFEMHelper::getSubElementType(element_type, s) ==
_quadrangle_4) {
Sc_igfem_it += 4;
dam_igfem_it += 4;
}
}
}
Math::setTolerance(default_tolerance);
}
return test_result;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_tangent_transfer.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_tangent_transfer.cc
index 61eacbdb0..6ea1fdb50 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_tangent_transfer.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_material_igfem_iterative_stiffness_reduction_tangent_transfer.cc
@@ -1,272 +1,272 @@
/**
* @file test_material_igfem_iterative_stiffness_reduction_tangent_transfer.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the tangent transfer for the material iterative
* stiffness reduction
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_saw_tooth_damage.hh"
#include "material_iterative_stiffness_reduction.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class TestMaterialSelector : public MaterialSelector {
public:
TestMaterialSelector(SolidMechanicsModelIGFEM & model)
: MaterialSelector(), model(model),
spatial_dimension(model.getSpatialDimension()) {}
UInt operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_igfem)
return 2;
else {
/// regular elements
const Mesh & mesh = model.getMesh();
Vector<Real> barycenter(this->spatial_dimension);
mesh.getBarycenter(element, barycenter);
/// check if element belongs to ASR gel
if (model.isInside(barycenter))
return 1;
}
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
- UInt spatial_dimension;
+ Int spatial_dimension;
};
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material_stiffness_reduction_2.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("test_damage_transfer.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
Math::setTolerance(1.e-14);
/// intialize the geometry and set the material selector
std::list<SK::Sphere_3> inclusions_list;
model.registerGeometryObject(inclusions_list, "inclusion");
Real val = 1000000000;
Real radius_squared = (val - 0.6) * (val - 0.6);
Vector<Real> center(spatial_dimension);
center(0) = 0;
center(1) = val;
SK::Sphere_3 sphere(SK::Point_3(center(0), center(1), 0.), radius_squared);
inclusions_list.push_back(sphere);
TestMaterialSelector * mat_selector = new TestMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
/// initialization of the model
model.initFull();
/// boundary conditions
mesh.computeBoundingBox();
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real left = lowerBounds(0);
Real eps = std::abs((top - bottom) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<bool> & boun = model.getBlockedDOFs();
Array<Real> & disp = model.getDisplacement();
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (std::abs(pos(n, 1) - bottom) < eps) {
boun(n, 1) = true;
disp(n, 1) = 0.;
}
if (std::abs(pos(n, 1) - top) < eps) {
boun(n, 1) = true;
disp(n, 1) = 1.e-3;
}
if (std::abs(pos(n, 0) - left) < eps) {
boun(n, 0) = true;
disp(n, 0) = 0.;
}
}
/// add fields that should be dumped
model.setBaseName("regular");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.addDumpField("ultimate_strain");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
;
model.addDumpFieldToDumper("igfem elements", "stress");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "residual");
model.addDumpFieldToDumper("igfem elements", "grad_u");
model.addDumpFieldToDumper("igfem elements", "damage");
model.addDumpFieldToDumper("igfem elements", "partitions");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "force");
model.addDumpFieldToDumper("igfem elements", "equivalent_stress");
model.addDumpFieldToDumper("igfem elements", "ultimate_strain");
model.dump();
model.dump("igfem elements");
/// get a reference to the damage materials
MaterialIterativeStiffnessReduction<spatial_dimension> & material =
dynamic_cast<MaterialIterativeStiffnessReduction<spatial_dimension> &>(
model.getMaterial(0));
MaterialIGFEMSawToothDamage<spatial_dimension> & igfem_material =
dynamic_cast<MaterialIGFEMSawToothDamage<spatial_dimension> &>(
model.getMaterial(2));
/// check that the tangent of the softening law has been computed correctly
const Array<Real> & Sc =
material.getInternal<Real>("Sc")(_triangle_3, _not_ghost);
Array<Real>::const_scalar_iterator Sc_it = Sc.begin();
const Array<Real> & D =
material.getInternal<Real>("tangent")(_triangle_3, _not_ghost);
Array<Real>::const_scalar_iterator D_it = D.begin();
Real E = material.getParam<Real>("E");
Real Gf = 20.;
Real ultimate_strain = 0;
Real crack_band_width = 0.25;
Real D_exact = 0.;
Math::setTolerance(1.e-13);
- for (UInt i = 0; i < Sc.getSize(); ++i, ++Sc_it, ++D_it) {
+ for (Int i = 0; i < Sc.getSize(); ++i, ++Sc_it, ++D_it) {
ultimate_strain = 2. * Gf / (*Sc_it * crack_band_width);
D_exact = *Sc_it / (ultimate_strain - (*Sc_it / E));
if (!Math::are_float_equal(*D_it, D_exact)) {
std::cout << "error in the tangent or ultimate strain" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
/// regular elements are linear triganle elements -> only one integration
/// point
const Array<Real> & eps_u =
material.getInternal<Real>("ultimate_strain")(_triangle_3, _not_ghost);
Real D_el_27 = D(27);
Real D_el_19 = D(19);
Real epsu_el_27 = eps_u(27);
Real epsu_el_19 = eps_u(19);
/// create the interface
Real new_radius = (val - 0.1);
model.moveInterface(new_radius);
model.dump();
model.dump("igfem elements");
/// check that the damage reduction step has been correctly computed
/// regular element id -> igfem element id
/// 27 -> 7; 19 -> 5
const Array<Real> & epsu_igfem = igfem_material.getInternal<Real>(
"ultimate_strain")(_igfem_triangle_5, _not_ghost);
Array<Real>::const_scalar_iterator epsu_igfem_it = epsu_igfem.begin();
const Array<Real> & D_igfem = igfem_material.getInternal<Real>("tangent")(
_igfem_triangle_5, _not_ghost);
Array<Real>::const_scalar_iterator D_igfem_it = D_igfem.begin();
/// check the igfem elements
UInt nb_igfem_elements = mesh.getNbElement(_igfem_triangle_5, _not_ghost);
UInt nb_quads = model.getFEEngine("IGFEMFEEngine")
.getNbIntegrationPoints(_igfem_triangle_5, _not_ghost);
const Array<UInt> & sub_material = igfem_material.getInternal<UInt>(
"sub_material")(_igfem_triangle_5, _not_ghost);
Array<UInt>::const_scalar_iterator sub_it = sub_material.begin();
- for (UInt e = 0; e < nb_igfem_elements; ++e) {
- for (UInt q = 0; q < nb_quads;
+ for (Int e = 0; e < nb_igfem_elements; ++e) {
+ for (Int q = 0; q < nb_quads;
++q, ++sub_it, ++D_igfem_it, ++epsu_igfem_it) {
if (!*sub_it) {
if (!Math::are_float_equal(*epsu_igfem_it, 0.) ||
!Math::are_float_equal(*D_igfem_it, 0.)) {
std::cout << "the tangent and ultimate strain of a sub-element must "
"be zero!!"
<< std::endl;
finalize();
return EXIT_FAILURE;
}
} else {
if (e == 7) {
if (!Math::are_float_equal(*epsu_igfem_it, epsu_el_27) ||
!Math::are_float_equal(*D_igfem_it, D_el_27)) {
std::cout << "error in tangent or ultimate strain!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
} else if (e == 5) {
if (!Math::are_float_equal(*epsu_igfem_it, epsu_el_19) ||
!Math::are_float_equal(*D_igfem_it, D_el_19)) {
std::cout << "error in tangent or ultimate strain!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
}
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_solid_mechanics_model_igfem.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_solid_mechanics_model_igfem.cc
index 75826b39b..2c5df7a3e 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_solid_mechanics_model_igfem.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_solid_mechanics_model_igfem.cc
@@ -1,337 +1,337 @@
/**
* @file test_solid_mechanics_model_igfem.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief test the solidmechancis model for IGFEM analysis
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dumper_paraview.hh"
#include "material_elastic.hh"
#include "mesh_geom_common.hh"
#include "solid_mechanics_model_igfem.hh"
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <math.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
void outputArray(const Mesh & mesh, const Array<Real> & array) {
StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
Int prank = comm.whoAmI();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
UInt nb_global_nodes = mesh.getNbGlobalNodes();
Array<Real> solution(nb_global_nodes, spatial_dimension, 0.);
Array<Real>::vector_iterator solution_begin =
solution.begin(spatial_dimension);
Array<Real>::const_vector_iterator array_it = array.begin(spatial_dimension);
for (UInt n = 0; n < mesh.getNbNodes(); ++n, ++array_it) {
if (mesh.isLocalOrMasterNode(n))
solution_begin[mesh.getNodeGlobalId(n)] = *array_it;
}
- comm.allReduce(solution.storage(),
+ comm.allReduce(solution.data(),
solution.getSize() * solution.getNbComponent(), _so_sum);
std::cout << std::fixed;
std::cout << std::setprecision(6);
if (prank == 0) {
Array<Real>::const_vector_iterator sol_it =
solution.begin(spatial_dimension);
for (UInt n = 0; n < nb_global_nodes; ++n, ++sol_it)
// Print absolute values to avoid parasite negative sign in machine
// precision zeros
std::cout << std::abs((*sol_it)(0)) << "," << std::abs((*sol_it)(1))
<< std::endl;
}
}
/* -------------------------------------------------------------------------- */
class Sphere {
public:
Sphere(const Vector<Real> & center, Real radius, Real tolerance = 0.)
: center(center), radius(radius), tolerance(tolerance) {}
bool isInside(const Vector<Real> & point) const {
return (point.distance(center) < radius + tolerance);
}
const Vector<Real> & getCenter() const { return center; }
Real & getRadius() { return radius; }
protected:
Vector<Real> center;
Real radius, tolerance;
};
void growGel(std::list<SK::Sphere_3> & query_list, Real new_radius) {
std::list<SK::Sphere_3>::const_iterator query_it = query_list.begin(),
query_end = query_list.end();
std::list<SK::Sphere_3> sphere_list;
for (; query_it != query_end; ++query_it) {
SK::Sphere_3 sphere(query_it->center(), new_radius * new_radius);
sphere_list.push_back(sphere);
}
query_list.zero();
query_list = sphere_list;
}
Real computeAlpha(Real inner_radius, Real outer_radius,
const Vector<Real> & lambda, const Vector<Real> & mu) {
Real alpha = (lambda(1) + mu(1) + mu(0)) * outer_radius * outer_radius /
((lambda(0) + mu(0)) * inner_radius * inner_radius +
(lambda(1) + mu(1)) * (outer_radius * outer_radius -
inner_radius * inner_radius) +
(mu(0) * outer_radius * outer_radius));
return alpha;
}
void applyBoundaryConditions(SolidMechanicsModelIGFEM & model,
Real inner_radius, Real outer_radius,
const Vector<Real> & lambda,
const Vector<Real> & mu) {
/// boundary conditions for circular inclusion:
Real alpha = computeAlpha(inner_radius, outer_radius, lambda, mu);
Mesh & mesh = model.getMesh();
mesh.computeBoundingBox();
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real left = lowerBounds(0);
Real right = upperBounds(0);
Real eps = std::abs((top - bottom) * 1e-12);
const Array<Real> & pos = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & boun = model.getBlockedDOFs();
Real radius = 0;
Real phi = 0;
disp.zero();
boun.zero();
/// absolute confinement
for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
if (std::abs(pos(i, 0) - left) < eps) {
radius = std::sqrt(pos(i, 0) * pos(i, 0) + pos(i, 1) * pos(i, 1));
phi = std::atan2(pos(i, 1), pos(i, 0));
boun(i, 0) = true;
disp(i, 0) = cos(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
boun(i, 1) = true;
disp(i, 1) = sin(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
}
if (std::abs(pos(i, 0) - right) < eps) {
radius = std::sqrt(pos(i, 0) * pos(i, 0) + pos(i, 1) * pos(i, 1));
phi = std::atan2(pos(i, 1), pos(i, 0));
boun(i, 0) = true;
disp(i, 0) = cos(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
boun(i, 1) = true;
disp(i, 1) = sin(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
}
if (std::abs(pos(i, 1) - top) < eps) {
radius = std::sqrt(pos(i, 0) * pos(i, 0) + pos(i, 1) * pos(i, 1));
phi = std::atan2(pos(i, 1), pos(i, 0));
boun(i, 0) = true;
disp(i, 0) = cos(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
boun(i, 1) = true;
disp(i, 1) = sin(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
}
if (std::abs(pos(i, 1) - bottom) < eps) {
radius = std::sqrt(pos(i, 0) * pos(i, 0) + pos(i, 1) * pos(i, 1));
phi = std::atan2(pos(i, 1), pos(i, 0));
boun(i, 0) = true;
disp(i, 0) = cos(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
boun(i, 1) = true;
disp(i, 1) = sin(phi) * ((radius - 4. / radius) * alpha + 4. / radius);
}
}
}
class SphereMaterialSelector : public DefaultMaterialIGFEMSelector {
public:
SphereMaterialSelector(std::vector<Sphere> & sphere_list,
SolidMechanicsModelIGFEM & model)
: DefaultMaterialIGFEMSelector(model), model(model),
spheres(sphere_list) {}
UInt operator()(const Element & elem) {
if (Mesh::getKind(elem.type) == _ek_igfem)
return this->fallback_value_igfem;
// return 2;//2model.getMaterialIndex(2);
const Mesh & mesh = model.getMesh();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Vector<Real> barycenter(spatial_dimension);
mesh.getBarycenter(elem, barycenter);
std::vector<Sphere>::const_iterator iit = spheres.begin();
std::vector<Sphere>::const_iterator eit = spheres.end();
for (; iit != eit; ++iit) {
const Sphere & sp = *iit;
if (sp.isInside(barycenter)) {
return 1; // model.getMaterialIndex("inside");;
}
}
return 0;
// return DefaultMaterialSelector::operator()(elem);
}
void update(Real new_radius) {
std::vector<Sphere>::iterator iit = spheres.begin();
std::vector<Sphere>::iterator eit = spheres.end();
for (; iit != eit; ++iit) {
Real & radius = iit->getRadius();
radius = new_radius;
}
}
protected:
SolidMechanicsModelIGFEM & model;
std::vector<Sphere> spheres;
};
typedef Spherical SK;
/// the following modeling problem is explained in:
/// T.-P. Fries "A corrected XFEM approximation without problems in blending
/// elements", 2008
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
/// problem dimension
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// mesh creation
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("plate.msh");
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
Math::setTolerance(1e-14);
/// geometry of IGFEM interface: circular inclusion
Real radius_inclusion = 0.401;
Vector<Real> center(spatial_dimension, 0.);
/// @todo: Simplify this: need to create two type of spheres:
/// one for the geometry and one for the material selector
SK::Sphere_3 sphere(SK::Point_3(center(0), center(1), 0),
radius_inclusion * radius_inclusion);
std::list<SK::Sphere_3> sphere_list;
sphere_list.push_back(sphere);
ID domain_name = "gel";
SphereMaterialSelector * mat_selector;
/// set material selector and initialize the model completely
std::vector<Sphere> spheres;
spheres.push_back(Sphere(center, radius_inclusion, 1.e-12));
mat_selector = new SphereMaterialSelector(spheres, model);
model.setMaterialSelector(*mat_selector);
model.initFull();
/// register the sphere list in the model
model.registerGeometryObject(sphere_list, domain_name);
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpField("material_index");
model.addDumpField("partitions");
model.addDumpFieldVector("displacement");
model.addDumpField("blocked_dofs");
model.addDumpField("stress");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldVectorToDumper("igfem elements", "real_displacement");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "stress");
model.addDumpFieldToDumper("igfem elements", "partitions");
/// dump mesh before the IGFEM interface is created
model.dump();
model.dump("igfem elements");
/// create the interface
model.update(domain_name);
/* --------------------------------------------------------------------------
*/
/// apply exact solution for the displacement along the outer boundary
Real outer_radius = 2.0;
/// get the Lame constants for the two non-igfem materials (frist two
/// materials in the material file):
/// Needed for compuation of boundary conditions
Vector<Real> lambda(2);
Vector<Real> mu(2);
- for (UInt m = 0; m < 2; ++m) {
+ for (Int m = 0; m < 2; ++m) {
MaterialElastic<spatial_dimension> & mat =
dynamic_cast<MaterialElastic<spatial_dimension> &>(
model.getMaterial(m));
lambda(m) = mat.getLambda();
mu(m) = mat.getMu();
}
applyBoundaryConditions(model, radius_inclusion, outer_radius, lambda, mu);
/// dump the mesh after the IGFEM interface has been created
model.dump();
model.dump("igfem elements");
/// solve the system
bool factorize = false;
bool converged = false;
Real error;
converged = model.solveStep<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
1e-12, error, 2, factorize);
if (!converged) {
std::cout << "Solving step did not yield a converged solution, error: "
<< error << std::endl;
return EXIT_FAILURE;
}
/// dump the solution
model.dump();
model.dump("igfem elements");
/// output the displacement in parallel
outputArray(mesh, model.getDisplacement());
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_transfer_internals.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_transfer_internals.cc
index 36416e5af..8415184b7 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_transfer_internals.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_transfer_internals.cc
@@ -1,298 +1,298 @@
/**
* @file test_transfer_internals.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
*
* @brief test to test the transfer of internals such as damage
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dumper_paraview.hh"
#include "mesh_geom_common.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
bool checkResults(Real & error, UInt & counter, SolidMechanicsModel & model,
Real diagonal);
class ASRMaterialSelector : public DefaultMaterialIGFEMSelector {
public:
ASRMaterialSelector(SolidMechanicsModelIGFEM & model)
: DefaultMaterialIGFEMSelector(model), model(model) {}
UInt operator()(const Element & elem) {
if (Mesh::getKind(elem.type) == _ek_igfem)
/// choose IGFEM material
return this->fallback_value_igfem;
const Mesh & mesh = model.getMesh();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Vector<Real> barycenter(spatial_dimension);
mesh.getBarycenter(elem, barycenter);
if (model.isInside(barycenter))
return 1;
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
};
typedef Spherical SK;
int main(int argc, char * argv[]) {
initialize("material_damage.dat", argc, argv);
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// problem dimension
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
/// mesh creation and partioning
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("fine_mesh.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation and initialization
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
/// create the list to store the gel pockets
std::list<SK::Sphere_3> gel_pocket_list;
model.registerGeometryObject(gel_pocket_list, "mat_1");
/// set the material selector
ASRMaterialSelector * mat_selector = new ASRMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
model.initFull();
/// add fields that should be dumped
model.setBaseName("regular_elements");
model.addDumpField("material_index");
model.addDumpField("damage");
model.addDumpField("Sc");
model.addDumpField("partitions");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "damage");
model.addDumpFieldToDumper("igfem elements", "lambda");
model.addDumpFieldToDumper("igfem elements", "partitions");
/// set damage state as a function of the position of the quadrature
/// point the damage state is the absolute value of bary center
/// position normalized by the half of the diagonal of the mesh (which is a
/// square)
/// compute the mesh diagonal
mesh.computeBoundingBox();
const Vector<Real> & lower_bounds = mesh.getLowerBounds();
const Vector<Real> & upper_bounds = mesh.getUpperBounds();
Real diagonal = upper_bounds.distance(lower_bounds);
/// compute barycenters and set damage state
GhostType ghost_type = _not_ghost;
ElementType el_type = _triangle_3;
UInt nb_element = mesh.getNbElement(el_type, ghost_type);
Array<Real> barycenter(nb_element, spatial_dimension);
Array<Real>::iterator<Vector<Real>> bary_it =
barycenter.begin(spatial_dimension);
for (UInt elem = 0; elem < nb_element; ++elem) {
mesh.getBarycenter(elem, el_type, bary_it->storage(), ghost_type);
UInt mat_index =
model.getMaterialByElement(el_type, ghost_type).begin()[elem];
UInt local_index =
model.getMaterialLocalNumbering(el_type, ghost_type).begin()[elem];
Material & mat = model.getMaterial(mat_index);
Array<Real> & damage = mat.getArray<Real>("damage", el_type, ghost_type);
Array<Real>::scalar_iterator damage_it = damage.begin();
damage_it[local_index] = (*bary_it).norm() / (0.5 * diagonal);
++bary_it;
}
/// dump
model.dump("igfem elements");
model.dump();
/// create the inclusions
SK::Sphere_3 sphere_1(SK::Point_3(0., 0., 0.), 0.13 * 0.13);
SK::Sphere_3 sphere_2(SK::Point_3(0.5, 0.5, 0.), 0.4 * 0.4);
SK::Sphere_3 sphere_3(SK::Point_3(-0.75, -0.75, 0.), 0.12 * 0.12);
SK::Sphere_3 sphere_4(SK::Point_3(0.625, -0.625, 0.), 0.25 * 0.25);
gel_pocket_list.push_back(sphere_1);
gel_pocket_list.push_back(sphere_2);
gel_pocket_list.push_back(sphere_3);
gel_pocket_list.push_back(sphere_4);
/// create the interface
model.update("mat_1");
/// dump
model.dump("igfem elements");
model.dump();
/// check that internals have been transferred correctly
Real error = 0.;
UInt counter = 0;
bool check_passed = checkResults(error, counter, model, diagonal);
if (!check_passed) {
finalize();
return EXIT_FAILURE;
}
comm.allReduce(&error, 1, _so_sum);
comm.allReduce(&counter, 1, _so_sum);
if (prank == 0) {
std::cout << "The error is: " << error << std::endl;
std::cout << "There are " << counter
<< " igfem quads with damage material in the mesh" << std::endl;
std::cout
<< "There should be 156 igfem quads with damage material in the mesh"
<< std::endl;
}
if (error > 1e-14 || counter != 156) {
finalize();
return EXIT_FAILURE;
}
// /// grow two of the gel pockets (gel pocket 1 and 3) and repeat the test
std::list<SK::Sphere_3> new_gel_pocket_list;
/// grow sphere 2
SK::Sphere_3 sphere_5(SK::Point_3(0., 0., 0.), 0.15 * 0.15);
/// grow sphere 3
SK::Sphere_3 sphere_6(SK::Point_3(-0.75, -0.75, 0.), 0.5 * 0.5);
new_gel_pocket_list.push_back(sphere_5);
new_gel_pocket_list.push_back(sphere_2);
new_gel_pocket_list.push_back(sphere_6);
new_gel_pocket_list.push_back(sphere_4);
gel_pocket_list.zero();
gel_pocket_list = new_gel_pocket_list;
model.update("mat_1");
/// check again that internals have been transferred correctly
error = 0.;
counter = 0;
check_passed = checkResults(error, counter, model, diagonal);
if (!check_passed) {
finalize();
return EXIT_FAILURE;
}
comm.allReduce(&error, 1, _so_sum);
comm.allReduce(&counter, 1, _so_sum);
if (prank == 0) {
std::cout << "The error is: " << error << std::endl;
std::cout << "There are " << counter
<< " igfem quads with damage material in the mesh" << std::endl;
std::cout
<< "There should be 150 igfem quads with damage material in the mesh"
<< std::endl;
}
if (error > 1e-14 || counter != 150) {
finalize();
return EXIT_FAILURE;
}
/// dump
model.dump("igfem elements");
model.dump();
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
bool checkResults(Real & error, UInt & counter, SolidMechanicsModel & model,
Real diagonal) {
/// check that damage values have been correctly transferred
FEEngine & fee = model.getFEEngine("IGFEMFEEngine");
GhostType ghost_type = _not_ghost;
Mesh & mesh = model.getMesh();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
bool check_passed = true;
/// loop over all IGFEM elements of type _not_ghost
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, ghost_type, _ek_igfem);
Mesh::type_iterator last =
mesh.lastType(spatial_dimension, ghost_type, _ek_igfem);
for (; it != last; ++it) {
ElementType igfem_el_type = *it;
UInt nb_igfem_element = mesh.getNbElement(igfem_el_type);
UInt nb_quads = fee.getNbIntegrationPoints(igfem_el_type, ghost_type);
Array<Real> barycenter_igfem(nb_igfem_element, spatial_dimension);
Array<Real>::vector_iterator bary_it =
barycenter_igfem.begin(spatial_dimension);
- UInt * conn_val = mesh.getConnectivity(igfem_el_type, ghost_type).storage();
+ UInt * conn_val = mesh.getConnectivity(igfem_el_type, ghost_type).data();
Array<Real> & nodes = mesh.getNodes();
UInt nb_parent_nodes = IGFEMHelper::getNbParentNodes(igfem_el_type);
/// compute the bary center of the underlying parent element
UInt nb_el_nodes = mesh.getNbNodesPerElement(igfem_el_type);
- for (UInt elem = 0; elem < nb_igfem_element; ++elem) {
+ for (Int elem = 0; elem < nb_igfem_element; ++elem) {
Real local_coord[spatial_dimension * nb_parent_nodes];
UInt offset = elem * nb_el_nodes;
- for (UInt n = 0; n < nb_parent_nodes; ++n) {
+ for (Int n = 0; n < nb_parent_nodes; ++n) {
memcpy(local_coord + n * spatial_dimension,
- nodes.storage() + conn_val[offset + n] * spatial_dimension,
+ nodes.data() + conn_val[offset + n] * spatial_dimension,
spatial_dimension * sizeof(Real));
}
Math::barycenter(local_coord, nb_parent_nodes, spatial_dimension,
bary_it->storage());
UInt mat_index =
model.getMaterialByElement(igfem_el_type, ghost_type).begin()[elem];
Material & mat = model.getMaterial(mat_index);
UInt local_index =
model.getMaterialLocalNumbering(igfem_el_type, ghost_type)
.begin()[elem];
Array<Real> & damage =
mat.getArray<Real>("damage", igfem_el_type, ghost_type);
Array<UInt> & sub_mat =
mat.getArray<UInt>("sub_material", igfem_el_type, ghost_type);
Array<Real> & strength =
mat.getArray<Real>("Sc", igfem_el_type, ghost_type);
Array<Real>::scalar_iterator damage_it = damage.begin();
Array<UInt>::scalar_iterator sub_mat_it = sub_mat.begin();
Array<Real>::scalar_iterator Sc_it = strength.begin();
- for (UInt q = 0; q < nb_quads; ++q) {
+ for (Int q = 0; q < nb_quads; ++q) {
UInt q_global = local_index * nb_quads + q;
if (sub_mat_it[q_global] == 1) {
if (std::abs(Sc_it[q_global] - 100) > 1e-15) {
check_passed = false;
return check_passed;
}
error += std::abs(
(damage_it[q_global] - (*bary_it).norm() / (0.5 * diagonal)));
++counter;
} else if ((std::abs(Sc_it[q_global]) > Math::getTolerance()) ||
(std::abs(damage_it[q_global]) > Math::getTolerance())) {
check_passed = false;
return check_passed;
}
}
++bary_it;
}
}
return check_passed;
}
diff --git a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_volume_computation.cc b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_volume_computation.cc
index 1f158015a..ca2f216ce 100644
--- a/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_volume_computation.cc
+++ b/extra_packages/igfem/test/test_solid_mechanics_model_igfem/test_volume_computation.cc
@@ -1,239 +1,239 @@
/**
* @file test_volume_computation.cc
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @date Thu Nov 26 12:20:15 2015
*
* @brief test the volume computation for the different sub-materials
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_igfem_saw_tooth_damage.hh"
#include "material_iterative_stiffness_reduction.hh"
#include "solid_mechanics_model_igfem.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class TestMaterialSelector : public MaterialSelector {
public:
TestMaterialSelector(SolidMechanicsModelIGFEM & model)
: MaterialSelector(), model(model),
spatial_dimension(model.getSpatialDimension()) {}
UInt operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_igfem)
return 2;
else {
/// regular elements
const Mesh & mesh = model.getMesh();
Vector<Real> barycenter(this->spatial_dimension);
mesh.getBarycenter(element, barycenter);
/// check if element belongs to ASR gel
if (model.isInside(barycenter))
return 1;
}
return 0;
}
protected:
SolidMechanicsModelIGFEM & model;
- UInt spatial_dimension;
+ Int spatial_dimension;
};
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Math::setTolerance(1e-13);
debug::setDebugLevel(dblWarning);
initialize("material_stiffness_reduction.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
StaticCommunicator & comm =
akantu::StaticCommunicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partion it
Mesh mesh(spatial_dimension);
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("test_damage_transfer.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
/// model creation
SolidMechanicsModelIGFEM model(mesh);
model.initParallel(partition);
delete partition;
Math::setTolerance(1.e-14);
/// intialize the geometry and set the material selector
std::list<SK::Sphere_3> inclusions_list;
model.registerGeometryObject(inclusions_list, "inclusion");
Real val = 1000000000;
Real radius_squared = (val - 0.1) * (val - 0.1);
Vector<Real> center(spatial_dimension);
center(0) = 0;
center(1) = val;
SK::Sphere_3 sphere(SK::Point_3(center(0), center(1), 0.), radius_squared);
inclusions_list.push_back(sphere);
TestMaterialSelector * mat_selector = new TestMaterialSelector(model);
model.setMaterialSelector(*mat_selector);
/// initialization of the model
model.initFull();
/// boundary conditions
mesh.computeBoundingBox();
const Vector<Real> & lowerBounds = mesh.getLowerBounds();
const Vector<Real> & upperBounds = mesh.getUpperBounds();
Real bottom = lowerBounds(1);
Real top = upperBounds(1);
Real left = lowerBounds(0);
Real eps = std::abs((top - bottom) * 1e-6);
const Array<Real> & pos = mesh.getNodes();
Array<bool> & boun = model.getBlockedDOFs();
Array<Real> & disp = model.getDisplacement();
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (std::abs(pos(n, 1) - bottom) < eps) {
boun(n, 1) = true;
disp(n, 1) = 0.;
}
if (std::abs(pos(n, 1) - top) < eps) {
boun(n, 1) = true;
disp(n, 1) = 1.e-3;
}
if (std::abs(pos(n, 0) - left) < eps) {
boun(n, 0) = true;
disp(n, 0) = 0.;
}
}
/// add fields that should be dumped
model.setBaseName("regular");
model.addDumpField("material_index");
model.addDumpFieldVector("displacement");
;
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
model.addDumpField("residual");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpField("partitions");
model.addDumpField("Sc");
model.addDumpField("force");
model.addDumpField("equivalent_stress");
model.addDumpField("ultimate_strain");
model.setBaseNameToDumper("igfem elements", "igfem elements");
model.addDumpFieldToDumper("igfem elements", "material_index");
model.addDumpFieldVectorToDumper("igfem elements", "displacement");
;
model.addDumpFieldToDumper("igfem elements", "stress");
model.addDumpFieldToDumper("igfem elements", "blocked_dofs");
model.addDumpFieldToDumper("igfem elements", "residual");
model.addDumpFieldToDumper("igfem elements", "grad_u");
model.addDumpFieldToDumper("igfem elements", "damage");
model.addDumpFieldToDumper("igfem elements", "partitions");
model.addDumpFieldToDumper("igfem elements", "Sc");
model.addDumpFieldToDumper("igfem elements", "force");
model.addDumpFieldToDumper("igfem elements", "equivalent_stress");
model.addDumpFieldToDumper("igfem elements", "ultimate_strain");
model.dump();
model.dump("igfem elements");
Real new_radius = (val - 0.1);
model.moveInterface(new_radius);
model.update("inclusion");
model.dump();
model.dump("igfem elements");
/// get a reference to the all the materials
const Material & standard_material_damage = model.getMaterial(0);
const Material & standard_material_elastic = model.getMaterial(1);
const Material & igfem_material = model.getMaterial(2);
const ElementType standard_type = _triangle_3;
const ElementType igfem_type = _igfem_triangle_5;
/// compute the volume on both sides of the interface
/// regular elements
const Array<UInt> & material_filter_0 =
standard_material_damage.getElementFilter(standard_type);
const Array<UInt> & material_filter_1 =
standard_material_elastic.getElementFilter(standard_type);
const Array<UInt> & material_filter_2 =
igfem_material.getElementFilter(igfem_type);
Array<Real> Volume_0(
material_filter_0.getSize() *
model.getFEEngine().getNbIntegrationPoints(standard_type),
1, 1.);
Real volume_material_damage = model.getFEEngine().integrate(
Volume_0, standard_type, _not_ghost, material_filter_0);
Array<Real> Volume_1(
material_filter_1.getSize() *
model.getFEEngine().getNbIntegrationPoints(standard_type),
1, 1.);
Real volume_material_elastic = model.getFEEngine().integrate(
Volume_1, standard_type, _not_ghost, material_filter_1);
/// igfem elements
const Array<UInt> & sub_mat =
igfem_material.getInternal<UInt>("sub_material")(igfem_type, _not_ghost);
Array<Real> sub_mat_to_real(sub_mat.getSize(), 1, 1.);
- for (UInt i = 0; i < sub_mat.getSize(); ++i)
+ for (Int i = 0; i < sub_mat.getSize(); ++i)
sub_mat_to_real(i) = Real(sub_mat(i));
Real volume_outside = model.getFEEngine("IGFEMFEEngine")
.integrate(sub_mat_to_real, igfem_type, _not_ghost,
material_filter_2);
Array<Real> IGFEMVolume(sub_mat.getSize(), 1, 1.);
Real total_igfem_volume =
model.getFEEngine("IGFEMFEEngine")
.integrate(IGFEMVolume, igfem_type, _not_ghost, material_filter_2);
Real volume_inside = total_igfem_volume - volume_outside;
Math::setTolerance(1.e-8);
if (!Math::are_float_equal(volume_material_damage, 0.5) ||
!Math::are_float_equal(volume_material_elastic, 0.25) ||
!Math::are_float_equal(volume_outside, 0.1) ||
!Math::are_float_equal(volume_inside, (0.15))) {
std::cout << "the test failed!!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/extra_packages/traction-at-split-node-contact/src/common/manual_restart.cc b/extra_packages/traction-at-split-node-contact/src/common/manual_restart.cc
index 73acca78f..c3985d894 100644
--- a/extra_packages/traction-at-split-node-contact/src/common/manual_restart.cc
+++ b/extra_packages/traction-at-split-node-contact/src/common/manual_restart.cc
@@ -1,136 +1,136 @@
/**
* @file manual_restart.cc
*
* @author Dana Christen <dana.christen@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Mar 16 2018
*
* @brief Tools to do a restart
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "manual_restart.hh"
#include "dof_manager_default.hh"
#include "dof_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
void dumpArray(const Array<Real> & array, const std::string & fname) {
std::ofstream outFile;
outFile.open(fname.c_str());
outFile.precision(9);
outFile.setf(std::ios::scientific);
- UInt size = array.size();
- UInt nb_component = array.getNbComponent();
+
+ auto size = array.size();
+ auto nb_component = array.getNbComponent();
outFile << size << std::endl;
outFile << nb_component << std::endl;
- Array<Real>::const_iterator<Vector<Real>> tit = array.begin(nb_component);
- Array<Real>::const_iterator<Vector<Real>> tend = array.end(nb_component);
- for (; tit != tend; ++tit) {
- for (UInt c = 0; c < nb_component; ++c) {
+
+ for (auto && v : make_view(array, nb_component)) {
+ for (Int c = 0; c < nb_component; ++c) {
if (c != 0) {
outFile << " ";
}
- outFile << (*tit)(c);
+ outFile << (v)(c);
}
outFile << std::endl;
}
outFile.close();
}
void loadArray(Array<Real> & array, const std::string & fname) {
std::ifstream inFile;
inFile.open(fname.c_str());
inFile.precision(9);
inFile.setf(std::ios::scientific);
- UInt size(0), nb_comp(0);
+ Int size(0), nb_comp(0);
inFile >> size;
inFile >> nb_comp;
AKANTU_DEBUG_ASSERT(array.getNbComponent() == nb_comp,
"BAD NUM OF COMPONENTS");
AKANTU_DEBUG_ASSERT(array.size() == size,
"loadArray: number of data points in file ("
<< size << ") does not correspond to array size ("
<< array.size() << ")!!");
- Array<Real>::iterator<Vector<Real>> tit = array.begin(nb_comp);
- Array<Real>::iterator<Vector<Real>> tend = array.end(nb_comp);
+
array.resize(size);
- for (UInt i(0); i < size; ++i, ++tit) {
- for (UInt c = 0; c < nb_comp; ++c) {
- inFile >> (*tit)(c);
+
+ for (auto && v : make_view(array, array.getNbComponent())) {
+ for (auto && c : v) {
+ inFile >> c;
}
}
inFile.close();
}
/* -------------------------------------------------------------------------- */
void loadRestart(akantu::SolidMechanicsModel & model, const std::string & fname,
akantu::UInt prank) {
- const akantu::Mesh & mesh = model.getMesh();
- const akantu::UInt spatial_dimension = model.getMesh().getSpatialDimension();
+ const auto & mesh = model.getMesh();
+ auto spatial_dimension = model.getMesh().getSpatialDimension();
auto & dof_manager = dynamic_cast<DOFManagerDefault &>(model.getDOFManager());
if (prank == 0) {
akantu::Array<akantu::Real> full_reload_array(mesh.getNbGlobalNodes(),
spatial_dimension);
loadArray(full_reload_array, fname);
dof_manager.getSynchronizer().scatter(model.getDisplacement(),
full_reload_array);
} else {
dof_manager.getSynchronizer().scatter(model.getDisplacement());
}
}
/* -------------------------------------------------------------------------- */
void loadRestart(akantu::SolidMechanicsModel & model,
const std::string & fname) {
loadArray(model.getDisplacement(), fname);
}
/* -------------------------------------------------------------------------- */
void dumpRestart(akantu::SolidMechanicsModel & model, const std::string & fname,
akantu::UInt prank) {
const akantu::Mesh & mesh = model.getMesh();
- const akantu::UInt spatial_dimension = model.getMesh().getSpatialDimension();
+ const akantu::Int spatial_dimension = model.getMesh().getSpatialDimension();
auto & dof_manager = dynamic_cast<DOFManagerDefault &>(model.getDOFManager());
if (prank == 0) {
akantu::Array<akantu::Real> full_array(mesh.getNbGlobalNodes(),
spatial_dimension);
dof_manager.getSynchronizer().gather(model.getDisplacement(), full_array);
dumpArray(full_array, fname);
} else {
dof_manager.getSynchronizer().gather(model.getDisplacement());
}
}
/* -------------------------------------------------------------------------- */
void dumpRestart(akantu::SolidMechanicsModel & model,
const std::string & fname) {
dumpArray(model.getDisplacement(), fname);
}
diff --git a/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.cc b/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.cc
index 15bed027b..20f21826b 100644
--- a/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.cc
+++ b/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.cc
@@ -1,244 +1,219 @@
/**
* @file synchronized_array.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue Sep 29 2020
*
* @brief implementation of synchronized array function
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// std
#include <fstream>
#include <iostream>
// simtools
#include "synchronized_array.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class T>
-SynchronizedArray<T>::SynchronizedArray(UInt size, UInt nb_component,
+SynchronizedArray<T>::SynchronizedArray(Int size, Int nb_component,
const_reference value, const ID & id,
const_reference default_value,
const std::string & restart_name)
: SynchronizedArrayBase(), Array<T>(size, nb_component, value, id),
default_value(default_value), restart_name(restart_name),
deleted_elements(0), nb_added_elements(size), depending_arrays(0) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class T>
void SynchronizedArray<T>::syncElements(SyncChoice sync_choice) {
AKANTU_DEBUG_IN();
if (sync_choice == _deleted) {
for (auto && array : depending_arrays) {
auto vec_size [[gnu::unused]] =
array->syncDeletedElements(this->deleted_elements);
AKANTU_DEBUG_ASSERT(vec_size == this->size_,
"Synchronized arrays do not have the same length"
<< "(may be a double synchronization)");
}
this->deleted_elements.clear();
}
else if (sync_choice == _added) {
for (auto && array : depending_arrays) {
auto vec_size [[gnu::unused]] =
array->syncAddedElements(this->nb_added_elements);
AKANTU_DEBUG_ASSERT(vec_size == this->size_,
"Synchronized arrays do not have the same length"
<< "(may be a double synchronization)");
}
this->nb_added_elements = 0;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class T>
-UInt SynchronizedArray<T>::syncDeletedElements(
- std::vector<UInt> & del_elements) {
- AKANTU_DEBUG_IN();
-
+Int SynchronizedArray<T>::syncDeletedElements(std::vector<Idx> & del_elements) {
AKANTU_DEBUG_ASSERT(
nb_added_elements == 0 and deleted_elements.empty(),
"Cannot sync with a SynchronizedArray if it has already been modified");
for (auto && el : del_elements) {
erase(el);
}
syncElements(_deleted);
- AKANTU_DEBUG_OUT();
return this->size_;
}
/* -------------------------------------------------------------------------- */
template <class T>
-UInt SynchronizedArray<T>::syncAddedElements(UInt nb_add_elements) {
- AKANTU_DEBUG_IN();
-
+Int SynchronizedArray<T>::syncAddedElements(Int nb_add_elements) {
AKANTU_DEBUG_ASSERT(
nb_added_elements == 0 and deleted_elements.empty(),
"Cannot sync with a SynchronizedArray if it has already been modified");
- for (UInt i = 0; i < nb_add_elements; ++i) {
+ for (Int i = 0; i < nb_add_elements; ++i) {
push_back(this->default_value);
}
syncElements(_added);
- AKANTU_DEBUG_OUT();
return this->size_;
}
/* -------------------------------------------------------------------------- */
template <typename T>
void SynchronizedArray<T>::registerDependingArray(
SynchronizedArrayBase & array) {
- AKANTU_DEBUG_IN();
-
this->depending_arrays.push_back(&array);
array.syncAddedElements(this->size_);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename T>
void SynchronizedArray<T>::printself(std::ostream & stream, int indent) const {
- AKANTU_DEBUG_IN();
-
std::string space(indent, AKANTU_INDENT);
stream << space << "SynchronizedArray<" << debug::demangle(typeid(T).name())
<< "> [" << std::endl;
stream << space << " + default_value : " << this->default_value
<< std::endl;
stream << space << " + nb_added_elements : " << this->nb_added_elements
<< std::endl;
stream << space << " + deleted_elements : ";
for (auto && deleted_element : deleted_elements) {
stream << deleted_element << " ";
}
stream << std::endl;
stream << space << " + depending_arrays : ";
for (auto && depending_array : this->depending_arrays) {
stream << depending_array->getID() << " ";
}
stream << std::endl;
Array<T>::printself(stream, indent + 1);
stream << space << "]" << std::endl;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename T>
void SynchronizedArray<T>::dumpRestartFile(
const std::string & file_name) const {
- AKANTU_DEBUG_IN();
-
AKANTU_DEBUG_ASSERT(
nb_added_elements == 0 and deleted_elements.empty(),
"Restart File for SynchronizedArray "
<< this->id << " should not be dumped as it is not synchronized yet");
std::stringstream name;
name << file_name << "-" << this->restart_name << ".rs";
std::ofstream out_restart;
out_restart.open(name.str().c_str());
out_restart << this->size_ << " " << this->nb_component << std::endl;
Real size_comp = this->size_ * this->nb_component;
- for (UInt i = 0; i < size_comp; ++i) {
+ for (Int i = 0; i < size_comp; ++i) {
out_restart << std::setprecision(12) << this->values[i] << " ";
}
- // out_restart << std::hex << std::setprecision(12) << this->values[i] << "
- // ";
- out_restart << std::endl;
- AKANTU_DEBUG_OUT();
+ out_restart << std::endl;
}
/* -------------------------------------------------------------------------- */
template <typename T>
void SynchronizedArray<T>::readRestartFile(const std::string & file_name) {
- AKANTU_DEBUG_IN();
-
AKANTU_DEBUG_ASSERT(
nb_added_elements == 0 and deleted_elements.empty(),
"Restart File for SynchronizedArray "
<< this->id << " should not be read as it is not synchronized yet");
std::stringstream name;
name << file_name << "-" << this->restart_name << ".rs";
std::ifstream infile;
infile.open(name.str().c_str());
std::string line;
// get size and nb_component info
AKANTU_DEBUG_ASSERT(infile.good(), "Could not read restart file for "
<< "SynchronizedArray " << this->id);
getline(infile, line);
std::stringstream size_comp(line);
size_comp >> this->size_;
size_comp >> this->nb_component;
// get elements in array
getline(infile, line);
std::stringstream data(line);
- for (UInt i = 0; i < this->size_ * this->nb_component; ++i) {
+ for (Int i = 0; i < this->size_ * this->nb_component; ++i) {
AKANTU_DEBUG_ASSERT(
!data.eof(),
"Read SynchronizedArray "
<< this->id
<< " got to the end of the file before having read all data!");
data >> this->values[i];
- // data >> std::hex >> this->values[i];
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template class SynchronizedArray<Real>;
template class SynchronizedArray<UInt>;
template class SynchronizedArray<Int>;
template class SynchronizedArray<bool>;
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.hh b/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.hh
index a88c6ca35..680bc0e36 100644
--- a/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.hh
+++ b/extra_packages/traction-at-split-node-contact/src/common/synchronized_array.hh
@@ -1,204 +1,192 @@
/**
* @file synchronized_array.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue Sep 29 2020
*
* @brief synchronized array: a array can be registered to another (hereafter
* called top) array. If an element is added to or removed from the top array,
* the registered array removes or adds at the same position an element. The two
* arrays stay therefore synchronized.
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AST_SYNCHRONIZED_ARRAY_HH_
#define AST_SYNCHRONIZED_ARRAY_HH_
/* -------------------------------------------------------------------------- */
// std
#include <vector>
// akantu
#include "aka_array.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
enum SyncChoice { _added, _deleted };
/* -------------------------------------------------------------------------- */
class SynchronizedArrayBase {
public:
SynchronizedArrayBase() = default;
~SynchronizedArrayBase() = default;
virtual ID getID() const { return "call should be virtual"; };
- virtual UInt syncDeletedElements(std::vector<UInt> & delete_el) = 0;
- virtual UInt syncAddedElements(UInt nb_added_el) = 0;
+ virtual Int syncDeletedElements(std::vector<Idx> & delete_el) = 0;
+ virtual Int syncAddedElements(Int nb_added_el) = 0;
};
/* -------------------------------------------------------------------------- */
template <class T>
class SynchronizedArray : public SynchronizedArrayBase, protected Array<T> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using value_type = typename Array<T>::value_type;
using reference = typename Array<T>::reference;
using pointer_type = typename Array<T>::pointer_type;
using const_reference = typename Array<T>::const_reference;
- SynchronizedArray(UInt size, UInt nb_component, const_reference value,
+ SynchronizedArray(Int size, Int nb_component, const_reference value,
const ID & id, const_reference default_value,
const std::string & restart_name);
~SynchronizedArray() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// push_back
template <typename P> inline void push_back(P && value);
/// erase
- inline void erase(UInt i);
+ inline void erase(Idx i);
// template<typename R>
// inline void erase(const iterator<R> & it);
/// synchronize elements
void syncElements(SyncChoice sync_choice);
/// dump restart file
void dumpRestartFile(const std::string & file_name) const;
/// read restart file
void readRestartFile(const std::string & file_name);
/// register depending array
void registerDependingArray(SynchronizedArrayBase & array);
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override;
/// find position of element
- Int find(const T & elem) const { return Array<T>::find(elem); };
+ using Array<T>::find;
/// set values to zero
- inline void zero() { Array<T>::zero(); };
- // inline void clear() { memset(values, 0, size*nb_component*sizeof(T)); };
+ using Array<T>::zero;
/// set all entries of the array to the value t
- /// @param t value to fill the array with
- inline void set(T t) { Array<T>::set(t); }
-
- /// set
- template <template <typename> class C> inline void set(const C<T> & vm) {
- Array<T>::set(vm);
- }
+ using Array<T>::set;
/// set all entries of the array to value t and set default value
inline void setAndChangeDefault(T t) {
this->set(t);
this->default_value = t;
}
/// copy the content of an other array
- void copy(const SynchronizedArray<T> & vect) { Array<T>::copy(vect); };
+ using Array<T>::copy;
/// give the address of the memory allocated for this array
- T * storage() const { return Array<T>::storage(); };
- // T * storage() const { return this->values; };
+ using Array<T>::data;
+ using Array<T>::storage;
// get nb component
- UInt getNbComponent() const { return Array<T>::getNbComponent(); };
+ using Array<T>::getNbComponent;
protected:
- UInt syncDeletedElements(std::vector<UInt> & del_elements) override;
- UInt syncAddedElements(UInt nb_add_elements) override;
+ Int syncDeletedElements(std::vector<Idx> & del_elements) override;
+ Int syncAddedElements(Int nb_add_elements) override;
/* ------------------------------------------------------------------------ */
/* Operators */
/* ------------------------------------------------------------------------ */
public:
- inline reference operator()(UInt i, UInt j = 0) {
- return Array<T>::operator()(i, j);
- }
- inline const_reference operator()(UInt i, UInt j = 0) const {
- return Array<T>::operator()(i, j);
- }
+ using Array<T>::operator();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_SET_MACRO(DefaultValue, default_value, T);
- UInt size() const { return this->size_; };
+ Int size() const { return this->size_; };
- ID getID() const override { return Array<T>::getID(); };
+ using Array<T>::getID;
const Array<T> & getArray() const {
const Array<T> & a = *(dynamic_cast<const Array<T> *>(this));
return a;
};
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// init value when new elements added
T default_value;
/// restart file_name
const std::string restart_name;
/// elements that have been deleted
- std::vector<UInt> deleted_elements;
+ std::vector<Idx> deleted_elements;
/// number of elements to add
UInt nb_added_elements;
/// pointers to arrays to be updated
std::vector<SynchronizedArrayBase *> depending_arrays;
};
/// standard output stream operator
template <typename T>
inline std::ostream & operator<<(std::ostream & stream,
const SynchronizedArray<T> & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "synchronized_array_inline_impl.hh"
#endif /* AST_SYNCHRONIZED_ARRAY_HH_ */
diff --git a/extra_packages/traction-at-split-node-contact/src/common/synchronized_array_inline_impl.hh b/extra_packages/traction-at-split-node-contact/src/common/synchronized_array_inline_impl.hh
index 5bac674fd..cc34ba37f 100644
--- a/extra_packages/traction-at-split-node-contact/src/common/synchronized_array_inline_impl.hh
+++ b/extra_packages/traction-at-split-node-contact/src/common/synchronized_array_inline_impl.hh
@@ -1,71 +1,63 @@
/**
* @file synchronized_array_inline_impl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Mar 16 2018
*
* @brief inlined methods for the synchronized array
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "synchronized_array.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename T>
template <typename P>
inline void SynchronizedArray<T>::push_back(P && value) {
- AKANTU_DEBUG_IN();
-
AKANTU_DEBUG_ASSERT(deleted_elements.size() == 0,
"Cannot push_back element if SynchronizedArray"
<< " is already modified without synchronization");
Array<T>::push_back(std::forward<P>(value));
this->nb_added_elements++;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <typename T> inline void SynchronizedArray<T>::erase(UInt i) {
- AKANTU_DEBUG_IN();
-
+template <typename T> inline void SynchronizedArray<T>::erase(Idx i) {
AKANTU_DEBUG_ASSERT(nb_added_elements == 0,
"Cannot erase element if SynchronizedArray"
<< " is already modified without synchronization");
- for (UInt j = 0; j < this->nb_component; ++j) {
+ for (Int j = 0; j < this->nb_component; ++j) {
this->values[i * this->nb_component + j] =
this->values[(this->size_ - 1) * this->nb_component + j];
}
this->size_--;
this->deleted_elements.push_back(i);
-
- AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_coulomb_tmpl.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_coulomb_tmpl.hh
index 5ffe63414..fec12d577 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_coulomb_tmpl.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_coulomb_tmpl.hh
@@ -1,162 +1,162 @@
/**
* @file ntn_friclaw_coulomb_tmpl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Jul 19 2019
*
* @brief implementation of coulomb friction
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_nodal_field.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Regularisation>
NTNFricLawCoulomb<Regularisation>::NTNFricLawCoulomb(NTNBaseContact & contact,
const ID & id)
: Regularisation(contact, id), mu(0, 1, 0., id + ":mu", 0., "mu") {
AKANTU_DEBUG_IN();
Regularisation::registerSynchronizedArray(this->mu);
this->registerParam("mu", this->mu, _pat_parsmod, "friction coefficient");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawCoulomb<Regularisation>::computeFrictionalStrength() {
AKANTU_DEBUG_IN();
// get contact arrays
const SynchronizedArray<bool> & is_in_contact =
this->internalGetIsInContact();
const SynchronizedArray<Real> & pressure = this->internalGetContactPressure();
// array to fill
SynchronizedArray<Real> & strength = this->internalGetFrictionalStrength();
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// node pair is NOT in contact
if (!is_in_contact(n)) {
strength(n) = 0.;
// node pair is in contact
} else {
// compute frictional strength
strength(n) = this->mu(n) * pressure(n);
}
}
Regularisation::computeFrictionalStrength();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawCoulomb<Regularisation>::registerSynchronizedArray(
SynchronizedArrayBase & array) {
AKANTU_DEBUG_IN();
this->mu.registerDependingArray(array);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawCoulomb<Regularisation>::dumpRestart(
const std::string & file_name) const {
AKANTU_DEBUG_IN();
this->mu.dumpRestartFile(file_name);
Regularisation::dumpRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawCoulomb<Regularisation>::readRestart(
const std::string & file_name) {
AKANTU_DEBUG_IN();
this->mu.readRestartFile(file_name);
Regularisation::readRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawCoulomb<Regularisation>::printself(std::ostream & stream,
int indent) const {
AKANTU_DEBUG_IN();
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
;
}
stream << space << "NTNFricLawCoulomb [" << std::endl;
Regularisation::printself(stream, ++indent);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawCoulomb<Regularisation>::addDumpFieldToDumper(
const std::string & dumper_name, const std::string & field_id) {
AKANTU_DEBUG_IN();
if (field_id == "mu") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->mu.getArray()));
}
/*
else if (field_id == "frictional_contact_pressure") {
this->internalAddDumpFieldToDumper(dumper_name,
field_id,
new
DumperIOHelper::NodalField<Real>(this->frictional_contact_pressure.getArray()));
}
*/
else {
Regularisation::addDumpFieldToDumper(dumper_name, field_id);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_cohesive_tmpl.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_cohesive_tmpl.hh
index 037c9c490..afb31915c 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_cohesive_tmpl.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_cohesive_tmpl.hh
@@ -1,184 +1,184 @@
/**
* @file ntn_friclaw_linear_cohesive_tmpl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Jul 19 2019
*
* @brief implementation of linear cohesive law
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
//#include "dumper_text.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Regularisation>
NTNFricLawLinearCohesive<Regularisation>::NTNFricLawLinearCohesive(
NTNBaseContact & contact, const ID & id)
: Regularisation(contact, id), G_c(0, 1, 0., id + ":G_c", 0., "G_c"),
tau_c(0, 1, 0., id + ":tau_c", 0., "tau_c"),
tau_r(0, 1, 0., id + ":tau_r", 0., "tau_r") {
AKANTU_DEBUG_IN();
Regularisation::registerSynchronizedArray(this->G_c);
Regularisation::registerSynchronizedArray(this->tau_c);
Regularisation::registerSynchronizedArray(this->tau_r);
this->registerParam("G_c", this->G_c, _pat_parsmod, "fracture energy");
this->registerParam("tau_c", this->tau_c, _pat_parsmod,
"peak shear strength");
this->registerParam("tau_r", this->tau_r, _pat_parsmod,
"residual shear strength");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearCohesive<Regularisation>::computeFrictionalStrength() {
AKANTU_DEBUG_IN();
// get arrays
const SynchronizedArray<bool> & is_in_contact =
this->internalGetIsInContact();
// const SynchronizedArray<Real> & slip = this->internalGetSlip();
const SynchronizedArray<Real> & slip = this->internalGetCumulativeSlip();
// array to fill
SynchronizedArray<Real> & strength = this->internalGetFrictionalStrength();
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// node pair is NOT in contact
if (!is_in_contact(n)) {
strength(n) = 0.;
// node pair is in contact
} else {
if (this->G_c(n) == 0.) {
// strength(n) = 0.;
strength(n) = this->tau_r(n);
} else {
Real slope = (this->tau_c(n) - this->tau_r(n)) *
(this->tau_c(n) - this->tau_r(n)) / (2 * this->G_c(n));
// no strength < tau_r
strength(n) =
std::max(this->tau_c(n) - slope * slip(n), this->tau_r(n));
// strength(n) = std::max(this->tau_c(n) - slope * slip(n), 0.); // no
// negative strength
}
}
}
Regularisation::computeFrictionalStrength();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearCohesive<Regularisation>::registerSynchronizedArray(
SynchronizedArrayBase & array) {
AKANTU_DEBUG_IN();
this->G_c.registerDependingArray(array);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearCohesive<Regularisation>::dumpRestart(
const std::string & file_name) const {
AKANTU_DEBUG_IN();
this->G_c.dumpRestartFile(file_name);
this->tau_c.dumpRestartFile(file_name);
this->tau_r.dumpRestartFile(file_name);
Regularisation::dumpRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearCohesive<Regularisation>::readRestart(
const std::string & file_name) {
AKANTU_DEBUG_IN();
this->G_c.readRestartFile(file_name);
this->tau_c.readRestartFile(file_name);
this->tau_r.readRestartFile(file_name);
Regularisation::readRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearCohesive<Regularisation>::printself(std::ostream & stream,
int indent) const {
AKANTU_DEBUG_IN();
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
;
}
stream << space << "NTNFricLawLinearCohesive [" << std::endl;
Regularisation::printself(stream, ++indent);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearCohesive<Regularisation>::addDumpFieldToDumper(
const std::string & dumper_name, const std::string & field_id) {
AKANTU_DEBUG_IN();
if (field_id == "G_c") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->G_c.getArray()));
} else if (field_id == "tau_c") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->tau_c.getArray()));
} else if (field_id == "tau_r") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->tau_r.getArray()));
} else {
Regularisation::addDumpFieldToDumper(dumper_name, field_id);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_no_healing_tmpl.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_no_healing_tmpl.hh
index 20cd67bc1..d4df39852 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_no_healing_tmpl.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_no_healing_tmpl.hh
@@ -1,87 +1,87 @@
/**
* @file ntn_friclaw_linear_slip_weakening_no_healing_tmpl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Wed Oct 17 2018
*
* @brief implementation of linear slip weakening
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Regularisation>
NTNFricLawLinearSlipWeakeningNoHealing<Regularisation>::
NTNFricLawLinearSlipWeakeningNoHealing(NTNBaseContact & contact,
const ID & id)
: NTNFricLawLinearSlipWeakening<Regularisation>(contact, id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakeningNoHealing<
Regularisation>::computeFrictionCoefficient() {
AKANTU_DEBUG_IN();
// get arrays
const SynchronizedArray<Real> & slip = this->internalGetCumulativeSlip();
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
if (slip(n) >= this->d_c(n)) {
this->mu(n) = this->mu_k(n);
} else {
// mu = mu_k + (1 - slip / Dc) * (mu_s - mu_k)
this->mu(n) = this->mu_k(n) + (1 - (slip(n) / this->d_c(n))) *
(this->mu_s(n) - this->mu_k(n));
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakeningNoHealing<Regularisation>::printself(
std::ostream & stream, int indent) const {
AKANTU_DEBUG_IN();
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
;
}
stream << space << "NTNFricLawLinearSlipWeakeningNoHealing [" << std::endl;
NTNFricLawLinearSlipWeakening<Regularisation>::printself(stream, ++indent);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_tmpl.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_tmpl.hh
index 1ced8d969..69d0f3788 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_tmpl.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_laws/ntn_friclaw_linear_slip_weakening_tmpl.hh
@@ -1,186 +1,186 @@
/**
* @file ntn_friclaw_linear_slip_weakening_tmpl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Jul 19 2019
*
* @brief implementation of linear slip weakening
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_text.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Regularisation>
NTNFricLawLinearSlipWeakening<Regularisation>::NTNFricLawLinearSlipWeakening(
NTNBaseContact & contact, const ID & id)
: NTNFricLawCoulomb<Regularisation>(contact, id),
mu_s(0, 1, 0., id + ":mu_s", 0., "mu_s"),
mu_k(0, 1, 0., id + ":mu_k", 0., "mu_k"),
d_c(0, 1, 0., id + ":d_c", 0., "d_c") {
AKANTU_DEBUG_IN();
NTNFricLawCoulomb<Regularisation>::registerSynchronizedArray(this->mu_s);
NTNFricLawCoulomb<Regularisation>::registerSynchronizedArray(this->mu_k);
NTNFricLawCoulomb<Regularisation>::registerSynchronizedArray(this->d_c);
this->registerParam("mu_s", this->mu_s, _pat_parsmod,
"static friction coefficient");
this->registerParam("mu_k", this->mu_k, _pat_parsmod,
"kinetic friction coefficient");
this->registerParam("d_c", this->d_c, _pat_parsmod, "slip weakening length");
this->setParameterAccessType("mu", _pat_readable);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakening<
Regularisation>::computeFrictionalStrength() {
AKANTU_DEBUG_IN();
computeFrictionCoefficient();
NTNFricLawCoulomb<Regularisation>::computeFrictionalStrength();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakening<
Regularisation>::computeFrictionCoefficient() {
AKANTU_DEBUG_IN();
// get arrays
const SynchronizedArray<bool> & stick = this->internalGetIsSticking();
const SynchronizedArray<Real> & slip = this->internalGetSlip();
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
if (stick(n)) {
this->mu(n) = this->mu_s(n);
} else {
if (slip(n) >= this->d_c(n)) {
this->mu(n) = this->mu_k(n);
} else {
// mu = mu_k + (1 - slip / Dc) * (mu_s - mu_k)
this->mu(n) = this->mu_k(n) + (1 - (slip(n) / this->d_c(n))) *
(this->mu_s(n) - this->mu_k(n));
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakening<Regularisation>::registerSynchronizedArray(
SynchronizedArrayBase & array) {
AKANTU_DEBUG_IN();
this->mu_s.registerDependingArray(array);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakening<Regularisation>::dumpRestart(
const std::string & file_name) const {
AKANTU_DEBUG_IN();
this->mu_s.dumpRestartFile(file_name);
this->mu_k.dumpRestartFile(file_name);
this->d_c.dumpRestartFile(file_name);
NTNFricLawCoulomb<Regularisation>::dumpRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakening<Regularisation>::readRestart(
const std::string & file_name) {
AKANTU_DEBUG_IN();
this->mu_s.readRestartFile(file_name);
this->mu_k.readRestartFile(file_name);
this->d_c.readRestartFile(file_name);
NTNFricLawCoulomb<Regularisation>::readRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakening<Regularisation>::printself(
std::ostream & stream, int indent) const {
AKANTU_DEBUG_IN();
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
;
}
stream << space << "NTNFricLawLinearSlipWeakening [" << std::endl;
NTNFricLawCoulomb<Regularisation>::printself(stream, ++indent);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Regularisation>
void NTNFricLawLinearSlipWeakening<Regularisation>::addDumpFieldToDumper(
const std::string & dumper_name, const std::string & field_id) {
AKANTU_DEBUG_IN();
if (field_id == "mu_s") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->mu_s.getArray()));
} else if (field_id == "mu_k") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->mu_k.getArray()));
} else if (field_id == "d_c") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->d_c.getArray()));
} else {
NTNFricLawCoulomb<Regularisation>::addDumpFieldToDumper(dumper_name,
field_id);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_no_regularisation.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_no_regularisation.cc
index d6b69d742..08589a88a 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_no_regularisation.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_no_regularisation.cc
@@ -1,164 +1,132 @@
/**
* @file ntn_fricreg_no_regularisation.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Jul 19 2019
*
* @brief implementation of no regularisation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "ntn_fricreg_no_regularisation.hh"
#include "dumper_nodal_field.hh"
#include "dumper_text.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
NTNFricRegNoRegularisation::NTNFricRegNoRegularisation(NTNBaseContact & contact,
const ID & id)
: NTNBaseFriction(contact, id),
frictional_contact_pressure(0, 1, 0., id + ":frictional_contact_pressure",
0., "frictional_contact_pressure") {
- AKANTU_DEBUG_IN();
-
NTNBaseFriction::registerSynchronizedArray(this->frictional_contact_pressure);
this->registerParam("frictional_contact_pressure",
this->frictional_contact_pressure, _pat_internal,
"contact pressure used for friction law");
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
const SynchronizedArray<Real> &
NTNFricRegNoRegularisation::internalGetContactPressure() {
- AKANTU_DEBUG_IN();
-
this->computeFrictionalContactPressure();
-
- AKANTU_DEBUG_OUT();
return this->frictional_contact_pressure;
}
/* -------------------------------------------------------------------------- */
void NTNFricRegNoRegularisation::computeFrictionalContactPressure() {
- AKANTU_DEBUG_IN();
-
- SolidMechanicsModel & model = this->contact.getModel();
- UInt dim = model.getSpatialDimension();
+ auto & model = this->contact.getModel();
+ auto dim = model.getSpatialDimension();
// get contact arrays
- const SynchronizedArray<bool> & is_in_contact =
- this->internalGetIsInContact();
- const Array<Real> & pressure = this->contact.getContactPressure().getArray();
- Array<Real>::const_iterator<Vector<Real>> it = pressure.begin(dim);
+ const auto & is_in_contact = this->internalGetIsInContact();
+ const auto & pressure = this->contact.getContactPressure().getArray();
+ auto it = pressure.begin(dim);
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// node pair is NOT in contact
- if (!is_in_contact(n)) {
+ if (not is_in_contact(n)) {
this->frictional_contact_pressure(n) = 0.;
// node pair is in contact
} else {
// compute frictional contact pressure
- const Vector<Real> & pres = it[n];
+ const auto & pres = it[n];
this->frictional_contact_pressure(n) = pres.norm();
}
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegNoRegularisation::registerSynchronizedArray(
SynchronizedArrayBase & array) {
- AKANTU_DEBUG_IN();
-
this->frictional_contact_pressure.registerDependingArray(array);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegNoRegularisation::dumpRestart(
const std::string & file_name) const {
- AKANTU_DEBUG_IN();
-
this->frictional_contact_pressure.dumpRestartFile(file_name);
NTNBaseFriction::dumpRestart(file_name);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegNoRegularisation::readRestart(const std::string & file_name) {
- AKANTU_DEBUG_IN();
-
this->frictional_contact_pressure.readRestartFile(file_name);
NTNBaseFriction::readRestart(file_name);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegNoRegularisation::printself(std::ostream & stream,
int indent) const {
- AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
-
+ std::string space(AKANTU_INDENT, indent);
stream << space << "NTNFricRegNoRegularisation [" << std::endl;
NTNBaseFriction::printself(stream, ++indent);
stream << space << "]" << std::endl;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegNoRegularisation::addDumpFieldToDumper(
const std::string & dumper_name, const std::string & field_id) {
AKANTU_DEBUG_IN();
if (field_id == "frictional_contact_pressure") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->frictional_contact_pressure.getArray()));
} else {
NTNBaseFriction::addDumpFieldToDumper(dumper_name, field_id);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_rubin_ampuero.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_rubin_ampuero.cc
index 9498816f4..5ed94373a 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_rubin_ampuero.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_rubin_ampuero.cc
@@ -1,171 +1,161 @@
/**
* @file ntn_fricreg_rubin_ampuero.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Jul 19 2019
*
* @brief implementation of no regularisation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "ntn_fricreg_rubin_ampuero.hh"
#include "dumper_nodal_field.hh"
#include "dumper_text.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
NTNFricRegRubinAmpuero::NTNFricRegRubinAmpuero(NTNBaseContact & contact,
const ID & id)
: NTNFricRegNoRegularisation(contact, id),
t_star(0, 1, 0., id + ":t_star", 0., "t_star") {
AKANTU_DEBUG_IN();
NTNFricRegNoRegularisation::registerSynchronizedArray(this->t_star);
this->registerParam("t_star", this->t_star, _pat_parsmod,
"time scale of regularization");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
const SynchronizedArray<Real> &
NTNFricRegRubinAmpuero::internalGetContactPressure() {
AKANTU_DEBUG_IN();
- SolidMechanicsModel & model = this->contact.getModel();
- UInt dim = model.getSpatialDimension();
- Real delta_t = model.getTimeStep();
+ auto & model = this->contact.getModel();
+ auto dim = model.getSpatialDimension();
+ auto delta_t = model.getTimeStep();
// get contact arrays
- const SynchronizedArray<bool> & is_in_contact =
- this->internalGetIsInContact();
- const Array<Real> & pressure = this->contact.getContactPressure().getArray();
- Array<Real>::const_iterator<Vector<Real>> it = pressure.begin(dim);
+ const auto & is_in_contact = this->internalGetIsInContact();
+ const auto & pressure = this->contact.getContactPressure().getArray();
+ auto it = pressure.begin(dim);
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// node pair is NOT in contact
- if (!is_in_contact(n)) {
+ if (not is_in_contact(n)) {
this->frictional_contact_pressure(n) = 0.;
// if t_star is too small compute like Coulomb friction (without
// regularization)
} else if (Math::are_float_equal(this->t_star(n), 0.)) {
- const Vector<Real> & pres = it[n];
+ const auto & pres = it[n];
this->frictional_contact_pressure(n) = pres.norm();
}
else {
// compute frictional contact pressure
// backward euler method: first order implicit numerical integration
// method
// \reg_pres_n+1 = (\reg_pres_n + \delta_t / \t_star * \cur_pres)
// / (1 + \delta_t / \t_star)
- Real alpha = delta_t / this->t_star(n);
- const Vector<Real> & pres = it[n];
+ auto alpha = delta_t / this->t_star(n);
+ const auto & pres = it[n];
this->frictional_contact_pressure(n) += alpha * pres.norm();
this->frictional_contact_pressure(n) /= 1 + alpha;
}
}
AKANTU_DEBUG_OUT();
return this->frictional_contact_pressure;
}
/* -------------------------------------------------------------------------- */
void NTNFricRegRubinAmpuero::setToSteadyState() {
- AKANTU_DEBUG_IN();
NTNFricRegNoRegularisation::computeFrictionalContactPressure();
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegRubinAmpuero::registerSynchronizedArray(
SynchronizedArrayBase & array) {
- AKANTU_DEBUG_IN();
-
this->t_star.registerDependingArray(array);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegRubinAmpuero::dumpRestart(const std::string & file_name) const {
AKANTU_DEBUG_IN();
this->t_star.dumpRestartFile(file_name);
NTNFricRegNoRegularisation::dumpRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegRubinAmpuero::readRestart(const std::string & file_name) {
AKANTU_DEBUG_IN();
this->t_star.readRestartFile(file_name);
NTNFricRegNoRegularisation::readRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegRubinAmpuero::printself(std::ostream & stream,
int indent) const {
AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(AKANTU_INDENT, indent);
stream << space << "NTNFricRegRubinAmpuero [" << std::endl;
NTNFricRegNoRegularisation::printself(stream, ++indent);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegRubinAmpuero::addDumpFieldToDumper(
const std::string & dumper_name, const std::string & field_id) {
AKANTU_DEBUG_IN();
if (field_id == "t_star") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->t_star.getArray()));
} else {
NTNFricRegNoRegularisation::addDumpFieldToDumper(dumper_name, field_id);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_simplified_prakash_clifton.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_simplified_prakash_clifton.cc
index 165f83e72..fffbf603d 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_simplified_prakash_clifton.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/friction_regularisations/ntn_fricreg_simplified_prakash_clifton.cc
@@ -1,159 +1,159 @@
/**
* @file ntn_fricreg_simplified_prakash_clifton.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Fri Jul 19 2019
*
* @brief implementation of simplified prakash clifton with one parameter
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "ntn_fricreg_simplified_prakash_clifton.hh"
#include "dumper_nodal_field.hh"
#include "dumper_text.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
NTNFricRegSimplifiedPrakashClifton::NTNFricRegSimplifiedPrakashClifton(
NTNBaseContact & contact, const ID & id)
: NTNFricRegNoRegularisation(contact, id),
t_star(0, 1, 0., id + ":t_star", 0., "t_star"),
spc_internal(0, 1, 0., id + ":spc_internal", 0., "spc_internal") {
AKANTU_DEBUG_IN();
NTNFricRegNoRegularisation::registerSynchronizedArray(this->t_star);
NTNFricRegNoRegularisation::registerSynchronizedArray(this->spc_internal);
this->registerParam("t_star", this->t_star, _pat_parsmod,
"time scale of regularisation");
this->registerParam("spc_internal", this->spc_internal, _pat_internal, "");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegSimplifiedPrakashClifton::computeFrictionalStrength() {
AKANTU_DEBUG_IN();
SolidMechanicsModel & model = this->contact.getModel();
Real delta_t = model.getTimeStep();
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
Real alpha = delta_t / this->t_star(n);
this->frictional_strength(n) += alpha * this->spc_internal(n);
this->frictional_strength(n) /= 1 + alpha;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegSimplifiedPrakashClifton::setToSteadyState() {
AKANTU_DEBUG_IN();
/// fill the spc_internal array
computeFrictionalStrength();
/// set strength without regularisation
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
this->frictional_strength(n) = this->spc_internal(n);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegSimplifiedPrakashClifton::registerSynchronizedArray(
SynchronizedArrayBase & array) {
AKANTU_DEBUG_IN();
this->t_star.registerDependingArray(array);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegSimplifiedPrakashClifton::dumpRestart(
const std::string & file_name) const {
AKANTU_DEBUG_IN();
this->t_star.dumpRestartFile(file_name);
this->spc_internal.dumpRestartFile(file_name);
NTNFricRegNoRegularisation::dumpRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegSimplifiedPrakashClifton::readRestart(
const std::string & file_name) {
AKANTU_DEBUG_IN();
this->t_star.readRestartFile(file_name);
this->spc_internal.readRestartFile(file_name);
NTNFricRegNoRegularisation::readRestart(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegSimplifiedPrakashClifton::printself(std::ostream & stream,
int indent) const {
AKANTU_DEBUG_IN();
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
;
}
stream << space << "NTNFricRegSimplifiedPrakashClifton [" << std::endl;
NTNFricRegNoRegularisation::printself(stream, ++indent);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNFricRegSimplifiedPrakashClifton::addDumpFieldToDumper(
const std::string & dumper_name, const std::string & field_id) {
AKANTU_DEBUG_IN();
if (field_id == "t_star") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->t_star.getArray()));
} else {
NTNFricRegNoRegularisation::addDumpFieldToDumper(dumper_name, field_id);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/mIIasym_contact.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/mIIasym_contact.cc
index 2507ef9bd..ca273654c 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/mIIasym_contact.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/mIIasym_contact.cc
@@ -1,121 +1,104 @@
/**
* @file mIIasym_contact.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Wed Oct 17 2018
*
* @brief contact for mode II anti-symmetric simulations
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "mIIasym_contact.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
MIIASYMContact::MIIASYMContact(SolidMechanicsModel & model, const ID & id)
: NTRFContact(model, id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MIIASYMContact::updateImpedance() {
AKANTU_DEBUG_IN();
NTRFContact::updateImpedance();
- for (UInt i = 0; i < this->impedance.size(); ++i) {
+ for (Int i = 0; i < this->impedance.size(); ++i) {
this->impedance(i) *= 0.5;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/// WARNING: this is only valid for the acceleration in equilibrium
void MIIASYMContact::computeRelativeNormalField(
const Array<Real> & field, Array<Real> & rel_normal_field) const {
AKANTU_DEBUG_IN();
NTRFContact::computeRelativeNormalField(field, rel_normal_field);
for (auto it_rtfield = rel_normal_field.begin();
it_rtfield != rel_normal_field.end(); ++it_rtfield) {
// in the anti-symmetric case
*it_rtfield *= 2.;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MIIASYMContact::computeRelativeTangentialField(
const Array<Real> & field, Array<Real> & rel_tang_field) const {
- AKANTU_DEBUG_IN();
-
NTRFContact::computeRelativeTangentialField(field, rel_tang_field);
- UInt dim = this->model.getSpatialDimension();
-
- for (Array<Real>::iterator<Vector<Real>> it_rtfield =
- rel_tang_field.begin(dim);
- it_rtfield != rel_tang_field.end(dim); ++it_rtfield) {
+ auto dim = this->model.getSpatialDimension();
+ for (auto && rt : make_view(rel_tang_field, dim)) {
// in the anti-symmetric case, the tangential fields become twice as large
- *it_rtfield *= 2.;
+ rt *= 2.;
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MIIASYMContact::computeContactPressureInEquilibrium() {
- AKANTU_DEBUG_IN();
-
NTRFContact::computeContactPressure();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MIIASYMContact::printself(std::ostream & stream, int indent) const {
- AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(AKANTU_INDENT, indent);
stream << space << "MIIASYMContact [" << std::endl;
NTRFContact::printself(stream, indent);
stream << space << "]" << std::endl;
-
- AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.cc
index 37c58e56f..7f9d53dfb 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.cc
@@ -1,567 +1,548 @@
/**
* @file ntn_base_contact.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue Sep 29 2020
*
* @brief implementation of ntn base contact
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "ntn_base_contact.hh"
#include "dof_manager_default.hh"
#include "dumpable_inline_impl.hh"
#include "dumper_nodal_field.hh"
#include "dumper_text.hh"
#include "element_synchronizer.hh"
#include "mesh_utils.hh"
#include "non_linear_solver_lumped.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
// NTNContactSynchElementFilter::NTNContactSynchElementFilter(
// NTNBaseContact & contact)
// : contact(contact),
// connectivity(contact.getModel().getMesh().getConnectivities()) {
// AKANTU_DEBUG_IN();
// AKANTU_DEBUG_OUT();
// }
/* -------------------------------------------------------------------------- */
// bool NTNContactSynchElementFilter::operator()(const Element & e) {
// AKANTU_DEBUG_IN();
// ElementType type = e.type;
// UInt element = e.element;
// GhostType ghost_type = e.ghost_type;
// // loop over all nodes of this element
// bool need_element = false;
// UInt nb_nodes = Mesh::getNbNodesPerElement(type);
// for (UInt n = 0; n < nb_nodes; ++n) {
// UInt nn = this->connectivity(type, ghost_type)(element, n);
// // if one nodes is in this contact, we need this element
// if (this->contact.getNodeIndex(nn) >= 0) {
// need_element = true;
// break;
// }
// }
// AKANTU_DEBUG_OUT();
// return need_element;
// }
/* -------------------------------------------------------------------------- */
NTNBaseContact::NTNBaseContact(SolidMechanicsModel & model, const ID & id)
: id(id), model(model),
slaves(0, 1, 0, id + ":slaves", std::numeric_limits<UInt>::quiet_NaN(),
"slaves"),
normals(0, model.getSpatialDimension(), 0, id + ":normals",
std::numeric_limits<Real>::quiet_NaN(), "normals"),
contact_pressure(
0, model.getSpatialDimension(), 0, id + ":contact_pressure",
std::numeric_limits<Real>::quiet_NaN(), "contact_pressure"),
is_in_contact(0, 1, false, id + ":is_in_contact", false, "is_in_contact"),
lumped_boundary_slaves(0, 1, 0, id + ":lumped_boundary_slaves",
std::numeric_limits<Real>::quiet_NaN(),
"lumped_boundary_slaves"),
impedance(0, 1, 0, id + ":impedance",
std::numeric_limits<Real>::quiet_NaN(), "impedance"),
slave_elements("slave_elements", id) {
AKANTU_DEBUG_IN();
auto & boundary_fem = this->model.getFEEngineBoundary();
for (auto && ghost_type : ghost_types) {
boundary_fem.initShapeFunctions(ghost_type);
}
auto & mesh = this->model.getMesh();
auto spatial_dimension = this->model.getSpatialDimension();
this->slave_elements.initialize(mesh,
_spatial_dimension = spatial_dimension - 1);
MeshUtils::buildNode2Elements(mesh, this->node_to_elements,
spatial_dimension - 1);
this->registerDumper<DumperText>("text_all", id, true);
this->addDumpFilteredMesh(mesh, slave_elements, slaves.getArray(),
spatial_dimension - 1, _not_ghost, _ek_regular);
// parallelisation
this->synch_registry = std::make_unique<SynchronizerRegistry>();
this->synch_registry->registerDataAccessor(*this);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
NTNBaseContact::~NTNBaseContact() = default;
/* -------------------------------------------------------------------------- */
void NTNBaseContact::initParallel() {
AKANTU_DEBUG_IN();
this->synchronizer = std::make_unique<ElementSynchronizer>(
this->model.getMesh().getElementSynchronizer());
this->synchronizer->filterScheme([&](auto && element) {
// loop over all nodes of this element
- Vector<UInt> conn = const_cast<const Mesh &>(this->model.getMesh())
- .getConnectivity(element);
+ auto && conn = this->model.getMesh().getConnectivity(element);
for (auto & node : conn) {
// if one nodes is in this contact, we need this element
if (this->getNodeIndex(node) >= 0) {
return true;
}
}
return false;
});
this->synch_registry->registerSynchronizer(*(this->synchronizer),
SynchronizationTag::_cf_nodal);
this->synch_registry->registerSynchronizer(*(this->synchronizer),
SynchronizationTag::_cf_incr);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void NTNBaseContact::findBoundaryElements(
- const Array<UInt> & interface_nodes, ElementTypeMapArray<UInt> & elements) {
+void NTNBaseContact::findBoundaryElements(const Array<Idx> & interface_nodes,
+ ElementTypeMapArray<Idx> & elements) {
AKANTU_DEBUG_IN();
// add connected boundary elements that have all nodes on this contact
for (const auto & node : interface_nodes) {
for (const auto & element : this->node_to_elements.getRow(node)) {
- Vector<UInt> conn = const_cast<const Mesh &>(this->model.getMesh())
- .getConnectivity(element);
+ Vector<Idx> conn = this->model.getMesh().getConnectivity(element);
auto nb_nodes = conn.size();
decltype(nb_nodes) nb_found_nodes = 0;
for (auto & nn : conn) {
- if (interface_nodes.find(nn) != UInt(-1)) {
+ if (interface_nodes.find(nn) != -1) {
nb_found_nodes++;
} else {
break;
}
}
// this is an element between all contact nodes
// and is not already in the elements
if ((nb_found_nodes == nb_nodes) &&
(elements(element.type, element.ghost_type).find(element.element) ==
- UInt(-1))) {
+ -1)) {
elements(element.type, element.ghost_type).push_back(element.element);
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void NTNBaseContact::addSplitNode(UInt node, UInt /*unused*/) {
+void NTNBaseContact::addSplitNode(Idx node, Idx /*unused*/) {
AKANTU_DEBUG_IN();
- UInt dim = this->model.getSpatialDimension();
+ Int dim = this->model.getSpatialDimension();
// add to node arrays
this->slaves.push_back(node);
// set contact as false
this->is_in_contact.push_back(false);
// before initializing
// set contact pressure, normal, lumped_boundary to Nan
this->contact_pressure.push_back(std::numeric_limits<Real>::quiet_NaN());
this->impedance.push_back(std::numeric_limits<Real>::quiet_NaN());
this->lumped_boundary_slaves.push_back(
std::numeric_limits<Real>::quiet_NaN());
- Vector<Real> nan_normal(dim, std::numeric_limits<Real>::quiet_NaN());
+ Vector<Real> nan_normal(dim);
+ nan_normal.fill(std::numeric_limits<Real>::quiet_NaN());
+
this->normals.push_back(nan_normal);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::registerSynchronizedArray(SynchronizedArrayBase & array) {
AKANTU_DEBUG_IN();
this->slaves.registerDependingArray(array);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::dumpRestart(const std::string & file_name) const {
AKANTU_DEBUG_IN();
this->slaves.dumpRestartFile(file_name);
this->normals.dumpRestartFile(file_name);
this->is_in_contact.dumpRestartFile(file_name);
this->contact_pressure.dumpRestartFile(file_name);
this->lumped_boundary_slaves.dumpRestartFile(file_name);
this->impedance.dumpRestartFile(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::readRestart(const std::string & file_name) {
AKANTU_DEBUG_IN();
this->slaves.readRestartFile(file_name);
this->normals.readRestartFile(file_name);
this->is_in_contact.readRestartFile(file_name);
this->contact_pressure.readRestartFile(file_name);
this->lumped_boundary_slaves.readRestartFile(file_name);
this->impedance.readRestartFile(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-UInt NTNBaseContact::getNbNodesInContact() const {
+Int NTNBaseContact::getNbNodesInContact() const {
AKANTU_DEBUG_IN();
- UInt nb_contact = 0;
+ Int nb_contact = 0;
- UInt nb_nodes = this->getNbContactNodes();
- const Mesh & mesh = this->model.getMesh();
+ auto nb_nodes = this->getNbContactNodes();
+ const auto & mesh = this->model.getMesh();
- for (UInt n = 0; n < nb_nodes; ++n) {
- bool is_local_node = mesh.isLocalOrMasterNode(this->slaves(n));
- bool is_pbc_slave_node = mesh.isPeriodicSlave(this->slaves(n));
+ for (Int n = 0; n < nb_nodes; ++n) {
+ auto is_local_node = mesh.isLocalOrMasterNode(this->slaves(n));
+ auto is_pbc_slave_node = mesh.isPeriodicSlave(this->slaves(n));
if (is_local_node && !is_pbc_slave_node && this->is_in_contact(n)) {
nb_contact++;
}
}
mesh.getCommunicator().allReduce(nb_contact, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
return nb_contact;
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::updateInternalData() {
AKANTU_DEBUG_IN();
updateNormals();
updateLumpedBoundary();
updateImpedance();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::updateLumpedBoundary() {
AKANTU_DEBUG_IN();
this->internalUpdateLumpedBoundary(this->slaves.getArray(),
this->slave_elements,
this->lumped_boundary_slaves);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::internalUpdateLumpedBoundary(
- const Array<UInt> & nodes, const ElementTypeMapArray<UInt> & elements,
+ const Array<Idx> & nodes, const ElementTypeMapArray<Idx> & elements,
SynchronizedArray<Real> & boundary) {
AKANTU_DEBUG_IN();
// set all values in lumped_boundary to zero
boundary.zero();
- UInt dim = this->model.getSpatialDimension();
- // UInt nb_contact_nodes = getNbContactNodes();
+ auto dim = this->model.getSpatialDimension();
- const FEEngine & boundary_fem = this->model.getFEEngineBoundary();
+ const auto & boundary_fem = this->model.getFEEngineBoundary();
- const Mesh & mesh = this->model.getMesh();
+ const auto & mesh = this->model.getMesh();
for (auto ghost_type : ghost_types) {
for (const auto & type : mesh.elementTypes(dim - 1, ghost_type)) {
- UInt nb_elements = mesh.getNbElement(type, ghost_type);
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- const Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
+ auto nb_elements = mesh.getNbElement(type, ghost_type);
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ const auto & connectivity = mesh.getConnectivity(type, ghost_type);
// get shapes and compute integral
- const Array<Real> & shapes = boundary_fem.getShapes(type, ghost_type);
+ const auto & shapes = boundary_fem.getShapes(type, ghost_type);
Array<Real> area(nb_elements, nb_nodes_per_element);
boundary_fem.integrate(shapes, area, nb_nodes_per_element, type,
ghost_type);
if (this->contact_surfaces.empty()) {
AKANTU_DEBUG_WARNING(
"No surfaces in ntn base contact."
<< " You have to define the lumped boundary by yourself.");
}
- Array<UInt>::const_iterator<UInt> elem_it =
- (elements)(type, ghost_type).begin();
- Array<UInt>::const_iterator<UInt> elem_it_end =
- (elements)(type, ghost_type).end();
// loop over contact nodes
- for (; elem_it != elem_it_end; ++elem_it) {
- for (UInt q = 0; q < nb_nodes_per_element; ++q) {
- UInt node = connectivity(*elem_it, q);
- UInt node_index = nodes.find(node);
- AKANTU_DEBUG_ASSERT(node_index != UInt(-1), "Could not find node "
- << node
- << " in the array!");
- Real area_to_add = area(*elem_it, q);
+ for (auto && elem : elements(type, ghost_type)) {
+ for (Int q = 0; q < nb_nodes_per_element; ++q) {
+ auto node = connectivity(elem, q);
+ auto node_index = nodes.find(node);
+ AKANTU_DEBUG_ASSERT(node_index != Int(-1), "Could not find node "
+ << node
+ << " in the array!");
+ Real area_to_add = area(elem, q);
boundary(node_index) += area_to_add;
}
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::computeAcceleration(Array<Real> & acceleration) const {
auto && dof_manager =
dynamic_cast<DOFManagerDefault &>(model.getDOFManager());
const auto & b = dof_manager.getResidual();
acceleration.resize(b.size());
const auto & blocked_dofs = dof_manager.getGlobalBlockedDOFs();
const auto & A = dof_manager.getLumpedMatrix("M");
Array<bool> blocked_dofs_bool(blocked_dofs.size());
for (auto && data : zip(blocked_dofs, blocked_dofs_bool)) {
std::get<1>(data) = (std::get<0>(data) != 0);
}
// pre-compute the acceleration
// (not increment acceleration, because residual is still Kf)
NonLinearSolverLumped::solveLumped(A, acceleration, b, this->model.getF_M2A(),
blocked_dofs_bool);
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::computeContactPressure() {
AKANTU_DEBUG_IN();
- UInt dim = this->model.getSpatialDimension();
- Real delta_t = this->model.getTimeStep();
- UInt nb_contact_nodes = getNbContactNodes();
+ auto dim = this->model.getSpatialDimension();
+ auto delta_t = this->model.getTimeStep();
+ auto nb_contact_nodes = getNbContactNodes();
AKANTU_DEBUG_ASSERT(delta_t > 0.,
"Cannot compute contact pressure if no time step is set");
// synchronize data
this->synch_registry->synchronize(SynchronizationTag::_cf_nodal);
Array<Real> acceleration(0, dim);
this->computeAcceleration(acceleration);
// compute relative normal fields of displacement, velocity and acceleration
Array<Real> r_disp(0, 1);
Array<Real> r_velo(0, 1);
Array<Real> r_acce(0, 1);
Array<Real> r_old_acce(0, 1);
computeNormalGap(r_disp);
// computeRelativeNormalField(this->model.getCurrentPosition(), r_disp);
computeRelativeNormalField(this->model.getVelocity(), r_velo);
computeRelativeNormalField(acceleration, r_acce);
computeRelativeNormalField(this->model.getAcceleration(), r_old_acce);
AKANTU_DEBUG_ASSERT(r_disp.size() == nb_contact_nodes,
"computeRelativeNormalField does not give back arrays "
<< "size == nb_contact_nodes. nb_contact_nodes = "
<< nb_contact_nodes
<< " | array size = " << r_disp.size());
// compute gap array for all nodes
Array<Real> gap(nb_contact_nodes, 1);
- Real * gap_p = gap.storage();
- Real * r_disp_p = r_disp.storage();
- Real * r_velo_p = r_velo.storage();
- Real * r_acce_p = r_acce.storage();
- Real * r_old_acce_p = r_old_acce.storage();
- for (UInt i = 0; i < nb_contact_nodes; ++i) {
+ Real * gap_p = gap.data();
+ Real * r_disp_p = r_disp.data();
+ Real * r_velo_p = r_velo.data();
+ Real * r_acce_p = r_acce.data();
+ Real * r_old_acce_p = r_old_acce.data();
+ for (Int i = 0; i < nb_contact_nodes; ++i) {
*gap_p = *r_disp_p + delta_t * *r_velo_p + delta_t * delta_t * *r_acce_p -
0.5 * delta_t * delta_t * *r_old_acce_p;
// increment pointers
gap_p++;
r_disp_p++;
r_velo_p++;
r_acce_p++;
r_old_acce_p++;
}
// check if gap is negative -> is in contact
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
if (gap(n) <= 0.) {
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
this->contact_pressure(n, d) =
this->impedance(n) * gap(n) / (2 * delta_t) * this->normals(n, d);
}
this->is_in_contact(n) = true;
} else {
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
this->contact_pressure(n, d) = 0.;
}
this->is_in_contact(n) = false;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::applyContactPressure() {
- AKANTU_DEBUG_IN();
+ auto nb_contact_nodes = getNbContactNodes();
+ auto dim = this->model.getSpatialDimension();
- UInt nb_contact_nodes = getNbContactNodes();
- UInt dim = this->model.getSpatialDimension();
+ auto & residual = this->model.getInternalForce();
- Array<Real> & residual = this->model.getInternalForce();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
+ auto slave = this->slaves(n);
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
- UInt slave = this->slaves(n);
-
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
// residual(master,d) += this->lumped_boundary(n,0) *
// this->contact_pressure(n,d);
residual(slave, d) -=
this->lumped_boundary_slaves(n) * this->contact_pressure(n, d);
}
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Int NTNBaseContact::getNodeIndex(UInt node) const {
+Int NTNBaseContact::getNodeIndex(Idx node) const {
return this->slaves.find(node);
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::printself(std::ostream & stream, int indent) const {
- AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(AKANTU_INDENT, indent);
stream << space << "NTNBaseContact [" << std::endl;
stream << space << " + id : " << id << std::endl;
stream << space << " + slaves : " << std::endl;
this->slaves.printself(stream, indent + 2);
stream << space << " + normals : " << std::endl;
this->normals.printself(stream, indent + 2);
stream << space << " + contact_pressure : " << std::endl;
this->contact_pressure.printself(stream, indent + 2);
stream << space << "]" << std::endl;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::syncArrays(SyncChoice sync_choice) {
- AKANTU_DEBUG_IN();
-
this->slaves.syncElements(sync_choice);
this->normals.syncElements(sync_choice);
this->is_in_contact.syncElements(sync_choice);
this->contact_pressure.syncElements(sync_choice);
this->lumped_boundary_slaves.syncElements(sync_choice);
this->impedance.syncElements(sync_choice);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseContact::addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) {
AKANTU_DEBUG_IN();
- const Array<UInt> & nodal_filter = this->slaves.getArray();
+ const auto & nodal_filter = this->slaves.getArray();
#define ADD_FIELD(field_id, field, type) \
internalAddDumpFieldToDumper( \
dumper_name, field_id, \
std::make_unique< \
- dumpers::NodalField<type, true, Array<type>, Array<UInt>>>( \
+ dumpers::NodalField<type, true, Array<type>, Array<Idx>>>( \
field, 0, 0, &nodal_filter))
if (field_id == "displacement") {
ADD_FIELD(field_id, this->model.getDisplacement(), Real);
} else if (field_id == "mass") {
ADD_FIELD(field_id, this->model.getMass(), Real);
} else if (field_id == "velocity") {
ADD_FIELD(field_id, this->model.getVelocity(), Real);
} else if (field_id == "acceleration") {
ADD_FIELD(field_id, this->model.getAcceleration(), Real);
} else if (field_id == "external_force") {
ADD_FIELD(field_id, this->model.getExternalForce(), Real);
} else if (field_id == "internal_force") {
ADD_FIELD(field_id, this->model.getInternalForce(), Real);
} else if (field_id == "blocked_dofs") {
ADD_FIELD(field_id, this->model.getBlockedDOFs(), bool);
} else if (field_id == "increment") {
ADD_FIELD(field_id, this->model.getIncrement(), Real);
} else if (field_id == "normal") {
internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->normals.getArray()));
} else if (field_id == "contact_pressure") {
internalAddDumpFieldToDumper(dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->contact_pressure.getArray()));
} else if (field_id == "is_in_contact") {
internalAddDumpFieldToDumper(dumper_name, field_id,
std::make_unique<dumpers::NodalField<bool>>(
this->is_in_contact.getArray()));
} else if (field_id == "lumped_boundary_slave") {
internalAddDumpFieldToDumper(dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->lumped_boundary_slaves.getArray()));
} else if (field_id == "impedance") {
internalAddDumpFieldToDumper(dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->impedance.getArray()));
} else {
std::cerr << "Could not add field '" << field_id
<< "' to the dumper. Just ignored it." << std::endl;
}
#undef ADD_FIELD
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.hh
index 4aef66622..d4d4650aa 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact.hh
@@ -1,252 +1,252 @@
/**
* @file ntn_base_contact.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue Sep 29 2020
*
* @brief base contact for ntn and ntrf contact
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AST_NTN_BASE_CONTACT_HH_
#define AST_NTN_BASE_CONTACT_HH_
/* -------------------------------------------------------------------------- */
// akantu
#include "aka_csr.hh"
#include "solid_mechanics_model.hh"
// simtools
#include "synchronized_array.hh"
namespace akantu {
class NTNBaseContact;
/* -------------------------------------------------------------------------- */
// class NTNContactSynchElementFilter : public SynchElementFilter {
// public:
// // constructor
// NTNContactSynchElementFilter(NTNBaseContact & contact);
// // answer to: do we need this element ?
// virtual bool operator()(const Element & e);
// private:
// const NTNBaseContact & contact;
// const ElementTypeMapArray<UInt> & connectivity;
// };
/* -------------------------------------------------------------------------- */
class NTNBaseContact : public DataAccessor<Element>, public Dumpable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NTNBaseContact(SolidMechanicsModel & model, const ID & id = "contact");
~NTNBaseContact() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initializes ntn contact parallel
virtual void initParallel();
/// add split node
- virtual void addSplitNode(UInt node, UInt /*unused*/ = 0);
+ virtual void addSplitNode(Idx node, Idx /*unused*/ = 0);
/// update normals, lumped boundary, and impedance
virtual void updateInternalData();
/// update (compute the normals)
virtual void updateNormals() = 0;
/// update the lumped boundary B matrix
virtual void updateLumpedBoundary();
/// update the impedance matrix
virtual void updateImpedance() = 0;
/// compute the normal contact force
virtual void computeContactPressure();
/// impose the normal contact force
virtual void applyContactPressure();
/// register synchronizedarrays for sync
virtual void registerSynchronizedArray(SynchronizedArrayBase & array);
/// dump restart file
virtual void dumpRestart(const std::string & file_name) const;
/// read restart file
virtual void readRestart(const std::string & file_name);
/// compute the normal gap
virtual void computeNormalGap(Array<Real> & gap) const = 0;
/// compute relative normal field (only value that has to be multiplied with
/// the normal)
/// relative to master nodes
virtual void
computeRelativeNormalField(const Array<Real> & field,
Array<Real> & rel_normal_field) const = 0;
/// compute relative tangential field (complet array)
/// relative to master nodes
virtual void
computeRelativeTangentialField(const Array<Real> & field,
Array<Real> & rel_tang_field) const = 0;
/// function to print the contain of the class
virtual void printself(std::ostream & stream, int indent = 0) const;
/// computes the acceleration
void computeAcceleration(Array<Real> & acceleration) const;
protected:
/// updateLumpedBoundary
virtual void
- internalUpdateLumpedBoundary(const Array<UInt> & nodes,
- const ElementTypeMapArray<UInt> & elements,
+ internalUpdateLumpedBoundary(const Array<Idx> & nodes,
+ const ElementTypeMapArray<Idx> & elements,
SynchronizedArray<Real> & boundary);
// to find the slave_elements or master_elements
- virtual void findBoundaryElements(const Array<UInt> & interface_nodes,
- ElementTypeMapArray<UInt> & elements);
+ virtual void findBoundaryElements(const Array<Idx> & interface_nodes,
+ ElementTypeMapArray<Idx> & elements);
/// synchronize arrays
virtual void syncArrays(SyncChoice sync_choice);
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Dumpable */
/* ------------------------------------------------------------------------ */
public:
void addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(Model, model, SolidMechanicsModel &)
- AKANTU_GET_MACRO(Slaves, slaves, const SynchronizedArray<UInt> &)
+ AKANTU_GET_MACRO(Slaves, slaves, const SynchronizedArray<Idx> &)
AKANTU_GET_MACRO(Normals, normals, const SynchronizedArray<Real> &)
AKANTU_GET_MACRO(ContactPressure, contact_pressure,
const SynchronizedArray<Real> &)
AKANTU_GET_MACRO(LumpedBoundarySlaves, lumped_boundary_slaves,
const SynchronizedArray<Real> &)
AKANTU_GET_MACRO(Impedance, impedance, const SynchronizedArray<Real> &)
AKANTU_GET_MACRO(IsInContact, is_in_contact, const SynchronizedArray<bool> &)
AKANTU_GET_MACRO(SlaveElements, slave_elements,
- const ElementTypeMapArray<UInt> &)
+ const ElementTypeMapArray<Idx> &)
AKANTU_GET_MACRO(SynchronizerRegistry, *synch_registry,
SynchronizerRegistry &)
/// get number of nodes that are in contact (globally, on all procs together)
/// is_in_contact = true
- virtual UInt getNbNodesInContact() const;
+ virtual Int getNbNodesInContact() const;
/// get index of node in either slaves or masters array
/// if node is in neither of them, return -1
- virtual Int getNodeIndex(UInt node) const;
+ virtual Idx getNodeIndex(Idx node) const;
/// get number of contact nodes: nodes in the system locally (on this proc)
/// is_in_contact = true and false, because just in the system
- virtual UInt getNbContactNodes() const { return this->slaves.size(); }
+ virtual Int getNbContactNodes() const { return this->slaves.size(); }
bool isNTNContact() const { return this->is_ntn_contact; }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
using SurfacePtrSet = std::set<const ElementGroup *>;
ID id;
SolidMechanicsModel & model;
/// array of slave nodes
- SynchronizedArray<UInt> slaves;
+ SynchronizedArray<Idx> slaves;
/// array of normals
SynchronizedArray<Real> normals;
/// array indicating if nodes are in contact
SynchronizedArray<Real> contact_pressure;
/// array indicating if nodes are in contact
SynchronizedArray<bool> is_in_contact;
/// boundary matrix for slave nodes
SynchronizedArray<Real> lumped_boundary_slaves;
/// impedance matrix
SynchronizedArray<Real> impedance;
/// contact surface
SurfacePtrSet contact_surfaces;
/// element list for dump and lumped_boundary
- ElementTypeMapArray<UInt> slave_elements;
+ ElementTypeMapArray<Idx> slave_elements;
CSR<Element> node_to_elements;
/// parallelisation
std::unique_ptr<SynchronizerRegistry> synch_registry;
std::unique_ptr<ElementSynchronizer> synchronizer;
bool is_ntn_contact{true};
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const NTNBaseContact & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "ntn_base_contact_inline_impl.hh"
#endif /* AST_NTN_BASE_CONTACT_HH_ */
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact_inline_impl.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact_inline_impl.hh
index 1b6372f69..6c1c60e46 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact_inline_impl.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_contact_inline_impl.hh
@@ -1,129 +1,126 @@
/**
* @file ntn_base_contact_inline_impl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Sun Dec 30 2018
*
* @brief ntn base contact inline functions
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "ntn_base_contact.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt NTNBaseContact::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+inline Int NTNBaseContact::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
- UInt size = 0;
- UInt spatial_dimension = this->model.getSpatialDimension();
+ Int size = 0;
+ Int spatial_dimension = this->model.getSpatialDimension();
- UInt nb_nodes = 0;
- Array<Element>::const_iterator<Element> it = elements.begin();
- Array<Element>::const_iterator<Element> end = elements.end();
- for (; it != end; ++it) {
- const Element & el = *it;
+ Int nb_nodes = 0;
+ for (const auto & el : elements) {
nb_nodes += Mesh::getNbNodesPerElement(el.type);
}
switch (tag) {
case SynchronizationTag::_cf_nodal: {
size += nb_nodes * spatial_dimension * sizeof(Real) *
3; // disp, vel and cur_pos
break;
}
case SynchronizationTag::_cf_incr: {
size += nb_nodes * spatial_dimension * sizeof(Real) * 1;
break;
}
default: {
}
}
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
inline void NTNBaseContact::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
switch (tag) {
case SynchronizationTag::_cf_nodal: {
DataAccessor::packNodalDataHelper(this->model.getDisplacement(), buffer,
elements, this->model.getMesh());
DataAccessor::packNodalDataHelper(this->model.getCurrentPosition(), buffer,
elements, this->model.getMesh());
DataAccessor::packNodalDataHelper(this->model.getVelocity(), buffer,
elements, this->model.getMesh());
break;
}
case SynchronizationTag::_cf_incr: {
DataAccessor::packNodalDataHelper(this->model.getIncrement(), buffer,
elements, this->model.getMesh());
break;
}
default: {
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
inline void NTNBaseContact::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
switch (tag) {
case SynchronizationTag::_cf_nodal: {
DataAccessor::unpackNodalDataHelper(this->model.getDisplacement(), buffer,
elements, this->model.getMesh());
DataAccessor::unpackNodalDataHelper(
const_cast<Array<Real> &>(this->model.getCurrentPosition()), buffer,
elements, this->model.getMesh());
DataAccessor::unpackNodalDataHelper(this->model.getVelocity(), buffer,
elements, this->model.getMesh());
break;
}
case SynchronizationTag::_cf_incr: {
DataAccessor::unpackNodalDataHelper(this->model.getIncrement(), buffer,
elements, this->model.getMesh());
break;
}
default: {
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_friction.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_friction.cc
index 5f8afe7fb..3b10e1e53 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_friction.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_base_friction.cc
@@ -1,376 +1,334 @@
/**
* @file ntn_base_friction.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue Sep 29 2020
*
* @brief implementation of ntn base friction
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "ntn_base_friction.hh"
#include "dof_manager_default.hh"
#include "dumper_nodal_field.hh"
#include "dumper_text.hh"
#include "non_linear_solver_lumped.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
NTNBaseFriction::NTNBaseFriction(NTNBaseContact & contact, const ID & id)
: Parsable(ParserType::_friction, id), contact(contact),
is_sticking(0, 1, true, id + ":is_sticking", true, "is_sticking"),
frictional_strength(0, 1, 0., id + ":frictional_strength", 0.,
"frictional_strength"),
friction_traction(0, contact.getModel().getSpatialDimension(), 0.,
id + ":friction_traction", 0., "friction_traction"),
slip(0, 1, 0., id + ":slip", 0., "slip"),
cumulative_slip(0, 1, 0., id + ":cumulative_slip", 0., "cumulative_slip"),
slip_velocity(0, contact.getModel().getSpatialDimension(), 0.,
id + ":slip_velocity", 0., "slip_velocity") {
AKANTU_DEBUG_IN();
this->contact.registerSynchronizedArray(this->is_sticking);
this->contact.registerSynchronizedArray(this->frictional_strength);
this->contact.registerSynchronizedArray(this->friction_traction);
this->contact.registerSynchronizedArray(this->slip);
this->contact.registerSynchronizedArray(this->cumulative_slip);
this->contact.registerSynchronizedArray(this->slip_velocity);
this->registerExternalDumper(contact.getDumper().shared_from_this(),
contact.getDefaultDumperName(), true);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::updateSlip() {
AKANTU_DEBUG_IN();
SolidMechanicsModel & model = this->contact.getModel();
- UInt dim = model.getSpatialDimension();
+ Int dim = model.getSpatialDimension();
// synchronize increment
this->contact.getSynchronizerRegistry().synchronize(
SynchronizationTag::_cf_incr);
Array<Real> rel_tan_incr(0, dim);
this->contact.computeRelativeTangentialField(model.getIncrement(),
rel_tan_incr);
- Array<Real>::const_iterator<Vector<Real>> it = rel_tan_incr.begin(dim);
+ auto it = rel_tan_incr.begin(dim);
- UInt nb_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_nodes; ++n) {
+ auto nb_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_nodes; ++n) {
if (this->is_sticking(n)) {
this->slip(n) = 0.;
} else {
- const Vector<Real> & rti = it[n];
+ const auto & rti = it[n];
this->slip(n) += rti.norm();
this->cumulative_slip(n) += rti.norm();
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::computeFrictionTraction() {
AKANTU_DEBUG_IN();
this->computeStickTraction();
this->computeFrictionalStrength();
- SolidMechanicsModel & model = this->contact.getModel();
- UInt dim = model.getSpatialDimension();
+ auto & model = this->contact.getModel();
+ auto dim = model.getSpatialDimension();
// get contact arrays
const SynchronizedArray<bool> & is_in_contact =
this->contact.getIsInContact();
- auto & traction =
- const_cast<Array<Real> &>(this->friction_traction.getArray());
- Array<Real>::iterator<Vector<Real>> it_fric_trac = traction.begin(dim);
+ const auto & traction = this->friction_traction.getArray();
+ auto it_fric_trac = traction.begin(dim);
this->is_sticking.zero(); // set to not sticking
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ Int nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// node pair is in contact
if (is_in_contact(n)) {
- Vector<Real> fric_trac = it_fric_trac[n];
+ auto && fric_trac = it_fric_trac[n];
// check if it is larger than frictional strength
- Real abs_fric = fric_trac.norm();
+ auto abs_fric = fric_trac.norm();
if (abs_fric != 0.) {
- Real alpha = this->frictional_strength(n) / abs_fric;
+ auto alpha = this->frictional_strength(n) / abs_fric;
// larger -> sliding
if (alpha < 1.) {
fric_trac *= alpha;
} else {
this->is_sticking(n) = true;
}
} else {
// frictional traction is already zero
this->is_sticking(n) = true;
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::computeStickTraction() {
- AKANTU_DEBUG_IN();
+ auto & model = this->contact.getModel();
+ auto dim = model.getSpatialDimension();
+ auto delta_t = model.getTimeStep();
- SolidMechanicsModel & model = this->contact.getModel();
- UInt dim = model.getSpatialDimension();
- Real delta_t = model.getTimeStep();
-
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
// get contact arrays
- const SynchronizedArray<Real> & impedance = this->contact.getImpedance();
- const SynchronizedArray<bool> & is_in_contact =
- this->contact.getIsInContact();
+ const auto & impedance = this->contact.getImpedance();
+ const auto & is_in_contact = this->contact.getIsInContact();
Array<Real> acceleration(0, dim);
this->contact.computeAcceleration(acceleration);
// compute relative normal fields of velocity and acceleration
Array<Real> r_velo(0, dim);
Array<Real> r_acce(0, dim);
Array<Real> r_old_acce(0, dim);
this->contact.computeRelativeTangentialField(model.getVelocity(), r_velo);
this->contact.computeRelativeTangentialField(acceleration, r_acce);
this->contact.computeRelativeTangentialField(model.getAcceleration(),
r_old_acce);
AKANTU_DEBUG_ASSERT(r_velo.size() == nb_contact_nodes,
"computeRelativeNormalField does not give back arrays "
<< "size == nb_contact_nodes. nb_contact_nodes = "
<< nb_contact_nodes
<< " | array size = " << r_velo.size());
// compute tangential gap_dot array for all nodes
Array<Real> gap_dot(nb_contact_nodes, dim);
for (auto && data : zip(make_view(gap_dot), make_view(r_velo),
make_view(r_acce), make_view(r_old_acce))) {
auto & gap_dot = std::get<0>(data);
auto & r_velo = std::get<1>(data);
auto & r_acce = std::get<2>(data);
auto & r_old_acce = std::get<3>(data);
gap_dot = r_velo + delta_t * r_acce - 1. / 2. * delta_t * r_old_acce;
}
// compute friction traction to stop sliding
- auto & traction =
- const_cast<Array<Real> &>(this->friction_traction.getArray());
+ const auto & traction = this->friction_traction.getArray();
auto it_fric_trac = traction.begin(dim);
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
- Vector<Real> fric_trac = it_fric_trac[n];
- // node pair is NOT in contact
- if (!is_in_contact(n)) {
- fric_trac.zero(); // set to zero
- }
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
+ auto && fric_trac = it_fric_trac[n];
- // node pair is in contact
- else {
+ if (not is_in_contact(n)) { // node pair is NOT in contact
+ fric_trac.zero(); // set to zero
+ } else { // node pair is in contact
// compute friction traction
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
fric_trac(d) = impedance(n) * gap_dot(n, d) / 2.;
}
}
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::applyFrictionTraction() {
- AKANTU_DEBUG_IN();
-
- SolidMechanicsModel & model = this->contact.getModel();
- Array<Real> & residual = model.getInternalForce();
- UInt dim = model.getSpatialDimension();
+ auto & model = this->contact.getModel();
+ auto & residual = model.getInternalForce();
+ auto dim = model.getSpatialDimension();
- const SynchronizedArray<UInt> & slaves = this->contact.getSlaves();
- const SynchronizedArray<Real> & lumped_boundary_slaves =
- this->contact.getLumpedBoundarySlaves();
+ const auto & slaves = this->contact.getSlaves();
+ const auto & lumped_boundary_slaves = this->contact.getLumpedBoundarySlaves();
- UInt nb_contact_nodes = this->contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
- UInt slave = slaves(n);
+ auto nb_contact_nodes = this->contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
+ auto slave = slaves(n);
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
residual(slave, d) -=
lumped_boundary_slaves(n) * this->friction_traction(n, d);
}
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::registerSynchronizedArray(SynchronizedArrayBase & array) {
- AKANTU_DEBUG_IN();
-
this->frictional_strength.registerDependingArray(array);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::dumpRestart(const std::string & file_name) const {
- AKANTU_DEBUG_IN();
-
this->is_sticking.dumpRestartFile(file_name);
this->frictional_strength.dumpRestartFile(file_name);
this->friction_traction.dumpRestartFile(file_name);
this->slip.dumpRestartFile(file_name);
this->cumulative_slip.dumpRestartFile(file_name);
this->slip_velocity.dumpRestartFile(file_name);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::readRestart(const std::string & file_name) {
- AKANTU_DEBUG_IN();
-
this->is_sticking.readRestartFile(file_name);
this->frictional_strength.readRestartFile(file_name);
this->friction_traction.readRestartFile(file_name);
this->cumulative_slip.readRestartFile(file_name);
this->slip_velocity.readRestartFile(file_name);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::setParam(const std::string & name, UInt node,
Real value) {
- AKANTU_DEBUG_IN();
-
auto & array = this->get(name).get<SynchronizedArray<Real>>();
Int index = this->contact.getNodeIndex(node);
if (index < 0) {
AKANTU_DEBUG_WARNING("Node "
<< node << " is not a contact node. "
<< "Therefore, cannot set interface parameter!!");
} else {
array(index) = value; // put value
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
UInt NTNBaseFriction::getNbStickingNodes() const {
- AKANTU_DEBUG_IN();
+ Int nb_stick = 0;
- UInt nb_stick = 0;
+ auto nb_nodes = this->contact.getNbContactNodes();
+ const auto & nodes = this->contact.getSlaves();
+ const auto & is_in_contact = this->contact.getIsInContact();
- UInt nb_nodes = this->contact.getNbContactNodes();
- const SynchronizedArray<UInt> & nodes = this->contact.getSlaves();
- const SynchronizedArray<bool> & is_in_contact =
- this->contact.getIsInContact();
+ const auto & mesh = this->contact.getModel().getMesh();
- const Mesh & mesh = this->contact.getModel().getMesh();
-
- for (UInt n = 0; n < nb_nodes; ++n) {
- bool is_local_node = mesh.isLocalOrMasterNode(nodes(n));
- bool is_pbc_slave_node = mesh.isPeriodicSlave(nodes(n));
+ for (Int n = 0; n < nb_nodes; ++n) {
+ auto is_local_node = mesh.isLocalOrMasterNode(nodes(n));
+ auto is_pbc_slave_node = mesh.isPeriodicSlave(nodes(n));
if (is_local_node && !is_pbc_slave_node && is_in_contact(n) &&
this->is_sticking(n)) {
nb_stick++;
}
}
mesh.getCommunicator().allReduce(nb_stick, SynchronizerOperation::_sum);
-
- AKANTU_DEBUG_OUT();
return nb_stick;
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::printself(std::ostream & stream, int indent) const {
- AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(AKANTU_INDENT, indent);
stream << space << "NTNBaseFriction [" << std::endl;
Parsable::printself(stream, indent);
stream << space << "]" << std::endl;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNBaseFriction::addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) {
AKANTU_DEBUG_IN();
if (field_id == "is_sticking") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<bool>>(
this->is_sticking.getArray()));
} else if (field_id == "frictional_strength") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->frictional_strength.getArray()));
} else if (field_id == "friction_traction") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->friction_traction.getArray()));
} else if (field_id == "slip") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(this->slip.getArray()));
} else if (field_id == "cumulative_slip") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->cumulative_slip.getArray()));
} else if (field_id == "slip_velocity") {
this->internalAddDumpFieldToDumper(
dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->slip_velocity.getArray()));
} else {
this->contact.addDumpFieldToDumper(dumper_name, field_id);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.cc
index 194cdad3e..714f45dcd 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.cc
@@ -1,556 +1,515 @@
/**
* @file ntn_contact.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue Sep 29 2020
*
* @brief implementation of ntn_contact
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "ntn_contact.hh"
#include "dumper_nodal_field.hh"
#include "dumper_text.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
NTNContact::NTNContact(SolidMechanicsModel & model, const ID & id)
: NTNBaseContact(model, id),
masters(0, 1, 0, id + ":masters", std::numeric_limits<UInt>::quiet_NaN(),
"masters"),
lumped_boundary_masters(0, 1, 0, id + ":lumped_boundary_masters",
std::numeric_limits<Real>::quiet_NaN(),
"lumped_boundary_masters"),
master_elements("master_elements", id) {
AKANTU_DEBUG_IN();
const Mesh & mesh = this->model.getMesh();
- UInt spatial_dimension = this->model.getSpatialDimension();
+ Int spatial_dimension = this->model.getSpatialDimension();
this->master_elements.initialize(mesh, _nb_component = 1,
_spatial_dimension = spatial_dimension - 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::pairInterfaceNodes(const ElementGroup & slave_boundary,
const ElementGroup & master_boundary,
- UInt surface_normal_dir, const Mesh & mesh,
- Array<UInt> & pairs) {
+ Int surface_normal_dir, const Mesh & mesh,
+ Array<Idx> & pairs) {
AKANTU_DEBUG_IN();
pairs.resize(0);
AKANTU_DEBUG_ASSERT(pairs.getNbComponent() == 2,
"Array of node pairs should have nb_component = 2,"
<< " but has nb_component = "
<< pairs.getNbComponent());
- UInt dim = mesh.getSpatialDimension();
+ Int dim = mesh.getSpatialDimension();
AKANTU_DEBUG_ASSERT(surface_normal_dir < dim,
"Mesh is of " << dim << " dimensions"
<< " and cannot have direction "
<< surface_normal_dir
<< " for surface normal");
// offset for projection computation
- Vector<UInt> offset(dim - 1);
- for (UInt i = 0, j = 0; i < dim; ++i) {
+ Vector<Int> offset(dim - 1);
+ for (Int i = 0, j = 0; i < dim; ++i) {
if (surface_normal_dir != i) {
offset(j) = i;
++j;
}
}
// find projected node coordinates
- const Array<Real> & coordinates = mesh.getNodes();
+ const auto & coordinates = mesh.getNodes();
// find slave nodes
Array<Real> proj_slave_coord(slave_boundary.getNbNodes(), dim - 1, 0.);
- Array<UInt> slave_nodes(slave_boundary.getNbNodes());
- UInt n(0);
+ Array<Idx> slave_nodes(slave_boundary.getNbNodes());
+ Int n(0);
for (auto && slave_node : slave_boundary.getNodeGroup().getNodes()) {
- for (UInt d = 0; d < dim - 1; ++d) {
+ for (Int d = 0; d < dim - 1; ++d) {
proj_slave_coord(n, d) = coordinates(slave_node, offset[d]);
slave_nodes(n) = slave_node;
}
++n;
}
// find master nodes
Array<Real> proj_master_coord(master_boundary.getNbNodes(), dim - 1, 0.);
- Array<UInt> master_nodes(master_boundary.getNbNodes());
+ Array<Idx> master_nodes(master_boundary.getNbNodes());
n = 0;
for (auto && master_node : master_boundary.getNodeGroup().getNodes()) {
- for (UInt d = 0; d < dim - 1; ++d) {
+ for (Int d = 0; d < dim - 1; ++d) {
proj_master_coord(n, d) = coordinates(master_node, offset[d]);
master_nodes(n) = master_node;
}
++n;
}
// find minimum distance between slave nodes to define tolerance
Real min_dist = std::numeric_limits<Real>::max();
- for (UInt i = 0; i < proj_slave_coord.size(); ++i) {
- for (UInt j = i + 1; j < proj_slave_coord.size(); ++j) {
+ for (Int i = 0; i < proj_slave_coord.size(); ++i) {
+ for (Int j = i + 1; j < proj_slave_coord.size(); ++j) {
Real dist = 0.;
- for (UInt d = 0; d < dim - 1; ++d) {
+ for (Int d = 0; d < dim - 1; ++d) {
dist += (proj_slave_coord(i, d) - proj_slave_coord(j, d)) *
(proj_slave_coord(i, d) - proj_slave_coord(j, d));
}
if (dist < min_dist) {
min_dist = dist;
}
}
}
min_dist = std::sqrt(min_dist);
Real local_tol = 0.1 * min_dist;
// find master slave node pairs
- for (UInt i = 0; i < proj_slave_coord.size(); ++i) {
- for (UInt j = 0; j < proj_master_coord.size(); ++j) {
+ for (Int i = 0; i < proj_slave_coord.size(); ++i) {
+ for (Int j = 0; j < proj_master_coord.size(); ++j) {
Real dist = 0.;
- for (UInt d = 0; d < dim - 1; ++d) {
+ for (Int d = 0; d < dim - 1; ++d) {
dist += (proj_slave_coord(i, d) - proj_master_coord(j, d)) *
(proj_slave_coord(i, d) - proj_master_coord(j, d));
}
dist = std::sqrt(dist);
if (dist < local_tol) { // it is a pair
- Vector<UInt> pair(2);
- pair[0] = slave_nodes(i);
- pair[1] = master_nodes(j);
- pairs.push_back(pair);
+ pairs.push_back(Vector<Idx>{slave_nodes(i), master_nodes(j)});
continue; // found master do not need to search further for this slave
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::addSurfacePair(const ID & slave, const ID & master,
- UInt surface_normal_dir) {
+ Int surface_normal_dir) {
AKANTU_DEBUG_IN();
- const Mesh & mesh = this->model.getMesh();
+ const auto & mesh = this->model.getMesh();
- const ElementGroup & slave_boundary = mesh.getElementGroup(slave);
- const ElementGroup & master_boundary = mesh.getElementGroup(master);
+ const auto & slave_boundary = mesh.getElementGroup(slave);
+ const auto & master_boundary = mesh.getElementGroup(master);
this->contact_surfaces.insert(&slave_boundary);
this->contact_surfaces.insert(&master_boundary);
- Array<UInt> pairs(0, 2);
+ Array<Idx> pairs(0, 2);
NTNContact::pairInterfaceNodes(slave_boundary, master_boundary,
surface_normal_dir, this->model.getMesh(),
pairs);
// eliminate pairs which contain a pbc slave node
- Array<UInt> pairs_no_PBC_slaves(0, 2);
- Array<UInt>::const_vector_iterator it = pairs.begin(2);
- Array<UInt>::const_vector_iterator end = pairs.end(2);
- for (; it != end; ++it) {
- const Vector<UInt> & pair = *it;
+ Array<Idx> pairs_no_PBC_slaves(0, 2);
+ for (auto && pair : make_view<2>(pairs)) {
if (not mesh.isPeriodicSlave(pair(0)) and
not mesh.isPeriodicSlave(pair(1))) {
pairs_no_PBC_slaves.push_back(pair);
}
}
this->addNodePairs(pairs_no_PBC_slaves);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void NTNContact::addNodePairs(const Array<UInt> & pairs) {
+void NTNContact::addNodePairs(const Array<Idx> & pairs) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(pairs.getNbComponent() == 2,
"Array of node pairs should have nb_component = 2,"
<< " but has nb_component = "
<< pairs.getNbComponent());
- UInt nb_pairs = pairs.size();
- for (UInt n = 0; n < nb_pairs; ++n) {
- this->addSplitNode(pairs(n, 0), pairs(n, 1));
+ for (auto && pair : make_view<2>(pairs)) {
+ this->addSplitNode(pair(0), pair(1));
}
// synchronize with depending nodes
findBoundaryElements(this->slaves.getArray(), this->slave_elements);
findBoundaryElements(this->masters.getArray(), this->master_elements);
+
updateInternalData();
syncArrays(_added);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void NTNContact::getNodePairs(Array<UInt> & pairs) const {
+void NTNContact::getNodePairs(Array<Idx> & pairs) const {
AKANTU_DEBUG_IN();
pairs.resize(0);
AKANTU_DEBUG_ASSERT(pairs.getNbComponent() == 2,
"Array of node pairs should have nb_component = 2,"
<< " but has nb_component = "
<< pairs.getNbComponent());
- UInt nb_pairs = this->getNbContactNodes();
- for (UInt n = 0; n < nb_pairs; ++n) {
- Vector<UInt> pair{this->slaves(n), this->masters(n)};
- pairs.push_back(pair);
+
+ auto nb_pairs = this->getNbContactNodes();
+ for (Int n = 0; n < nb_pairs; ++n) {
+ pairs.push_back(Vector<Idx>{this->slaves(n), this->masters(n)});
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void NTNContact::addSplitNode(UInt slave, UInt master) {
+void NTNContact::addSplitNode(Idx slave, Idx master) {
AKANTU_DEBUG_IN();
NTNBaseContact::addSplitNode(slave);
this->masters.push_back(master);
this->lumped_boundary_masters.push_back(
std::numeric_limits<Real>::quiet_NaN());
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/*
This function only works for surface elements with one quad point. For
surface elements with more quad points, it computes still, but the result
might not be what you are looking for.
*/
void NTNContact::updateNormals() {
AKANTU_DEBUG_IN();
// set normals to zero
this->normals.zero();
// contact information
- UInt dim = this->model.getSpatialDimension();
- UInt nb_contact_nodes = this->getNbContactNodes();
-
+ auto dim = this->model.getSpatialDimension();
this->synch_registry->synchronize(
SynchronizationTag::_cf_nodal); // synchronize current pos
- const Array<Real> & cur_pos = this->model.getCurrentPosition();
+ const auto & cur_pos = this->model.getCurrentPosition();
- FEEngine & boundary_fem = this->model.getFEEngineBoundary();
- const Mesh & mesh = this->model.getMesh();
+ auto & boundary_fem = this->model.getFEEngineBoundary();
+ const auto & mesh = this->model.getMesh();
for (auto ghost_type : ghost_types) {
for (const auto & type : mesh.elementTypes(dim - 1, ghost_type)) {
// compute the normals
Array<Real> quad_normals(0, dim);
boundary_fem.computeNormalsOnIntegrationPoints(cur_pos, quad_normals,
type, ghost_type);
- UInt nb_quad_points =
+ auto nb_quad_points =
boundary_fem.getNbIntegrationPoints(type, ghost_type);
// new version: compute normals only based on master elements (and not all
// boundary elements)
// -------------------------------------------------------------------------------------
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- const Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ const auto & connectivity = mesh.getConnectivity(type, ghost_type);
// loop over contact nodes
for (auto & element : (this->master_elements)(type, ghost_type)) {
- for (UInt q = 0; q < nb_nodes_per_element; ++q) {
- UInt node = connectivity(element, q);
- UInt node_index = this->masters.find(node);
- AKANTU_DEBUG_ASSERT(node_index != UInt(-1), "Could not find node "
- << node
- << " in the array!");
-
- for (UInt q = 0; q < nb_quad_points; ++q) {
+ for (Int q = 0; q < nb_nodes_per_element; ++q) {
+ auto node = connectivity(element, q);
+ auto node_index = this->masters.find(node);
+ AKANTU_DEBUG_ASSERT(node_index != -1, "Could not find node "
+ << node
+ << " in the array!");
+
+ for (Int q = 0; q < nb_quad_points; ++q) {
// add quad normal to master normal
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
this->normals(node_index, d) +=
quad_normals(element * nb_quad_points + q, d);
}
}
}
}
}
}
- Real * master_normals = this->normals.storage();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
- if (dim == 2) {
- Math::normalize2(&(master_normals[n * dim]));
- } else if (dim == 3) {
- Math::normalize3(&(master_normals[n * dim]));
- }
+ for (auto && n : make_view(this->normals, dim)) {
+ n.normalize();
}
- // // normalize normals
- // auto nit = this->normals.begin();
- // auto nend = this->normals.end();
- // for (; nit != nend; ++nit) {
- // nit->normalize();
- // }
-
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::dumpRestart(const std::string & file_name) const {
AKANTU_DEBUG_IN();
NTNBaseContact::dumpRestart(file_name);
this->masters.dumpRestartFile(file_name);
this->lumped_boundary_masters.dumpRestartFile(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::readRestart(const std::string & file_name) {
AKANTU_DEBUG_IN();
NTNBaseContact::readRestart(file_name);
this->masters.readRestartFile(file_name);
this->lumped_boundary_masters.readRestartFile(file_name);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::updateImpedance() {
AKANTU_DEBUG_IN();
- UInt nb_contact_nodes = getNbContactNodes();
+ auto nb_contact_nodes = getNbContactNodes();
Real delta_t = this->model.getTimeStep();
AKANTU_DEBUG_ASSERT(delta_t != NAN,
"Time step is NAN. Have you set it already?");
const Array<Real> & mass = this->model.getMass();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
- UInt master = this->masters(n);
- UInt slave = this->slaves(n);
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
+ auto master = this->masters(n);
+ auto slave = this->slaves(n);
Real imp = (this->lumped_boundary_masters(n) / mass(master)) +
(this->lumped_boundary_slaves(n) / mass(slave));
imp = 2 / delta_t / imp;
this->impedance(n) = imp;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::updateLumpedBoundary() {
AKANTU_DEBUG_IN();
internalUpdateLumpedBoundary(this->slaves.getArray(), this->slave_elements,
this->lumped_boundary_slaves);
internalUpdateLumpedBoundary(this->masters.getArray(), this->master_elements,
this->lumped_boundary_masters);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::applyContactPressure() {
- AKANTU_DEBUG_IN();
+ auto nb_ntn_pairs = getNbContactNodes();
+ auto dim = this->model.getSpatialDimension();
- UInt nb_ntn_pairs = getNbContactNodes();
- UInt dim = this->model.getSpatialDimension();
+ auto & residual = this->model.getInternalForce();
- Array<Real> & residual = this->model.getInternalForce();
+ for (Int n = 0; n < nb_ntn_pairs; ++n) {
+ auto master = this->masters(n);
+ auto slave = this->slaves(n);
- for (UInt n = 0; n < nb_ntn_pairs; ++n) {
- UInt master = this->masters(n);
- UInt slave = this->slaves(n);
-
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
residual(master, d) +=
this->lumped_boundary_masters(n) * this->contact_pressure(n, d);
residual(slave, d) -=
this->lumped_boundary_slaves(n) * this->contact_pressure(n, d);
}
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::computeRelativeTangentialField(
const Array<Real> & field, Array<Real> & rel_tang_field) const {
- AKANTU_DEBUG_IN();
-
// resize arrays to zero
rel_tang_field.resize(0);
- UInt dim = this->model.getSpatialDimension();
+ Int dim = this->model.getSpatialDimension();
auto it_field = field.begin(dim);
auto it_normal = this->normals.getArray().begin(dim);
Vector<Real> rfv(dim);
Vector<Real> np_rfv(dim);
- UInt nb_contact_nodes = this->slaves.size();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->slaves.size();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// nodes
- UInt slave = this->slaves(n);
- UInt master = this->masters(n);
+ auto slave = this->slaves(n);
+ auto master = this->masters(n);
// relative field vector (slave - master)
- rfv = Vector<Real>(it_field[slave]);
- rfv -= Vector<Real>(it_field[master]);
+ rfv = it_field[slave] - it_field[master];
// normal projection of relative field
const Vector<Real> normal_v = it_normal[n];
- np_rfv = normal_v;
- np_rfv *= rfv.dot(normal_v);
+ np_rfv = normal_v * rfv.dot(normal_v);
// subract normal projection from relative field to get the tangential
// projection
rfv -= np_rfv;
rel_tang_field.push_back(rfv);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::computeRelativeNormalField(
const Array<Real> & field, Array<Real> & rel_normal_field) const {
AKANTU_DEBUG_IN();
// resize arrays to zero
rel_normal_field.resize(0);
- UInt dim = this->model.getSpatialDimension();
- // Real * field_p = field.storage();
- // Real * normals_p = this->normals.storage();
+ Int dim = this->model.getSpatialDimension();
- Array<Real>::const_iterator<Vector<Real>> it_field = field.begin(dim);
- Array<Real>::const_iterator<Vector<Real>> it_normal =
- this->normals.getArray().begin(dim);
+ auto it_field = make_view(field, dim).begin();
+ auto it_normal = make_view(this->normals.getArray(), dim).begin();
Vector<Real> rfv(dim);
- UInt nb_contact_nodes = this->getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// nodes
- UInt slave = this->slaves(n);
- UInt master = this->masters(n);
+ auto slave = this->slaves(n);
+ auto master = this->masters(n);
// relative field vector (slave - master)
- rfv = Vector<Real>(it_field[slave]);
- rfv -= Vector<Real>(it_field[master]);
+ rfv = it_field[slave] - it_field[master];
// length of normal projection of relative field
- const Vector<Real> normal_v = it_normal[n];
- rel_normal_field.push_back(rfv.dot(normal_v));
+ rel_normal_field.push_back(rfv.dot(it_normal[n]));
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Int NTNContact::getNodeIndex(UInt node) const {
- AKANTU_DEBUG_IN();
-
- Int slave_i = NTNBaseContact::getNodeIndex(node);
- Int master_i = this->masters.find(node);
+Int NTNContact::getNodeIndex(Idx node) const {
+ auto slave_i = NTNBaseContact::getNodeIndex(node);
+ auto master_i = this->masters.find(node);
- AKANTU_DEBUG_OUT();
return std::max(slave_i, master_i);
}
/* -------------------------------------------------------------------------- */
void NTNContact::printself(std::ostream & stream, int indent) const {
AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(AKANTU_INDENT, indent);
stream << space << "NTNContact [" << std::endl;
NTNBaseContact::printself(stream, indent);
stream << space << " + masters : " << std::endl;
this->masters.printself(stream, indent + 2);
stream << space << " + lumped_boundary_mastres : " << std::endl;
this->lumped_boundary_masters.printself(stream, indent + 2);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::syncArrays(SyncChoice sync_choice) {
AKANTU_DEBUG_IN();
NTNBaseContact::syncArrays(sync_choice);
this->masters.syncElements(sync_choice);
this->lumped_boundary_masters.syncElements(sync_choice);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTNContact::addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) {
AKANTU_DEBUG_IN();
/*
const Array<UInt> & nodal_filter = this->slaves.getArray();
#define ADD_FIELD(field_id, field, type) \
internalAddDumpFieldToDumper(dumper_name, \
field_id, \
new DumperIOHelper::NodalField< type, true, \
Array<type>, \
Array<UInt> >(field, 0, 0, &nodal_filter))
*/
if (field_id == "lumped_boundary_master") {
internalAddDumpFieldToDumper(dumper_name, field_id,
std::make_unique<dumpers::NodalField<Real>>(
this->lumped_boundary_masters.getArray()));
} else {
NTNBaseContact::addDumpFieldToDumper(dumper_name, field_id);
}
/*
#undef ADD_FIELD
*/
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.hh
index 5c14da23b..c87d4c38f 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_contact.hh
@@ -1,167 +1,167 @@
/**
* @file ntn_contact.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue Sep 29 2020
*
* @brief contact for node to node discretization
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AST_NTN_CONTACT_HH_
#define AST_NTN_CONTACT_HH_
/* -------------------------------------------------------------------------- */
// simtools
#include "ntn_base_contact.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
class NTNContact : public NTNBaseContact {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NTNContact(SolidMechanicsModel & model, const ID & id = "contact");
~NTNContact() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// add surface pair and pair nodes according to the surface normal
void addSurfacePair(const ID & slave, const ID & master,
- UInt surface_normal_dir);
+ Int surface_normal_dir);
/// fills the pairs vector with interface node pairs (*,0)=slaves,
/// (*,1)=masters
static void pairInterfaceNodes(const ElementGroup & slave_boundary,
const ElementGroup & master_boundary,
- UInt surface_normal_dir, const Mesh & mesh,
- Array<UInt> & pairs);
+ Int surface_normal_dir, const Mesh & mesh,
+ Array<Idx> & pairs);
// add node pairs from a list with pairs(*,0)=slaves and pairs(*,1)=masters
- void addNodePairs(const Array<UInt> & pairs);
+ void addNodePairs(const Array<Idx> & pairs);
/// add node pair
- void addSplitNode(UInt slave, UInt master) override;
+ void addSplitNode(Idx slave, Idx master) override;
/// update (compute the normals on the master nodes)
void updateNormals() override;
/// update the lumped boundary B matrix
void updateLumpedBoundary() override;
/// update the impedance matrix
void updateImpedance() override;
/// impose the normal contact force
void applyContactPressure() override;
/// dump restart file
void dumpRestart(const std::string & file_name) const override;
/// read restart file
void readRestart(const std::string & file_name) override;
/// compute the normal gap
void computeNormalGap(Array<Real> & gap) const override {
this->computeRelativeNormalField(this->model.getCurrentPosition(), gap);
};
/// compute relative normal field (only value that has to be multiplied with
/// the normal)
/// relative to master nodes
void
computeRelativeNormalField(const Array<Real> & field,
Array<Real> & rel_normal_field) const override;
/// compute relative tangential field (complet array)
/// relative to master nodes
void
computeRelativeTangentialField(const Array<Real> & field,
Array<Real> & rel_tang_field) const override;
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override;
protected:
/// synchronize arrays
void syncArrays(SyncChoice sync_choice) override;
/* ------------------------------------------------------------------------ */
/* Dumpable */
/* ------------------------------------------------------------------------ */
public:
void addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) override;
// virtual void addDumpFieldVector(const std::string & field_id);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(Masters, masters, const SynchronizedArray<UInt> &)
+ AKANTU_GET_MACRO(Masters, masters, const SynchronizedArray<Idx> &)
AKANTU_GET_MACRO(LumpedBoundaryMasters, lumped_boundary_masters,
const SynchronizedArray<Real> &)
/// get interface node pairs (*,0) are slaves, (*,1) are masters
- void getNodePairs(Array<UInt> & pairs) const;
+ void getNodePairs(Array<Idx> & pairs) const;
/// get index of node in either slaves or masters array
/// if node is in neither of them, return -1
- Int getNodeIndex(UInt node) const override;
+ Idx getNodeIndex(Idx node) const override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// array of master nodes
- SynchronizedArray<UInt> masters;
+ SynchronizedArray<Idx> masters;
/// lumped boundary of master nodes
SynchronizedArray<Real> lumped_boundary_masters;
// element list for dump and lumped_boundary
- ElementTypeMapArray<UInt> master_elements;
+ ElementTypeMapArray<Idx> master_elements;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
//#include "ntn_contact_inline_impl.hh"
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const NTNContact & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#endif /* AST_NTN_CONTACT_HH_ */
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_friction_tmpl.hh b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_friction_tmpl.hh
index 473799932..3d5016080 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_friction_tmpl.hh
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntn_friction_tmpl.hh
@@ -1,99 +1,94 @@
/**
* @file ntn_friction_tmpl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Wed Oct 17 2018
*
* @brief base class for ntn and ntrf friction (template functions
* implementation)
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "ntn_contact.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <template <class> class FrictionLaw, class Regularisation>
NTNFriction<FrictionLaw, Regularisation>::NTNFriction(NTNBaseContact & contact,
const ID & id)
: FrictionLaw<Regularisation>(contact, id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <template <class> class FrictionLaw, class Regularisation>
void NTNFriction<FrictionLaw, Regularisation>::applyFrictionTraction() {
AKANTU_DEBUG_IN();
auto & ntn_contact = dynamic_cast<NTNContact &>(this->contact);
- SolidMechanicsModel & model = ntn_contact.getModel();
- Array<Real> & residual = model.getInternalForce();
- UInt dim = model.getSpatialDimension();
+ auto & model = ntn_contact.getModel();
+ auto & residual = model.getInternalForce();
+ auto dim = model.getSpatialDimension();
- const SynchronizedArray<UInt> & masters = ntn_contact.getMasters();
- const SynchronizedArray<UInt> & slaves = ntn_contact.getSlaves();
- const SynchronizedArray<Real> & l_boundary_slaves =
- ntn_contact.getLumpedBoundarySlaves();
- const SynchronizedArray<Real> & l_boundary_masters =
- ntn_contact.getLumpedBoundaryMasters();
+ const auto & masters = ntn_contact.getMasters();
+ const auto & slaves = ntn_contact.getSlaves();
+ const auto & l_boundary_slaves = ntn_contact.getLumpedBoundarySlaves();
+ const auto & l_boundary_masters = ntn_contact.getLumpedBoundaryMasters();
- UInt nb_contact_nodes = ntn_contact.getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
- UInt master = masters(n);
- UInt slave = slaves(n);
+ Int nb_contact_nodes = ntn_contact.getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
+ auto master = masters(n);
+ auto slave = slaves(n);
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
residual(master, d) +=
l_boundary_masters(n) * this->friction_traction(n, d);
residual(slave, d) -=
l_boundary_slaves(n) * this->friction_traction(n, d);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <template <class> class FrictionLaw, class Regularisation>
void NTNFriction<FrictionLaw, Regularisation>::printself(std::ostream & stream,
int indent) const {
AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(AKANTU_INDENT, indent);
stream << space << "NTNFriction [" << std::endl;
FrictionLaw<Regularisation>::printself(stream, ++indent);
stream << space << "]" << std::endl;
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntrf_contact.cc b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntrf_contact.cc
index 6c6e9c106..87c089452 100644
--- a/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntrf_contact.cc
+++ b/extra_packages/traction-at-split-node-contact/src/ntn_contact/ntrf_contact.cc
@@ -1,322 +1,269 @@
/**
* @file ntrf_contact.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Mar 16 2018
* @date last modification: Tue May 21 2019
*
* @brief contact for node to rigid flat interface
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
// simtools
#include "ntrf_contact.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
NTRFContact::NTRFContact(SolidMechanicsModel & model, const ID & id)
: NTNBaseContact(model, id), reference_point(model.getSpatialDimension()),
normal(model.getSpatialDimension()) {
AKANTU_DEBUG_IN();
is_ntn_contact = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::setReferencePoint(Real x, Real y, Real z) {
AKANTU_DEBUG_IN();
Real coord[3];
coord[0] = x;
coord[1] = y;
coord[2] = z;
- UInt dim = this->model.getSpatialDimension();
- for (UInt d = 0; d < dim; ++d) {
+ Int dim = this->model.getSpatialDimension();
+ for (Int d = 0; d < dim; ++d) {
this->reference_point(d) = coord[d];
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::setNormal(Real x, Real y, Real z) {
AKANTU_DEBUG_IN();
- UInt dim = this->model.getSpatialDimension();
+ Int dim = this->model.getSpatialDimension();
Real coord[3];
coord[0] = x;
coord[1] = y;
coord[2] = z;
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
this->normal(d) = coord[d];
}
this->normal.normalize();
this->updateNormals();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::addSurface(const ID & surf) {
AKANTU_DEBUG_IN();
const Mesh & mesh_ref = this->model.getMesh();
try {
const ElementGroup & boundary = mesh_ref.getElementGroup(surf);
this->contact_surfaces.insert(&boundary);
// find slave nodes
for (auto && node : boundary.getNodeGroup().getNodes()) {
if (not mesh_ref.isPeriodicSlave(node)) {
this->addSplitNode(node);
}
}
} catch (debug::Exception & e) {
AKANTU_DEBUG_INFO("NTRFContact addSurface did not found subboundary "
<< surf
<< " and ignored it. Other procs might have it :)");
}
// synchronize with depending nodes
findBoundaryElements(this->slaves.getArray(), this->slave_elements);
updateInternalData();
syncArrays(_added);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::addNodes(Array<UInt> & nodes) {
AKANTU_DEBUG_IN();
UInt nb_nodes = nodes.size();
UInt nb_compo = nodes.getNbComponent();
for (UInt n = 0; n < nb_nodes; ++n) {
for (UInt c = 0; c < nb_compo; ++c) {
this->addSplitNode(nodes(n, c));
}
}
// synchronize with depending nodes
findBoundaryElements(this->slaves.getArray(), this->slave_elements);
updateInternalData();
syncArrays(_added);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::updateNormals() {
AKANTU_DEBUG_IN();
// normal is the same for all slaves
this->normals.set(this->normal);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::updateImpedance() {
AKANTU_DEBUG_IN();
- UInt nb_contact_nodes = getNbContactNodes();
+ auto nb_contact_nodes = getNbContactNodes();
Real delta_t = this->model.getTimeStep();
AKANTU_DEBUG_ASSERT(delta_t != NAN,
"Time step is NAN. Have you set it already?");
const Array<Real> & mass = this->model.getMass();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
- UInt slave = this->slaves(n);
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
+ auto slave = this->slaves(n);
Real imp = this->lumped_boundary_slaves(n) / mass(slave);
imp = 2 / delta_t / imp;
this->impedance(n) = imp;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::computeRelativeTangentialField(
const Array<Real> & field, Array<Real> & rel_tang_field) const {
AKANTU_DEBUG_IN();
// resize arrays to zero
rel_tang_field.resize(0);
- UInt dim = this->model.getSpatialDimension();
+ auto dim = this->model.getSpatialDimension();
- Array<Real>::const_iterator<Vector<Real>> it_field = field.begin(dim);
- Array<Real>::const_iterator<Vector<Real>> it_normal =
- this->normals.getArray().begin(dim);
+ auto it_field = field.begin(dim);
+ auto it_normal = this->normals.getArray().begin(dim);
Vector<Real> rfv(dim);
Vector<Real> np_rfv(dim);
- UInt nb_contact_nodes = this->slaves.size();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->slaves.size();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// nodes
- UInt node = this->slaves(n);
+ auto node = this->slaves(n);
// relative field vector
rfv = it_field[node];
- ;
// normal projection of relative field
- const Vector<Real> & normal_v = it_normal[n];
- np_rfv = normal_v;
- np_rfv *= rfv.dot(normal_v);
+ np_rfv = it_normal[n] * rfv.dot(it_normal[n]);
// subtract normal projection from relative field to get the tangential
// projection
rfv -= np_rfv;
rel_tang_field.push_back(rfv);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::computeNormalGap(Array<Real> & gap) const {
AKANTU_DEBUG_IN();
gap.resize(0);
- UInt dim = this->model.getSpatialDimension();
+ Int dim = this->model.getSpatialDimension();
- Array<Real>::const_iterator<Vector<Real>> it_cur_pos =
- this->model.getCurrentPosition().begin(dim);
- Array<Real>::const_iterator<Vector<Real>> it_normal =
- this->normals.getArray().begin(dim);
+ auto it_cur_pos = this->model.getCurrentPosition().begin(dim);
+ auto it_normal = this->normals.getArray().begin(dim);
Vector<Real> gap_v(dim);
- UInt nb_contact_nodes = this->getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ Int nb_contact_nodes = this->getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// nodes
- UInt node = this->slaves(n);
+ auto node = this->slaves(n);
// gap vector
- gap_v = it_cur_pos[node];
- gap_v -= this->reference_point;
+ gap_v = it_cur_pos[node] - this->reference_point;
// length of normal projection of gap vector
- const Vector<Real> & normal_v = it_normal[n];
- gap.push_back(gap_v.dot(normal_v));
+ gap.push_back(gap_v.dot(it_normal[n]));
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::computeRelativeNormalField(
const Array<Real> & field, Array<Real> & rel_normal_field) const {
- AKANTU_DEBUG_IN();
-
// resize arrays to zero
rel_normal_field.resize(0);
- UInt dim = this->model.getSpatialDimension();
+ auto dim = this->model.getSpatialDimension();
- Array<Real>::const_iterator<Vector<Real>> it_field = field.begin(dim);
- Array<Real>::const_iterator<Vector<Real>> it_normal =
- this->normals.getArray().begin(dim);
+ auto it_field = field.begin(dim);
+ auto it_normal = this->normals.getArray().begin(dim);
- UInt nb_contact_nodes = this->getNbContactNodes();
- for (UInt n = 0; n < nb_contact_nodes; ++n) {
+ auto nb_contact_nodes = this->getNbContactNodes();
+ for (Int n = 0; n < nb_contact_nodes; ++n) {
// nodes
- UInt node = this->slaves(n);
-
- const Vector<Real> & field_v = it_field[node];
- const Vector<Real> & normal_v = it_normal[n];
+ auto node = this->slaves(n);
- rel_normal_field.push_back(field_v.dot(normal_v));
+ rel_normal_field.push_back(it_field[node].dot(it_normal[n]));
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::printself(std::ostream & stream, int indent) const {
- AKANTU_DEBUG_IN();
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(AKANTU_INDENT, indent);
stream << space << "NTRFContact [" << std::endl;
NTNBaseContact::printself(stream, indent);
stream << space << "]" << std::endl;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NTRFContact::addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) {
- AKANTU_DEBUG_IN();
-
- /*
- const Array<UInt> & nodal_filter = this->slaves.getArray();
-
-#define ADD_FIELD(field_id, field, type) \
- internalAddDumpFieldToDumper(dumper_name, \
- field_id, \
- new DumperIOHelper::NodalField< type, true, \
- Array<type>, \
- Array<UInt> >(field, 0, 0, &nodal_filter))
- */
-
- /*
- if(field_id == "displacement") {
- ADD_FIELD(field_id, this->model.getDisplacement(), Real);
- }
- else if(field_id == "contact_pressure") {
- internalAddDumpFieldToDumper(dumper_name,
- field_id,
- new
- DumperIOHelper::NodalField<Real>(this->contact_pressure.getArray()));
- }
- else {*/
NTNBaseContact::addDumpFieldToDumper(dumper_name, field_id);
- //}
-
- /*
-#undef ADD_FIELD
- */
-
- AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/packages/blas.cmake b/packages/blas.cmake
deleted file mode 100644
index 591058bf2..000000000
--- a/packages/blas.cmake
+++ /dev/null
@@ -1,75 +0,0 @@
-#===============================================================================
-# @file blas.cmake
-#
-# @author Nicolas Richart <nicolas.richart@epfl.ch>
-#
-# @date creation: Tue Oct 16 2012
-# @date last modification: Thu May 11 2017
-#
-# @brief package description for blas support
-#
-#
-# @section LICENSE
-#
-# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
-# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
-#
-# Akantu is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option) any
-# later version.
-#
-# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with Akantu. If not, see <http://www.gnu.org/licenses/>.
-#
-#===============================================================================
-
-
-package_declare(BLAS EXTERNAL
- DESCRIPTION "Use BLAS for arithmetic operations"
- EXTRA_PACKAGE_OPTIONS LANGUAGE Fortran)
-
-set(_default_blas $ENV{BLA_VENDOR})
-if(NOT _default_blas)
- set(_default_blas All)
-endif()
-
-set(AKANTU_USE_BLAS_VENDOR "${_default_blas}" CACHE STRING "Version of blas to use")
-mark_as_advanced(AKANTU_USE_BLAS_VENDOR)
-set_property(CACHE AKANTU_USE_BLAS_VENDOR PROPERTY STRINGS
- All
- ACML
- ACML_GPU
- ACML_MP
- ATLAS
- Apple
- CXML
- DXML
- Generic
- Goto
- IBMESSL
- Intel
- Intel10_32
- Intel10_64lp
- Intel10_64lp_seq
- NAS
- OpenBLAS
- PhiPACK
- SCSL
- SGIMATH
- SunPerf
- )
-
-set(ENV{BLA_VENDOR} ${AKANTU_USE_BLAS_VENDOR})
-
-if(BLAS_mkl_core_LIBRARY)
- set(AKANTU_USE_BLAS_MKL CACHE INTERNAL "" FORCE)
-endif()
-
-package_set_package_system_dependency(BLAS deb libblas3)
-package_set_package_system_dependency(BLAS deb-src libblas3)
diff --git a/packages/cohesive_element.cmake b/packages/cohesive_element.cmake
index 38c92873a..fbc6b6448 100644
--- a/packages/cohesive_element.cmake
+++ b/packages/cohesive_element.cmake
@@ -1,116 +1,87 @@
#===============================================================================
# @file cohesive_element.cmake
#
# @author Mauro Corrado <mauro.corrado@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
# @author Marco Vocialta <marco.vocialta@epfl.ch>
#
# @date creation: Tue Oct 16 2012
# @date last modification: Thu Mar 11 2021
#
# @brief package description for cohesive elements
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
package_declare(cohesive_element
DESCRIPTION "Use cohesive_element package of Akantu"
DEPENDS lapack solid_mechanics)
package_declare_sources(cohesive_element
fe_engine/cohesive_element.hh
fe_engine/fe_engine_template_cohesive.cc
fe_engine/shape_cohesive.hh
fe_engine/shape_cohesive_inline_impl.hh
mesh_utils/cohesive_element_inserter.cc
mesh_utils/cohesive_element_inserter.hh
mesh_utils/cohesive_element_inserter_inline_impl.hh
mesh_utils/cohesive_element_inserter_parallel.cc
mesh_utils/cohesive_element_inserter_helper.cc
mesh_utils/cohesive_element_inserter_helper.hh
model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc
model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh
model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc
model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc
model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh
model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.hh
model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh
model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc
)
-
-package_declare_elements(cohesive_element
- ELEMENT_TYPES
- _cohesive_1d_2
- _cohesive_2d_4
- _cohesive_2d_6
- _cohesive_3d_12
- _cohesive_3d_16
- _cohesive_3d_6
- _cohesive_3d_8
- KIND cohesive
- GEOMETRICAL_TYPES
- _gt_cohesive_1d_2
- _gt_cohesive_2d_4
- _gt_cohesive_2d_6
- _gt_cohesive_3d_12
- _gt_cohesive_3d_16
- _gt_cohesive_3d_6
- _gt_cohesive_3d_8
- FE_ENGINE_LISTS
- compute_normals_on_integration_points
- contains
- get_shapes_derivatives
- gradient_on_integration_points
- interpolate_on_integration_points
- inverse_map
- lagrange_base
- )
-
package_declare_material_infos(cohesive_element
LIST AKANTU_COHESIVE_MATERIAL_LIST
INCLUDE material_cohesive_includes.hh
)
diff --git a/packages/core.cmake b/packages/core.cmake
index 10660f10e..3369118a3 100644
--- a/packages/core.cmake
+++ b/packages/core.cmake
@@ -1,433 +1,367 @@
#===============================================================================
# @file core.cmake
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Mon Nov 21 2011
# @date last modification: Fri Apr 09 2021
#
# @brief package description for core
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
package_declare(core NOT_OPTIONAL
DESCRIPTION "core package for Akantu"
- FEATURES_PUBLIC cxx_strong_enums cxx_defaulted_functions
- cxx_deleted_functions cxx_auto_type cxx_decltype_auto
- FEATURES_PRIVATE cxx_lambdas cxx_nullptr cxx_range_for
- cxx_delegating_constructors
- DEPENDS INTERFACE akantu_iterators Boost
+ DEPENDS INTERFACE akantu_iterators Boost Eigen3
)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
- package_set_compile_flags(core "-Wall -Wextra -pedantic")
+ package_set_compile_flags(core CXX "-Wall -Wextra -pedantic")
else()
- package_set_compile_flags(core "-Wall")
+ package_set_compile_flags(core CXX "-Wall")
endif()
+if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0.0)
+ package_set_compile_flags(core CXX "-Wall -Wextra -pedantic -Wno-attributes")
+endif()
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9))
+ package_set_compile_flags(core CXX "-Wall -Wextra -pedantic -Wno-undefined-var-template -Wno-unknown-attributes")
+endif()
+
+
package_declare_sources(core
common/aka_array.cc
common/aka_array.hh
common/aka_array_filter.hh
common/aka_array_tmpl.hh
common/aka_array_printer.hh
common/aka_bbox.hh
- common/aka_blas_lapack.hh
common/aka_circular_array.hh
common/aka_circular_array_inline_impl.hh
common/aka_common.cc
common/aka_common.hh
common/aka_common_inline_impl.hh
+ common/aka_constexpr_map.hh
common/aka_csr.hh
+ common/aka_element_classes_info.hh
common/aka_element_classes_info_inline_impl.hh
common/aka_enum_macros.hh
common/aka_error.cc
common/aka_error.hh
common/aka_event_handler_manager.hh
common/aka_extern.cc
common/aka_factory.hh
common/aka_fwd.hh
common/aka_grid_dynamic.hh
common/aka_math.cc
common/aka_math.hh
common/aka_math_tmpl.hh
common/aka_named_argument.hh
common/aka_random_generator.hh
common/aka_safe_enum.hh
+ common/aka_tensor.hh
common/aka_types.hh
+ common/aka_types_eigen_matrix_plugin.hh
+ common/aka_types_eigen_matrix_base_plugin.hh
+ common/aka_types_eigen_plain_object_base_plugin.hh
+ common/aka_view_iterators.hh
common/aka_voigthelper.hh
common/aka_voigthelper_tmpl.hh
common/aka_voigthelper.cc
common/aka_warning.hh
common/aka_warning_restore.hh
fe_engine/element_class.hh
fe_engine/element_class_helper.hh
fe_engine/element_class_tmpl.hh
fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh
fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh
fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh
fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh
fe_engine/element_classes/element_class_point_1_inline_impl.hh
fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh
fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh
fe_engine/element_classes/element_class_segment_2_inline_impl.hh
fe_engine/element_classes/element_class_segment_3_inline_impl.hh
fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh
fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh
fe_engine/element_classes/element_class_triangle_3_inline_impl.hh
fe_engine/element_classes/element_class_triangle_6_inline_impl.hh
fe_engine/element_type_conversion.hh
fe_engine/fe_engine.cc
fe_engine/fe_engine.hh
fe_engine/fe_engine_inline_impl.hh
fe_engine/fe_engine_template.hh
fe_engine/fe_engine_template_tmpl_field.hh
fe_engine/fe_engine_template_tmpl.hh
fe_engine/geometrical_element_property.hh
fe_engine/geometrical_element_property.cc
fe_engine/gauss_integration.cc
fe_engine/gauss_integration_tmpl.hh
fe_engine/integrator.hh
fe_engine/integrator_gauss.hh
fe_engine/integrator_gauss_inline_impl.hh
fe_engine/interpolation_element_tmpl.hh
fe_engine/integration_point.hh
fe_engine/shape_functions.hh
fe_engine/shape_functions.cc
fe_engine/shape_functions_inline_impl.hh
fe_engine/shape_lagrange_base.cc
fe_engine/shape_lagrange_base.hh
fe_engine/shape_lagrange_base_inline_impl.hh
fe_engine/shape_lagrange.hh
fe_engine/shape_lagrange_inline_impl.hh
fe_engine/element.hh
io/dumper/dumpable.hh
io/dumper/dumpable.cc
io/dumper/dumpable_dummy.hh
io/dumper/dumpable_inline_impl.hh
io/dumper/dumper_field.hh
io/dumper/dumper_material_padders.hh
io/dumper/dumper_filtered_connectivity.hh
io/dumper/dumper_element_partition.hh
io/mesh_io.cc
io/mesh_io.hh
io/mesh_io/mesh_io_diana.cc
io/mesh_io/mesh_io_diana.hh
io/mesh_io/mesh_io_msh.cc
io/mesh_io/mesh_io_msh.hh
#io/model_io.cc
#io/model_io.hh
io/parser/algebraic_parser.hh
io/parser/input_file_parser.hh
io/parser/parsable.cc
io/parser/parsable.hh
io/parser/parser.cc
io/parser/parser_real.cc
io/parser/parser_random.cc
io/parser/parser_types.cc
io/parser/parser_input_files.cc
io/parser/parser.hh
io/parser/parser_tmpl.hh
io/parser/parser_grammar_tmpl.hh
io/parser/cppargparse/cppargparse.hh
io/parser/cppargparse/cppargparse.cc
io/parser/cppargparse/cppargparse_tmpl.hh
io/parser/parameter_registry.cc
io/parser/parameter_registry.hh
io/parser/parameter_registry_tmpl.hh
mesh/element_group.cc
mesh/element_group.hh
mesh/element_group_inline_impl.hh
mesh/element_type_map.cc
mesh/element_type_map.hh
mesh/element_type_map_tmpl.hh
mesh/element_type_map_filter.hh
mesh/group_manager.cc
mesh/group_manager.hh
mesh/group_manager_inline_impl.hh
mesh/mesh.cc
mesh/mesh.hh
mesh/mesh_periodic.cc
mesh/mesh_accessor.hh
mesh/mesh_events.hh
mesh/mesh_filter.hh
mesh/mesh_global_data_updater.hh
mesh/mesh_data.cc
mesh/mesh_data.hh
mesh/mesh_data_tmpl.hh
mesh/mesh_inline_impl.hh
mesh/node_group.cc
mesh/node_group.hh
mesh/node_group_inline_impl.hh
mesh/mesh_iterators.hh
mesh_utils/mesh_partition.cc
mesh_utils/mesh_partition.hh
mesh_utils/mesh_partition/mesh_partition_mesh_data.cc
mesh_utils/mesh_partition/mesh_partition_mesh_data.hh
mesh_utils/mesh_partition/mesh_partition_scotch.hh
mesh_utils/mesh_utils_pbc.cc
mesh_utils/mesh_utils.cc
mesh_utils/mesh_utils.hh
mesh_utils/mesh_utils_distribution.cc
mesh_utils/mesh_utils_distribution.hh
mesh_utils/mesh_utils.hh
mesh_utils/mesh_utils_inline_impl.hh
mesh_utils/global_ids_updater.hh
mesh_utils/global_ids_updater.cc
mesh_utils/global_ids_updater_inline_impl.hh
model/common/boundary_condition/boundary_condition.hh
model/common/boundary_condition/boundary_condition_functor.hh
model/common/boundary_condition/boundary_condition_functor_inline_impl.hh
model/common/boundary_condition/boundary_condition_tmpl.hh
model/common/non_local_toolbox/neighborhood_base.hh
model/common/non_local_toolbox/neighborhood_base.cc
model/common/non_local_toolbox/neighborhood_base_inline_impl.hh
model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh
model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc
model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh
model/common/non_local_toolbox/non_local_manager.hh
model/common/non_local_toolbox/non_local_manager.cc
model/common/non_local_toolbox/non_local_manager_inline_impl.hh
model/common/non_local_toolbox/non_local_manager_callback.hh
model/common/non_local_toolbox/non_local_neighborhood_base.hh
model/common/non_local_toolbox/non_local_neighborhood_base.cc
model/common/non_local_toolbox/non_local_neighborhood.hh
model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh
model/common/non_local_toolbox/non_local_neighborhood_inline_impl.hh
model/common/non_local_toolbox/base_weight_function.hh
+ model/common/non_local_toolbox/base_weight_function.cc
model/common/non_local_toolbox/base_weight_function_inline_impl.hh
model/common/model_solver.cc
model/common/model_solver.hh
model/common/solver_callback.hh
model/common/solver_callback.cc
model/common/dof_manager/dof_manager.cc
model/common/dof_manager/dof_manager.hh
model/common/dof_manager/dof_manager_default.cc
model/common/dof_manager/dof_manager_default.hh
model/common/dof_manager/dof_manager_default_inline_impl.hh
model/common/dof_manager/dof_manager_inline_impl.hh
model/common/non_linear_solver/non_linear_solver.cc
model/common/non_linear_solver/non_linear_solver.hh
model/common/non_linear_solver/non_linear_solver_default.hh
model/common/non_linear_solver/non_linear_solver_lumped.cc
model/common/non_linear_solver/non_linear_solver_lumped.hh
model/common/time_step_solvers/time_step_solver.hh
model/common/time_step_solvers/time_step_solver.cc
model/common/time_step_solvers/time_step_solver_default.cc
model/common/time_step_solvers/time_step_solver_default.hh
model/common/time_step_solvers/time_step_solver_default_explicit.hh
model/common/integration_scheme/generalized_trapezoidal.cc
model/common/integration_scheme/generalized_trapezoidal.hh
model/common/integration_scheme/integration_scheme.cc
model/common/integration_scheme/integration_scheme.hh
model/common/integration_scheme/integration_scheme_1st_order.cc
model/common/integration_scheme/integration_scheme_1st_order.hh
model/common/integration_scheme/integration_scheme_2nd_order.cc
model/common/integration_scheme/integration_scheme_2nd_order.hh
model/common/integration_scheme/newmark-beta.cc
model/common/integration_scheme/newmark-beta.hh
model/common/integration_scheme/pseudo_time.cc
model/common/integration_scheme/pseudo_time.hh
model/model.cc
model/model.hh
model/model_inline_impl.hh
model/model_options.hh
solver/solver_vector.hh
solver/solver_vector_default.hh
solver/solver_vector_default_tmpl.hh
solver/solver_vector_distributed.cc
solver/solver_vector_distributed.hh
solver/sparse_matrix.cc
solver/sparse_matrix.hh
solver/sparse_matrix_aij.cc
solver/sparse_matrix_aij.hh
solver/sparse_matrix_aij_inline_impl.hh
solver/sparse_matrix_inline_impl.hh
solver/sparse_solver.cc
solver/sparse_solver.hh
solver/sparse_solver_inline_impl.hh
solver/terms_to_assemble.hh
synchronizer/communication_buffer_inline_impl.hh
synchronizer/communication_descriptor.hh
synchronizer/communication_descriptor_tmpl.hh
synchronizer/communication_request.hh
synchronizer/communication_tag.hh
synchronizer/communications.hh
synchronizer/communications_tmpl.hh
synchronizer/communicator.cc
synchronizer/communicator.hh
synchronizer/communicator_dummy_inline_impl.hh
synchronizer/communicator_event_handler.hh
synchronizer/communicator_inline_impl.hh
synchronizer/data_accessor.cc
synchronizer/data_accessor.hh
synchronizer/dof_synchronizer.cc
synchronizer/dof_synchronizer.hh
synchronizer/dof_synchronizer_inline_impl.hh
synchronizer/element_info_per_processor.cc
synchronizer/element_info_per_processor.hh
synchronizer/element_info_per_processor_tmpl.hh
synchronizer/element_synchronizer.cc
synchronizer/element_synchronizer.hh
synchronizer/facet_synchronizer.cc
synchronizer/facet_synchronizer.hh
synchronizer/facet_synchronizer_inline_impl.hh
synchronizer/grid_synchronizer.cc
synchronizer/grid_synchronizer.hh
synchronizer/grid_synchronizer_tmpl.hh
synchronizer/master_element_info_per_processor.cc
synchronizer/node_info_per_processor.cc
synchronizer/node_info_per_processor.hh
synchronizer/node_synchronizer.cc
synchronizer/node_synchronizer.hh
synchronizer/node_synchronizer_inline_impl.hh
synchronizer/periodic_node_synchronizer.cc
synchronizer/periodic_node_synchronizer.hh
synchronizer/slave_element_info_per_processor.cc
synchronizer/synchronizer.cc
synchronizer/synchronizer.hh
synchronizer/synchronizer_impl.hh
synchronizer/synchronizer_impl_tmpl.hh
synchronizer/synchronizer_registry.cc
synchronizer/synchronizer_registry.hh
synchronizer/synchronizer_tmpl.hh
synchronizer/communication_buffer.hh
)
set(AKANTU_SPIRIT_SOURCES
io/mesh_io/mesh_io_abaqus.cc
io/parser/parser_real.cc
io/parser/parser_random.cc
io/parser/parser_types.cc
io/parser/parser_input_files.cc
PARENT_SCOPE
)
-package_declare_elements(core
- ELEMENT_TYPES
- _point_1
- _segment_2
- _segment_3
- _triangle_3
- _triangle_6
- _quadrangle_4
- _quadrangle_8
- _tetrahedron_4
- _tetrahedron_10
- _pentahedron_6
- _pentahedron_15
- _hexahedron_8
- _hexahedron_20
- KIND regular
- GEOMETRICAL_TYPES
- _gt_point
- _gt_segment_2
- _gt_segment_3
- _gt_triangle_3
- _gt_triangle_6
- _gt_quadrangle_4
- _gt_quadrangle_8
- _gt_tetrahedron_4
- _gt_tetrahedron_10
- _gt_hexahedron_8
- _gt_hexahedron_20
- _gt_pentahedron_6
- _gt_pentahedron_15
- INTERPOLATION_TYPES
- _itp_lagrange_point_1
- _itp_lagrange_segment_2
- _itp_lagrange_segment_3
- _itp_lagrange_triangle_3
- _itp_lagrange_triangle_6
- _itp_lagrange_quadrangle_4
- _itp_serendip_quadrangle_8
- _itp_lagrange_tetrahedron_4
- _itp_lagrange_tetrahedron_10
- _itp_lagrange_hexahedron_8
- _itp_serendip_hexahedron_20
- _itp_lagrange_pentahedron_6
- _itp_lagrange_pentahedron_15
- GEOMETRICAL_SHAPES
- _gst_point
- _gst_triangle
- _gst_square
- _gst_prism
- GAUSS_INTEGRATION_TYPES
- _git_point
- _git_segment
- _git_triangle
- _git_tetrahedron
- _git_pentahedron
- INTERPOLATION_KIND _itk_lagrangian
- FE_ENGINE_LISTS
- gradient_on_integration_points
- interpolate_on_integration_points
- interpolate
- compute_normals_on_integration_points
- inverse_map
- contains
- compute_shapes
- compute_shapes_derivatives
- get_N
- compute_dnds
- compute_d2nds2
- compute_jmat
- get_shapes_derivatives
- lagrange_base
- assemble_fields
- )
-
find_program(READLINK_COMMAND readlink)
find_program(ADDR2LINE_COMMAND addr2line)
find_program(PATCH_COMMAND patch)
mark_as_advanced(READLINK_COMMAND)
mark_as_advanced(ADDR2LINE_COMMAND)
package_declare_extra_files_to_package(core
SOURCES
common/aka_element_classes_info.hh.in
common/aka_config.hh.in
)
-
-if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9))
- package_set_compile_flags(core CXX "-Wno-undefined-var-template")
-endif()
diff --git a/packages/damage_non_local.cmake b/packages/damage_non_local.cmake
index 72b453f15..0b9b38300 100644
--- a/packages/damage_non_local.cmake
+++ b/packages/damage_non_local.cmake
@@ -1,61 +1,64 @@
#===============================================================================
# @file damage_non_local.cmake
#
# @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Fri Jun 15 2012
# @date last modification: Thu Dec 17 2020
#
# @brief package description for non-local materials
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
package_declare(damage_non_local
DESCRIPTION "Package for Non-local damage constitutives laws Akantu"
DEPENDS lapack)
package_declare_sources(damage_non_local
model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh
+ model/solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh
model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.cc
model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.hh
model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh
+ model/solid_mechanics/materials/weight_functions/damaged_weight_function.cc
model/solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh
model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh
+ model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.cc
model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh
model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh
model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh
model/solid_mechanics/materials/weight_functions/stress_based_weight_function.hh
model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc
model/solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.hh
)
package_declare_material_infos(damage_non_local
LIST AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST
INCLUDE material_non_local_includes.hh
)
diff --git a/packages/debug_tools.cmake b/packages/debug_tools.cmake
new file mode 100644
index 000000000..a88678439
--- /dev/null
+++ b/packages/debug_tools.cmake
@@ -0,0 +1,9 @@
+package_declare(debug_tools
+ DESCRIPTION "Tools to help debug"
+ BOOST_COMPONENTS graph
+ )
+
+package_declare_sources(debug_tools
+ mesh_utils/boost_graph_converter.hh
+ mesh_utils/boost_graph_converter.cc
+ )
diff --git a/packages/eigen.cmake b/packages/eigen.cmake
new file mode 100644
index 000000000..002e0d71c
--- /dev/null
+++ b/packages/eigen.cmake
@@ -0,0 +1,16 @@
+package_declare(Eigen3 EXTERNAL
+ DESCRIPTION "Add Eigen3 dependency to akantu"
+ SYSTEM AUTO third-party/cmake/eigen3.cmake
+ EXTRA_PACKAGE_OPTIONS ARGS 3.4
+ )
+
+mark_as_advanced(Eigen3_DIR)
+package_add_third_party_script_variable(Eigen3
+ EIGEN3_VERSION "3.4.0")
+package_add_third_party_script_variable(Eigen3
+ EIGEN3_GIT "https://gitlab.com/libeigen/eigen.git")
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU"
+ AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.0.0")
+ package_set_compile_flags(Eigen3 CXX "-Wno-array-bounds -Wno-use-after-free -Wno-stringop-overread")
+endif()
diff --git a/packages/heat_transfer.cmake b/packages/heat_transfer.cmake
index 5c7eaef2e..154a017a1 100644
--- a/packages/heat_transfer.cmake
+++ b/packages/heat_transfer.cmake
@@ -1,41 +1,40 @@
#===============================================================================
# @file heat_transfer.cmake
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Mon Nov 21 2011
# @date last modification: Mon Mar 30 2015
#
# @brief package description for heat transfer
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
package_declare(heat_transfer
DESCRIPTION "Use Heat Transfer package of Akantu")
package_declare_sources(heat_transfer
model/heat_transfer/heat_transfer_model.cc
model/heat_transfer/heat_transfer_model.hh
- model/heat_transfer/heat_transfer_model_inline_impl.hh
)
diff --git a/packages/lapack.cmake b/packages/lapack.cmake
deleted file mode 100644
index 1a7f9387f..000000000
--- a/packages/lapack.cmake
+++ /dev/null
@@ -1,39 +0,0 @@
-#===============================================================================
-# @file lapack.cmake
-#
-# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
-# @author Nicolas Richart <nicolas.richart@epfl.ch>
-#
-# @date creation: Fri Oct 19 2012
-# @date last modification: Mon Mar 30 2015
-#
-# @brief package description for lapack support
-#
-#
-# @section LICENSE
-#
-# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
-# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
-#
-# Akantu is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option) any
-# later version.
-#
-# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with Akantu. If not, see <http://www.gnu.org/licenses/>.
-#
-#===============================================================================
-
-
-package_declare(LAPACK EXTERNAL
- DESCRIPTION "Use LAPACK for arithmetic operations"
- EXTRA_PACKAGE_OPTIONS LANGUAGE Fortran)
-
-package_set_package_system_dependency(LAPACK deb liblapack3)
-package_set_package_system_dependency(LAPACK deb-src liblapack-dev)
diff --git a/packages/mpi.cmake b/packages/mpi.cmake
index 01b67f901..73ea479fd 100644
--- a/packages/mpi.cmake
+++ b/packages/mpi.cmake
@@ -1,160 +1,160 @@
#===============================================================================
# @file mpi.cmake
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Mon Nov 21 2011
# @date last modification: Fri Dec 13 2019
#
# @brief package description for mpi
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
-set(MPI_CXX_SKIP_MPICXX TRUE CACHE BOOL "" FORCE)
+set(MPI_CXX_SKIP_MPICXX TRUE CACHE BOOL "NO CXX support for mpi" FORCE)
package_declare(MPI EXTERNAL
DESCRIPTION "Add MPI support in akantu"
EXTRA_PACKAGE_OPTIONS PREFIX MPI_C MPI ARGS "COMPONENTS;C"
)
package_declare_sources(MPI
synchronizer/mpi_communicator_data.hh
synchronizer/communicator_mpi_inline_impl.hh
)
function(_add_to_mpi_preflags flag)
if(NOT MPIEXEC_PREFLAGS MATCHES "${flag}")
string(STRIP "${flag} ${MPIEXEC_PREFLAGS}" _preflags)
set(MPIEXEC_PREFLAGS "${_preflags}" CACHE STRING "" FORCE)
endif()
endfunction()
function(add_extra_mpi_options)
unset(MPI_ID CACHE)
package_get_include_dir(MPI _include_dir)
foreach(_inc_dir ${_include_dir})
if(EXISTS "${_inc_dir}/mpi.h")
if(NOT MPI_ID)
file(STRINGS "${_inc_dir}/mpi.h" _mpi_version REGEX "#define MPI_(SUB)?VERSION .*")
foreach(_ver ${_mpi_version})
string(REGEX MATCH "MPI_(VERSION|SUBVERSION) *([0-9]+)" _tmp "${_ver}")
set(_mpi_${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
endforeach()
set(MPI_STD_VERSION "${_mpi_VERSION}.${_mpi_SUBVERSION}" CACHE INTERNAL "")
endif()
if(NOT MPI_ID)
# check if openmpi
file(STRINGS "${_inc_dir}/mpi.h" _ompi_version REGEX "#define OMPI_.*_VERSION .*")
if(_ompi_version)
set(MPI_ID "OpenMPI" CACHE INTERNAL "")
foreach(_version ${_ompi_version})
string(REGEX MATCH "OMPI_(.*)_VERSION (.*)" _tmp "${_version}")
if(_tmp)
set(MPI_VERSION_${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
endif()
endforeach()
set(MPI_ID_VERSION "${MPI_VERSION_MAJOR}.${MPI_VERSION_MINOR}.${MPI_VERSION_RELEASE}"
CACHE INTERNAL "")
_add_to_mpi_preflags("--oversubscribe")
if(AKANTU_RUN_IN_DOCKER)
_add_to_mpi_preflags("--allow-run-as-root")
endif()
endif()
endif()
if(NOT MPI_ID)
# check if intelmpi
file(STRINGS "${_inc_dir}/mpi.h" _impi_version REGEX "#define I_MPI_VERSION .*")
if(_impi_version)
set(MPI_ID "IntelMPI" CACHE INTERNAL "")
string(REGEX MATCH "I_MPI_VERSION \"(.*)\"" _tmp "${_impi_version}")
if(_tmp)
set(MPI_ID_VERSION "${CMAKE_MATCH_1}" CACHE INTERNAL "")
endif()
endif()
endif()
if(NOT MPI_ID)
# check if mvapich2
file(STRINGS "${_inc_dir}/mpi.h" _mvapich2_version REGEX "#define MVAPICH2_VERSION .*")
if(_mvapich2_version)
set(MPI_ID "MPVAPICH2" CACHE INTERNAL "")
string(REGEX MATCH "MVAPICH2_VERSION \"(.*)\"" _tmp "${_mvapich2_version}")
if(_tmp)
set(MPI_ID_VERSION "${CMAKE_MATCH_1}" CACHE INTERNAL "")
endif()
endif()
endif()
if(NOT MPI_ID)
# check if mpich (mpich as to be checked after all the mpi that derives from it)
file(STRINGS "${_inc_dir}/mpi.h" _mpich_version REGEX "#define MPICH_VERSION .*")
if(_mpich_version)
set(MPI_ID "MPICH" CACHE INTERNAL "")
string(REGEX MATCH "I_MPI_VERSION \"(.*)\"" _tmp "${_mpich_version}")
if(_tmp)
set(MPI_ID_VERSION "${CMAKE_MATCH_1}" CACHE INTERNAL "")
endif()
endif()
endif()
endif()
endforeach()
if(MPI_ID STREQUAL "IntelMPI" OR
MPI_ID STREQUAL "MPICH" OR
MPI_ID STREQUAL "MVAPICH2")
set(_flags "-DMPICH_IGNORE_CXX_SEEK")
elseif(MPI_ID STREQUAL "OpenMPI")
set(_flags "-DOMPI_SKIP_MPICXX")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set( _flags "${_flags} -Wno-literal-suffix")
endif()
endif()
include(FindPackageMessage)
if(MPI_FOUND)
find_package_message(MPI "MPI ID: ${MPI_ID} ${MPI_ID_VERSION} (MPI standard ${MPI_STD_VERSION})" "${MPI_STD_VERSION}")
endif()
set(MPI_EXTRA_COMPILE_FLAGS "${_flags}" CACHE STRING "Extra flags for MPI" FORCE)
mark_as_advanced(MPI_EXTRA_COMPILE_FLAGS)
#package_get_source_files(MPI _srcs _pub _priv)
#list(APPEND _srcs "common/aka_error.cc")
#set_property(SOURCE ${_srcs} PROPERTY COMPILE_FLAGS "${_flags}")
package_set_compile_flags(MPI CXX ${_flags})
endfunction()
package_on_enabled_script(MPI
"
add_extra_mpi_options()
mask_package_options(MPI)
"
)
package_set_package_system_dependency(MPI deb mpi-default-bin)
package_set_package_system_dependency(MPI deb-src mpi-default-dev)
diff --git a/packages/pybind11.cmake b/packages/pybind11.cmake
deleted file mode 100644
index 5931ac988..000000000
--- a/packages/pybind11.cmake
+++ /dev/null
@@ -1,47 +0,0 @@
-#===============================================================================
-# @file pybind11.cmake
-#
-# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
-# @author Nicolas Richart <nicolas.richart@epfl.ch>
-#
-# @date creation: Fri Dec 22 2017
-# @date last modification: Wed Dec 04 2019
-#
-# @brief package description for the pybind11 binding
-#
-#
-# @section LICENSE
-#
-# Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
-# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
-#
-# Akantu is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option) any
-# later version.
-#
-# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with Akantu. If not, see <http://www.gnu.org/licenses/>.
-#
-#===============================================================================
-
-
-set(PYBIND11_PYTHON_VERSION ${AKANTU_PREFERRED_PYTHON_VERSION} CACHE INTERNAL "")
-
-package_declare(pybind11 EXTERNAL
- EXTRA_PACKAGE_OPTIONS ARGS "2.4.2;CONFIG" LINK_LIBRARIES pybind11::embed PREFIX pybind11
- DESCRIPTION "Akantu's pybind11 interface"
- SYSTEM AUTO third-party/cmake/pybind11.cmake
- DEPENDS python
- EXCLUDE_FROM_ALL
- )
-
-package_add_third_party_script_variable(pybind11
- PYBIND11_VERSION "v2.4.2")
-package_add_third_party_script_variable(pybind11
- PYBIND11_GIT "https://github.com/pybind/pybind11.git")
diff --git a/packages/python.cmake b/packages/python.cmake
deleted file mode 100644
index 4d78889a4..000000000
--- a/packages/python.cmake
+++ /dev/null
@@ -1,80 +0,0 @@
-#===============================================================================
-# @file python_interpreter.cmake
-#
-# @author Nicolas Richart <nicolas.richart@epfl.ch>
-#
-# @date creation: Wed Oct 31 2018
-# @date last modification: Wed Oct 31 2018
-#
-# @brief packages description for the external dependency to the python interpreted
-#
-#
-# @section LICENSE
-#
-# Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
-# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
-#
-# Akantu is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option) any
-# later version.
-#
-# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with Akantu. If not, see <http://www.gnu.org/licenses/>.
-#
-#===============================================================================
-if(FALSE AND CMAKE_VERSION VERSION_GREATER 3.21)
- if (PYTHON_EXECUTABLE)
- get_filename_component(_python_bin_dir "${PYTHON_EXECUTABLE}" DIRECTORY)
- get_filename_component(_python_root_dir "${_python_bin_dir}" DIRECTORY)
- set(Python_ROOT_DIR "${_python_bin_dir}" CACHE INTERNAL "")
- message(STATUS "Python hint: ${Python_ROOT_DIR}")
- endif()
-
-
- package_declare(Python EXTERNAL DESCRIPTION "Akantu's python dependency"
- EXTRA_PACKAGE_OPTIONS ARGS
- COMPONENTS Interpreter;Development
- )
-
- package_on_enabled_script(Python
- "set(Python_SITELIB \${Python_SITELIB} CACHE INTERNAL \"\")
-set(Python_EXECUTABLE \${Python_EXECUTABLE} CACHE INTERNAL \"\")
-set(Python_INCLUDE_DIRS \${Python_INCLUDE_DIRS} CACHE INTERNAL \"\")
-set(Python_VERSION_MAJOR \${Python_VERSION_MAJOR} CACHE INTERNAL \"\")
-set(Python_VERSION_MINOR \${Python_VERSION_MINOR} CACHE INTERNAL \"\")
-")
-else()
- if (PYTHON_LIBRARY MATCHES "\\.a$")
- set(PYTHON_LIBRARY NOTFOUND CACHE INTERNAL "")
- endif()
- package_declare(Python ADVANCED META DESCRIPTION "Akantu's python dependency"
- DEPENDS PythonLibsNew PythonInterp
- )
-
- package_declare(PythonInterp EXTERNAL
- DESCRIPTION "Akantu's python Interpreter"
- )
-
- package_on_enabled_script(PythonInterp
- "set(Python_EXECUTABLE \${PYTHON_EXECUTABLE} CACHE INTERNAL \"\")")
-
- package_declare(PythonLibsNew EXTERNAL
- DESCRIPTION "Akantu's python Development"
- )
-
- package_on_enabled_script(PythonLibsNew
- "set(Python_INCLUDE_DIRS \${PYTHON_INCLUDE_DIRS} CACHE INTERNAL \"\")
-set(Python_VERSION_MAJOR \${PYTHON_VERSION_MAJOR} CACHE INTERNAL \"\")
-set(Python_VERSION_MINOR \${PYTHON_VERSION_MINOR} CACHE INTERNAL \"\")
-")
-
- # package_declare(Numpy EXTERNAL
- # DESCRIPTION "Akantu's python Numpy"
- # )
-endif()
diff --git a/packages/structural_mechanics.cmake b/packages/structural_mechanics.cmake
index 7c908c2f3..223d1c425 100644
--- a/packages/structural_mechanics.cmake
+++ b/packages/structural_mechanics.cmake
@@ -1,79 +1,57 @@
#===============================================================================
# @file structural_mechanics.cmake
#
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Mon Nov 21 2011
# @date last modification: Mon Dec 02 2019
#
# @brief package description for structural mechanics
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
package_declare(structural_mechanics
DESCRIPTION "Use Structural mechanics model package of Akantu"
DEPENDS implicit)
package_declare_sources(structural_mechanics
fe_engine/element_class_structural.hh
fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.hh
fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.hh
fe_engine/element_classes/element_class_hermite_inline_impl.hh
fe_engine/fe_engine_template_tmpl_struct.hh
fe_engine/shape_structural.cc
fe_engine/shape_structural.hh
fe_engine/shape_structural_inline_impl.hh
io/mesh_io/mesh_io_msh_struct.cc
io/mesh_io/mesh_io_msh_struct.hh
model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh
model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh
model/structural_mechanics/structural_elements/structural_element_kirchhoff_shell.hh
model/structural_mechanics/structural_mechanics_model.cc
model/structural_mechanics/structural_mechanics_model.hh
model/structural_mechanics/structural_mechanics_model_boundary.cc
model/structural_mechanics/structural_mechanics_model_inline_impl.hh
model/structural_mechanics/structural_mechanics_model_mass.cc
)
-package_declare_elements(structural_mechanics
- ELEMENT_TYPES
- _bernoulli_beam_2
- _bernoulli_beam_3
- _discrete_kirchhoff_triangle_18
- KIND structural
- INTERPOLATION_TYPES
- _itp_hermite_2
- _itp_bernoulli_beam_2
- _itp_bernoulli_beam_3
- _itp_discrete_kirchhoff_triangle_6
- _itp_discrete_kirchhoff_triangle_18
- INTERPOLATION_KIND
- _itk_structural
- FE_ENGINE_LISTS
- gradient_on_integration_points
- interpolate_on_integration_points
- compute_shapes
- compute_shapes_derivatives
- get_shapes_derivatives
- assemble_fields
- )
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 5cd6a4456..824892831 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -1,145 +1,148 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Fri Dec 12 2014
# @date last modification: Fri May 07 2021
#
# @brief CMake file for the python wrapping of akantu
#
#
# @section LICENSE
#
# Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
-set(PYBIND11_PYTHON_VERSION ${AKANTU_PREFERRED_PYTHON_VERSION} CACHE INTERNAL "")
-
if(NOT SKBUILD)
package_get_all_include_directories(
AKANTU_LIBRARY_INCLUDE_DIRS
)
package_get_all_external_informations(
PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR
INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR
LIBRARIES AKANTU_EXTERNAL_LIBRARIES
)
endif()
set(PYAKANTU_SRCS
py_aka_common.cc
py_aka_error.cc
py_akantu.cc
py_boundary_conditions.cc
py_dof_manager.cc
py_fe_engine.cc
py_group_manager.cc
py_integration_scheme.cc
py_mesh.cc
py_model.cc
py_parser.cc
py_solver.cc
py_dumpable.cc
)
package_is_activated(solid_mechanics _is_activated)
if (_is_activated)
list(APPEND PYAKANTU_SRCS
py_solid_mechanics_model.cc
py_material.cc
py_material_selector.cc
)
endif()
package_is_activated(cohesive_element _is_activated)
if (_is_activated)
list(APPEND PYAKANTU_SRCS
py_solid_mechanics_model_cohesive.cc
py_fragment_manager.cc
)
endif()
package_is_activated(heat_transfer _is_activated)
if (_is_activated)
list(APPEND PYAKANTU_SRCS
py_heat_transfer_model.cc
)
endif()
package_is_activated(contact_mechanics _is_activated)
if(_is_activated)
list(APPEND PYAKANTU_SRCS
py_contact_mechanics_model.cc
py_model_couplers.cc
)
endif()
package_is_activated(phase_field _is_activated)
if (_is_activated)
list(APPEND PYAKANTU_SRCS
py_phase_field_model.cc
)
endif()
package_is_activated(structural_mechanics _is_activated)
if (_is_activated)
list(APPEND PYAKANTU_SRCS
py_structural_mechanics_model.cc
)
endif()
pybind11_add_module(py11_akantu ${PYAKANTU_SRCS})
# to avoid compilation warnings from pybind11
target_include_directories(py11_akantu
SYSTEM BEFORE
PRIVATE ${PYBIND11_INCLUDE_DIR}
PRIVATE ${pybind11_INCLUDE_DIR}
PRIVATE ${Python_INCLUDE_DIRS})
target_link_libraries(py11_akantu PUBLIC akantu)
set_target_properties(py11_akantu PROPERTIES
DEBUG_POSTFIX ""
LIBRARY_OUTPUT_DIRECTORY akantu)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ target_compile_options(py11_akantu PUBLIC -fsized-deallocation)
+endif()
+
+
file(COPY akantu DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
if(NOT Python_MAJOR)
set(Python_VERSION_MAJOR ${PYTHON_VERSION_MAJOR})
set(Python_VERSION_MINOR ${PYTHON_VERSION_MINOR})
endif()
if(NOT SKBUILD)
set(_python_install_dir
${CMAKE_INSTALL_LIBDIR}/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages/akantu)
else()
set(_python_install_dir python/akantu)
endif()
install(TARGETS py11_akantu
LIBRARY DESTINATION ${_python_install_dir})
if(NOT SKBUILD)
install(DIRECTORY akantu
DESTINATION ${_python_install_dir}
FILES_MATCHING PATTERN "*.py")
endif()
diff --git a/python/akantu/__init__.py b/python/akantu/__init__.py
index ad5fc2748..1beea099d 100644
--- a/python/akantu/__init__.py
+++ b/python/akantu/__init__.py
@@ -1,73 +1,72 @@
-
""" __init__.py: akantu python module"""
__author__ = "Guillaume Anciaux and Nicolas Richart"
__credits__ = [
"Guillaume Anciaux <guillaume.anciaux@epfl.ch>",
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import warnings as _aka_warn
import scipy.sparse as _aka_sparse
import numpy as _aka_np
from . import py11_akantu as _py11_akantu
private_keys = set(dir(_py11_akantu)) - set(dir())
for k in private_keys:
globals()[k] = getattr(_py11_akantu, k)
if _py11_akantu.has_mpi():
try:
from mpi4py import MPI # noqa: F401
except Exception:
pass
def initialize(*args, **kwargs):
raise RuntimeError("No need to call initialize,"
" use parseInput to read an input file")
def finalize(*args, **kwargs):
_aka_warn.warn("No need to call finalize", DeprecationWarning)
class AkantuSparseMatrix (_aka_sparse.coo_matrix):
def __init__(self, aka_sparse):
self.aka_sparse = aka_sparse
matrix_type = self.aka_sparse.getMatrixType()
sz = self.aka_sparse.size()
row = self.aka_sparse.getIRN()[:, 0] - 1
col = self.aka_sparse.getJCN()[:, 0] - 1
data = self.aka_sparse.getA()[:, 0]
row = row.copy()
col = col.copy()
data = data.copy()
if matrix_type == _py11_akantu._symmetric:
non_diags = (row != col)
row_sup = col[non_diags]
col_sup = row[non_diags]
data_sup = data[non_diags]
col = _aka_np.concatenate((col, col_sup))
row = _aka_np.concatenate((row, row_sup))
data = _aka_np.concatenate((data, data_sup))
_aka_sparse.coo_matrix.__init__(
self, (data, (row, col)), shape=(sz, sz), dtype=data.dtype)
FromStress = _py11_akantu.FromHigherDim
FromTraction = _py11_akantu.FromSameDim
_py11_akantu.__initialize()
__version__ = _py11_akantu.getVersion()
diff --git a/python/py_aka_array.hh b/python/py_aka_array.hh
index 6da82a07c..5a005c74f 100644
--- a/python/py_aka_array.hh
+++ b/python/py_aka_array.hh
@@ -1,282 +1,287 @@
/**
* @file py_aka_array.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Oct 31 2018
* @date last modification: Fri Nov 13 2020
*
* @brief pybind11 interface to akantu Arrays
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <aka_array.hh>
/* -------------------------------------------------------------------------- */
+#include <pybind11/eigen.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
namespace _aka = akantu;
namespace akantu {
namespace detail {
template <class T> struct is_array_type : public std::false_type {};
- template <class T> struct is_array_type<Vector<T>> : public std::true_type {};
- template <class T> struct is_array_type<Matrix<T>> : public std::true_type {};
+ // template <class T> struct is_array_type<Vector<T>> : public std::true_type
+ // {}; template <class T> struct is_array_type<Matrix<T>> : public
+ // std::true_type {};
template <class T> struct is_array_type<Array<T>> : public std::true_type {};
/* ------------------------------------------------------------------------ */
template <typename T> class ArrayProxy : public Array<T> {
protected:
// deallocate the memory
void deallocate() final {}
// allocate the memory
- void allocate(UInt /*size*/, UInt /*nb_component*/) final {}
+ void allocate(Int /*size*/, Int /*nb_component*/)
+ final {}
// allocate and initialize the memory
- void allocate(UInt /*size*/, UInt /*nb_component*/,
+ void allocate(Int /*size*/, Int /*nb_component*/,
const T & /*value*/) final {}
public:
- ArrayProxy(T * data, UInt size, UInt nb_component) {
+ ArrayProxy(T * data, Int size, Int nb_component) {
this->values = data;
this->size_ = size;
this->nb_component = nb_component;
}
ArrayProxy(const Array<T> & src) {
- this->values = src.storage();
+ this->values = src.data();
this->size_ = src.size();
this->nb_component = src.getNbComponent();
}
~ArrayProxy() override { this->values = nullptr; }
- void resize(UInt size, const T & /*val*/) final {
+ void resize(Int size, const T & /*val*/) final {
if (size != this->size()) {
AKANTU_EXCEPTION("cannot resize a temporary array");
}
// std::fill(this->begin(), this->end(), val);
}
- void resize(UInt new_size) final {
+ void resize(Int new_size) final {
if (new_size != this->size()) {
AKANTU_EXCEPTION("cannot resize a temporary array");
}
}
- void reserve(UInt /*size*/, UInt /*new_size*/) final {
- AKANTU_EXCEPTION("cannot resize a temporary array");
- }
+ void reserve(Int /*size*/, Int /*new_size*/)
+ final { AKANTU_EXCEPTION("cannot resize a temporary array"); }
};
/* ------------------------------------------------------------------------ */
template <typename T> struct ProxyType {};
- template <typename T> struct ProxyType<Vector<T>> { using type = Vector<T>; };
- template <typename T> struct ProxyType<Matrix<T>> { using type = Matrix<T>; };
+ // template <typename T> struct ProxyType<Vector<T>> { using type = Vector<T>;
+ // }; template <typename T> struct ProxyType<Matrix<T>> { using type =
+ // Matrix<T>; };
template <typename T> struct ProxyType<Array<T>> {
using type = ArrayProxy<T>;
};
template <typename array> using ProxyType_t = typename ProxyType<array>::type;
} // namespace detail
} // namespace akantu
namespace pybind11 {
namespace detail {
template <typename T> struct AkaArrayType {
using type =
array_t<typename T::value_type, array::c_style | array::forcecast>;
};
- template <typename T> struct AkaArrayType<_aka::Vector<T>> {
- using type = array_t<T, array::f_style | array::forcecast>;
- };
- template <typename T> struct AkaArrayType<_aka::Matrix<T>> {
- using type = array_t<T, array::f_style | array::forcecast>;
- };
+ // template <typename T> struct AkaArrayType<_aka::Vector<T>> {
+ // using type = array_t<T, array::f_style | array::forcecast>;
+ // };
+ // template <typename T> struct AkaArrayType<_aka::Matrix<T>> {
+ // using type = array_t<T, array::f_style | array::forcecast>;
+ // };
template <typename U> using array_type_t = typename AkaArrayType<U>::type;
/* ------------------------------------------------------------------------ */
- template <typename T>
- decltype(auto) create_proxy(array_type_t<_aka::Vector<T>> & ref,
- const _aka::Vector<T> * /*unused*/) {
- return std::make_unique<_aka::detail::ProxyType_t<_aka::Vector<T>>>(
- ref.mutable_data(), ref.shape(0));
- }
-
- template <typename T>
- decltype(auto) create_proxy(array_type_t<_aka::Matrix<T>> & ref,
- const _aka::Matrix<T> * /*unused*/) {
- return std::make_unique<_aka::detail::ProxyType_t<_aka::Matrix<T>>>(
- ref.mutable_data(), ref.shape(0), ref.shape(1));
- }
+ // template <typename T>
+ // decltype(auto) create_proxy(array_type_t<_aka::Vector<T>> & ref,
+ // const _aka::Vector<T> * /*unused*/) {
+ // return std::make_unique<_aka::detail::ProxyType_t<_aka::Vector<T>>>(
+ // ref.mutable_data(), ref.shape(0));
+ // }
+
+ // template <typename T>
+ // decltype(auto) create_proxy(array_type_t<_aka::Matrix<T>> & ref,
+ // const _aka::Matrix<T> * /*unused*/) {
+ // return std::make_unique<_aka::detail::ProxyType_t<_aka::Matrix<T>>>(
+ // ref.mutable_data(), ref.shape(0), ref.shape(1));
+ // }
template <typename T>
decltype(auto) create_proxy(array_type_t<_aka::Array<T>> & ref,
const _aka::Array<T> * /*unused*/) {
return std::make_unique<_aka::detail::ProxyType_t<_aka::Array<T>>>(
ref.mutable_data(), ref.shape(0), ref.shape(1));
}
/* ------------------------------------------------------------------------ */
template <typename T>
py::handle aka_array_cast(const _aka::Array<T> & src,
py::handle base = handle(), bool writeable = true) {
array a;
a = array_type_t<_aka::Array<T>>({src.size(), src.getNbComponent()},
- src.storage(), base);
-
- if (not writeable) {
- array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
- }
-
- return a.release();
- }
-
- template <typename T>
- py::handle aka_array_cast(const _aka::Vector<T> & src,
- py::handle base = handle(), bool writeable = true) {
- array a;
- a = array_type_t<_aka::Vector<T>>({src.size()}, src.storage(), base);
+ src.data(), base);
if (not writeable) {
array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
}
return a.release();
}
- template <typename T>
- py::handle aka_array_cast(const _aka::Matrix<T> & src,
- py::handle base = handle(), bool writeable = true) {
- array a;
- a = array_type_t<_aka::Matrix<T>>({src.size(0), src.size(1)}, src.storage(),
- base);
-
- if (not writeable) {
- array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
- }
-
- return a.release();
- }
+ // template <typename T>
+ // py::handle aka_array_cast(const _aka::Vector<T> & src,
+ // py::handle base = handle(), bool writeable =
+ // true) {
+ // array a;
+ // a = array_type_t<_aka::Vector<T>>({src.size()}, src.data(), base);
+
+ // if (not writeable) {
+ // array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
+ // }
+
+ // return a.release();
+ // }
+
+ // template <typename T>
+ // py::handle aka_array_cast(const _aka::Matrix<T> & src,
+ // py::handle base = handle(), bool writeable =
+ // true) {
+ // array a;
+ // a = array_type_t<_aka::Matrix<T>>({src.size(0), src.size(1)}, src.data(),
+ // base);
+
+ // if (not writeable) {
+ // array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
+ // }
+
+ // return a.release();
+ // }
/* ------------------------------------------------------------------------ */
template <typename AkaArrayType>
class type_caster<
AkaArrayType,
std::enable_if_t<_aka::detail::is_array_type<AkaArrayType>::value>> {
protected:
using T = typename AkaArrayType::value_type;
using type = AkaArrayType;
using proxy_type = _aka::detail::ProxyType_t<AkaArrayType>;
using array_type = array_type_t<AkaArrayType>;
std::unique_ptr<proxy_type> array_proxy;
array_type_t<AkaArrayType> copy_or_ref;
public:
#if PYBIND11_VERSION_MAJOR >= 2 && PYBIND11_VERSION_MINOR >= 3
static constexpr auto name = _("AkaArray");
operator type &&() && { return std::move(*array_proxy); }
template <typename T_>
using cast_op_type = pybind11::detail::movable_cast_op_type<T_>;
#else
static PYBIND11_DESCR name() { return type_descr(_("AkaArray")); };
template <typename _T>
using cast_op_type = pybind11::detail::cast_op_type<_T>;
#endif
operator type *() { return array_proxy.get(); }
operator type &() { return *array_proxy; }
/**
* Conversion part 1 (Python->C++)
*/
bool load(handle src, bool convert) {
bool need_copy = not isinstance<array_type>(src);
auto && fits = [&](auto && aref) {
auto && dims = aref.ndim();
if (dims < 1 || dims > 2) {
return false;
}
return true;
};
if (not need_copy) {
// We don't need a converting copy, but we also need to check whether
// the strides are compatible with the Ref's stride requirements
auto aref = py::cast<array_type>(src);
if (not fits(aref)) {
return false;
}
copy_or_ref = std::move(aref);
} else {
if (not convert) {
return false;
}
auto copy = array_type::ensure(src);
if (not copy) {
return false;
}
if (not fits(copy)) {
return false;
}
copy_or_ref = std::move(array_type::ensure(src));
loader_life_support::add_patient(copy_or_ref);
}
AkaArrayType * dispatch = nullptr; // cannot detect T from the expression
array_proxy = create_proxy(copy_or_ref, dispatch);
return true;
}
/**
* Conversion part 2 (C++ -> Python)
*/
static handle cast(const type & src, return_value_policy policy,
handle parent) {
switch (policy) {
case return_value_policy::copy:
return aka_array_cast<T>(src);
case return_value_policy::reference_internal:
return aka_array_cast<T>(src, parent);
case return_value_policy::reference:
case return_value_policy::automatic:
case return_value_policy::automatic_reference:
return aka_array_cast<T>(src, none());
default:
pybind11_fail("Invalid return_value_policy for ArrayProxy type");
}
}
};
} // namespace detail
} // namespace pybind11
diff --git a/python/py_boundary_conditions.cc b/python/py_boundary_conditions.cc
index c33b40949..89c656062 100644
--- a/python/py_boundary_conditions.cc
+++ b/python/py_boundary_conditions.cc
@@ -1,129 +1,129 @@
/**
* @file py_boundary_conditions.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date creation: Mon Dec 02 2019
* @date last modification: Mon Dec 02 2019
*
* @brief pybind11 interface to boundary conditions
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_boundary_conditions.hh"
#include "py_aka_array.hh"
#include "py_akantu_pybind11_compatibility.hh"
/* -------------------------------------------------------------------------- */
#include <boundary_condition_functor.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
namespace akantu {
namespace {
/* ------------------------------------------------------------------------ */
template <typename daughter = BC::Dirichlet::DirichletFunctor>
class PyDirichletFunctor : public daughter {
public:
/* Inherit the constructors */
using daughter::daughter;
/* Trampoline (need one for each virtual function) */
- void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal,
+ void operator()(Int node, Vector<bool> & flags, Vector<Real> & primal,
const Vector<Real> & coord) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_NAME(void, daughter, "__call__", operator(), node,
flags, primal, coord);
}
};
/* ------------------------------------------------------------------------ */
template <typename daughter = BC::Neumann::NeumannFunctor>
class PyNeumannFunctor : public daughter {
public:
/* Inherit the constructors */
using daughter::daughter;
/* Trampoline (need one for each virtual function) */
void operator()(const IntegrationPoint & quad_point, Vector<Real> & dual,
const Vector<Real> & coord,
const Vector<Real> & normals) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE_NAME(void, daughter, "__call__", operator(),
quad_point, dual, coord, normals);
}
};
/* ------------------------------------------------------------------------ */
template <typename Functor, typename Constructor>
decltype(auto) register_dirichlet_functor(py::module mod, const char * name,
Constructor && cons) {
py::class_<Functor, PyDirichletFunctor<Functor>,
BC::Dirichlet::DirichletFunctor>(mod, name)
.def(cons);
}
/* ------------------------------------------------------------------------ */
template <typename Functor, typename Constructor>
decltype(auto) register_neumann_functor(py::module mod, const char * name,
Constructor && cons) {
py::class_<Functor, PyNeumannFunctor<Functor>, BC::Neumann::NeumannFunctor>(
mod, name)
.def(cons);
}
} // namespace
/* -------------------------------------------------------------------------- */
void register_boundary_conditions(py::module & mod) {
py::class_<BC::Functor>(mod, "BCFunctor");
py::class_<BC::Dirichlet::DirichletFunctor, PyDirichletFunctor<>,
BC::Functor>(mod, "DirichletFunctor")
.def(py::init())
.def(py::init<SpatialDirection>());
py::class_<BC::Neumann::NeumannFunctor, PyNeumannFunctor<>, BC::Functor>(
mod, "NeumannFunctor")
.def(py::init());
register_dirichlet_functor<BC::Dirichlet::FixedValue>(
mod, "FixedValue", py::init<Real, BC::Axis>());
register_dirichlet_functor<BC::Dirichlet::IncrementValue>(
mod, "IncrementValue", py::init<Real, BC::Axis>());
register_dirichlet_functor<BC::Dirichlet::Increment>(
mod, "Increment", py::init<Vector<Real> &>());
register_neumann_functor<BC::Neumann::FromHigherDim>(
mod, "FromHigherDim", py::init<Matrix<Real> &>());
register_neumann_functor<BC::Neumann::FromSameDim>(
mod, "FromSameDim", py::init<Vector<Real> &>());
register_neumann_functor<BC::Neumann::FreeBoundary>(mod, "FreeBoundary",
py::init());
}
} // namespace akantu
diff --git a/python/py_contact_mechanics_model.cc b/python/py_contact_mechanics_model.cc
index 22bf46504..f1880b278 100644
--- a/python/py_contact_mechanics_model.cc
+++ b/python/py_contact_mechanics_model.cc
@@ -1,211 +1,236 @@
/**
* @file py_contact_mechanics_model.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Jun 20 2019
* @date last modification: Thu Jun 24 2021
*
* @brief Contact mechanics python binding
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <contact_detector.hh>
#include <contact_element.hh>
#include <contact_mechanics_model.hh>
#include <geometry_utils.hh>
#include <mesh_events.hh>
#include <parsable.hh>
#include <surface_selector.hh>
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
#define def_function_nocopy(func_name) \
def( \
#func_name, \
[](ContactMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
}, \
py::return_value_policy::reference)
#define def_function(func_name) \
def(#func_name, [](ContactMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
})
namespace {
class ContactElementsView {
public:
ContactElementsView(const Array<ContactElement> & contact_elements)
: contact_elements(contact_elements) {}
auto begin() const { return contact_elements.begin(); }
auto end() const { return contact_elements.end(); }
auto size() const { return contact_elements.size(); }
auto operator[](size_t i) const { return contact_elements(i); }
auto contains(const ContactElement & contact_element) const {
return std::find(contact_elements.begin(), contact_elements.end(),
contact_element) != contact_elements.end();
}
private:
const Array<ContactElement> & contact_elements;
};
} // namespace
/* -------------------------------------------------------------------------- */
void register_contact_mechanics_model(py::module & mod) {
py::class_<ContactDetector>(mod, "ContactDetector",
py::multiple_inheritance())
.def(py::init<Mesh &, const ID &>(), py::arg("mesh"),
py::arg("id") = "contact_detector")
.def(py::init<Mesh &, Array<Real>, const ID &>(), py::arg("mesh"),
py::arg("positions"), py::arg("id") = "contact_detector")
.def("setSurfaceSelector", &ContactDetector::setSurfaceSelector);
py::class_<SurfaceSelector, std::shared_ptr<SurfaceSelector>>(
mod, "SurfaceSelector", py::multiple_inheritance())
.def(py::init<Mesh &>(), py::arg("mesh"));
py::class_<PhysicalSurfaceSelector, SurfaceSelector,
std::shared_ptr<PhysicalSurfaceSelector>>(
mod, "PhysicalSurfaceSelector")
.def(py::init<Mesh &>(), py::arg("mesh"));
py::class_<CohesiveSurfaceSelector, SurfaceSelector,
std::shared_ptr<CohesiveSurfaceSelector>>(
mod, "CohesiveSurfaceSelector")
.def(py::init<Mesh &>(), py::arg("mesh"));
py::class_<AllSurfaceSelector, SurfaceSelector,
std::shared_ptr<AllSurfaceSelector>>(mod, "AllSurfaceSelector")
.def(py::init<Mesh &>(), py::arg("mesh"));
py::class_<ContactMechanicsModelOptions>(mod, "ContactMechanicsModelOptions")
.def(py::init<AnalysisMethod>(),
py::arg("analysis_method") = _explicit_contact);
/* ------------------------------------------------------------------------ */
py::class_<ContactElementsView>(mod, "ContactElementsView")
.def("__iter__",
[](const ContactElementsView & self) {
return py::make_iterator(self.begin(), self.end());
})
.def("__size__",
[](const ContactElementsView & self) { return self.size(); })
.def(
"__contains__",
[](const ContactElementsView & self, const ContactElement & element) {
return self.contains(element);
})
.def("__getitem__",
[](const ContactElementsView & self, size_t i) { return self[i]; });
/* ------------------------------------------------------------------------ */
py::class_<ContactMechanicsModel, Model>(mod, "ContactMechanicsModel",
py::multiple_inheritance())
.def(py::init<Mesh &, UInt, const ID &, std::shared_ptr<DOFManager>,
const ModelType>(),
py::arg("mesh"), py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "contact_mechanics_model",
py::arg("dof_manager") = nullptr,
py::arg("model_type") = ModelType::_contact_mechanics_model)
.def(
"initFull",
[](ContactMechanicsModel & self,
const ContactMechanicsModelOptions & options) {
self.initFull(options);
},
py::arg("options") = ContactMechanicsModelOptions())
.def(
"initFull",
[](ContactMechanicsModel & self,
const AnalysisMethod & analysis_method) {
self.initFull(_analysis_method = analysis_method);
},
py::arg("_analysis_method"))
.def_function(search)
.def_function(assembleStiffnessMatrix)
.def_function(assembleInternalForces)
.def_function_nocopy(getExternalForce)
.def_function_nocopy(getNormalForce)
.def_function_nocopy(getTangentialForce)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getGaps)
.def_function_nocopy(getNormals)
.def_function_nocopy(getNodalArea)
- .def_function_nocopy(getContactDetector)
+ .def("getContactDetector", &ContactMechanicsModel::getContactDetector,
+ py::return_value_policy::reference)
.def("getContactElements", [](ContactMechanicsModel & self) {
return ContactElementsView(self.getContactElements());
});
py::class_<ContactElement>(mod, "ContactElement")
.def(py::init<>())
.def_readwrite("master", &ContactElement::master)
.def_readwrite("slave", &ContactElement::slave)
.def("__repr__", [](ContactElement & self) {
return "{master: " + std::to_string(self.master) +
", slave: " + std::to_string(self.slave) + "}";
});
py::class_<GeometryUtils>(mod, "GeometryUtils")
.def_static(
"normal",
- py::overload_cast<const Mesh &, const Array<Real> &, const Element &,
- Vector<Real> &, bool>(&GeometryUtils::normal),
+ [](const Mesh & mesh, const Array<Real> & positions,
+ const Element & element, bool outward) {
+ auto && coords =
+ mesh.extractNodalValuesFromElement(positions, element);
+ return GeometryUtils::normal(mesh, coords, element, outward);
+ },
py::arg("mesh"), py::arg("positions"), py::arg("element"),
- py::arg("normal"), py::arg("outward") = true)
+ py::arg("outward") = true)
.def_static(
"covariantBasis",
- py::overload_cast<const Mesh &, const Array<Real> &, const Element &,
- const Vector<Real> &, Vector<Real> &,
- Matrix<Real> &>(&GeometryUtils::covariantBasis),
+ [](const Mesh & mesh, const Array<Real> & positions,
+ const Element & element, const Vector<Real> & normal,
+ Vector<Real> & natural_coord) {
+ auto && coords =
+ mesh.extractNodalValuesFromElement(positions, element);
+ return GeometryUtils::covariantBasis(coords, element, normal,
+ natural_coord);
+ },
py::arg("mesh"), py::arg("positions"), py::arg("element"),
- py::arg("normal"), py::arg("natural_projection"), py::arg("basis"))
- .def_static("curvature", &GeometryUtils::curvature)
- .def_static("contravariantBasis", &GeometryUtils::contravariantBasis,
- py::arg("covariant_basis"), py::arg("basis"))
- .def_static("realProjection",
- py::overload_cast<const Mesh &, const Array<Real> &,
- const Vector<Real> &, const Element &,
- const Vector<Real> &, Vector<Real> &>(
- &GeometryUtils::realProjection),
- py::arg("mesh"), py::arg("positions"), py::arg("slave"),
- py::arg("element"), py::arg("normal"), py::arg("projection"))
+ py::arg("normal"), py::arg("natural_projection"))
+ .def_static(
+ "curvature",
+ [](const Mesh & mesh, const Array<Real> & positions,
+ const Element & element, const Vector<Real> & natural_coord) {
+ auto && coords =
+ mesh.extractNodalValuesFromElement(positions, element);
+ return GeometryUtils::curvature(coords, element, natural_coord);
+ })
+ .def_static(
+ "contravariantBasis",
+ [](const Vector<Real> & covariant) {
+ return GeometryUtils::contravariantBasis(covariant);
+ },
+ py::arg("covariant_basis"))
+ .def_static(
+ "realProjection",
+ [](const Mesh & mesh, const Array<Real> & positions,
+ const Vector<Real> & slave, const Element & element,
+ const Vector<Real> & normal) {
+ auto && coords =
+ mesh.extractNodalValuesFromElement(positions, element);
+ return GeometryUtils::realProjection(coords, slave, normal);
+ },
+ py::arg("mesh"), py::arg("positions"), py::arg("slave"),
+ py::arg("element"), py::arg("normal"))
.def_static("isBoundaryElement", &GeometryUtils::isBoundaryElement);
}
} // namespace akantu
diff --git a/python/py_dof_manager.cc b/python/py_dof_manager.cc
index e268e7586..540882a72 100644
--- a/python/py_dof_manager.cc
+++ b/python/py_dof_manager.cc
@@ -1,216 +1,216 @@
/*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
#include "py_dof_manager.hh"
#include "py_aka_array.hh"
#include "py_akantu_pybind11_compatibility.hh"
/* -------------------------------------------------------------------------- */
#include <dof_manager.hh>
#include <non_linear_solver.hh>
#include <solver_callback.hh>
#include <time_step_solver.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace {
class PySolverCallback : public SolverCallback {
public:
using SolverCallback::SolverCallback;
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(MatrixType, SolverCallback, getMatrixType,
matrix_id);
}
/// callback to assemble a Matrix
void assembleMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(void, SolverCallback, assembleMatrix, matrix_id);
}
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(void, SolverCallback, assembleLumpedMatrix,
matrix_id);
}
/// callback to assemble the residual (rhs)
void assembleResidual() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE_PURE(void, SolverCallback, assembleResidual);
+ PYBIND11_OVERRIDE_PURE(void, SolverCallback, assembleResidual, );
}
/// callback for the predictor (in case of dynamic simulation)
void predictor() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, SolverCallback, predictor);
+ PYBIND11_OVERRIDE(void, SolverCallback, predictor, );
}
/// callback for the corrector (in case of dynamic simulation)
void corrector() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, SolverCallback, corrector);
+ PYBIND11_OVERRIDE(void, SolverCallback, corrector, );
}
void beforeSolveStep() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, SolverCallback, beforeSolveStep);
+ PYBIND11_OVERRIDE(void, SolverCallback, beforeSolveStep, );
}
void afterSolveStep(bool converged) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, SolverCallback, afterSolveStep, converged);
}
};
class PyInterceptSolverCallback : public InterceptSolverCallback {
public:
using InterceptSolverCallback::InterceptSolverCallback;
MatrixType getMatrixType(const ID & matrix_id) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(MatrixType, InterceptSolverCallback, getMatrixType,
matrix_id);
}
void assembleMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, assembleMatrix,
matrix_id);
}
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, assembleLumpedMatrix,
matrix_id);
}
void assembleResidual() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, InterceptSolverCallback, assembleResidual);
+ PYBIND11_OVERRIDE(void, InterceptSolverCallback, assembleResidual, );
}
void predictor() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, InterceptSolverCallback, predictor);
+ PYBIND11_OVERRIDE(void, InterceptSolverCallback, predictor, );
}
void corrector() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, InterceptSolverCallback, corrector);
+ PYBIND11_OVERRIDE(void, InterceptSolverCallback, corrector, );
}
void beforeSolveStep() override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, InterceptSolverCallback, beforeSolveStep);
+ PYBIND11_OVERRIDE(void, InterceptSolverCallback, beforeSolveStep, );
}
void afterSolveStep(bool converged) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, afterSolveStep,
converged);
}
};
} // namespace
/* -------------------------------------------------------------------------- */
void register_dof_manager(py::module & mod) {
py::class_<DOFManager, std::shared_ptr<DOFManager>>(mod, "DOFManager")
.def("getMatrix", &DOFManager::getMatrix,
py::return_value_policy::reference)
.def(
"getNewMatrix",
[](DOFManager & self, const std::string & name,
const std::string & matrix_to_copy_id) -> decltype(auto) {
return self.getNewMatrix(name, matrix_to_copy_id);
},
py::return_value_policy::reference)
.def(
"getResidual",
[](DOFManager & self) -> decltype(auto) {
return self.getResidual();
},
py::return_value_policy::reference)
.def("getArrayPerDOFs", &DOFManager::getArrayPerDOFs)
.def(
"hasMatrix",
[](DOFManager & self, const ID & name) -> bool {
return self.hasMatrix(name);
},
py::arg("name"))
.def("assembleToResidual", &DOFManager::assembleToResidual,
py::arg("dof_id"), py::arg("array_to_assemble"),
py::arg("scale_factor") = 1.)
.def("assembleToLumpedMatrix", &DOFManager::assembleToLumpedMatrix,
py::arg("dof_id"), py::arg("array_to_assemble"),
py::arg("lumped_mtx"), py::arg("scale_factor") = 1.)
.def("assemblePreassembledMatrix",
&DOFManager::assemblePreassembledMatrix, py::arg("matrix_id"),
py::arg("terms"))
.def("zeroResidual", &DOFManager::zeroResidual);
py::class_<NonLinearSolver, Parsable>(mod, "NonLinearSolver")
.def(
"set",
[](NonLinearSolver & self, const std::string & id, const Real & val) {
if (id == "max_iterations") {
self.set(id, int(val));
} else {
self.set(id, val);
}
})
.def("set",
[](NonLinearSolver & self, const std::string & id,
const SolveConvergenceCriteria & val) { self.set(id, val); });
py::class_<TimeStepSolver>(mod, "TimeStepSolver")
.def("getIntegrationScheme", &TimeStepSolver::getIntegrationScheme);
py::class_<SolverCallback, PySolverCallback>(mod, "SolverCallback")
.def(py::init_alias<DOFManager &>())
.def("getMatrixType", &SolverCallback::getMatrixType)
.def("assembleMatrix", &SolverCallback::assembleMatrix)
.def("assembleLumpedMatrix", &SolverCallback::assembleLumpedMatrix)
.def("assembleResidual",
[](SolverCallback & self) { self.assembleResidual(); })
.def("predictor", &SolverCallback::predictor)
.def("corrector", &SolverCallback::corrector)
.def("beforeSolveStep", &SolverCallback::beforeSolveStep)
.def("afterSolveStep", &SolverCallback::afterSolveStep)
.def_property_readonly("dof_manager", &SolverCallback::getSCDOFManager,
py::return_value_policy::reference);
py::class_<InterceptSolverCallback, SolverCallback,
PyInterceptSolverCallback>(mod, "InterceptSolverCallback")
.def(py::init_alias<SolverCallback &>());
}
} // namespace akantu
diff --git a/python/py_fe_engine.cc b/python/py_fe_engine.cc
index 11af53f0a..193388631 100644
--- a/python/py_fe_engine.cc
+++ b/python/py_fe_engine.cc
@@ -1,160 +1,147 @@
/**
* @file py_fe_engine.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 27 2019
* @date last modification: Sat Dec 12 2020
*
* @brief pybind11 interface to FEEngine
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
#include "py_aka_common.hh"
/* -------------------------------------------------------------------------- */
#include <element.hh>
#include <fe_engine.hh>
#include <integration_point.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/functional.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
void register_fe_engine(py::module & mod) {
py::class_<Element>(mod, "Element")
- .def(py::init([](ElementType type, UInt id) {
+ .def(py::init([](ElementType type, Int id) {
return new Element{type, id, _not_ghost};
}))
- .def(py::init([](ElementType type, UInt id, GhostType ghost_type) {
+ .def(py::init([](ElementType type, Int id, GhostType ghost_type) {
return new Element{type, id, ghost_type};
}))
.def("__lt__",
[](Element & self, const Element & other) { return (self < other); })
.def("__repr__", [](Element & self) { return std::to_string(self); });
mod.attr("ElementNull") = ElementNull;
py::class_<FEEngine>(mod, "FEEngine")
.def(
"getNbIntegrationPoints",
- [](FEEngine & fem, const ElementType & type,
- const GhostType & ghost_type) {
+ [](FEEngine & fem, ElementType type, GhostType ghost_type) {
return fem.getNbIntegrationPoints(type, ghost_type);
},
py::arg("type"), py::arg("ghost_type") = _not_ghost)
.def(
"gradientOnIntegrationPoints",
[](FEEngine & fem, const Array<Real> & u, Array<Real> & nablauq,
- UInt nb_degree_of_freedom, ElementType type, GhostType ghost_type,
- const Array<UInt> * filter_elements) {
- if (filter_elements == nullptr) {
- // This is due to the ArrayProxy that looses the
- // empty_filter information
- filter_elements = &empty_filter;
- }
+ const Int nb_degree_of_freedom, ElementType type,
+ GhostType ghost_type, const Array<Idx> & filter_elements) {
fem.gradientOnIntegrationPoints(u, nablauq, nb_degree_of_freedom,
- type, ghost_type, *filter_elements);
+ type, ghost_type, filter_elements);
},
py::arg("u"), py::arg("nablauq"), py::arg("nb_degree_of_freedom"),
py::arg("type"), py::arg("ghost_type") = _not_ghost,
- py::arg("filter_elements") = nullptr)
+ py::arg("filter_elements") = empty_filter)
.def(
"interpolateOnIntegrationPoints",
[](FEEngine & self, const Array<Real> & u, Array<Real> & uq,
- UInt nb_degree_of_freedom, ElementType type, GhostType ghost_type,
- const Array<UInt> * filter_elements) {
- if (filter_elements == nullptr) {
- // This is due to the ArrayProxy that looses the
- // empty_filter information
- filter_elements = &empty_filter;
- }
-
- self.interpolateOnIntegrationPoints(u, uq, nb_degree_of_freedom,
- type, ghost_type,
- *filter_elements);
+ Int nb_degree_of_freedom, ElementType type, GhostType ghost_type,
+ const Array<Idx> & filter_elements) {
+ self.interpolateOnIntegrationPoints(
+ u, uq, nb_degree_of_freedom, type, ghost_type, filter_elements);
},
py::arg("u"), py::arg("uq"), py::arg("nb_degree_of_freedom"),
py::arg("type"), py::arg("ghost_type") = _not_ghost,
- py::arg("filter_elements") = nullptr)
+ py::arg("filter_elements") = empty_filter)
.def(
"interpolateOnIntegrationPoints",
[](FEEngine & self, const Array<Real> & u,
ElementTypeMapArray<Real> & uq,
- const ElementTypeMapArray<UInt> * filter_elements) {
+ const ElementTypeMapArray<Idx> * filter_elements) {
self.interpolateOnIntegrationPoints(u, uq, filter_elements);
},
py::arg("u"), py::arg("uq"), py::arg("filter_elements") = nullptr)
.def(
"computeIntegrationPointsCoordinates",
[](FEEngine & self, ElementTypeMapArray<Real> & coordinates,
- const ElementTypeMapArray<UInt> * filter_elements)
+ const ElementTypeMapArray<Idx> * filter_elements)
-> decltype(auto) {
return self.computeIntegrationPointsCoordinates(coordinates,
filter_elements);
},
py::arg("coordinates"), py::arg("filter_elements") = nullptr)
.def(
"assembleFieldLumped",
[](FEEngine & fem,
const std::function<void(Matrix<Real> &, const Element &)> &
field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
ElementType type, GhostType ghost_type) {
fem.assembleFieldLumped(field_funct, matrix_id, dof_id, dof_manager,
type, ghost_type);
},
py::arg("field_funct"), py::arg("matrix_id"), py::arg("dof_id"),
py::arg("dof_manager"), py::arg("type"),
py::arg("ghost_type") = _not_ghost)
.def(
"assembleFieldMatrix",
[](FEEngine & fem,
const std::function<void(Matrix<Real> &, const Element &)> &
field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
ElementType type, GhostType ghost_type = _not_ghost) {
fem.assembleFieldMatrix(field_funct, matrix_id, dof_id, dof_manager,
type, ghost_type);
},
py::arg("field_funct"), py::arg("matrix_id"), py::arg("dof_id"),
py::arg("dof_manager"), py::arg("type"),
py::arg("ghost_type") = _not_ghost)
.def("getElementInradius",
[](FEEngine & self, const Element & element) {
return self.getElementInradius(element);
})
.def("getNormalsOnIntegrationPoints",
&FEEngine::getNormalsOnIntegrationPoints, py::arg("type"),
py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference);
py::class_<IntegrationPoint>(mod, "IntegrationPoint");
}
} // namespace akantu
diff --git a/python/py_group_manager.cc b/python/py_group_manager.cc
index 6e648e6a9..a5d82d771 100644
--- a/python/py_group_manager.cc
+++ b/python/py_group_manager.cc
@@ -1,186 +1,184 @@
/**
* @file py_group_manager.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Jun 16 2019
* @date last modification: Mon Dec 02 2019
*
* @brief pybind11 interface to GroupManager, ElementGroup and NodeGroup
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <element_group.hh>
#include <node_group.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
void register_group_manager(py::module & mod) {
/* ------------------------------------------------------------------------ */
py::class_<NodeGroup>(mod, "NodeGroup")
.def(
"getNodes",
[](NodeGroup & self) -> decltype(auto) { return self.getNodes(); },
py::return_value_policy::reference)
.def("__len__", &NodeGroup::size)
.def(
"__iter__",
[](const NodeGroup & self) {
return py::make_iterator(self.begin(), self.end());
},
py::keep_alive<0, 1>())
- .def("__contains__",
- [](const NodeGroup & self, UInt node) {
- return self.find(node) != UInt(-1);
- })
+ .def("__contains__", [](const NodeGroup & self,
+ UInt node) { return self.find(node) != -1; })
.def("getName", &NodeGroup::getName)
.def("clear", &NodeGroup::clear)
.def("empty", &NodeGroup::empty)
.def("append", &NodeGroup::append)
.def(
"add",
[](NodeGroup & self, UInt node, bool check_for_duplicate) {
auto && it = self.add(node, check_for_duplicate);
return *it;
},
py::arg("node"), py::arg("check_for_duplicate") = true)
.def("remove", &NodeGroup::add);
/* ------------------------------------------------------------------------ */
py::class_<ElementGroup>(mod, "ElementGroup")
.def(
"getNodeGroup",
[](ElementGroup & self) -> decltype(auto) {
return self.getNodeGroup();
},
py::return_value_policy::reference)
.def("getName", &ElementGroup::getName)
.def(
"getElements",
[](ElementGroup & self) -> decltype(auto) {
return self.getElements();
},
py::return_value_policy::reference)
.def(
"getNodeGroup",
[](ElementGroup & self) -> decltype(auto) {
return self.getNodeGroup();
},
py::return_value_policy::reference)
.def("__len__", [](const ElementGroup & self) { return self.size(); })
.def("clear", [](ElementGroup & self) { self.clear(); })
.def("empty", &ElementGroup::empty)
.def("append", &ElementGroup::append)
.def("optimize", &ElementGroup::optimize)
.def(
"add",
[](ElementGroup & self, const Element & element, bool add_nodes,
bool check_for_duplicate) {
self.add(element, add_nodes, check_for_duplicate);
},
py::arg("element"), py::arg("add_nodes") = false,
py::arg("check_for_duplicate") = true)
.def("fillFromNodeGroup", &ElementGroup::fillFromNodeGroup)
.def("addDimension", &ElementGroup::addDimension);
/* ------------------------------------------------------------------------ */
py::class_<GroupManager>(mod, "GroupManager")
.def(
"getElementGroup",
[](GroupManager & self, const std::string & name) -> decltype(auto) {
return self.getElementGroup(name);
},
py::return_value_policy::reference)
.def("iterateElementGroups",
[](GroupManager & self) -> decltype(auto) {
std::vector<std::reference_wrapper<ElementGroup>> groups;
for (auto & group : self.iterateElementGroups()) {
groups.emplace_back(group);
}
return groups;
})
.def("iterateNodeGroups",
[](GroupManager & self) -> decltype(auto) {
std::vector<std::reference_wrapper<NodeGroup>> groups;
for (auto & group : self.iterateNodeGroups()) {
groups.emplace_back(group);
}
return groups;
})
.def("createNodeGroup", &GroupManager::createNodeGroup,
py::return_value_policy::reference)
.def(
"createElementGroup",
- [](GroupManager & self, const std::string & id,
- UInt spatial_dimension, bool replace_group) -> decltype(auto) {
+ [](GroupManager & self, const std::string & id, Int spatial_dimension,
+ bool replace_group) -> decltype(auto) {
return self.createElementGroup(id, spatial_dimension,
replace_group);
},
py::arg("id"), py::arg("spatial_dimension"),
py::arg("replace_group") = false, py::return_value_policy::reference)
.def("createGroupsFromMeshDataUInt",
&GroupManager::createGroupsFromMeshData<UInt>)
.def("createElementGroupFromNodeGroup",
&GroupManager::createElementGroupFromNodeGroup, py::arg("name"),
py::arg("node_group"), py::arg("dimension") = _all_dimensions)
.def(
"getNodeGroup",
[](GroupManager & self, const std::string & name) -> decltype(auto) {
return self.getNodeGroup(name);
},
py::return_value_policy::reference)
.def(
"nodeGroups",
[](GroupManager & self) {
std::vector<NodeGroup *> groups;
for (auto & g : self.iterateNodeGroups()) {
groups.push_back(&g);
}
return groups;
},
py::return_value_policy::reference)
.def(
"elementGroups",
[](GroupManager & self) {
std::vector<ElementGroup *> groups;
for (auto & g : self.iterateElementGroups()) {
groups.push_back(&g);
}
return groups;
},
py::return_value_policy::reference)
.def("createBoundaryGroupFromGeometry",
&GroupManager::createBoundaryGroupFromGeometry);
}
} // namespace akantu
diff --git a/python/py_material.cc b/python/py_material.cc
index 90a92c22b..72a9364da 100644
--- a/python/py_material.cc
+++ b/python/py_material.cc
@@ -1,378 +1,379 @@
/**
* @file py_material.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Jun 20 2019
* @date last modification: Fri Apr 09 2021
*
* @brief pybind11 interface to Material
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
#include "py_akantu_pybind11_compatibility.hh"
/* -------------------------------------------------------------------------- */
#include <material_selector.hh>
#include <solid_mechanics_model.hh>
#if defined(AKANTU_COHESIVE_ELEMENT)
#include <material_cohesive_linear.hh>
#include <solid_mechanics_model_cohesive.hh>
#endif
#include <material_elastic.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace {
template <typename _Material> class PyMaterial : public _Material {
public:
/* Inherit the constructors */
using _Material::_Material;
~PyMaterial() override = default;
void initMaterial() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, initMaterial, );
};
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(void, _Material, computeStress, el_type,
ghost_type);
}
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, computeTangentModuli, el_type,
tangent_matrix, ghost_type);
}
void computePotentialEnergy(ElementType el_type) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, computePotentialEnergy, el_type);
}
Real getPushWaveSpeed(const Element & element) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(Real, _Material, getPushWaveSpeed, element);
}
Real getShearWaveSpeed(const Element & element) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(Real, _Material, getShearWaveSpeed, element);
}
template <typename T>
- void registerInternal(const std::string & name, UInt nb_component) {
+ void registerInternal(const std::string & name, Int nb_component) {
auto && internal = std::make_shared<InternalField<T>>(name, *this);
AKANTU_DEBUG_INFO("alloc internal " << name << " "
<< &this->internals[name]);
internal->initialize(nb_component);
this->internals[name] = internal;
}
protected:
std::map<std::string, std::shared_ptr<ElementTypeMapBase>> internals;
};
/* ------------------------------------------------------------------------ */
template <typename _Material>
void register_material_classes(py::module & mod, const std::string & name) {
py::class_<_Material, Material, Parsable, PyMaterial<_Material>>(
mod, name.c_str(), py::multiple_inheritance())
.def(py::init<SolidMechanicsModel &, const ID &>());
}
#if defined(AKANTU_COHESIVE_ELEMENT)
template <typename _Material> class PyMaterialCohesive : public _Material {
public:
/* Inherit the constructors */
using _Material::_Material;
~PyMaterialCohesive() override = default;
void initMaterial() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, initMaterial, );
};
- void computeStress(ElementType el_type,
- GhostType ghost_type = _not_ghost) final {}
+ void computeStress(ElementType /*el_type*/,
+ GhostType /*ghost_type*/ = _not_ghost) final {}
void checkInsertion(bool check_only) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, checkInsertion, check_only);
}
- void computeTraction(const Array<Real> & normal, ElementType el_type,
+ void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE_PURE(void, _Material, computeTraction, normal, el_type,
+ PYBIND11_OVERRIDE_PURE(void, _Material, computeTraction, el_type,
ghost_type);
}
- void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
- GhostType ghost_type = _not_ghost) final {}
+ void computeTangentModuli(ElementType /*el_type*/,
+ Array<Real> & /*tangent_matrix*/,
+ GhostType /*ghost_type*/ = _not_ghost) final {}
void computeTangentTraction(ElementType el_type,
Array<Real> & tangent_matrix,
- const Array<Real> & normal,
GhostType ghost_type = _not_ghost) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, computeTangentTraction, el_type,
- tangent_matrix, normal, ghost_type);
+ tangent_matrix, ghost_type);
}
template <typename T>
- void registerInternal(const std::string & name, UInt nb_component) {
+ void registerInternal(const std::string & name, Int nb_component) {
auto && internal =
std::make_shared<CohesiveInternalField<T>>(name, *this);
AKANTU_DEBUG_INFO("alloc internal " << name << " "
<< &this->internals[name]);
internal->initialize(nb_component);
this->internals[name] = internal;
}
protected:
std::map<std::string, std::shared_ptr<ElementTypeMapBase>> internals;
};
template <typename _Material>
void register_material_cohesive_classes(py::module & mod,
const std::string & name) {
py::class_<_Material, Material, Parsable, PyMaterialCohesive<_Material>>(
mod, name.c_str(), py::multiple_inheritance())
.def(py::init<SolidMechanicsModelCohesive &, const ID &>());
}
#endif
/* ------------------------------------------------------------------------ */
template <typename T>
void register_internal_field(py::module & mod, const std::string & name) {
py::class_<InternalField<T>, ElementTypeMapArray<T>,
std::shared_ptr<InternalField<T>>>(
mod, ("InternalField" + name).c_str());
}
} // namespace
/* -------------------------------------------------------------------------- */
void register_material(py::module & mod) {
py::class_<MaterialFactory>(mod, "MaterialFactory")
.def_static(
"getInstance",
[]() -> MaterialFactory & { return Material::getFactory(); },
py::return_value_policy::reference)
.def("registerAllocator",
[](MaterialFactory & self, const std::string id, py::function func) {
self.registerAllocator(
id,
- [func, id](UInt dim, const ID & /*unused*/,
+ [func, id](Int dim, const ID & /*unused*/,
SolidMechanicsModel & model,
const ID & option) -> std::unique_ptr<Material> {
py::object obj = func(dim, id, model, option);
auto & ptr = py::cast<Material &>(obj);
obj.release();
return std::unique_ptr<Material>(&ptr);
});
})
.def("getPossibleAllocators", &MaterialFactory::getPossibleAllocators);
register_internal_field<Real>(mod, "Real");
register_internal_field<UInt>(mod, "UInt");
+ register_internal_field<Int>(mod, "Int");
py::class_<Material, Parsable, PyMaterial<Material>>(
mod, "Material", py::multiple_inheritance())
.def(py::init<SolidMechanicsModel &, const ID &>())
.def(
"getGradU",
[](Material & self, ElementType el_type,
GhostType ghost_type = _not_ghost) -> decltype(auto) {
return self.getGradU(el_type, ghost_type);
},
py::arg("el_type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"getStress",
[](Material & self, ElementType el_type,
GhostType ghost_type = _not_ghost) -> decltype(auto) {
return self.getStress(el_type, ghost_type);
},
py::arg("el_type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"getPotentialEnergy",
[](Material & self, ElementType el_type) -> decltype(auto) {
return self.getPotentialEnergy(el_type);
},
py::arg("el_type"), py::return_value_policy::reference)
.def(
"getPotentialEnergy",
- [](Material & self, ElementType el_type, UInt index) -> Real {
- return self.getPotentialEnergy(el_type, index);
+ [](Material & self, Element element) -> Real {
+ return self.getPotentialEnergy(element);
},
- py::arg("el_type"), py::arg("index"))
+ py::arg("element"))
.def("getPotentialEnergy",
[](Material & self) -> Real { return self.getPotentialEnergy(); })
.def("initMaterial", &Material::initMaterial)
.def("getModel", &Material::getModel)
.def("registerInternalReal",
- [](Material & self, const std::string & name, UInt nb_component) {
+ [](Material & self, const std::string & name, Int nb_component) {
return dynamic_cast<PyMaterial<Material> &>(self)
.registerInternal<Real>(name, nb_component);
})
.def("registerInternalUInt",
- [](Material & self, const std::string & name, UInt nb_component) {
+ [](Material & self, const std::string & name, Int nb_component) {
return dynamic_cast<PyMaterial<Material> &>(self)
.registerInternal<UInt>(name, nb_component);
})
.def(
"getInternalReal",
[](Material & self, const ID & id) -> decltype(auto) {
return self.getInternal<Real>(id);
},
py::arg("id"), py::return_value_policy::reference)
.def(
"getInternalUInt",
[](Material & self, const ID & id) -> decltype(auto) {
return self.getInternal<UInt>(id);
},
py::arg("id"), py::return_value_policy::reference)
.def(
"getElementFilter",
[](Material & self) -> decltype(auto) {
return self.getElementFilter();
},
py::return_value_policy::reference)
/*
* These functions override the `Parsable` interface.
* This ensure that the `updateInternalParameters()` function is called.
*/
.def(
"setReal",
[](Material & self, const ID & name, const Real value) -> void {
self.setParam(name, value);
return;
},
py::arg("name"), py::arg("value"))
.def(
"setBool",
[](Material & self, const ID & name, const bool value) -> void {
self.setParam(name, value);
return;
},
py::arg("name"), py::arg("value"))
.def(
"setString",
[](Material & self, const ID & name,
const std::string & value) -> void {
self.setParam(name, value);
return;
},
py::arg("name"), py::arg("value"))
.def(
"setInt",
[](Material & self, const ID & name, const int value) -> void {
self.setParam(name, value);
return;
},
py::arg("name"), py::arg("value"))
.def("getPushWaveSpeed", &Material::getPushWaveSpeed)
.def("getShearWaveSpeed", &Material::getShearWaveSpeed)
.def("__repr__", [](Material & self) {
std::stringstream sstr;
sstr << self;
return sstr.str();
});
register_material_classes<MaterialElastic<2>>(mod, "MaterialElastic2D");
register_material_classes<MaterialElastic<3>>(mod, "MaterialElastic3D");
#if defined(AKANTU_COHESIVE_ELEMENT)
/* ------------------------------------------------------------------------ */
py::class_<MaterialCohesive, Material, Parsable,
PyMaterialCohesive<MaterialCohesive>>(mod, "MaterialCohesive",
py::multiple_inheritance())
.def(py::init<SolidMechanicsModelCohesive &, const ID &>())
.def("registerInternalReal",
[](MaterialCohesive & self, const std::string & name,
UInt nb_component) {
return dynamic_cast<PyMaterialCohesive<MaterialCohesive> &>(self)
.registerInternal<Real>(name, nb_component);
})
.def("registerInternalUInt",
[](MaterialCohesive & self, const std::string & name,
UInt nb_component) {
return dynamic_cast<PyMaterialCohesive<MaterialCohesive> &>(self)
.registerInternal<UInt>(name, nb_component);
})
.def(
"getFacetFilter",
[](MaterialCohesive & self) -> decltype(auto) {
return self.getFacetFilter();
},
py::return_value_policy::reference)
.def(
"getFacetFilter",
[](MaterialCohesive & self, ElementType type,
GhostType ghost_type) -> decltype(auto) {
return self.getFacetFilter(type, ghost_type);
},
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"getOpening",
[](MaterialCohesive & self, ElementType type, GhostType ghost_type)
-> decltype(auto) { return self.getOpening(type, ghost_type); },
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"getTraction",
[](MaterialCohesive & self, ElementType type, GhostType ghost_type)
-> decltype(auto) { return self.getTraction(type, ghost_type); },
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference);
register_material_cohesive_classes<MaterialCohesiveLinear<2>>(
mod, "MaterialCohesiveLinear2D");
register_material_cohesive_classes<MaterialCohesiveLinear<3>>(
mod, "MaterialCohesiveLinear3D");
#endif
}
} // namespace akantu
diff --git a/python/py_material_selector.cc b/python/py_material_selector.cc
index 63057b74a..207dad93d 100644
--- a/python/py_material_selector.cc
+++ b/python/py_material_selector.cc
@@ -1,117 +1,117 @@
/**
* @file py_material_selector.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed May 26 2021
* @date last modification: Wed May 26 2021
*
* @brief Material selector python binding
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_material_selector.hh"
#include "py_akantu_pybind11_compatibility.hh"
/* -------------------------------------------------------------------------- */
#include <material_selector.hh>
#include <solid_mechanics_model.hh>
#if defined(AKANTU_COHESIVE_ELEMENT)
#include <material_selector_cohesive.hh>
#include <solid_mechanics_model_cohesive.hh>
#endif
/* -------------------------------------------------------------------------- */
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace {
template <class Base = MaterialSelector>
class PyMaterialSelector : public Base {
public:
/* Inherit the constructors */
using Base::Base;
~PyMaterialSelector() override = default;
- UInt operator()(const Element & element) override {
+ Idx operator()(const Element & element) override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE_NAME(UInt, MaterialSelector, "__call__", operator(),
+ PYBIND11_OVERRIDE_NAME(Idx, MaterialSelector, "__call__", operator(),
element);
}
};
template <class MaterialSelectorDaughter>
decltype(auto) register_material_selectors(py::module & mod,
const std::string & class_name) {
return py::class_<MaterialSelectorDaughter, MaterialSelector,
PyMaterialSelector<MaterialSelectorDaughter>,
std::shared_ptr<MaterialSelectorDaughter>>(
mod, class_name.c_str());
}
} // namespace
void register_material_selector(py::module & mod) {
py::class_<MaterialSelector, PyMaterialSelector<>,
std::shared_ptr<MaterialSelector>>(mod, "MaterialSelector")
.def(py::init())
.def("setFallback",
[](MaterialSelector & self, UInt f) { self.setFallback(f); })
.def("setFallback",
[](MaterialSelector & self,
const std::shared_ptr<MaterialSelector> & fallback_selector) {
self.setFallback(fallback_selector);
})
.def("__call__", &MaterialSelector::operator());
register_material_selectors<DefaultMaterialSelector>(
mod, "DefaultMaterialSelector")
- .def(py::init<const ElementTypeMapArray<UInt> &>());
+ .def(py::init<const ElementTypeMapArray<Int> &>());
register_material_selectors<MeshDataMaterialSelector<std::string>>(
mod, "MeshDataMaterialSelectorString")
.def(py::init<const std::string &, const SolidMechanicsModel &, UInt>(),
py::arg("name"), py::arg("model"), py::arg("first_index") = 1);
#if defined(AKANTU_COHESIVE_ELEMENT)
register_material_selectors<DefaultMaterialCohesiveSelector>(
mod, "DefaultMaterialCohesiveSelector")
.def(py::init<const SolidMechanicsModelCohesive &>());
register_material_selectors<MeshDataMaterialCohesiveSelector>(
mod, "MeshDataMaterialCohesiveSelector")
.def(py::init<const SolidMechanicsModelCohesive &>());
register_material_selectors<MaterialCohesiveRulesSelector>(
mod, "MaterialCohesiveRulesSelector")
.def(py::init<const SolidMechanicsModelCohesive &,
const MaterialCohesiveRules &, const ID &>(),
py::arg("model"), py::arg("rules"),
py::arg("mesh_data_id") = "physical_names");
#endif
}
} // namespace akantu
diff --git a/python/py_mesh.cc b/python/py_mesh.cc
index 050f0ae56..6fbfccafc 100644
--- a/python/py_mesh.cc
+++ b/python/py_mesh.cc
@@ -1,254 +1,259 @@
/**
* @file py_mesh.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Philip Mueller <philip.paul.mueller@bluemail.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Jun 16 2019
* @date last modification: Mon Mar 15 2021
*
* @brief pybind11 interface to Mesh
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_config.hh"
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <mesh.hh>
#include <mesh_accessor.hh>
#include <mesh_utils.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace {
/* ------------------------------------------------------------------------ */
template <typename T>
- decltype(auto) register_element_type_map_array(py::module & mod,
- const std::string & name) {
- return py::class_<ElementTypeMapArray<T>,
- std::shared_ptr<ElementTypeMapArray<T>>>(
- mod, ("ElementTypeMapArray" + name).c_str())
- .def(py::init<const ID &, const ID &>(),
- py::arg("id") = "by_element_type_array",
- py::arg("parent_id") = "no_parent")
- .def(
- "__call__",
- [](ElementTypeMapArray<T> & self, ElementType type,
- GhostType ghost_type) -> decltype(auto) {
- return self(type, ghost_type);
- },
- py::arg("type"), py::arg("ghost_type") = _not_ghost,
- py::return_value_policy::reference, py::keep_alive<0, 1>())
- .def(
- "elementTypes",
- [](ElementTypeMapArray<T> & self, UInt _dim, GhostType _ghost_type,
- ElementKind _kind) -> std::vector<ElementType> {
- auto types = self.elementTypes(_dim, _ghost_type, _kind);
- std::vector<ElementType> _types;
- for (auto && t : types) {
- _types.push_back(t);
- }
- return _types;
- },
- py::arg("dim") = _all_dimensions,
- py::arg("ghost_type") = _not_ghost, py::arg("kind") = _ek_regular)
- .def(
- "initialize",
- [](ElementTypeMapArray<T> & self, const Mesh & mesh,
- GhostType ghost_type = _casper, UInt nb_component = 1,
- UInt spatial_dimension = UInt(-2),
- ElementKind element_kind = _ek_not_defined,
- bool with_nb_element = false,
- bool with_nb_nodes_per_element = false, T default_value = T(),
- bool do_not_default = false) {
- self.initialize(
- mesh, _ghost_type = ghost_type, _nb_component = nb_component,
- _spatial_dimension = (spatial_dimension == UInt(-2)
- ? mesh.getSpatialDimension()
- : spatial_dimension),
- _element_kind = element_kind,
- _with_nb_element = with_nb_element,
- _with_nb_nodes_per_element = with_nb_nodes_per_element,
- _default_value = default_value,
- _do_not_default = do_not_default);
- },
- py::arg("mesh"), py::arg("ghost_type") = _casper,
- py::arg("nb_component") = 1,
- py::arg("spatial_dimension") = UInt(-2),
- py::arg("element_kind") = _ek_not_defined,
- py::arg("with_nb_element") = false,
- py::arg("with_nb_nodes_per_element") = false,
- py::arg("default_value") = T(), py::arg("do_not_default") = false);
+ auto register_element_type_map_array(py::module & mod,
+ const std::string & name) {
+ auto element_type_map_class =
+ py::class_<ElementTypeMapArray<T>,
+ std::shared_ptr<ElementTypeMapArray<T>>>(
+ mod, ("ElementTypeMapArray" + name).c_str())
+ .def(py::init<const ID &, const ID &>(),
+ py::arg("id") = "by_element_type_array",
+ py::arg("parent_id") = "no_parent")
+ .def(
+ "__call__",
+ [](ElementTypeMapArray<T> & self, ElementType type,
+ GhostType ghost_type) -> decltype(auto) {
+ return self(type, ghost_type);
+ },
+ py::arg("type"), py::arg("ghost_type") = _not_ghost,
+ py::return_value_policy::reference, py::keep_alive<0, 1>())
+ .def(
+ "elementTypes",
+ [](ElementTypeMapArray<T> & self, UInt _dim,
+ GhostType _ghost_type,
+ ElementKind _kind) -> std::vector<ElementType> {
+ auto types = self.elementTypes(_dim, _ghost_type, _kind);
+ std::vector<ElementType> _types;
+ for (auto && t : types) {
+ _types.push_back(t);
+ }
+ return _types;
+ },
+ py::arg("dim") = _all_dimensions,
+ py::arg("ghost_type") = _not_ghost,
+ py::arg("kind") = _ek_regular)
+ .def(
+ "initialize",
+ [](ElementTypeMapArray<T> & self, const Mesh & mesh,
+ GhostType ghost_type, Int nb_component,
+ Int spatial_dimension, ElementKind element_kind,
+ bool with_nb_element, bool with_nb_nodes_per_element,
+ T default_value, bool do_not_default) {
+ self.initialize(
+ mesh, _ghost_type = ghost_type,
+ _nb_component = nb_component,
+ _spatial_dimension =
+ (spatial_dimension == -2 ? mesh.getSpatialDimension()
+ : spatial_dimension),
+ _element_kind = element_kind,
+ _with_nb_element = with_nb_element,
+ _with_nb_nodes_per_element = with_nb_nodes_per_element,
+ _default_value = default_value,
+ _do_not_default = do_not_default);
+ },
+ py::arg("mesh"), py::arg("ghost_type") = _casper,
+ py::arg("nb_component") = 1, py::arg("spatial_dimension") = -2,
+ py::arg("element_kind") = _ek_not_defined,
+ py::arg("with_nb_element") = false,
+ py::arg("with_nb_nodes_per_element") = false,
+ py::arg("default_value") = T{},
+ py::arg("do_not_default") = false);
+
+ return element_type_map_class;
}
} // namespace
/* -------------------------------------------------------------------------- */
void register_mesh(py::module & mod) {
py::class_<Mesh::PeriodicSlaves>(mod, "PeriodicSlaves")
.def(
"__iter__",
[](Mesh::PeriodicSlaves & _this) {
return py::make_iterator(_this.begin(), _this.end());
},
py::keep_alive<0, 1>());
py::class_<MeshData>(mod, "MeshData")
.def(
"getElementalDataUInt",
[](MeshData & _this, const ID & name) -> decltype(auto) {
return _this.getElementalData<UInt>(name);
},
py::return_value_policy::reference)
.def(
"getElementalDataReal",
[](MeshData & _this, const ID & name) -> decltype(auto) {
return _this.getElementalData<Real>(name);
},
py::return_value_policy::reference);
py::class_<Mesh, GroupManager, Dumpable, MeshData>(mod, "Mesh",
py::multiple_inheritance())
- .def(py::init<UInt, const ID &>(), py::arg("spatial_dimension"),
+ .def(py::init<Int, const ID &>(), py::arg("spatial_dimension"),
py::arg("id") = "mesh")
.def("read", &Mesh::read, py::arg("filename"),
py::arg("mesh_io_type") = _miot_auto, "read the mesh from a file")
.def(
"getNodes",
[](Mesh & self) -> decltype(auto) { return self.getNodes(); },
py::return_value_policy::reference)
.def("getNbNodes", &Mesh::getNbNodes)
.def(
"getConnectivity",
[](Mesh & self, ElementType type) -> decltype(auto) {
return self.getConnectivity(type);
},
py::return_value_policy::reference)
.def(
"getConnectivities",
[](Mesh & self) -> decltype(auto) {
return self.getConnectivities();
},
py::return_value_policy::reference)
.def(
"addConnectivityType",
[](Mesh & self, ElementType type, GhostType ghost_type) -> void {
self.addConnectivityType(type, ghost_type);
},
py::arg("type"), py::arg("ghost_type") = _not_ghost)
.def("distribute", [](Mesh & self) { self.distribute(); })
.def("isDistributed",
[](const Mesh & self) { return self.isDistributed(); })
.def("fillNodesToElements", &Mesh::fillNodesToElements,
py::arg("dimension") = _all_dimensions)
.def("getAssociatedElements",
- [](Mesh & self, const UInt & node, py::list list) {
+ [](Mesh & self, const Idx & node, py::list list) {
Array<Element> elements;
self.getAssociatedElements(node, elements);
for (auto && element : elements) {
list.append(element);
}
})
.def("makePeriodic",
[](Mesh & self, const SpatialDirection & direction) {
self.makePeriodic(direction);
})
.def(
"getNbElement",
- [](Mesh & self, const UInt spatial_dimension, GhostType ghost_type,
+ [](Mesh & self, const Int spatial_dimension, GhostType ghost_type,
ElementKind kind) {
return self.getNbElement(spatial_dimension, ghost_type, kind);
},
py::arg("spatial_dimension") = _all_dimensions,
py::arg("ghost_type") = _not_ghost, py::arg("kind") = _ek_not_defined)
.def(
"getNbElement",
[](Mesh & self, ElementType type, GhostType ghost_type) {
return self.getNbElement(type, ghost_type);
},
py::arg("type"), py::arg("ghost_type") = _not_ghost)
.def_static(
"getSpatialDimension",
[](ElementType & type) { return Mesh::getSpatialDimension(type); })
.def(
"getDataReal",
[](Mesh & _this, const ID & name, ElementType type,
GhostType ghost_type) -> decltype(auto) {
return _this.getData<Real>(name, type, ghost_type);
},
py::arg("name"), py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"hasDataReal",
[](Mesh & _this, const ID & name, ElementType type,
GhostType ghost_type) -> bool {
return _this.hasData<Real>(name, type, ghost_type);
},
py::arg("name"), py::arg("type"), py::arg("ghost_type") = _not_ghost)
.def("isPeriodic", [](const Mesh & _this) { return _this.isPeriodic(); })
.def("getPeriodicMaster", &Mesh::getPeriodicMaster)
.def("getPeriodicSlaves", &Mesh::getPeriodicSlaves)
.def("isPeriodicSlave", &Mesh::isPeriodicSlave)
.def("isPeriodicMaster", &Mesh::isPeriodicMaster)
.def(
"getMeshFacets",
[](const Mesh & self) -> const Mesh & {
return self.getMeshFacets();
},
py::return_value_policy::reference)
.def("initMeshFacets", &Mesh::initMeshFacets,
py::arg("id") = "mesh_facets", py::return_value_policy::reference);
/* ------------------------------------------------------------------------ */
py::class_<MeshUtils>(mod, "MeshUtils")
.def_static("buildFacets", &MeshUtils::buildFacets);
py::class_<MeshAccessor>(mod, "MeshAccessor")
.def(py::init<Mesh &>(), py::arg("mesh"))
.def(
"resizeConnectivity",
- [](MeshAccessor & self, UInt new_size, ElementType type, GhostType gt)
+ [](MeshAccessor & self, Int new_size, ElementType type, GhostType gt)
-> void { self.resizeConnectivity(new_size, type, gt); },
py::arg("new_size"), py::arg("type"),
py::arg("ghost_type") = _not_ghost)
.def(
"resizeNodes",
- [](MeshAccessor & self, UInt new_size) -> void {
+ [](MeshAccessor & self, Int new_size) -> void {
self.resizeNodes(new_size);
},
py::arg("new_size"))
.def("makeReady", &MeshAccessor::makeReady);
register_element_type_map_array<Real>(mod, "Real");
register_element_type_map_array<UInt>(mod, "UInt");
+ register_element_type_map_array<Int>(mod, "Int");
register_element_type_map_array<bool>(mod, "bool");
// register_element_type_map_array<std::string>(mod, "String");
}
} // namespace akantu
diff --git a/python/py_phase_field_model.cc b/python/py_phase_field_model.cc
index 960970144..6a45d8c39 100644
--- a/python/py_phase_field_model.cc
+++ b/python/py_phase_field_model.cc
@@ -1,144 +1,141 @@
/**
* @file py_phase_field_model.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sun Jun 16 2019
* @date last modification: Fri Jun 25 2021
*
* @brief Phase field python binding
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <coupler_solid_phasefield.hh>
#include <non_linear_solver.hh>
#include <phase_field_model.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
#define def_deprecated(func_name, mesg) \
def(func_name, [](py::args, py::kwargs) { AKANTU_ERROR(mesg); })
#define def_function_nocopy(func_name) \
def( \
#func_name, \
[](PhaseFieldModel & self) -> decltype(auto) { \
return self.func_name(); \
}, \
py::return_value_policy::reference)
#define def_function(func_name) \
def(#func_name, [](PhaseFieldModel & self) -> decltype(auto) { \
return self.func_name(); \
})
/* -------------------------------------------------------------------------- */
-[[gnu::visibility("default")]] void
-register_phase_field_model(py::module & mod) {
+void register_phase_field_model(py::module & mod) {
py::class_<PhaseFieldModelOptions>(mod, "PhaseFieldModelOptions")
.def(py::init<AnalysisMethod>(), py::arg("analysis_method") = _static);
py::class_<PhaseFieldModel, Model>(mod, "PhaseFieldModel",
py::multiple_inheritance())
- .def(py::init<Mesh &, UInt, const ID &, const ModelType>(),
+ .def(py::init<Mesh &, Int, const ID &, const ModelType>(),
py::arg("mesh"), py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "phase_field_model",
py::arg("model_type") = ModelType::_phase_field_model)
.def(
"initFull",
[](PhaseFieldModel & self, const PhaseFieldModelOptions & options) {
self.initFull(options);
},
py::arg("_analysis_method") = PhaseFieldModelOptions())
.def(
"initFull",
[](PhaseFieldModel & self, const AnalysisMethod & analysis_method) {
self.initFull(_analysis_method = analysis_method);
},
py::arg("_analysis_method"))
.def_deprecated("applyDirichletBC", "Deprecated: use applyBC")
.def("applyBC",
[](PhaseFieldModel & self, BC::Dirichlet::DirichletFunctor & func,
const std::string & element_group) {
self.applyBC(func, element_group);
})
.def("applyBC",
[](PhaseFieldModel & self, BC::Neumann::NeumannFunctor & func,
const std::string & element_group) {
self.applyBC(func, element_group);
})
.def("setTimeStep", &PhaseFieldModel::setTimeStep, py::arg("time_step"),
py::arg("solver_id") = "")
.def_function(assembleStiffnessMatrix)
.def_function(assembleInternalForces)
.def_function_nocopy(getDamage)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getBlockedDOFs)
.def_function_nocopy(getMesh)
.def(
"getPhaseField",
- [](PhaseFieldModel & self, UInt phase_field_id) -> decltype(auto) {
+ [](PhaseFieldModel & self, Idx phase_field_id) -> decltype(auto) {
return self.getPhaseField(phase_field_id);
},
py::arg("phase_field_id"), py::return_value_policy::reference)
.def(
"getPhaseField",
[](PhaseFieldModel & self,
const ID & phase_field_name) -> decltype(auto) {
return self.getPhaseField(phase_field_name);
},
py::arg("phase_field_name"), py::return_value_policy::reference)
.def("getPhaseFieldIndex", &PhaseFieldModel::getPhaseFieldIndex)
.def("setPhaseFieldSelector", &PhaseFieldModel::setPhaseFieldSelector);
}
-[[gnu::visibility("default")]] void
-register_phase_field_coupler(py::module & mod) {
-
+void register_phase_field_coupler(py::module & mod) {
py::class_<CouplerSolidPhaseField, Model>(mod, "CouplerSolidPhaseField")
- .def(py::init<Mesh &, UInt, const ID &, const ModelType>(),
+ .def(py::init<Mesh &, Int, const ID &, const ModelType>(),
py::arg("mesh"), py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "coupler_solid_phasefield",
py::arg("model_type") = ModelType::_coupler_solid_phasefield)
.def("solve",
[](CouplerSolidPhaseField & self, const ID & solid_solver_id,
const ID & phase_solver_id) {
self.solve(solid_solver_id, phase_solver_id);
})
.def("getSolidMechanicsModel",
&CouplerSolidPhaseField::getSolidMechanicsModel,
py::return_value_policy::reference)
.def("getPhaseFieldModel", &CouplerSolidPhaseField::getPhaseFieldModel,
py::return_value_policy::reference);
}
} // namespace akantu
diff --git a/python/py_solid_mechanics_model_cohesive.cc b/python/py_solid_mechanics_model_cohesive.cc
index 81dce61dc..3debe9c3b 100644
--- a/python/py_solid_mechanics_model_cohesive.cc
+++ b/python/py_solid_mechanics_model_cohesive.cc
@@ -1,133 +1,133 @@
/**
* @file py_solid_mechanics_model_cohesive.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jul 21 2020
* @date last modification: Tue Sep 29 2020
*
* @brief pybind11 interface to SolidMechanicsModelCohesive
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <non_linear_solver.hh>
#include <solid_mechanics_model_cohesive.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
#define def_deprecated(func_name, mesg) \
def(func_name, [](py::args, py::kwargs) { AKANTU_ERROR(mesg); })
#define def_function_nocopy(func_name) \
def( \
#func_name, \
[](SolidMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
}, \
py::return_value_policy::reference)
#define def_function(func_name) \
def(#func_name, [](SolidMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
})
void register_solid_mechanics_model_cohesive(py::module & mod) {
py::class_<CohesiveElementInserter>(mod, "CohesiveElementInserter")
.def("setLimit", &CohesiveElementInserter::setLimit)
.def(
"getCheckFacets",
[](CohesiveElementInserter & self) -> decltype(auto) {
return self.getCheckFacets();
},
py::return_value_policy::reference)
.def(
"getCheckFacets",
[](CohesiveElementInserter & self, ElementType type,
GhostType ghost_type) -> decltype(auto) {
return self.getCheckFacets(type, ghost_type);
},
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"getInsertionFacets",
[](CohesiveElementInserter & self) -> decltype(auto) {
return self.getInsertionFacetsByElement();
},
py::return_value_policy::reference)
.def(
"getInsertionFacets",
[](CohesiveElementInserter & self, ElementType type,
GhostType ghost_type) -> decltype(auto) {
return self.getInsertionFacets(type, ghost_type);
},
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def("addPhysicalSurface", &CohesiveElementInserter::addPhysicalSurface)
.def("addPhysicalVolume", &CohesiveElementInserter::addPhysicalVolume);
py::class_<SolidMechanicsModelCohesiveOptions, SolidMechanicsModelOptions>(
mod, "SolidMechanicsModelCohesiveOptions")
.def(py::init<AnalysisMethod, bool>(),
py::arg("analysis_method") = _explicit_lumped_mass,
py::arg("is_extrinsic") = false);
py::class_<SolidMechanicsModelCohesive, SolidMechanicsModel>(
mod, "SolidMechanicsModelCohesive")
- .def(py::init<Mesh &, UInt, const ID &>(), py::arg("mesh"),
+ .def(py::init<Mesh &, Int, const ID &>(), py::arg("mesh"),
py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "solid_mechanics_model")
.def(
"initFull",
[](SolidMechanicsModel & self, const AnalysisMethod & analysis_method,
bool is_extrinsic) {
self.initFull(_analysis_method = analysis_method,
_is_extrinsic = is_extrinsic);
},
py::arg("_analysis_method") = _explicit_lumped_mass,
py::arg("_is_extrinsic") = false)
.def("checkCohesiveStress",
&SolidMechanicsModelCohesive::checkCohesiveStress)
.def("getElementInserter",
&SolidMechanicsModelCohesive::getElementInserter,
py::return_value_policy::reference)
.def("getStressOnFacets", &SolidMechanicsModelCohesive::getStressOnFacets,
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def("getTangents", &SolidMechanicsModelCohesive::getTangents,
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def("updateAutomaticInsertion",
&SolidMechanicsModelCohesive::updateAutomaticInsertion);
}
} // namespace akantu
diff --git a/python/py_solver.cc b/python/py_solver.cc
index d5e20670d..a66bcf93e 100644
--- a/python/py_solver.cc
+++ b/python/py_solver.cc
@@ -1,119 +1,119 @@
/**
* @file py_solver.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 29 2020
* @date last modification: Sat Mar 06 2021
*
* @brief pybind11 interface to Solver and SparseMatrix
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_solver.hh"
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <model.hh>
#include <non_linear_solver.hh>
#include <sparse_matrix_aij.hh>
#include <terms_to_assemble.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
void register_solvers(py::module & mod) {
py::class_<SparseMatrix>(mod, "SparseMatrix")
.def("getMatrixType", &SparseMatrix::getMatrixType)
.def("size", &SparseMatrix::size)
.def("zero", &SparseMatrix::zero)
.def("saveProfile", &SparseMatrix::saveProfile)
.def("saveMatrix", &SparseMatrix::saveMatrix)
.def(
- "add", [](SparseMatrix & self, UInt i, UInt j) { self.add(i, j); },
+ "add", [](SparseMatrix & self, Int i, Int j) { self.add(i, j); },
"Add entry in the profile")
.def(
"add",
- [](SparseMatrix & self, UInt i, UInt j, Real value) {
+ [](SparseMatrix & self, Int i, Int j, Real value) {
self.add(i, j, value);
},
"Add the value to the matrix")
.def(
"add",
[](SparseMatrix & self, SparseMatrix & A, Real alpha) {
self.add(A, alpha);
},
"Add a matrix to the matrix", py::arg("A"), py::arg("alpha") = 1.)
.def("isFinite", &SparseMatrix::isFinite)
.def("getRelease",
- [](const SparseMatrix & self) -> UInt { return self.getRelease(); })
+ [](const SparseMatrix & self) -> Int { return self.getRelease(); })
.def("__call__",
- [](const SparseMatrix & self, UInt i, UInt j) { return self(i, j); })
+ [](const SparseMatrix & self, Int i, Int j) { return self(i, j); })
.def("getRelease", &SparseMatrix::getRelease);
py::class_<SparseMatrixAIJ, SparseMatrix>(mod, "SparseMatrixAIJ")
.def("getIRN", &SparseMatrixAIJ::getIRN)
.def("getJCN", &SparseMatrixAIJ::getJCN)
.def("getA", &SparseMatrixAIJ::getA);
py::class_<SolverVector>(mod, "SolverVector")
.def(
"getValues",
[](SolverVector & self) -> decltype(auto) {
return static_cast<const Array<Real> &>(self);
},
py::return_value_policy::reference_internal,
"Transform this into a vector, Is not copied.")
.def("isDistributed",
[](const SolverVector & self) { return self.isDistributed(); });
py::class_<TermsToAssemble::TermToAssemble>(mod, "TermToAssemble")
.def(py::init<Int, Int>())
.def(py::self += Real())
.def_property_readonly("i", &TermsToAssemble::TermToAssemble::i)
.def_property_readonly("j", &TermsToAssemble::TermToAssemble::j);
py::class_<TermsToAssemble>(mod, "TermsToAssemble")
.def(py::init<const ID &, const ID &>())
.def("getDOFIdM", &TermsToAssemble::getDOFIdM)
.def("getDOFIdN", &TermsToAssemble::getDOFIdN)
.def(
"__call__",
- [](TermsToAssemble & self, UInt i, UInt j, Real val) {
+ [](TermsToAssemble & self, Int i, Int j, Real val) {
auto & term = self(i, j);
term = val;
return term;
},
py::arg("i"), py::arg("j"), py::arg("val") = 0.,
py::return_value_policy::reference);
}
} // namespace akantu
diff --git a/python/py_structural_mechanics_model.cc b/python/py_structural_mechanics_model.cc
index 366953881..a7968f81f 100644
--- a/python/py_structural_mechanics_model.cc
+++ b/python/py_structural_mechanics_model.cc
@@ -1,179 +1,179 @@
/**
* @file py_structural_mechanics_model.cc
*
* @author Philip Mueller <philip.paul.mueller@bluemail.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Feb 03 2021
* @date last modification: Thu Apr 01 2021
*
* @brief pybind11 interface to StructuralMechanicsModel
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <structural_mechanics_model.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
#define def_deprecated(func_name, mesg) \
def(func_name, [](py::args, py::kwargs) { AKANTU_ERROR(mesg); })
#define def_function_nocopy(func_name) \
def( \
#func_name, \
[](StructuralMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
}, \
py::return_value_policy::reference)
#define def_function_(func_name) \
def(#func_name, [](StructuralMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
})
#define def_plainmember(M) def_readwrite(#M, &StructuralMaterial::M)
/* -------------------------------------------------------------------------- */
void register_structural_mechanics_model(pybind11::module & mod) {
/* First we have to register the material class
* The wrapper aims to mimic the behaviour of the real material.
*/
py::class_<StructuralMaterial>(mod, "StructuralMaterial")
.def(py::init<>())
.def(py::init<const StructuralMaterial &>())
.def_plainmember(E)
.def_plainmember(A)
.def_plainmember(I)
.def_plainmember(Iz)
.def_plainmember(Iy)
.def_plainmember(GJ)
.def_plainmember(rho)
.def_plainmember(t)
.def_plainmember(nu);
/* Now we create the structural model wrapper
* Note that this is basically a port from the solid mechanic part.
*/
py::class_<StructuralMechanicsModel, Model>(mod, "StructuralMechanicsModel")
.def(py::init<Mesh &, UInt, const ID &>(), py::arg("mesh"),
py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "structural_mechanics_model")
.def(
"initFull",
[](StructuralMechanicsModel & self,
const AnalysisMethod & analysis_method) -> void {
self.initFull(_analysis_method = analysis_method);
},
py::arg("_analysis_method"))
.def("initFull",
[](StructuralMechanicsModel & self) -> void { self.initFull(); })
.def_function_nocopy(getExternalForce)
.def_function_nocopy(getDisplacement)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getVelocity)
.def_function_nocopy(getAcceleration)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getBlockedDOFs)
.def_function_nocopy(getMesh)
.def("setTimeStep", &StructuralMechanicsModel::setTimeStep,
py::arg("time_step"), py::arg("solver_id") = "")
.def(
"getElementMaterial",
- [](StructuralMechanicsModel & self, const ElementType & type,
+ [](StructuralMechanicsModel & self, ElementType type,
GhostType ghost_type) -> decltype(auto) {
return self.getElementMaterial(type, ghost_type);
},
"This function returns the map that maps elements to materials.",
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"getMaterialByElement",
[](StructuralMechanicsModel & self, Element element)
-> decltype(auto) { return self.getMaterialByElement(element); },
"This function returns the `StructuralMaterial` instance that is "
"associated with element `element`.",
py::arg("element"), py::return_value_policy::reference)
.def(
"addMaterial",
[](StructuralMechanicsModel & self, StructuralMaterial & mat,
const ID & name) -> UInt { return self.addMaterial(mat, name); },
"This function adds the `StructuralMaterial` `mat` to `self`."
" The function returns the ID of the new material.",
py::arg("mat"), py::arg("name") = "")
.def(
"getMaterial",
[](const StructuralMechanicsModel & self,
UInt material_index) -> StructuralMaterial {
return self.getMaterial(material_index);
},
"This function returns the `i`th material of `self`."
" The function returns a copy of the material.",
py::arg("material_index"), py::return_value_policy::copy)
.def(
"getMaterial",
[](const StructuralMechanicsModel & self, const ID & name)
-> StructuralMaterial { return self.getMaterial(name); },
"This function returns the `i`th material of `self`."
" The function returns a copy of the material.",
py::arg("material_index"), py::return_value_policy::copy)
.def(
"getNbMaterials",
[](StructuralMechanicsModel & self) { return self.getNbMaterials(); },
"Returns the number of different materials inside `self`.")
.def("getKineticEnergy", &StructuralMechanicsModel::getKineticEnergy,
"Compute kinetic energy")
.def("getPotentialEnergy", &StructuralMechanicsModel::getPotentialEnergy,
"Compute potential energy")
.def("getEnergy", &StructuralMechanicsModel::getEnergy,
"Compute the specified energy")
.def(
"getLumpedMass",
[](const StructuralMechanicsModel & self) -> decltype(auto) {
return self.getLumpedMass();
},
py::return_value_policy::reference_internal)
.def(
"getMass",
[](const StructuralMechanicsModel & self) -> decltype(auto) {
return self.getMass();
},
py::return_value_policy::reference_internal)
.def("assembleLumpedMassMatrix",
&StructuralMechanicsModel::assembleLumpedMassMatrix,
"Assembles the lumped mass matrix")
.def("hasLumpedMass", &StructuralMechanicsModel::hasLumpedMass);
}
} // namespace akantu
diff --git "a/requirements.txt\n" "b/requirements.txt\n"
new file mode 100644
index 000000000..6bad10388
--- /dev/null
+++ "b/requirements.txt\n"
@@ -0,0 +1,2 @@
+numpy
+scipy
diff --git a/setup.py b/setup.py
index d244a44cb..14700011d 100755
--- a/setup.py
+++ b/setup.py
@@ -1,118 +1,118 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
-import re
import os.path
import pybind11 as py11
import configparser
from setuptools import find_packages
from packaging.version import LegacyVersion
from skbuild.exceptions import SKBuildError
from skbuild.cmaker import get_cmake_version
try:
from skbuild import setup
except ImportError:
sys.stderr.write(
"Please update pip, you need pip 10 or greater,\n"
" or you need to install the PEP 518 requirements in"
" pyproject.toml yourself"
)
raise
# This is needed for semver.py to be importable
source_folder = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(source_folder, "cmake"))
parser = configparser.ConfigParser()
parser.read("setup.cfg")
cmake_args = ["-Dpybind11_DIR:PATH={}".format(py11.get_cmake_dir())]
if "cmake_config" in parser:
for k, v in parser["cmake_config"].items():
k = k.upper()
cmake_args.append("-D{}:BOOL={}".format(k, v))
akantu_libs = []
if "CI_AKANTU_INSTALL_PREFIX" in os.environ:
ci_akantu_install_prefix = os.environ["CI_AKANTU_INSTALL_PREFIX"]
- akantu_dir = os.path.join(ci_akantu_install_prefix, "lib", "cmake", "Akantu")
+ akantu_dir = os.path.join(ci_akantu_install_prefix,
+ "lib", "cmake", "Akantu")
akantu_libs.extend(
[
# paths comming from the manylinux install via gitlab-ci
"/softs/view/lib/*",
"/softs/view/lib64/*",
os.path.join(ci_akantu_install_prefix, "lib64/*"),
os.path.join(ci_akantu_install_prefix, "lib/*"),
]
)
cmake_args.extend(
[
"-DAKANTU_BYPASS_AKANTU_TARGET:BOOL=ON",
"-DAkantu_DIR:PATH={}".format(akantu_dir),
]
)
setup_kw = {}
try:
import semver
_version = semver.get_version()
setup_kw = {
"version": _version,
}
cmake_args.append("-DAKANTU_VERSION={}".format(_version))
except ImportError:
pass
# Add CMake as a build requirement if cmake is not installed or is too low a
# version
setup_requires = []
try:
if LegacyVersion(get_cmake_version()) < LegacyVersion("3.4"):
setup_requires.append("cmake")
except SKBuildError:
setup_requires.append("cmake")
with open(os.path.join(source_folder, "README.md"), "r") as fh:
long_description = fh.read()
setup(
name="akantu",
url="https://akantu.ch",
author="Nicolas Richart",
author_email="nicolas.richart@epfl.ch",
description="Akantu: Swiss-Made Open-Source Finite-Element Library",
long_description=long_description,
long_description_content_type="text/markdown",
platforms="",
license="L-GPLv3",
license_files=["COPYING", "COPYING.lesser"],
project_urls={
"Bug Tracker": "https://github.com/akantu/akantu/issues",
},
setup_requires=setup_requires,
install_requires=["numpy", "scipy"],
package_data={"AkantuLibs": akantu_libs},
packages=find_packages(where="python"),
package_dir={"": "python"},
include_package_data=False,
cmake_args=cmake_args,
cmake_languages=["CXX"],
classifiers=[
"Development Status :: 4 - Beta",
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Intended Audience :: Science/Research",
- "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
+ "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", # noqa
"Natural Language :: English",
"Operating System :: POSIX :: Linux",
"Programming Language :: C++",
"Programming Language :: Python",
"Topic :: Education",
"Topic :: Scientific/Engineering",
],
**setup_kw,
)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0e64c1fbc..1e2bc07f0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,275 +1,271 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Mon Jun 14 2010
# @date last modification: Tue Feb 13 2018
#
# @brief CMake file for the library
#
# @section LICENSE
#
# Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
#===============================================================================
# Package Management
#===============================================================================
package_get_all_source_files(
AKANTU_LIBRARY_SRCS
AKANTU_LIBRARY_PUBLIC_HDRS
AKANTU_LIBRARY_PRIVATE_HDRS
)
package_get_all_include_directories(
AKANTU_LIBRARY_INCLUDE_DIRS
)
package_get_all_external_informations(
PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR
INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR
LIBRARIES AKANTU_EXTERNAL_LIBRARIES
)
package_get_all_compilation_flags(CXX _cxx_flags)
set(AKANTU_EXTRA_CXX_FLAGS
"${_cxx_flags}" CACHE STRING "Extra flags defined by loaded packages" FORCE)
mark_as_advanced(AKANTU_EXTRA_CXX_FLAGS)
foreach(src_ ${AKANTU_SPIRIT_SOURCES})
set_property(SOURCE ${src_} PROPERTY COMPILE_FLAGS "-g0 -Werror")
endforeach()
#===========================================================================
# header for blas/lapack (any other fortran libraries)
#===========================================================================
package_is_activated(BLAS _blas_activated)
package_is_activated(LAPACK _lapack_activated)
if(_blas_activated OR _lapack_activated)
if(CMAKE_Fortran_COMPILER)
# ugly hack
set(CMAKE_Fortran_COMPILER_LOADED TRUE)
endif()
include(FortranCInterface)
FortranCInterface_HEADER(
"${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh"
MACRO_NAMESPACE "AKA_FC_")
mark_as_advanced(CDEFS)
list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS
"${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh"
)
endif()
list(APPEND AKANTU_LIBRARY_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}")
set(AKANTU_INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR} ${AKANTU_LIBRARY_INCLUDE_DIRS}
CACHE INTERNAL "Internal include directories to link with Akantu as a subproject")
#===========================================================================
# configurations
#===========================================================================
package_get_all_material_includes(AKANTU_MATERIAL_INCLUDES)
package_get_all_material_lists(AKANTU_MATERIAL_LISTS)
configure_file(model/solid_mechanics/material_list.hh.in
"${CMAKE_CURRENT_BINARY_DIR}/material_list.hh" @ONLY)
-package_get_element_lists()
-configure_file(common/aka_element_classes_info.hh.in
- "${CMAKE_CURRENT_BINARY_DIR}/aka_element_classes_info.hh" @ONLY)
-
configure_file(common/aka_config.hh.in
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh" @ONLY)
list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS
"${CMAKE_CURRENT_BINARY_DIR}/material_list.hh"
- "${CMAKE_CURRENT_BINARY_DIR}/aka_element_classes_info.hh"
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh")
configure_file(common/aka_config.cc.in
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.cc" @ONLY)
list(APPEND AKANTU_LIBRARY_SRCS
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.cc")
#===============================================================================
# Debug infos
#===============================================================================
set(AKANTU_GDB_DIR ${PROJECT_SOURCE_DIR}/cmake)
if(UNIX AND NOT APPLE)
string(TOUPPER "${CMAKE_BUILD_TYPE}" _u_build_type)
if(_u_build_type STREQUAL "DEBUG" OR _u_build_type STREQUAL "RELWITHDEBINFO")
configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in
"${PROJECT_BINARY_DIR}/libakantu-gdb.py"
@ONLY)
configure_file(${PROJECT_SOURCE_DIR}/cmake/akantu-debug.cc.in
"${PROJECT_BINARY_DIR}/akantu-debug.cc" @ONLY)
list(APPEND AKANTU_LIBRARY_SRCS ${PROJECT_BINARY_DIR}/akantu-debug.cc)
endif()
else()
find_program(GDB_EXECUTABLE gdb)
if(GDB_EXECUTABLE)
execute_process(COMMAND
${GDB_EXECUTABLE} --batch -x "${PROJECT_SOURCE_DIR}/cmake/gdb_python_path"
OUTPUT_VARIABLE AKANTU_PYTHON_GDB_DIR
ERROR_QUIET
RESULT_VARIABLE _res)
if(_res EQUAL 0 AND UNIX)
set(GDB_USER_CONFIG $ENV{HOME}/.gdb/auto-load)
file(MAKE_DIRECTORY ${GDB_USER_CONFIG})
configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in
"${GDB_USER_CONFIG}/${CMAKE_SHARED_LIBRARY_PREFIX}akantu${CMAKE_SHARED_LIBRARY_SUFFIX}.${AKANTU_VERSION}-gdb.py"
@ONLY)
endif()
endif()
endif()
#===============================================================================
# GIT info
#===============================================================================
#include(AkantuBuildOptions)
#git_version_info(akantu_git_info ALL
# OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/akantu_git_info.hh
# )
#list(APPEND AKANTU_LIBRARY_SRCS ${CMAKE_CURRENT_BINARY_DIR}/akantu_git_info.hh)
#===============================================================================
# Library generation
#===============================================================================
add_library(akantu ${AKANTU_LIBRARY_SRCS})
target_include_directories(akantu
PRIVATE $<BUILD_INTERFACE:${AKANTU_INCLUDE_DIRS}>
INTERFACE $<INSTALL_INTERFACE:include/akantu>
)
# small trick for build includes in public
set_property(TARGET akantu APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
$<BUILD_INTERFACE:${AKANTU_INCLUDE_DIRS}>)
target_include_directories(akantu SYSTEM
PUBLIC ${AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR}
)
target_include_directories(akantu SYSTEM
PRIVATE ${AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR}
)
target_link_libraries(akantu PUBLIC ${AKANTU_EXTERNAL_LIBRARIES})
+separate_arguments(_separated_cxx_flags UNIX_COMMAND ${_cxx_flags})
+target_compile_options(akantu PUBLIC ${_separated_cxx_flags})
+
set_target_properties(akantu
PROPERTIES
${AKANTU_LIBRARY_PROPERTIES} # this contains the version
- COMPILE_FLAGS "${_cxx_flags}"
- #PRIVATE_HEADER ${AKANTU_LIBRARY_PRIVATE_HDRS}
)
if(NOT AKANTU_SHARED)
set_property(TARGET akantu PROPERTY
POSITION_INDEPENDENT_CODE ${AKANTU_POSITION_INDEPENDENT})
endif()
if(AKANTU_LIBRARY_PUBLIC_HDRS)
set_property(TARGET akantu PROPERTY PUBLIC_HEADER ${AKANTU_LIBRARY_PUBLIC_HDRS})
endif()
if(AKANTU_LIBRARY_PRIVATE_HDRS)
set_property(TARGET akantu PROPERTY PRIVATE_HEADER ${AKANTU_LIBRARY_PRIVATE_HDRS})
endif()
-if(NOT CMAKE_VERSION VERSION_LESS 3.1)
- package_get_all_features_public(_PUBLIC_features)
- package_get_all_features_private(_PRIVATE_features)
- foreach(_type PRIVATE PUBLIC)
- if(_${_type}_features)
- target_compile_features(akantu ${_type} ${_${_type}_features})
- endif()
- endforeach()
-else()
- set_target_properties(akantu
- PROPERTIES
- CXX_STANDARD 14
- )
-endif()
+target_compile_features(akantu PUBLIC cxx_std_17)
+set_target_properties(akantu
+ PROPERTIES CXX_STANDARD ${AKANTU_CXX_STANDARD})
package_get_all_extra_dependencies(_extra_target_dependencies)
if(_extra_target_dependencies)
# This only adding todo: find a solution for when a dependency was add the is removed...
add_dependencies(akantu ${_extra_target_dependencies})
endif()
package_get_all_export_list(AKANTU_EXPORT_LIST)
list(APPEND AKANTU_EXPORT_LIST akantu)
# TODO separate public from private headers
install(TARGETS akantu
EXPORT ${AKANTU_TARGETS_EXPORT}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Akantu_runtime
# NAMELINK_ONLY
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
# COMPONENT Akantu_development
# NAMELINK_SKIP Akantu_development
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Akantu_runtime
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT Akantu_runtime
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/akantu/
COMPONENT Akantu_development
)
if("${AKANTU_TARGETS_EXPORT}" STREQUAL "AkantuTargets")
install(EXPORT AkantuTargets
DESTINATION lib/cmake/${PROJECT_NAME}
COMPONENT dev)
#Export for build tree
export(EXPORT AkantuTargets
FILE "${CMAKE_BINARY_DIR}/AkantuTargets.cmake")
export(PACKAGE Akantu)
endif()
#===============================================================================
# Adding module names for debug
package_get_all_packages(_pkg_list)
foreach(_pkg ${_pkg_list})
_package_get_real_name(${_pkg} _pkg_name)
_package_get_source_files(${_pkg} _srcs _public_hdrs _private_hdrs)
string(TOLOWER "${_pkg_name}" _l_package_name)
set_property(SOURCE ${_srcs} ${_public_hdrs} ${_private_hdrs}
APPEND PROPERTY COMPILE_DEFINITIONS AKANTU_MODULE=${_l_package_name})
endforeach()
# print out the list of materials
generate_material_list()
register_target_to_tidy(akantu)
register_tidy_all(${AKANTU_LIBRARY_SRCS})
register_code_to_format(
${AKANTU_LIBRARY_SRCS}
${AKANTU_LIBRARY_PUBLIC_HDRS}
${AKANTU_LIBRARY_PRIVATE_HDRS}
)
+
+cmake_policy(SET CMP0069 NEW)
+
+include(CheckIPOSupported)
+check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error LANGUAGES CXX)
+if(ipo_supported)
+ message(STATUS "IPO/LTO enabled")
+ set_property(TARGET akantu PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+else()
+ message(STATUS "IPO/LTO not supported: <${ipo_error}>")
+endif()
diff --git a/src/common/aka_array.cc b/src/common/aka_array.cc
index cac1d33b9..21ca9c1ce 100644
--- a/src/common/aka_array.cc
+++ b/src/common/aka_array.cc
@@ -1,98 +1,87 @@
/**
* @file aka_array.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief Implementation of akantu::Array
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <memory>
#include <utility>
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Functions ArrayBase */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <> UInt Array<Real>::find(const Real & elem) const {
+template <> Idx Array<Real>::find(const Real & elem) const {
AKANTU_DEBUG_IN();
Real epsilon = std::numeric_limits<Real>::epsilon();
auto it = std::find_if(begin(), end(), [&elem, &epsilon](auto && a) {
return std::abs(a - elem) <= epsilon;
});
AKANTU_DEBUG_OUT();
- return (it != end()) ? end() - it : UInt(-1);
+ return (it != end()) ? end() - it : -1;
}
/* -------------------------------------------------------------------------- */
template <>
-Array<ElementType> &
-Array<ElementType>::operator*=(const ElementType & /*alpha*/) {
+auto Array<ElementType>::operator*=(const ElementType & /*alpha*/) -> Array & {
AKANTU_TO_IMPLEMENT();
- return *this;
}
template <>
-Array<ElementType> &
-Array<ElementType>::operator-=(const Array<ElementType> & /*vect*/) {
+auto Array<ElementType>::operator-=(const Array & /*vect*/) -> Array & {
AKANTU_TO_IMPLEMENT();
- return *this;
}
template <>
-Array<ElementType> &
-Array<ElementType>::operator+=(const Array<ElementType> & /*vect*/) {
+auto Array<ElementType>::operator+=(const Array & /*vect*/) -> Array & {
AKANTU_TO_IMPLEMENT();
- return *this;
}
-template <> Array<char> & Array<char>::operator*=(const char & /*alpha*/) {
+template <> auto Array<char>::operator*=(const char & /*alpha*/) -> Array & {
AKANTU_TO_IMPLEMENT();
- return *this;
}
-template <>
-Array<char> & Array<char>::operator-=(const Array<char> & /*vect*/) {
+template <> auto Array<char>::operator-=(const Array & /*vect*/) -> Array & {
AKANTU_TO_IMPLEMENT();
- return *this;
}
-template <>
-Array<char> & Array<char>::operator+=(const Array<char> & /*vect*/) {
+template <> auto Array<char>::operator+=(const Array & /*vect*/) -> Array & {
AKANTU_TO_IMPLEMENT();
- return *this;
}
} // namespace akantu
diff --git a/src/common/aka_array.hh b/src/common/aka_array.hh
index 21d980519..e195a046c 100644
--- a/src/common/aka_array.hh
+++ b/src/common/aka_array.hh
@@ -1,450 +1,433 @@
/**
* @file aka_array.hh
*
* @author Till Junge <till.junge@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Sun Nov 22 2020
*
* @brief Array container for Akantu This container differs from the
* std::vector from the fact it as 2 dimensions a main dimension and the size
* stored per entries
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_types.hh"
+#include "aka_view_iterators.hh"
/* -------------------------------------------------------------------------- */
#include <typeinfo>
#include <vector>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ARRAY_HH_
#define AKANTU_ARRAY_HH_
namespace akantu {
/// class that afford to store vectors in static memory
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
class ArrayBase {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
+ using size_type = Int;
+
explicit ArrayBase(const ID & id = "") : id(id) {}
ArrayBase(const ArrayBase & other, const ID & id = "") {
this->id = (id.empty()) ? other.id : id;
}
ArrayBase(ArrayBase && other) = default;
ArrayBase & operator=(const ArrayBase & other) = default;
ArrayBase & operator=(ArrayBase && other) noexcept = default;
virtual ~ArrayBase() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// get the amount of space allocated in bytes
- virtual UInt getMemorySize() const = 0;
+ virtual Int getMemorySize() const = 0;
// changed empty to match std::vector empty
inline bool empty() const __attribute__((warn_unused_result)) {
return size_ == 0;
}
/// function to print the containt of the class
virtual void printself(std::ostream & stream, int indent = 0) const = 0;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Get the Size of the Array
- UInt size() const { return size_; }
+ decltype(auto) size() const { return size_; }
/// Get the number of components
- AKANTU_GET_MACRO(NbComponent, nb_component, UInt);
- /// Get the name of th array
- AKANTU_GET_MACRO(ID, id, const ID &);
+ decltype(auto) getNbComponent() const { return nb_component; }
+ /// Get the name of th arrya
+ AKANTU_GET_MACRO_AUTO(ID, id);
/// Set the name of th array
AKANTU_SET_MACRO(ID, id, const ID &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// id of the vector
ID id;
/// the size used
- UInt size_{0};
+ Int size_{0};
/// number of components
- UInt nb_component{1};
+ Int nb_component{1};
};
-/* -------------------------------------------------------------------------- */
-namespace {
- template <std::size_t dim, typename T> struct IteratorHelper {};
-
- template <typename T> struct IteratorHelper<0, T> { using type = T; };
- template <typename T> struct IteratorHelper<1, T> { using type = Vector<T>; };
- template <typename T> struct IteratorHelper<2, T> { using type = Matrix<T>; };
- template <typename T> struct IteratorHelper<3, T> {
- using type = Tensor3<T>;
- };
-
- template <std::size_t dim, typename T>
- using IteratorHelper_t = typename IteratorHelper<dim, T>::type;
-} // namespace
-
/* -------------------------------------------------------------------------- */
/* Memory handling layer */
/* -------------------------------------------------------------------------- */
enum class ArrayAllocationType {
_default,
_pod,
};
template <typename T>
struct ArrayAllocationTrait
: public std::conditional_t<
- std::is_scalar<T>::value,
+ aka::is_scalar<T>::value,
std::integral_constant<ArrayAllocationType,
ArrayAllocationType::_pod>,
std::integral_constant<ArrayAllocationType,
ArrayAllocationType::_default>> {};
/* -------------------------------------------------------------------------- */
template <typename T,
ArrayAllocationType allocation_trait = ArrayAllocationTrait<T>::value>
class ArrayDataLayer : public ArrayBase {
public:
using value_type = T;
+ using size_type = typename ArrayBase::size_type;
using reference = value_type &;
using pointer_type = value_type *;
using const_reference = const value_type &;
public:
~ArrayDataLayer() override = default;
/// Allocation of a new vector
- explicit ArrayDataLayer(UInt size = 0, UInt nb_component = 1,
+ explicit ArrayDataLayer(Int size = 0, Int nb_component = 1,
const ID & id = "");
/// Allocation of a new vector with a default value
- ArrayDataLayer(UInt size, UInt nb_component, const_reference value,
+ ArrayDataLayer(Int size, Int nb_component, const_reference value,
const ID & id = "");
/// Copy constructor (deep copy)
ArrayDataLayer(const ArrayDataLayer & vect, const ID & id = "");
/// Copy constructor (deep copy)
explicit ArrayDataLayer(const std::vector<value_type> & vect);
// copy operator
ArrayDataLayer & operator=(const ArrayDataLayer & other);
// move constructor
ArrayDataLayer(ArrayDataLayer && other) noexcept = default;
// move assign
ArrayDataLayer & operator=(ArrayDataLayer && other) noexcept = default;
protected:
// deallocate the memory
virtual void deallocate() {}
// allocate the memory
- virtual void allocate(UInt size, UInt nb_component);
+ virtual void allocate(Int size, Int nb_component);
// allocate and initialize the memory
- virtual void allocate(UInt size, UInt nb_component, const T & value);
+ virtual void allocate(Int size, Int nb_component, const T & value);
public:
/// append a tuple of size nb_component containing value
inline void push_back(const_reference value);
/// append a vector
// inline void push_back(const value_type new_elem[]);
/// append a Vector or a Matrix
- template <template <typename> class C,
- typename = std::enable_if_t<aka::is_tensor<C<T>>::value or
- aka::is_tensor_proxy<C<T>>::value>>
- inline void push_back(const C<T> & new_elem);
+ template <typename Derived>
+ inline void push_back(const Eigen::MatrixBase<Derived> & new_elem);
/// changes the allocated size but not the size, if new_size = 0, the size is
/// set to min(current_size and reserve size)
- virtual void reserve(UInt size, UInt new_size = UInt(-1));
+ virtual void reserve(Int size, Int new_size = Int(-1));
/// change the size of the Array
- virtual void resize(UInt size);
+ virtual void resize(Int size);
/// change the size of the Array and initialize the values
- virtual void resize(UInt size, const T & val);
+ virtual void resize(Int size, const T & val);
/// get the amount of space allocated in bytes
- inline UInt getMemorySize() const override;
+ inline Int getMemorySize() const override;
/// Get the real size allocated in memory
- inline UInt getAllocatedSize() const;
+ inline Int getAllocatedSize() const;
/// give the address of the memory allocated for this vector
- T * storage() const { return values; };
+ [[deprecated("use data instead to be stl compatible")]] T * storage() const {
+ return values;
+ };
+
+ T * data() const { return values; };
protected:
/// allocation type agnostic data access
T * values{nullptr};
/// data storage
std::vector<T> data_storage;
};
/* -------------------------------------------------------------------------- */
/* Actual Array */
/* -------------------------------------------------------------------------- */
template <typename T, bool is_scal> class Array : public ArrayDataLayer<T> {
private:
using parent = ArrayDataLayer<T>;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using value_type = typename parent::value_type;
+ using size_type = typename parent::size_type;
using reference = typename parent::reference;
using pointer_type = typename parent::pointer_type;
using const_reference = typename parent::const_reference;
using array_type = Array<T>;
~Array() override;
Array() : Array(0){};
/// Allocation of a new vector
- explicit Array(UInt size, UInt nb_component = 1, const ID & id = "");
+ explicit Array(Int size, Int nb_component = 1, const ID & id = "");
/// Allocation of a new vector with a default value
- explicit Array(UInt size, UInt nb_component, const_reference value,
+ explicit Array(Int size, Int nb_component, const_reference value,
const ID & id = "");
/// Copy constructor
Array(const Array & vect, const ID & id = "");
/// Copy constructor (deep copy)
explicit Array(const std::vector<T> & vect);
// copy operator
Array & operator=(const Array & other);
// move constructor
Array(Array && other) noexcept = default;
// move assign
Array & operator=(Array && other) noexcept = default;
/* ------------------------------------------------------------------------ */
/* Iterator */
/* ------------------------------------------------------------------------ */
- /// \todo protected: does not compile with intel check why
-public:
- template <class R, class it, class IR = R,
- bool is_tensor_ = aka::is_tensor<std::decay_t<R>>::value>
- class iterator_internal;
-
-public:
- /* ------------------------------------------------------------------------ */
-
- /* ------------------------------------------------------------------------ */
- template <typename R = T> class const_iterator;
- template <typename R = T> class iterator;
-
- /* ------------------------------------------------------------------------ */
-
/// iterator for Array of nb_component = 1
- using scalar_iterator = iterator<T>;
+ using scalar_iterator = view_iterator<T>;
/// const_iterator for Array of nb_component = 1
- using const_scalar_iterator = const_iterator<T>;
+ using const_scalar_iterator = const_view_iterator<T>;
/// iterator returning Vectors of size n on entries of Array with
/// nb_component = n
- using vector_iterator = iterator<Vector<T>>;
+ using vector_iterator = view_iterator<VectorProxy<T>>;
/// const_iterator returning Vectors of n size on entries of Array with
/// nb_component = n
- using const_vector_iterator = const_iterator<Vector<T>>;
+ using const_vector_iterator = const_view_iterator<VectorProxy<const T>>;
/// iterator returning Matrices of size (m, n) on entries of Array with
/// nb_component = m*n
- using matrix_iterator = iterator<Matrix<T>>;
+ using matrix_iterator = view_iterator<MatrixProxy<T>>;
/// const iterator returning Matrices of size (m, n) on entries of Array with
/// nb_component = m*n
- using const_matrix_iterator = const_iterator<Matrix<T>>;
+ using const_matrix_iterator = const_view_iterator<MatrixProxy<const T>>;
/// iterator returning Tensor3 of size (m, n, k) on entries of Array with
/// nb_component = m*n*k
- using tensor3_iterator = iterator<Tensor3<T>>;
+ using tensor3_iterator = view_iterator<Tensor3Proxy<T>>;
/// const iterator returning Tensor3 of size (m, n, k) on entries of Array
/// with nb_component = m*n*k
- using const_tensor3_iterator = const_iterator<Tensor3<T>>;
+ using const_tensor3_iterator = const_view_iterator<Tensor3Proxy<T>>;
/* ------------------------------------------------------------------------ */
- template <typename... Ns> inline decltype(auto) begin(Ns &&... n);
- template <typename... Ns> inline decltype(auto) end(Ns &&... n);
-
- template <typename... Ns> inline decltype(auto) begin(Ns &&... n) const;
- template <typename... Ns> inline decltype(auto) end(Ns &&... n) const;
+ template <typename... Ns> inline auto begin(Ns &&... n);
+ template <typename... Ns> inline auto end(Ns &&... n);
+ template <typename... Ns> inline auto begin(Ns &&... n) const;
+ template <typename... Ns> inline auto end(Ns &&... n) const;
- template <typename... Ns> inline decltype(auto) begin_reinterpret(Ns &&... n);
- template <typename... Ns> inline decltype(auto) end_reinterpret(Ns &&... n);
+ template <typename... Ns> inline auto cbegin(Ns &&... n) const;
+ template <typename... Ns> inline auto cend(Ns &&... n) const;
template <typename... Ns>
- inline decltype(auto) begin_reinterpret(Ns &&... n) const;
+ [[deprecated("use make_view instead")]] inline auto
+ begin_reinterpret(Ns &&... n);
+ template <typename... Ns>
+ [[deprecated("use make_view instead")]] inline auto
+ end_reinterpret(Ns &&... n);
+ template <typename... Ns>
+ [[deprecated("use make_view instead")]] inline auto
+ begin_reinterpret(Ns &&... n) const;
template <typename... Ns>
- inline decltype(auto) end_reinterpret(Ns &&... n) const;
+ [[deprecated("use make_view instead")]] inline auto
+ end_reinterpret(Ns &&... n) const;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// search elem in the vector, return the position of the first occurrence or
/// -1 if not found
- UInt find(const_reference elem) const;
+ Idx find(const_reference elem) const;
/// @see Array::find(const_reference elem) const
- // UInt find(T elem[]) const;
+ // Int find(T elem[]) const;
/// append a value to the end of the Array
inline void push_back(const_reference value) { parent::push_back(value); }
/// append a Vector or a Matrix
- template <template <typename> class C,
- typename = std::enable_if_t<aka::is_tensor<C<T>>::value or
- aka::is_tensor_proxy<C<T>>::value>>
- inline void push_back(const C<T> & new_elem) {
+ template <typename Derived>
+ inline void push_back(const Eigen::MatrixBase<Derived> & new_elem) {
parent::push_back(new_elem);
}
- /// append the content of the iterator at the end of the Array
- template <typename Ret> inline void push_back(const iterator<Ret> & it) {
+ template <typename Ret>
+ inline void push_back(const const_view_iterator<Ret> & it) {
+ push_back(*it);
+ }
+
+ template <typename Ret> inline void push_back(const view_iterator<Ret> & it) {
push_back(*it);
}
/// erase the value at position i
- inline void erase(UInt i);
- /// ask Nico, clarify
- template <typename R> inline iterator<R> erase(const iterator<R> & it);
+ inline void erase(Idx i);
+
+ /// erase the entry corresponding to the iterator
+ template <typename R> inline auto erase(const view_iterator<R> & it);
/// @see Array::find(const_reference elem) const
- template <template <typename> class C,
- typename = std::enable_if_t<aka::is_tensor<C<T>>::value or
- aka::is_tensor_proxy<C<T>>::value>>
- inline UInt find(const C<T> & elem);
+ template <typename C, std::enable_if_t<aka::is_tensor<C>::value> * = nullptr>
+ inline Idx find(const C & elem);
/// set all entries of the array to the value t
/// @param t value to fill the array with
inline void set(T t) {
std::fill_n(this->values, this->size_ * this->nb_component, t);
}
+ /// set all tuples of the array to a given vector or matrix
+ /// @param vm Matrix or Vector to fill the array with
+ template <typename C, std::enable_if_t<aka::is_tensor<C>::value> * = nullptr>
+ inline void set(const C & vm);
+
/// set the array to T{}
inline void zero() { this->set({}); }
/// resize the array to 0
inline void clear() { this->resize(0); }
- /// set all tuples of the array to a given vector or matrix
- /// @param vm Matrix or Vector to fill the array with
- template <template <typename> class C,
- typename = std::enable_if_t<aka::is_tensor<C<T>>::value or
- aka::is_tensor_proxy<C<T>>::value>>
- inline void set(const C<T> & vm);
-
/// Append the content of the other array to the current one
- void append(const Array<T> & other);
+ void append(const Array & other);
/// copy another Array in the current Array, the no_sanity_check allows you to
/// force the copy in cases where you know what you do with two non matching
/// Arrays in terms of n
- void copy(const Array<T, is_scal> & other, bool no_sanity_check = false);
+ void copy(const Array & other, bool no_sanity_check = false);
/// function to print the containt of the class
void printself(std::ostream & stream, int indent = 0) const override;
/// Tests if all elements are finite.
template <typename OT = T,
std::enable_if_t<std::is_arithmetic<OT>::value> * = nullptr>
bool isFinite() const noexcept;
/* ------------------------------------------------------------------------ */
/* Operators */
/* ------------------------------------------------------------------------ */
public:
/// substraction entry-wise
- Array<T, is_scal> & operator-=(const Array<T, is_scal> & other);
+ Array & operator-=(const Array & vect);
/// addition entry-wise
- Array<T, is_scal> & operator+=(const Array<T, is_scal> & other);
+ Array & operator+=(const Array & vect);
/// multiply evry entry by alpha
- Array<T, is_scal> & operator*=(const T & alpha);
+ Array & operator*=(const T & alpha);
/// check if the array are identical entry-wise
bool operator==(const Array<T, is_scal> & other) const;
/// @see Array::operator==(const Array<T, is_scal> & other) const
bool operator!=(const Array<T, is_scal> & other) const;
/// return a reference to the j-th entry of the i-th tuple
- inline reference operator()(UInt i, UInt j = 0);
+ inline reference operator()(Idx i, Idx j = 0);
/// return a const reference to the j-th entry of the i-th tuple
- inline const_reference operator()(UInt i, UInt j = 0) const;
+ inline const_reference operator()(Idx i, Idx j = 0) const;
/// return a reference to the ith component of the 1D array
- inline reference operator[](UInt i);
+ inline reference operator[](Idx i);
/// return a const reference to the ith component of the 1D array
- inline const_reference operator[](UInt i) const;
+ inline const_reference operator[](Idx i) const;
};
/* -------------------------------------------------------------------------- */
/* Inline Functions Array<T, is_scal> */
/* -------------------------------------------------------------------------- */
template <typename T, bool is_scal>
inline std::ostream & operator<<(std::ostream & stream,
const Array<T, is_scal> & _this) {
_this.printself(stream);
return stream;
}
/* -------------------------------------------------------------------------- */
/* Inline Functions ArrayBase */
/* -------------------------------------------------------------------------- */
inline std::ostream & operator<<(std::ostream & stream,
const ArrayBase & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "aka_array_tmpl.hh"
#endif /* AKANTU_ARRAY_HH_ */
diff --git a/src/common/aka_array_filter.hh b/src/common/aka_array_filter.hh
index 03cca3905..b8d7c463b 100644
--- a/src/common/aka_array_filter.hh
+++ b/src/common/aka_array_filter.hh
@@ -1,217 +1,42 @@
/**
* @file aka_array.hh
*
* @author Till Junge <till.junge@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Jan 16 2018
*
* @brief Array container for Akantu
* This container differs from the std::vector from the fact it as 2 dimensions
* a main dimension and the size stored per entries
*
*
* Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ARRAY_FILTER_HH_
#define AKANTU_ARRAY_FILTER_HH_
namespace akantu {
-/* -------------------------------------------------------------------------- */
-/* ArrayFilter */
-/* -------------------------------------------------------------------------- */
-template <typename T> class ArrayFilter {
- /* ------------------------------------------------------------------------ */
- /* Typedefs */
- /* ------------------------------------------------------------------------ */
-public:
- /// standard iterator
- template <typename R = T> class iterator {
- inline bool operator!=(__attribute__((unused)) iterator<R> & other) {
- throw;
- };
- inline bool operator==(__attribute__((unused)) iterator<R> & other) {
- throw;
- };
-
- inline iterator<R> & operator++() { throw; };
- inline T operator*() {
- throw;
- return T();
- };
- };
-
- /// const iterator
- template <template <class S> class original_iterator, typename Shape,
- typename filter_iterator>
- class const_iterator {
-
- public:
- UInt getCurrentIndex() {
- return (*this->filter_it * this->nb_item_per_elem +
- this->sub_element_counter);
- }
-
- inline const_iterator() = default;
- inline const_iterator(const original_iterator<Shape> & origin_it,
- const filter_iterator & filter_it,
- UInt nb_item_per_elem)
- : origin_it(origin_it), filter_it(filter_it),
- nb_item_per_elem(nb_item_per_elem), sub_element_counter(0){};
-
- inline bool operator!=(const_iterator & other) const {
- return !((*this) == other);
- }
- inline bool operator==(const_iterator & other) const {
- return (this->origin_it == other.origin_it &&
- this->filter_it == other.filter_it &&
- this->sub_element_counter == other.sub_element_counter);
- }
-
- inline bool operator!=(const const_iterator & other) const {
- return !((*this) == other);
- }
- inline bool operator==(const const_iterator & other) const {
- return (this->origin_it == other.origin_it &&
- this->filter_it == other.filter_it &&
- this->sub_element_counter == other.sub_element_counter);
- }
-
- inline const_iterator & operator++() {
-
- ++sub_element_counter;
- if (sub_element_counter == nb_item_per_elem) {
- sub_element_counter = 0;
- ++filter_it;
- }
- return *this;
- };
-
- inline Shape operator*() {
- return origin_it[nb_item_per_elem * (*filter_it) + sub_element_counter];
- };
-
- private:
- original_iterator<Shape> origin_it;
- filter_iterator filter_it;
-
- /// the number of item per element
- UInt nb_item_per_elem;
- /// counter for every sub element group
- UInt sub_element_counter;
- };
-
- using vector_iterator = iterator<Vector<T>>;
-
- using array_type = Array<T>;
-
- using const_vector_iterator =
- const_iterator<array_type::template const_iterator, Vector<T>,
- Array<UInt>::const_iterator<UInt>>;
-
- using value_type = typename array_type::value_type;
-
- /* ------------------------------------------------------------------------ */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------ */
-
-public:
- ArrayFilter(const Array<T> & array, const Array<UInt> & filter,
- UInt nb_item_per_elem)
- : array(array), filter(filter), nb_item_per_elem(nb_item_per_elem){};
-
- /* ------------------------------------------------------------------------ */
- /* Methods */
- /* ------------------------------------------------------------------------ */
- const_vector_iterator begin_reinterpret(UInt n, UInt new_size) const {
- AKANTU_DEBUG_ASSERT(
- n * new_size == this->getNbComponent() * this->size(),
- "The new values for size ("
- << new_size << ") and nb_component (" << n
- << ") are not compatible with the one of this array("
- << this->size() << "," << this->getNbComponent() << ")");
- UInt new_full_array_size = this->array.size() * array.getNbComponent() / n;
- UInt new_nb_item_per_elem = this->nb_item_per_elem;
- if (new_size != 0 && n != 0) {
- new_nb_item_per_elem = this->array.getNbComponent() *
- this->filter.size() * this->nb_item_per_elem /
- (n * new_size);
- }
-
- return const_vector_iterator(
- this->array.begin_reinterpret(n, new_full_array_size),
- this->filter.begin(), new_nb_item_per_elem);
- };
-
- const_vector_iterator end_reinterpret(UInt n, UInt new_size) const {
- AKANTU_DEBUG_ASSERT(
- n * new_size == this->getNbComponent() * this->size(),
- "The new values for size ("
- << new_size << ") and nb_component (" << n
- << ") are not compatible with the one of this array("
- << this->size() << "," << this->getNbComponent() << ")");
- UInt new_full_array_size =
- this->array.size() * this->array.getNbComponent() / n;
- UInt new_nb_item_per_elem = this->nb_item_per_elem;
- if (new_size != 0 && n != 0) {
- new_nb_item_per_elem = this->array.getNbComponent() *
- this->filter.size() * this->nb_item_per_elem /
- (n * new_size);
- }
-
- return const_vector_iterator(
- this->array.begin_reinterpret(n, new_full_array_size),
- this->filter.end(), new_nb_item_per_elem);
- };
-
- vector_iterator begin_reinterpret(UInt /*unused*/, UInt /*unused*/) {
- throw;
- };
-
- vector_iterator end_reinterpret(UInt /*unused*/, UInt /*unused*/) { throw; };
-
- /// return the size of the filtered array which is the filter size
- UInt size() const { return this->filter.size() * this->nb_item_per_elem; };
- /// the number of components of the filtered array
- UInt getNbComponent() const { return this->array.getNbComponent(); };
-
- bool empty() const __attribute__((warn_unused_result)) {
- return (size() == 0);
- }
-
- /* ------------------------------------------------------------------------ */
- /* Class Members */
- /* ------------------------------------------------------------------------ */
-
-private:
- /// reference to array of data
- const Array<T> & array;
- /// reference to the filter used to select elements
- const Array<UInt> & filter;
- /// the number of item per element
- UInt nb_item_per_elem;
-};
-
} // namespace akantu
#endif // AKANTU_ARRAY_FILTER_HH_
diff --git a/src/common/aka_array_printer.hh b/src/common/aka_array_printer.hh
index eeaa1f327..9d51c13c0 100644
--- a/src/common/aka_array_printer.hh
+++ b/src/common/aka_array_printer.hh
@@ -1,104 +1,104 @@
/**
* @file aka_array_printer.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Jul 03 2019
* @date last modification: Tue Sep 29 2020
*
* @brief Helper to print arrays on screen
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_ARRAY_PRINTER_HH_
#define AKANTU_AKA_ARRAY_PRINTER_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class container, bool no_explicit = true> class ArrayPrinter {
public:
ArrayPrinter(const container & cont) : cont(cont) {}
void printself(std::ostream & stream, int indent = 0) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "{";
- for (UInt i = 0; i < this->cont.size(); ++i) {
+ for (Int i = 0; i < this->cont.size(); ++i) {
stream << this->cont[i];
if (i != this->cont.size() - 1)
stream << ", ";
}
stream << "}";
}
private:
const container & cont;
};
/* -------------------------------------------------------------------------- */
template <class T> class ArrayPrinter<Array<T>> {
public:
ArrayPrinter(const Array<T> & cont) : cont(cont) {}
void printself(std::ostream & stream, int indent = 0) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "{";
- for (UInt i = 0; i < this->cont.size(); ++i) {
+ for (Int i = 0; i < this->cont.size(); ++i) {
stream << "{";
- for (UInt j = 0; j < this->cont.getNbComponent(); ++j) {
+ for (Int j = 0; j < this->cont.getNbComponent(); ++j) {
stream << this->cont(i, j);
if (j != this->cont.getNbComponent() - 1)
stream << ", ";
}
stream << "}";
if (i != this->cont.size() - 1)
stream << ", ";
}
stream << "}";
}
private:
const Array<T> & cont;
};
template <class container>
decltype(auto) make_printer(const container & array) {
return ArrayPrinter<container>(array);
}
/* -------------------------------------------------------------------------- */
template <class T>
inline std::ostream & operator<<(std::ostream & stream,
const ArrayPrinter<T> & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#endif /* AKANTU_AKA_ARRAY_PRINTER_HH_ */
diff --git a/src/common/aka_array_tmpl.hh b/src/common/aka_array_tmpl.hh
index 664bbba09..cdc933ad5 100644
--- a/src/common/aka_array_tmpl.hh
+++ b/src/common/aka_array_tmpl.hh
@@ -1,1372 +1,1199 @@
/**
* @file aka_array_tmpl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Jul 15 2010
* @date last modification: Fri Feb 26 2021
*
* @brief Inline functions of the classes Array<T> and ArrayBase
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* Inline Functions Array<T> */
/* -------------------------------------------------------------------------- */
#include "aka_array.hh" // NOLINT
/* -------------------------------------------------------------------------- */
+#include <algorithm>
#include <memory>
+#include <type_traits>
+/* -------------------------------------------------------------------------- */
+//#ifndef __AKANTU_AKA_ARRAY_TMPL_HH__
+//#define __AKANTU_AKA_ARRAY_TMPL_HH__
/* -------------------------------------------------------------------------- */
-
-#ifndef AKANTU_AKA_ARRAY_TMPL_HH_
-#define AKANTU_AKA_ARRAY_TMPL_HH_
namespace akantu {
namespace debug {
struct ArrayException : public Exception {};
} // namespace debug
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(UInt size,
- UInt nb_component,
+ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(Int size, Int nb_component,
const ID & id)
: ArrayBase(id) {
allocate(size, nb_component);
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(UInt size,
- UInt nb_component,
+ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(Int size, Int nb_component,
const_reference value,
const ID & id)
: ArrayBase(id) {
allocate(size, nb_component, value);
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(const ArrayDataLayer & vect,
const ID & id)
: ArrayBase(vect, id) {
this->data_storage = vect.data_storage;
this->size_ = vect.size_;
this->nb_component = vect.nb_component;
this->values = this->data_storage.data();
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(
const std::vector<value_type> & vect) {
this->data_storage = vect;
this->size_ = vect.size();
this->nb_component = 1;
this->values = this->data_storage.data();
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
ArrayDataLayer<T, allocation_trait> &
ArrayDataLayer<T, allocation_trait>::operator=(const ArrayDataLayer & other) {
if (this != &other) {
this->data_storage = other.data_storage;
this->nb_component = other.nb_component;
this->size_ = other.size_;
this->values = this->data_storage.data();
}
return *this;
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-void ArrayDataLayer<T, allocation_trait>::allocate(UInt new_size,
- UInt nb_component) {
+void ArrayDataLayer<T, allocation_trait>::allocate(Int new_size,
+ Int nb_component) {
this->nb_component = nb_component;
this->resize(new_size);
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-void ArrayDataLayer<T, allocation_trait>::allocate(UInt new_size,
- UInt nb_component,
+void ArrayDataLayer<T, allocation_trait>::allocate(Int new_size,
+ Int nb_component,
const T & val) {
this->nb_component = nb_component;
this->resize(new_size, val);
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-void ArrayDataLayer<T, allocation_trait>::resize(UInt new_size) {
+void ArrayDataLayer<T, allocation_trait>::resize(Int new_size) {
this->data_storage.resize(new_size * this->nb_component);
this->values = this->data_storage.data();
this->size_ = new_size;
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-void ArrayDataLayer<T, allocation_trait>::resize(UInt new_size,
+void ArrayDataLayer<T, allocation_trait>::resize(Int new_size,
const T & value) {
this->data_storage.resize(new_size * this->nb_component, value);
this->values = this->data_storage.data();
this->size_ = new_size;
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-void ArrayDataLayer<T, allocation_trait>::reserve(UInt size, UInt new_size) {
- if (new_size != UInt(-1)) {
+void ArrayDataLayer<T, allocation_trait>::reserve(Int size, Int new_size) {
+ if (new_size != -1) {
this->data_storage.resize(new_size * this->nb_component);
}
this->data_storage.reserve(size * this->nb_component);
this->values = this->data_storage.data();
}
/* -------------------------------------------------------------------------- */
/**
* append a tuple to the array with the value value for all components
* @param value the new last tuple or the array will contain nb_component copies
* of value
*/
template <typename T, ArrayAllocationType allocation_trait>
inline void ArrayDataLayer<T, allocation_trait>::push_back(const T & value) {
this->data_storage.push_back(value);
this->values = this->data_storage.data();
this->size_ += 1;
}
/* -------------------------------------------------------------------------- */
/**
* append a matrix or a vector to the array
* @param new_elem a reference to a Matrix<T> or Vector<T> */
template <typename T, ArrayAllocationType allocation_trait>
-template <template <typename> class C, typename>
-inline void
-ArrayDataLayer<T, allocation_trait>::push_back(const C<T> & new_elem) {
+template <typename Derived>
+inline void ArrayDataLayer<T, allocation_trait>::push_back(
+ const Eigen::MatrixBase<Derived> & new_elem) {
AKANTU_DEBUG_ASSERT(
nb_component == new_elem.size(),
"The vector("
<< new_elem.size()
<< ") as not a size compatible with the Array (nb_component="
<< nb_component << ").");
- for (UInt i = 0; i < new_elem.size(); ++i) {
- this->data_storage.push_back(new_elem[i]);
+ for (Idx i = 0; i < new_elem.size(); ++i) {
+ this->data_storage.push_back(new_elem.array()[i]);
}
this->values = this->data_storage.data();
this->size_ += 1;
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-inline UInt ArrayDataLayer<T, allocation_trait>::getAllocatedSize() const {
+inline Int ArrayDataLayer<T, allocation_trait>::getAllocatedSize() const {
return this->data_storage.capacity() / this->nb_component;
}
/* -------------------------------------------------------------------------- */
template <typename T, ArrayAllocationType allocation_trait>
-inline UInt ArrayDataLayer<T, allocation_trait>::getMemorySize() const {
+inline Int ArrayDataLayer<T, allocation_trait>::getMemorySize() const {
return this->data_storage.capacity() * sizeof(T);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <typename T>
class ArrayDataLayer<T, ArrayAllocationType::_pod> : public ArrayBase {
public:
using value_type = T;
using reference = value_type &;
using pointer_type = value_type *;
+ using size_type = typename ArrayBase::size_type;
using const_reference = const value_type &;
public:
~ArrayDataLayer() override { deallocate(); }
/// Allocation of a new vector
- ArrayDataLayer(UInt size = 0, UInt nb_component = 1, const ID & id = "")
+ ArrayDataLayer(Int size = 0, Int nb_component = 1, const ID & id = "")
: ArrayBase(id) {
allocate(size, nb_component);
}
/// Allocation of a new vector with a default value
- ArrayDataLayer(UInt size, UInt nb_component, const_reference value,
+ ArrayDataLayer(Int size, Int nb_component, const_reference value,
const ID & id = "")
: ArrayBase(id) {
allocate(size, nb_component, value);
}
/// Copy constructor (deep copy)
ArrayDataLayer(const ArrayDataLayer & vect, const ID & id = "")
: ArrayBase(vect, id) {
allocate(vect.size(), vect.getNbComponent());
- std::copy_n(vect.storage(), this->size_ * this->nb_component, values);
+ std::copy_n(vect.data(), this->size_ * this->nb_component, values);
}
/// Copy constructor (deep copy)
explicit ArrayDataLayer(const std::vector<value_type> & vect) {
allocate(vect.size(), 1);
std::copy_n(vect.data(), this->size_ * this->nb_component, values);
}
// copy operator
inline ArrayDataLayer & operator=(const ArrayDataLayer & other) {
if (this != &other) {
allocate(other.size(), other.getNbComponent());
- std::copy_n(other.storage(), this->size_ * this->nb_component, values);
+ std::copy_n(other.data(), this->size_ * this->nb_component, values);
}
return *this;
}
// move constructor
inline ArrayDataLayer(ArrayDataLayer && other) noexcept = default;
// move assign
inline ArrayDataLayer & operator=(ArrayDataLayer && other) noexcept = default;
protected:
// deallocate the memory
virtual void deallocate() {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory,
// cppcoreguidelines-no-malloc)
free(this->values);
}
// allocate the memory
- virtual inline void allocate(UInt size, UInt nb_component) {
+ virtual inline void allocate(Int size, Int nb_component) {
if (size != 0) { // malloc can return a non NULL pointer in case size is 0
this->values = static_cast<T *>( // NOLINT
std::malloc(nb_component * size * sizeof(T))); // NOLINT
}
if (this->values == nullptr and size != 0) {
throw std::bad_alloc();
}
this->nb_component = nb_component;
this->allocated_size = this->size_ = size;
}
// allocate and initialize the memory
- virtual inline void allocate(UInt size, UInt nb_component, const T & value) {
+ virtual inline void allocate(Int size, Int nb_component, const T & value) {
allocate(size, nb_component);
std::fill_n(values, size * nb_component, value);
}
public:
/// append a tuple of size nb_component containing value
inline void push_back(const_reference value) {
resize(this->size_ + 1, value);
}
/// append a Vector or a Matrix
- template <template <typename> class C,
- typename = std::enable_if_t<aka::is_tensor<C<T>>::value or
- aka::is_tensor_proxy<C<T>>::value>>
- inline void push_back(const C<T> & new_elem) {
+ template <typename Derived>
+ inline void push_back(const Eigen::MatrixBase<Derived> & new_elem) {
AKANTU_DEBUG_ASSERT(
nb_component == new_elem.size(),
"The vector("
<< new_elem.size()
<< ") as not a size compatible with the Array (nb_component="
<< nb_component << ").");
this->resize(this->size_ + 1);
- std::copy_n(new_elem.storage(), new_elem.size(),
- values + this->nb_component * (this->size_ - 1));
+ make_view(*this, new_elem.rows(), new_elem.cols())
+ .begin()[this->size_ - 1] = new_elem;
}
/// changes the allocated size but not the size
- virtual void reserve(UInt size, UInt new_size = UInt(-1)) {
- UInt tmp_size = this->size_;
- if (new_size != UInt(-1)) {
+ virtual void reserve(Int size, Int new_size = Int(-1)) {
+ auto tmp_size = this->size_;
+ if (new_size != Int(-1)) {
tmp_size = new_size;
}
+
this->resize(size);
this->size_ = std::min(this->size_, tmp_size);
}
/// change the size of the Array
- virtual void resize(UInt size) {
+ virtual void resize(Int size) {
if (size * this->nb_component == 0) {
free(values); // NOLINT: cppcoreguidelines-no-malloc
values = nullptr;
this->allocated_size = 0;
} else {
if (this->values == nullptr) {
this->allocate(size, this->nb_component);
return;
}
Int diff = size - allocated_size;
- UInt size_to_allocate = (std::abs(diff) > AKANTU_MIN_ALLOCATION) ? size
- : (diff > 0)
- ? allocated_size + AKANTU_MIN_ALLOCATION
- : allocated_size;
+ Int size_to_allocate = (std::abs(diff) > AKANTU_MIN_ALLOCATION) ? size
+ : (diff > 0)
+ ? allocated_size + AKANTU_MIN_ALLOCATION
+ : allocated_size;
if (size_to_allocate ==
allocated_size) { // otherwhy the reserve + push_back might fail...
this->size_ = size;
return;
}
auto * tmp_ptr = reinterpret_cast<T *>( // NOLINT
realloc(this->values,
size_to_allocate * this->nb_component * sizeof(T)));
if (tmp_ptr == nullptr) {
throw std::bad_alloc();
}
this->values = tmp_ptr;
this->allocated_size = size_to_allocate;
}
this->size_ = size;
}
/// change the size of the Array and initialize the values
- virtual void resize(UInt size, const T & val) {
- UInt tmp_size = this->size_;
+ virtual void resize(Int size, const T & val) {
+ Int tmp_size = this->size_;
this->resize(size);
if (size > tmp_size) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
std::fill_n(values + this->nb_component * tmp_size,
(size - tmp_size) * this->nb_component, val);
}
}
/// get the amount of space allocated in bytes
- inline UInt getMemorySize() const final {
+ inline size_type getMemorySize() const final {
return this->allocated_size * this->nb_component * sizeof(T);
}
/// Get the real size allocated in memory
- inline UInt getAllocatedSize() const { return this->allocated_size; }
+ inline Int getAllocatedSize() const { return this->allocated_size; }
/// give the address of the memory allocated for this vector
- T * storage() const { return values; };
+ [[deprecated("use data instead to be stl compatible")]] T * storage() const {
+ return values;
+ };
+
+ T * data() const { return values; };
protected:
/// allocation type agnostic data access
T * values{nullptr};
- UInt allocated_size{0};
+ Int allocated_size{0};
};
/* -------------------------------------------------------------------------- */
template <class T, bool is_scal>
-inline auto Array<T, is_scal>::operator()(UInt i, UInt j) -> reference {
+inline auto Array<T, is_scal>::operator()(Int i, Int j) -> reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_) && (j < this->nb_component),
"The value at position ["
<< i << "," << j << "] is out of range in array \""
<< this->id << "\"");
return this->values[i * this->nb_component + j];
}
/* -------------------------------------------------------------------------- */
template <class T, bool is_scal>
-inline auto Array<T, is_scal>::operator()(UInt i, UInt j) const
+inline auto Array<T, is_scal>::operator()(Int i, Int j) const
-> const_reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_) && (j < this->nb_component),
"The value at position ["
<< i << "," << j << "] is out of range in array \""
<< this->id << "\"");
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
return this->values[i * this->nb_component + j];
}
template <class T, bool is_scal>
-inline auto Array<T, is_scal>::operator[](UInt i) -> reference {
+inline auto Array<T, is_scal>::operator[](Int i) -> reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_ * this->nb_component),
"The value at position ["
<< i << "] is out of range in array \"" << this->id
<< "\"");
return this->values[i];
}
/* -------------------------------------------------------------------------- */
template <class T, bool is_scal>
-inline auto Array<T, is_scal>::operator[](UInt i) const -> const_reference {
+inline auto Array<T, is_scal>::operator[](Int i) const -> const_reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_ * this->nb_component),
"The value at position ["
<< i << "] is out of range in array \"" << this->id
<< "\"");
return this->values[i];
}
/* -------------------------------------------------------------------------- */
/**
* erase an element. If the erased element is not the last of the array, the
* last element is moved into the hole in order to maintain contiguity. This
* may invalidate existing iterators (For instance an iterator obtained by
* Array::end() is no longer correct) and will change the order of the
* elements.
* @param i index of element to erase
*/
-template <class T, bool is_scal> inline void Array<T, is_scal>::erase(UInt i) {
+template <class T, bool is_scal> inline void Array<T, is_scal>::erase(Idx i) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT((this->size_ > 0), "The array is empty");
AKANTU_DEBUG_ASSERT((i < this->size_), "The element at position ["
<< i << "] is out of range (" << i
<< ">=" << this->size_ << ")");
if (i != (this->size_ - 1)) {
- for (UInt j = 0; j < this->nb_component; ++j) {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+ for (Idx j = 0; j < this->nb_component; ++j) {
this->values[i * this->nb_component + j] =
this->values[(this->size_ - 1) * this->nb_component + j];
}
}
this->resize(this->size_ - 1);
AKANTU_DEBUG_OUT();
}
+/* ------------------------------------------------------------------------ */
+template <class T, bool is_scal>
+template <typename R>
+inline auto Array<T, is_scal>::erase(const view_iterator<R> & it) {
+ auto && curr = it.data();
+ Idx pos = (curr - this->values) / this->nb_component;
+ erase(pos);
+ view_iterator<R> rit = it;
+ return --rit;
+}
+
/* -------------------------------------------------------------------------- */
/**
* Subtract another array entry by entry from this array in place. Both arrays
* must
* have the same size and nb_component. If the arrays have different shapes,
* code compiled in debug mode will throw an expeption and optimised code
* will behave in an unpredicted manner
* @param other array to subtract from this
* @return reference to modified this
*/
template <class T, bool is_scal>
Array<T, is_scal> &
-Array<T, is_scal>::operator-=(const Array<T, is_scal> & other) {
- AKANTU_DEBUG_ASSERT((this->size_ == other.size_) &&
- (this->nb_component == other.nb_component),
+Array<T, is_scal>::operator-=(const Array<T, is_scal> & vect) {
+ AKANTU_DEBUG_ASSERT((this->size_ == vect.size_) &&
+ (this->nb_component == vect.nb_component),
"The too array don't have the same sizes");
T * a = this->values;
- T * b = other.storage();
- for (UInt i = 0; i < this->size_ * this->nb_component; ++i) {
+ T * b = vect.data();
+ for (Idx i = 0; i < this->size_ * this->nb_component; ++i) {
*a -= *b;
++a;
++b;
}
return *this;
}
/* --------------------------------------------------------------------------
*/
/**
* Add another array entry by entry to this array in
* place. Both arrays must have the same size and
* nb_component. If the arrays have different shapes, code
* compiled in debug mode will throw an expeption and
* optimised code will behave in an unpredicted manner
* @param other array to add to this
* @return reference to modified this
*/
template <class T, bool is_scal>
Array<T, is_scal> &
-Array<T, is_scal>::operator+=(const Array<T, is_scal> & other) {
- AKANTU_DEBUG_ASSERT((this->size_ == other.size()) &&
- (this->nb_component == other.nb_component),
+Array<T, is_scal>::operator+=(const Array<T, is_scal> & vect) {
+ AKANTU_DEBUG_ASSERT((this->size_ == vect.size()) &&
+ (this->nb_component == vect.nb_component),
"The too array don't have the same sizes");
T * a = this->values;
- T * b = other.storage();
- for (UInt i = 0; i < this->size_ * this->nb_component; ++i) {
+ T * b = vect.data();
+ for (Idx i = 0; i < this->size_ * this->nb_component; ++i) {
*a++ += *b++;
}
return *this;
}
/* --------------------------------------------------------------------------
*/
/**
* Multiply all entries of this array by a scalar in place
* @param alpha scalar multiplicant
* @return reference to modified this
*/
template <class T, bool is_scal>
-Array<T, is_scal> & Array<T, is_scal>::operator*=(const T & alpha) {
+auto Array<T, is_scal>::operator*=(const T & alpha) -> Array & {
T * a = this->values;
- for (UInt i = 0; i < this->size_ * this->nb_component; ++i) {
+ for (Idx i = 0; i < this->size_ * this->nb_component; ++i) {
*a++ *= alpha;
}
return *this;
}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------- */
/**
* Compare this array element by element to another.
* @param other array to compare to
* @return true it all element are equal and arrays have
* the same shape, else false
*/
template <class T, bool is_scal>
-bool Array<T, is_scal>::operator==(const Array<T, is_scal> & other) const {
+bool Array<T, is_scal>::operator==(const Array & other) const {
bool equal = this->nb_component == other.nb_component &&
this->size_ == other.size_ && this->id == other.id;
if (not equal) {
return false;
}
- if (this->values == other.storage()) {
+
+ if (this->values == other.data()) {
return true;
}
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
return std::equal(this->values,
this->values + this->size_ * this->nb_component,
- other.storage());
+ other.data());
}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
bool Array<T, is_scal>::operator!=(const Array<T, is_scal> & other) const {
return !operator==(other);
}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
/**
* set all tuples of the array to a given vector or matrix
* @param vm Matrix or Vector to fill the array with
*/
template <class T, bool is_scal>
-template <template <typename> class C, typename>
-inline void Array<T, is_scal>::set(const C<T> & vm) {
- AKANTU_DEBUG_ASSERT(this->nb_component == vm.size(),
- "The size of the object does not "
- "match the number of components");
- for (T * it = this->values;
- it < this->values + this->nb_component * this->size_;
- it += this->nb_component) {
- std::copy_n(vm.storage(), this->nb_component, it);
+template <typename C, std::enable_if_t<aka::is_tensor<C>::value> *>
+inline void Array<T, is_scal>::set(const C & elem) {
+ AKANTU_DEBUG_ASSERT(
+ this->nb_component == elem.array().size(),
+ "The size of the object does not match the number of components");
+
+ for (auto && v : make_view(*this, this->nb_component)) {
+ v = elem.reshaped(this->nb_component, 1);
}
}
-/* --------------------------------------------------------------------------
- */
+
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
-void Array<T, is_scal>::append(const Array<T> & other) {
- AKANTU_DEBUG_ASSERT(this->nb_component == other.nb_component,
- "Cannot append an array with a "
- "different number of component");
- UInt old_size = this->size_;
+void Array<T, is_scal>::append(const Array & other) {
+ AKANTU_DEBUG_ASSERT(
+ this->nb_component == other.nb_component,
+ "Cannot append an array with a different number of component");
+ Idx old_size = this->size_;
this->resize(this->size_ + other.size());
T * tmp = this->values + this->nb_component * old_size;
- std::copy_n(other.storage(), other.size() * this->nb_component, tmp);
+ std::copy_n(other.data(), other.size() * this->nb_component, tmp);
}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
/* Functions Array<T, is_scal> */
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
-Array<T, is_scal>::Array(UInt size, UInt nb_component, const ID & id)
+Array<T, is_scal>::Array(Int size, Int nb_component, const ID & id)
: parent(size, nb_component, id) {}
template <>
-inline Array<std::string, false>::Array(UInt size, UInt nb_component,
+inline Array<std::string, false>::Array(Int size, Int nb_component,
const ID & id)
: parent(size, nb_component, "", id) {}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
-Array<T, is_scal>::Array(UInt size, UInt nb_component, const_reference value,
+Array<T, is_scal>::Array(Int size, Int nb_component, const_reference value,
const ID & id)
: parent(size, nb_component, value, id) {}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
Array<T, is_scal>::Array(const Array & vect, const ID & id)
: parent(vect, id) {}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
-Array<T, is_scal> &
-Array<T, is_scal>::operator=(const Array<T, is_scal> & other) {
+auto Array<T, is_scal>::operator=(const Array & other) -> Array & {
AKANTU_DEBUG_WARNING("You are copying the array "
<< this->id << " are you sure it is on purpose");
-
if (&other == this) {
return *this;
}
parent::operator=(other);
return *this;
}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
Array<T, is_scal>::Array(const std::vector<T> & vect) : parent(vect) {}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal> Array<T, is_scal>::~Array() = default;
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
/**
* search elem in the array, return the position of the
* first occurrence or -1 if not found
* @param elem the element to look for
* @return index of the first occurrence of elem or -1 if
* elem is not present
*/
template <class T, bool is_scal>
-UInt Array<T, is_scal>::find(const_reference elem) const {
+Idx Array<T, is_scal>::find(const_reference elem) const {
AKANTU_DEBUG_IN();
auto begin = this->begin();
auto end = this->end();
auto it = std::find(begin, end, elem);
AKANTU_DEBUG_OUT();
- return (it != end) ? it - begin : UInt(-1);
+ return (it != end) ? it - begin : Idx(-1);
}
-/* --------------------------------------------------------------------------
- */
-// template <class T, bool is_scal> UInt Array<T,
-// is_scal>::find(T elem[]) const
-// {
-// AKANTU_DEBUG_IN();
-// T * it = this->values;
-// UInt i = 0;
-// for (; i < this->size_; ++i) {
-// if (*it == elem[0]) {
-// T * cit = it;
-// UInt c = 0;
-// for (; (c < this->nb_component) && (*cit ==
-// elem[c]); ++c, ++cit)
-// ;
-// if (c == this->nb_component) {
-// AKANTU_DEBUG_OUT();
-// return i;
-// }
-// }
-// it += this->nb_component;
-// }
-// return UInt(-1);
-// }
-
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
-template <template <typename> class C, typename>
-inline UInt Array<T, is_scal>::find(const C<T> & elem) {
+template <typename V, std::enable_if_t<aka::is_tensor<V>::value> *>
+inline Idx Array<T, is_scal>::find(const V & elem) {
AKANTU_DEBUG_ASSERT(elem.size() == this->nb_component,
"Cannot find an element with a wrong size ("
<< elem.size() << ") != " << this->nb_component);
- return this->find(*elem.storage());
+ auto && view = make_view(*this, elem.size());
+
+ auto begin = view.begin();
+ auto end = view.end();
+ auto it = std::find(begin, end, elem);
+
+ return (it != end) ? it - begin : Idx(-1);
}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
/**
* copy the content of another array. This overwrites the
* current content.
* @param other Array to copy into this array. It has to
* have the same nb_component as this. If compiled in
* debug mode, an incorrect other will result in an
* exception being thrown. Optimised code may result in
* unpredicted behaviour.
* @param no_sanity_check turns off all checkes
*/
template <class T, bool is_scal>
void Array<T, is_scal>::copy(const Array<T, is_scal> & other,
bool no_sanity_check) {
AKANTU_DEBUG_IN();
if (not no_sanity_check and (other.nb_component != this->nb_component)) {
AKANTU_ERROR("The two arrays do not have the same "
"number of components");
}
this->resize((other.size_ * other.nb_component) / this->nb_component);
- std::copy_n(other.storage(), this->size_ * this->nb_component, this->values);
+ std::copy_n(other.data(), this->size_ * this->nb_component, this->values);
AKANTU_DEBUG_OUT();
}
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <bool is_scal> class ArrayPrintHelper {
public:
template <typename T>
static void print_content(const Array<T> & vect, std::ostream & stream,
int indent) {
std::string space(indent, AKANTU_INDENT);
stream << space << " + values : {";
- for (UInt i = 0; i < vect.size(); ++i) {
+ for (Idx i = 0; i < vect.size(); ++i) {
stream << "{";
- for (UInt j = 0; j < vect.getNbComponent(); ++j) {
+ for (Idx j = 0; j < vect.getNbComponent(); ++j) {
stream << vect(i, j);
if (j != vect.getNbComponent() - 1) {
stream << ", ";
}
}
stream << "}";
if (i != vect.size() - 1) {
stream << ", ";
}
}
stream << "}" << std::endl;
}
};
template <> class ArrayPrintHelper<false> {
public:
template <typename T>
static void print_content(__attribute__((unused)) const Array<T> & vect,
__attribute__((unused)) std::ostream & stream,
__attribute__((unused)) int indent) {}
};
-/* --------------------------------------------------------------------------
- */
+/* ------------------------------------------------------------------------ */
template <class T, bool is_scal>
void Array<T, is_scal>::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
std::streamsize prec = stream.precision();
std::ios_base::fmtflags ff = stream.flags();
stream.setf(std::ios_base::showbase);
stream.precision(2);
stream << space << "Array<" << debug::demangle(typeid(T).name()) << "> ["
<< std::endl;
stream << space << " + id : " << this->id << std::endl;
stream << space << " + size : " << this->size_ << std::endl;
stream << space << " + nb_component : " << this->nb_component << std::endl;
stream << space << " + allocated size : " << this->getAllocatedSize()
<< std::endl;
stream << space
<< " + memory size : " << printMemorySize<T>(this->getMemorySize())
<< std::endl;
if (not AKANTU_DEBUG_LEVEL_IS_TEST()) {
stream << space << " + address : " << std::hex << this->values
<< std::dec << std::endl;
}
stream.precision(prec);
stream.flags(ff);
if (AKANTU_DEBUG_TEST(dblDump) || AKANTU_DEBUG_LEVEL_IS_TEST()) {
ArrayPrintHelper<is_scal or std::is_enum<T>::value>::print_content(
*this, stream, indent);
}
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
template <typename T, bool is_scal>
template <typename OT, std::enable_if_t<std::is_arithmetic<OT>::value> *>
bool Array<T, is_scal>::isFinite() const noexcept {
return std::all_of(this->values,
this->values + this->size_ * this->nb_component,
[](auto && a) { return std::isfinite(a); });
}
-/* -------------------------------------------------------------------------- */
-/* Inline Functions ArrayBase */
-/* -------------------------------------------------------------------------- */
-
-// inline bool ArrayBase::empty() { return (this->size_ ==
-// 0); }
-
-/* -------------------------------------------------------------------------- */
-/* Iterators */
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-template <class R, class daughter, class IR, bool is_tensor>
-class Array<T, is_scal>::iterator_internal {
-public:
- using value_type = R;
- using pointer = R *;
- using reference = R &;
- using const_reference = const R &;
- using internal_value_type = IR;
- using internal_pointer = IR *;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
- static_assert(not is_tensor, "Cannot handle tensors");
-
-public:
- iterator_internal(pointer data = nullptr) : ret(data), initial(data){};
- iterator_internal(const iterator_internal & it) = default;
- iterator_internal(iterator_internal && it) noexcept = default;
-
- virtual ~iterator_internal() = default;
-
- inline iterator_internal & operator=(const iterator_internal & it) = default;
- inline iterator_internal &
- operator=(iterator_internal && it) noexcept = default;
-
- UInt getCurrentIndex() { return (this->ret - this->initial); };
-
- inline reference operator*() { return *ret; };
- inline const_reference operator*() const { return *ret; };
- inline pointer operator->() { return ret; };
- inline daughter & operator++() {
- ++ret;
- return static_cast<daughter &>(*this);
- };
- inline daughter & operator--() {
- --ret;
- return static_cast<daughter &>(*this);
- };
-
- inline daughter & operator+=(const UInt n) {
- ret += n;
- return static_cast<daughter &>(*this);
- }
- inline daughter & operator-=(const UInt n) {
- ret -= n;
- return static_cast<daughter &>(*this);
- }
-
- inline reference operator[](const UInt n) { return ret[n]; }
-
- inline bool operator==(const iterator_internal & other) const {
- return ret == other.ret;
- }
- inline bool operator!=(const iterator_internal & other) const {
- return ret != other.ret;
- }
- inline bool operator<(const iterator_internal & other) const {
- return ret < other.ret;
- }
- inline bool operator<=(const iterator_internal & other) const {
- return ret <= other.ret;
- }
- inline bool operator>(const iterator_internal & other) const {
- return ret > other.ret;
- }
- inline bool operator>=(const iterator_internal & other) const {
- return ret >= other.ret;
- }
-
- inline daughter operator-(difference_type n) const {
- return daughter(ret - n);
- }
- inline daughter operator+(difference_type n) const {
- return daughter(ret + n);
- }
-
- inline difference_type operator-(const iterator_internal & b) const {
- return ret - b.ret;
- }
-
- inline pointer data() const { return ret; }
-
-protected:
- pointer ret{nullptr};
- pointer initial{nullptr};
-};
-
-/* --------------------------------------------------------------------------
- */
-/**
- * Specialization for scalar types
- */
-template <class T, bool is_scal>
-template <class R, class daughter, class IR>
-class Array<T, is_scal>::iterator_internal<R, daughter, IR, true> {
-public:
- using value_type = R;
- using pointer = R *;
- using pointer_type = typename Array<T, is_scal>::pointer_type;
- using reference = R &;
- using proxy = typename R::proxy;
- using const_proxy = const typename R::proxy;
- using const_reference = const R &;
- using internal_value_type = IR;
- using internal_pointer = IR *;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
-
+/* ------------------------------------------------------------------------ */
+/* ArrayFilter */
+/* ------------------------------------------------------------------------ */
+template <typename T> class ArrayFilter {
public:
- iterator_internal() = default;
-
- iterator_internal(pointer_type data, UInt _offset)
- : _offset(_offset), initial(data), ret(nullptr), ret_ptr(data) {
- AKANTU_ERROR("The constructor should never be called "
- "it is just an ugly trick...");
- }
-
- iterator_internal(std::unique_ptr<internal_value_type> && wrapped)
- : _offset(wrapped->size()), initial(wrapped->storage()),
- ret(std::move(wrapped)), ret_ptr(ret->storage()) {}
-
- iterator_internal(const iterator_internal & it) {
- if (this != &it) {
- this->_offset = it._offset;
- this->initial = it.initial;
- this->ret_ptr = it.ret_ptr;
- this->ret = std::make_unique<internal_value_type>(*it.ret, false);
+ /// const iterator
+ template <class original_iterator, typename filter_iterator>
+ class const_iterator {
+ public:
+ Idx getCurrentIndex() {
+ return (*this->filter_it * this->nb_item_per_elem +
+ this->sub_element_counter);
}
- }
- iterator_internal(iterator_internal && it) noexcept = default;
+ inline const_iterator() = default;
+ inline const_iterator(original_iterator origin_it,
+ filter_iterator filter_it, Int nb_item_per_elem)
+ : origin_it(std::move(origin_it)), filter_it(std::move(filter_it)),
+ nb_item_per_elem(nb_item_per_elem), sub_element_counter(0){};
- virtual ~iterator_internal() = default;
+ inline bool operator!=(const_iterator & other) const {
+ return !((*this) == other);
+ }
+ inline bool operator==(const_iterator & other) const {
+ return (this->origin_it == other.origin_it &&
+ this->filter_it == other.filter_it &&
+ this->sub_element_counter == other.sub_element_counter);
+ }
- inline iterator_internal & operator=(const iterator_internal & it) {
- if (this != &it) {
- this->_offset = it._offset;
- this->initial = it.initial;
- this->ret_ptr = it.ret_ptr;
- if (this->ret) {
- this->ret->shallowCopy(*it.ret);
- } else {
- this->ret = std::make_unique<internal_value_type>(*it.ret, false);
- }
+ inline bool operator!=(const const_iterator & other) const {
+ return !((*this) == other);
+ }
+ inline bool operator==(const const_iterator & other) const {
+ return (this->origin_it == other.origin_it &&
+ this->filter_it == other.filter_it &&
+ this->sub_element_counter == other.sub_element_counter);
}
- return *this;
- }
- inline iterator_internal &
- operator=(iterator_internal && it) noexcept = default;
+ inline const_iterator & operator++() {
+ ++sub_element_counter;
+ if (sub_element_counter == nb_item_per_elem) {
+ sub_element_counter = 0;
+ ++filter_it;
+ }
+ return *this;
+ };
- UInt getCurrentIndex() {
- return (this->ret_ptr - this->initial) / this->_offset;
- };
+ inline decltype(auto) operator*() {
+ return origin_it[nb_item_per_elem * (*filter_it) + sub_element_counter];
+ };
- inline reference operator*() {
- ret->values = ret_ptr;
- return *ret;
- };
- inline const_reference operator*() const {
- ret->values = ret_ptr;
- return *ret;
- };
- inline pointer operator->() {
- ret->values = ret_ptr;
- return ret.get();
- };
- inline daughter & operator++() {
- ret_ptr += _offset;
- return static_cast<daughter &>(*this);
- };
- inline daughter & operator--() {
- ret_ptr -= _offset;
- return static_cast<daughter &>(*this);
+ private:
+ original_iterator origin_it;
+ filter_iterator filter_it;
+ /// the number of item per element
+ Int nb_item_per_elem;
+ /// counter for every sub element group
+ Int sub_element_counter;
};
- inline daughter & operator+=(const UInt n) {
- ret_ptr += _offset * n;
- return static_cast<daughter &>(*this);
- }
- inline daughter & operator-=(const UInt n) {
- ret_ptr -= _offset * n;
- return static_cast<daughter &>(*this);
- }
-
- inline proxy operator[](const UInt n) {
- ret->values = ret_ptr + n * _offset;
- return proxy(*ret);
- }
- inline const_proxy operator[](const UInt n) const { // NOLINT
- ret->values = ret_ptr + n * _offset;
- return const_proxy(*ret);
- }
-
- inline bool operator==(const iterator_internal & other) const {
- return this->ret_ptr == other.ret_ptr;
- }
- inline bool operator!=(const iterator_internal & other) const {
- return this->ret_ptr != other.ret_ptr;
- }
- inline bool operator<(const iterator_internal & other) const {
- return this->ret_ptr < other.ret_ptr;
- }
- inline bool operator<=(const iterator_internal & other) const {
- return this->ret_ptr <= other.ret_ptr;
- }
- inline bool operator>(const iterator_internal & other) const {
- return this->ret_ptr > other.ret_ptr;
- }
- inline bool operator>=(const iterator_internal & other) const {
- return this->ret_ptr >= other.ret_ptr;
- }
-
- inline daughter operator+(difference_type n) const {
- daughter tmp(static_cast<const daughter &>(*this));
- tmp += n;
- return tmp;
- }
- inline daughter operator-(difference_type n) const {
- daughter tmp(static_cast<const daughter &>(*this));
- tmp -= n;
- return tmp;
- }
-
- inline difference_type operator-(const iterator_internal & b) const {
- return (this->ret_ptr - b.ret_ptr) / _offset;
- }
-
- inline pointer_type data() const { return ret_ptr; }
- inline difference_type offset() const { return _offset; }
-
-protected:
- UInt _offset{0};
- pointer_type initial{nullptr};
- std::unique_ptr<internal_value_type> ret{nullptr};
- pointer_type ret_ptr{nullptr};
-};
-
-/* -------------------------------------------------------------------------- */
-/* Iterators */
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-template <typename R>
-class Array<T, is_scal>::const_iterator
- : public iterator_internal<const R, Array<T, is_scal>::const_iterator<R>,
- R> {
-public:
- using parent = iterator_internal<const R, const_iterator, R>;
- using value_type = typename parent::value_type;
- using pointer = typename parent::pointer;
- using reference = typename parent::reference;
- using difference_type = typename parent::difference_type;
- using iterator_category = typename parent::iterator_category;
-
+ using vector_iterator = void; // iterator<Vector<T>>;
+ using array_type = Array<T>;
+ using const_vector_iterator =
+ const_iterator<typename array_type::const_vector_iterator,
+ Array<Idx>::const_scalar_iterator>;
+ using value_type = typename array_type::value_type;
+
+private:
+ /* ---------------------------------------------------------------------- */
+ /* Constructors/Destructors */
+ /* ---------------------------------------------------------------------- */
public:
- ~const_iterator() override = default;
-
- const_iterator() = default;
- const_iterator(const const_iterator & it) = default;
- const_iterator(const_iterator && it) noexcept = default;
-
- const_iterator & operator=(const const_iterator & it) = default;
- const_iterator & operator=(const_iterator && it) noexcept = default;
-
- template <typename P,
- typename = std::enable_if_t<not aka::is_tensor<P>::value>>
- const_iterator(P * data) : parent(data) {}
-
- template <typename UP_P, typename = std::enable_if_t<aka::is_tensor<
- typename UP_P::element_type>::value>>
- const_iterator(UP_P && tensor) : parent(std::forward<UP_P>(tensor)) {}
-};
-
-/* -------------------------------------------------------------------------- */
-template <class T, class R, bool is_tensor_ = aka::is_tensor<R>::value>
-struct ConstConverterIteratorHelper {
- using const_iterator = typename Array<T>::template const_iterator<R>;
- using iterator = typename Array<T>::template iterator<R>;
-
- static inline const_iterator convert(const iterator & it) {
- return const_iterator(std::unique_ptr<R>(new R(*it, false)));
- }
-};
+ ArrayFilter(const Array<T> & array, const Array<Idx> & filter,
+ Int nb_item_per_elem)
+ : array(array), filter(filter), nb_item_per_elem(nb_item_per_elem){};
+
+ decltype(auto) begin_reinterpret(Int n, Int new_size) const {
+ Int new_nb_item_per_elem = this->nb_item_per_elem;
+ if (new_size != 0 && n != 0)
+ new_nb_item_per_elem = this->array.getNbComponent() *
+ this->filter.size() * this->nb_item_per_elem /
+ (n * new_size);
+
+ return const_vector_iterator(make_view(this->array, n).begin(),
+ this->filter.begin(), new_nb_item_per_elem);
+ };
-template <class T, class R> struct ConstConverterIteratorHelper<T, R, false> {
- using const_iterator = typename Array<T>::template const_iterator<R>;
- using iterator = typename Array<T>::template iterator<R>;
- static inline const_iterator convert(const iterator & it) {
- return const_iterator(it.data());
- }
-};
+ decltype(auto) end_reinterpret(Int n, Int new_size) const {
+ Int new_nb_item_per_elem = this->nb_item_per_elem;
+ if (new_size != 0 && n != 0)
+ new_nb_item_per_elem = this->array.getNbComponent() *
+ this->filter.size() * this->nb_item_per_elem /
+ (n * new_size);
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-template <typename R>
-class Array<T, is_scal>::iterator
- : public iterator_internal<R, Array<T, is_scal>::iterator<R>> {
-public:
- using parent = iterator_internal<R, iterator>;
- using value_type = typename parent::value_type;
- using pointer = typename parent::pointer;
- using reference = typename parent::reference;
- using difference_type = typename parent::difference_type;
- using iterator_category = typename parent::iterator_category;
+ return const_vector_iterator(make_view(this->array, n).begin(),
+ this->filter.end(), new_nb_item_per_elem);
+ };
-public:
- ~iterator() override = default;
- iterator() = default;
- iterator(const iterator & it) = default;
- iterator(iterator && it) noexcept = default;
- iterator & operator=(const iterator & it) = default;
- iterator & operator=(iterator && it) noexcept = default;
-
- template <typename P,
- typename = std::enable_if_t<not aka::is_tensor<P>::value>>
- iterator(P * data) : parent(data) {}
-
- template <typename UP_P, typename = std::enable_if_t<aka::is_tensor<
- typename UP_P::element_type>::value>>
- iterator(UP_P && tensor) : parent(std::forward<UP_P>(tensor)) {}
-
- operator const_iterator<R>() {
- return ConstConverterIteratorHelper<T, R>::convert(*this);
- }
+ // vector_iterator begin_reinterpret(Int, Int) { throw; };
+ // vector_iterator end_reinterpret(Int, Int) { throw; };
+
+ /// return the size of the filtered array which is the filter size
+ Int size() const { return this->filter.size() * this->nb_item_per_elem; };
+ /// the number of components of the filtered array
+ Int getNbComponent() const { return this->array.getNbComponent(); };
+
+ /// tells if the container is empty
+ [[nodiscard]] bool empty() const { return (size() == 0); }
+ /* ---------------------------------------------------------------------- */
+ /* Class Members */
+ /* ---------------------------------------------------------------------- */
+private:
+ /// reference to array of data
+ const Array<T> & array;
+ /// reference to the filter used to select elements
+ const Array<Idx> & filter;
+ /// the number of item per element
+ Int nb_item_per_elem;
};
-/* -------------------------------------------------------------------------- */
-/* Begin/End functions implementation */
-/* -------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------ */
+/* Begin/End functions implementation */
+/* ------------------------------------------------------------------------ */
namespace detail {
template <class Tuple, size_t... Is>
constexpr auto take_front_impl(Tuple && t,
std::index_sequence<Is...> /*idxs*/) {
return std::make_tuple(std::get<Is>(std::forward<Tuple>(t))...);
}
template <size_t N, class Tuple> constexpr auto take_front(Tuple && t) {
return take_front_impl(std::forward<Tuple>(t),
std::make_index_sequence<N>{});
}
- template <typename... V> constexpr auto product_all(V &&... v) {
- std::common_type_t<int, V...> result = 1;
- (void)std::initializer_list<int>{(result *= v, 0)...};
- return result;
- }
-
template <typename... T> std::string to_string_all(T &&... t) {
if (sizeof...(T) == 0) {
return "";
}
std::stringstream ss;
bool noComma = true;
ss << "(";
(void)std::initializer_list<bool>{
(ss << (noComma ? "" : ", ") << t, noComma = false)...};
ss << ")";
return ss.str();
}
template <std::size_t N> struct InstantiationHelper {
template <typename type, typename T, typename... Ns>
static auto instantiate(T && data, Ns... ns) {
return std::make_unique<type>(data, ns...);
}
};
template <> struct InstantiationHelper<0> {
template <typename type, typename T> static auto instantiate(T && data) {
return data;
}
};
template <typename Arr, typename T, typename... Ns>
- decltype(auto) get_iterator(Arr && array, T * data, Ns &&... ns) {
- using type = IteratorHelper_t<sizeof...(Ns) - 1, T>;
- using array_type = std::decay_t<Arr>;
- using iterator =
- std::conditional_t<std::is_const<std::remove_reference_t<Arr>>::value,
- typename array_type::template const_iterator<type>,
- typename array_type::template iterator<type>>;
+ decltype(auto) __attribute__((visibility("hidden")))
+ get_iterator(Arr && array, T * data, Ns &&... ns) {
+ const bool is_const_arr =
+ std::is_const<std::remove_reference_t<Arr>>::value;
+ using type = ViewIteratorHelper_t<sizeof...(Ns) - 1, T>;
+ using iterator = std::conditional_t<is_const_arr, const_view_iterator<type>,
+ view_iterator<type>>;
static_assert(sizeof...(Ns), "You should provide a least one size");
if (array.getNbComponent() * array.size() !=
- product_all(std::forward<Ns>(ns)...)) {
+ Int(product_all(std::forward<Ns>(ns)...))) {
AKANTU_CUSTOM_EXCEPTION_INFO(
debug::ArrayException(),
"The iterator on "
<< debug::demangle(typeid(Arr).name())
<< to_string_all(array.size(), array.getNbComponent())
<< "is not compatible with the type "
<< debug::demangle(typeid(type).name()) << to_string_all(ns...));
}
- auto && wrapped = aka::apply(
- [&](auto... n) {
- return InstantiationHelper<sizeof...(n)>::template instantiate<type>(
- data, n...);
- },
- take_front<sizeof...(Ns) - 1>(std::make_tuple(ns...)));
-
- return iterator(std::move(wrapped));
+ return std::apply([&](auto... n) { return iterator(data, n...); },
+ take_front<sizeof...(Ns) - 1>(std::make_tuple(ns...)));
}
} // namespace detail
-/* -------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------ */
+/* ------------------------------------------------------------------------ */
+template <class T, bool is_scal>
+template <typename... Ns>
+inline auto Array<T, is_scal>::begin(Ns &&... ns) {
+ return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...,
+ this->size_);
+}
+
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::begin(Ns &&... ns) {
+inline auto Array<T, is_scal>::end(Ns &&... ns) {
+ return detail::get_iterator(*this,
+ this->values + this->nb_component * this->size_,
+ std::forward<Ns>(ns)..., this->size_);
+}
+
+template <class T, bool is_scal>
+template <typename... Ns>
+inline auto Array<T, is_scal>::begin(Ns &&... ns) const {
return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...,
this->size_);
}
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::end(Ns &&... ns) {
+inline auto Array<T, is_scal>::end(Ns &&... ns) const {
return detail::get_iterator(*this,
this->values + this->nb_component * this->size_,
std::forward<Ns>(ns)..., this->size_);
}
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::begin(Ns &&... ns) const {
+inline auto Array<T, is_scal>::cbegin(Ns &&... ns) const {
return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...,
this->size_);
}
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::end(Ns &&... ns) const {
+inline auto Array<T, is_scal>::cend(Ns &&... ns) const {
return detail::get_iterator(*this,
this->values + this->nb_component * this->size_,
std::forward<Ns>(ns)..., this->size_);
}
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns &&... ns) {
+inline auto Array<T, is_scal>::begin_reinterpret(Ns &&... ns) {
return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...);
}
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::end_reinterpret(Ns &&... ns) {
+inline auto Array<T, is_scal>::end_reinterpret(Ns &&... ns) {
return detail::get_iterator(
*this, this->values + detail::product_all(std::forward<Ns>(ns)...),
std::forward<Ns>(ns)...);
}
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns &&... ns) const {
+inline auto Array<T, is_scal>::begin_reinterpret(Ns &&... ns) const {
return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...);
}
template <class T, bool is_scal>
template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::end_reinterpret(Ns &&... ns) const {
+inline auto Array<T, is_scal>::end_reinterpret(Ns &&... ns) const {
return detail::get_iterator(
*this, this->values + detail::product_all(std::forward<Ns>(ns)...),
std::forward<Ns>(ns)...);
}
-/* -------------------------------------------------------------------------- */
-/* Views */
-/* -------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------ */
+/* Views */
+/* ------------------------------------------------------------------------ */
namespace detail {
template <typename Array, typename... Ns> class ArrayView {
using tuple = std::tuple<Ns...>;
public:
+ using size_type = Idx;
+
~ArrayView() = default;
- ArrayView(Array && array, Ns... ns) noexcept
+ constexpr ArrayView(Array && array, Ns... ns) noexcept
: array(array), sizes(std::move(ns)...) {}
- ArrayView(const ArrayView & array_view) = default;
- ArrayView & operator=(const ArrayView & array_view) = default;
+ constexpr ArrayView(const ArrayView & array_view) = default;
+ constexpr ArrayView(ArrayView && array_view) noexcept = default;
- ArrayView(ArrayView && array_view) noexcept = default;
- ArrayView & operator=(ArrayView && array_view) noexcept = default;
+ constexpr ArrayView & operator=(const ArrayView & array_view) = default;
+ constexpr ArrayView & operator=(ArrayView && array_view) noexcept = default;
- decltype(auto) begin() {
- return aka::apply(
- [&](auto &&... ns) { return array.get().begin_reinterpret(ns...); },
+ auto begin() {
+ return std::apply(
+ [&](auto &&... ns) {
+ return detail::get_iterator(array.get(), array.get().data(),
+ std::forward<decltype(ns)>(ns)...);
+ },
sizes);
}
- decltype(auto) begin() const {
- return aka::apply(
- [&](auto &&... ns) { return array.get().begin_reinterpret(ns...); },
+ auto begin() const {
+ return std::apply(
+ [&](auto &&... ns) {
+ return detail::get_iterator(array.get(), array.get().data(),
+ std::forward<decltype(ns)>(ns)...);
+ },
sizes);
}
- decltype(auto) end() {
- return aka::apply(
- [&](auto &&... ns) { return array.get().end_reinterpret(ns...); },
+ auto end() {
+ return std::apply(
+ [&](auto &&... ns) {
+ return detail::get_iterator(
+ array.get(),
+ array.get().data() +
+ detail::product_all(std::forward<decltype(ns)>(ns)...),
+ std::forward<decltype(ns)>(ns)...);
+ },
sizes);
}
- decltype(auto) end() const {
- return aka::apply(
- [&](auto &&... ns) { return array.get().end_reinterpret(ns...); },
+ auto end() const {
+ return std::apply(
+ [&](auto &&... ns) {
+ return detail::get_iterator(
+ array.get(),
+ array.get().data() +
+ detail::product_all(std::forward<decltype(ns)>(ns)...),
+ std::forward<decltype(ns)>(ns)...);
+ },
sizes);
}
- decltype(auto) size() const {
+ auto cbegin() const { return this->begin(); }
+ auto cend() const { return this->end(); }
+
+ constexpr auto size() const {
return std::get<std::tuple_size<tuple>::value - 1>(sizes);
}
- decltype(auto) dims() const { return std::tuple_size<tuple>::value - 1; }
+ constexpr auto dims() const { return std::tuple_size<tuple>::value - 1; }
private:
std::reference_wrapper<std::remove_reference_t<Array>> array;
tuple sizes;
};
+
+ /* ---------------------------------------------------------------------- */
+ template <typename T, typename... Ns>
+ class ArrayView<const ArrayFilter<T> &, Ns...> {
+ using tuple = std::tuple<Ns...>;
+
+ public:
+ constexpr ArrayView(const ArrayFilter<T> & array, Ns... ns)
+ : array(array), sizes(std::move(ns)...) {}
+
+ constexpr ArrayView(const ArrayView & array_view) = default;
+ constexpr ArrayView(ArrayView && array_view) = default;
+
+ constexpr ArrayView & operator=(const ArrayView & array_view) = default;
+ constexpr ArrayView & operator=(ArrayView && array_view) = default;
+
+ auto begin() const {
+ return std::apply(
+ [&](auto &&... ns) {
+ return array.get().begin_reinterpret(
+ std::forward<decltype(ns)>(ns)...);
+ },
+ sizes);
+ }
+
+ auto end() const {
+ return std::apply(
+ [&](auto &&... ns) {
+ return array.get().end_reinterpret(
+ std::forward<decltype(ns)>(ns)...);
+ },
+ sizes);
+ }
+
+ auto cbegin() const { return this->begin(); }
+ auto cend() const { return this->end(); }
+
+ constexpr auto size() const {
+ return std::get<std::tuple_size<tuple>::value - 1>(sizes);
+ }
+
+ constexpr auto dims() const { return std::tuple_size<tuple>::value - 1; }
+
+ private:
+ std::reference_wrapper<const ArrayFilter<T>> array;
+ tuple sizes;
+ };
} // namespace detail
-/* -------------------------------------------------------------------------- */
-template <typename Array, typename... Ns>
+/* ------------------------------------------------------------------------ */
+template <typename Array, typename... Ns,
+ std::enable_if_t<aka::conjunction<
+ std::is_integral<std::decay_t<Ns>>...>::value> * = nullptr>
decltype(auto) make_view(Array && array, const Ns... ns) {
- static_assert(aka::conjunction<std::is_integral<std::decay_t<Ns>>...>::value,
- "Ns should be integral types");
AKANTU_DEBUG_ASSERT((detail::product_all(ns...) != 0),
"You must specify non zero dimensions");
auto size = std::forward<decltype(array)>(array).size() *
std::forward<decltype(array)>(array).getNbComponent() /
detail::product_all(ns...);
return detail::ArrayView<Array, std::common_type_t<size_t, Ns>...,
std::common_type_t<size_t, decltype(size)>>(
std::forward<Array>(array), std::move(ns)..., size);
}
-/* --------------------------------------------------------------------------
- */
-template <class T, bool is_scal>
-template <typename R>
-inline typename Array<T, is_scal>::template iterator<R>
-Array<T, is_scal>::erase(const iterator<R> & it) {
- T * curr = it.data();
- UInt pos = (curr - this->values) / this->nb_component;
- erase(pos);
- iterator<R> rit = it;
- return --rit;
+template <typename Array, typename... Ns>
+decltype(auto) make_const_view(const Array & array, const Ns... ns) {
+ return make_view(array, std::move(ns)...);
}
} // namespace akantu
-#endif /* AKANTU_AKA_ARRAY_TMPL_HH_ */
+//#endif /* __AKANTU_AKA_ARRAY_TMPL_HH__ */
diff --git a/src/common/aka_bbox.hh b/src/common/aka_bbox.hh
index 2d48b4122..1461b7e4d 100644
--- a/src/common/aka_bbox.hh
+++ b/src/common/aka_bbox.hh
@@ -1,279 +1,292 @@
/**
* @file aka_bbox.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Feb 14 2018
* @date last modification: Tue Sep 29 2020
*
* @brief A simple bounding box class
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
+#include "aka_math.hh"
#include "aka_types.hh"
#include "communicator.hh"
/* -------------------------------------------------------------------------- */
#include <map>
+#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_BBOX_HH_
#define AKANTU_AKA_BBOX_HH_
namespace akantu {
class BBox {
public:
BBox() = default;
- BBox(UInt spatial_dimension)
- : dim(spatial_dimension),
- lower_bounds(spatial_dimension, std::numeric_limits<Real>::max()),
- upper_bounds(spatial_dimension, std::numeric_limits<Real>::lowest()) {}
+ BBox(Int spatial_dimension)
+ : dim(spatial_dimension), lower_bounds(spatial_dimension),
+ upper_bounds(spatial_dimension) {
+ lower_bounds.fill(std::numeric_limits<Real>::max());
+ upper_bounds.fill(-std::numeric_limits<Real>::max());
+ }
BBox(const BBox & other)
: dim(other.dim), empty{false}, lower_bounds(other.lower_bounds),
upper_bounds(other.upper_bounds) {}
BBox & operator=(const BBox & other) {
if (this != &other) {
this->dim = other.dim;
this->lower_bounds = other.lower_bounds;
this->upper_bounds = other.upper_bounds;
this->empty = other.empty;
}
return *this;
}
inline BBox & operator+=(const Vector<Real> & position) {
AKANTU_DEBUG_ASSERT(
this->dim == position.size(),
"You are adding a point of a wrong dimension to the bounding box");
this->empty = false;
for (auto s : arange(dim)) {
lower_bounds(s) = std::min(lower_bounds(s), position(s));
upper_bounds(s) = std::max(upper_bounds(s), position(s));
}
return *this;
}
/* ------------------------------------------------------------------------ */
inline bool intersects(const BBox & other,
const SpatialDirection & direction) const {
AKANTU_DEBUG_ASSERT(
this->dim == other.dim,
"You are intersecting bounding boxes of different dimensions");
return Math::intersects(lower_bounds(direction), upper_bounds(direction),
other.lower_bounds(direction),
other.upper_bounds(direction));
}
inline bool intersects(const BBox & other) const {
if (this->empty or other.empty) {
return false;
}
bool intersects_ = true;
for (auto s : arange(this->dim)) {
intersects_ &= this->intersects(other, SpatialDirection(s));
}
return intersects_;
}
/* ------------------------------------------------------------------------ */
inline BBox intersection(const BBox & other) const {
AKANTU_DEBUG_ASSERT(
this->dim == other.dim,
"You are intersecting bounding boxes of different dimensions");
BBox intersection_(this->dim);
intersection_.empty = not this->intersects(other);
if (intersection_.empty) {
return intersection_;
}
for (auto s : arange(this->dim)) {
// is lower point in range ?
bool point1 = Math::is_in_range(other.lower_bounds(s), lower_bounds(s),
upper_bounds(s));
// is upper point in range ?
bool point2 = Math::is_in_range(other.upper_bounds(s), lower_bounds(s),
upper_bounds(s));
if (point1 and not point2) {
// |-----------| this (i)
// |-----------| other(i)
// 1 2
intersection_.lower_bounds(s) = other.lower_bounds(s);
intersection_.upper_bounds(s) = upper_bounds(s);
} else if (point1 && point2) {
// |-----------------| this (i)
// |-----------| other(i)
// 1 2
intersection_.lower_bounds(s) = other.lower_bounds(s);
intersection_.upper_bounds(s) = other.upper_bounds(s);
} else if (!point1 && point2) {
// |-----------| this (i)
// |-----------| other(i)
// 1 2
intersection_.lower_bounds(s) = this->lower_bounds(s);
intersection_.upper_bounds(s) = other.upper_bounds(s);
} else {
// |-----------| this (i)
// |-----------------| other(i)
// 1 2
intersection_.lower_bounds(s) = this->lower_bounds(s);
intersection_.upper_bounds(s) = this->upper_bounds(s);
}
}
return intersection_;
}
/* ------------------------------------------------------------------------ */
inline bool contains(const Vector<Real> & point) const {
- return (point >= lower_bounds) and (point <= upper_bounds);
+ return (point.array() >= lower_bounds.array()).all() and
+ (point.array() <= upper_bounds.array()).all();
}
/* ------------------------------------------------------------------------ */
inline void reset() {
lower_bounds.set(std::numeric_limits<Real>::max());
upper_bounds.set(std::numeric_limits<Real>::lowest());
}
/* --------------------------------------------------------------------------
*/
inline void getCenter(Vector<Real> & center) {
- center = upper_bounds;
- center += lower_bounds;
- center /= 2.;
+ center = (upper_bounds + lower_bounds) / 2.;
}
/* ------------------------------------------------------------------------ */
const Vector<Real> & getLowerBounds() const { return lower_bounds; }
const Vector<Real> & getUpperBounds() const { return upper_bounds; }
- Vector<Real> & getLowerBounds() { return lower_bounds; }
- Vector<Real> & getUpperBounds() { return upper_bounds; }
+ template <typename D>
+ void setLowerBounds(const Eigen::MatrixBase<D> & lower_bounds) {
+ this->lower_bounds = lower_bounds;
+ this->empty = false;
+ }
+ template <typename D>
+ void setUpperBounds(const Eigen::MatrixBase<D> & upper_bounds) {
+ this->upper_bounds = upper_bounds;
+ this->empty = false;
+ }
/* ------------------------------------------------------------------------ */
inline Real size(const SpatialDirection & direction) const {
return upper_bounds(direction) - lower_bounds(direction);
}
Vector<Real> size() const {
Vector<Real> size_(dim);
for (auto s : arange(this->dim)) {
size_(s) = this->size(SpatialDirection(s));
}
return size_;
}
inline operator bool() const { return not empty; }
/* ------------------------------------------------------------------------ */
BBox allSum(const Communicator & communicator) const {
Matrix<Real> reduce_bounds(dim, 2);
- Vector<Real>(reduce_bounds(0)) = lower_bounds;
- Vector<Real>(reduce_bounds(1)) = Real(-1.) * upper_bounds;
+ reduce_bounds(0) = lower_bounds;
+ reduce_bounds(1) = Real(-1.) * upper_bounds;
communicator.allReduce(reduce_bounds, SynchronizerOperation::_min);
BBox global(dim);
- global.lower_bounds = Vector<Real>(reduce_bounds(0));
- global.upper_bounds = Real(-1.) * Vector<Real>(reduce_bounds(1));
+ global.lower_bounds = reduce_bounds(0);
+ global.upper_bounds = Real(-1.) * reduce_bounds(1);
global.empty = false;
return global;
}
std::vector<BBox> allGather(const Communicator & communicator) const {
auto prank = communicator.whoAmI();
auto nb_proc = communicator.getNbProc();
Array<Real> bboxes_data(nb_proc, dim * 2 + 1);
- auto * base = bboxes_data.storage() + prank * (2 * dim + 1);
- Vector<Real>(base + dim * 0, dim) = lower_bounds;
- Vector<Real>(base + dim * 1, dim) = upper_bounds;
+ auto * base = bboxes_data.data() + prank * (2 * dim + 1);
+ MatrixProxy<Real> bounds(base, dim, 2);
+ bounds(0) = lower_bounds;
+ bounds(1) = upper_bounds;
base[dim * 2] = empty ? 1. : 0.; // ugly trick
communicator.allGather(bboxes_data);
std::vector<BBox> bboxes;
bboxes.reserve(nb_proc);
for (auto p : arange(nb_proc)) {
bboxes.emplace_back(dim);
auto & bbox = bboxes.back();
- auto * base = bboxes_data.storage() + p * (2 * dim + 1);
- bbox.lower_bounds = Vector<Real>(base + dim * 0, dim);
- bbox.upper_bounds = Vector<Real>(base + dim * 1, dim);
+ auto * base = bboxes_data.data() + p * (2 * dim + 1);
+ MatrixProxy<Real> bounds(base, dim, 2);
+ bbox.lower_bounds = bounds(0);
+ bbox.upper_bounds = bounds(1);
bbox.empty = (base[dim * 2] == 1.);
}
return bboxes;
}
- std::map<UInt, BBox> intersection(const BBox & other,
- const Communicator & communicator) const {
+ std::map<Int, BBox> intersection(const BBox & other,
+ const Communicator & communicator) const {
// todo: change for a custom reduction algorithm
auto other_bboxes = other.allGather(communicator);
- std::map<UInt, BBox> intersections;
+ std::map<Int, BBox> intersections;
for (const auto & bbox : enumerate(other_bboxes)) {
auto && tmp = this->intersection(std::get<1>(bbox));
if (tmp) {
intersections[std::get<0>(bbox)] = tmp;
}
}
return intersections;
}
void printself(std::ostream & stream) const {
stream << "BBox[";
if (not empty) {
stream << lower_bounds << " - " << upper_bounds;
}
stream << "]";
}
protected:
- UInt dim{0};
+ Int dim{0};
bool empty{true};
Vector<Real> lower_bounds;
Vector<Real> upper_bounds;
};
inline std::ostream & operator<<(std::ostream & stream, const BBox & bbox) {
bbox.printself(stream);
return stream;
}
} // namespace akantu
#endif /* AKANTU_AKA_BBOX_HH_ */
diff --git a/src/common/aka_blas_lapack.hh b/src/common/aka_blas_lapack.hh
deleted file mode 100644
index 67cda6a0a..000000000
--- a/src/common/aka_blas_lapack.hh
+++ /dev/null
@@ -1,346 +0,0 @@
-/**
- * @file aka_blas_lapack.hh
- *
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
- *
- * @date creation: Wed Mar 06 2013
- * @date last modification: Tue Sep 29 2020
- *
- * @brief Interface of the Fortran BLAS/LAPACK libraries
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include "aka_error.hh"
-/* -------------------------------------------------------------------------- */
-
-#ifndef AKANTU_AKA_BLAS_LAPACK_HH_
-#define AKANTU_AKA_BLAS_LAPACK_HH_
-
-/* -------------------------------------------------------------------------- */
-#ifdef AKANTU_USE_BLAS
-#include "aka_fortran_mangling.hh"
-extern "C" {
-
-/* ------------------------------------------------------------------------ */
-/* Double precision */
-/* ------------------------------------------------------------------------ */
-// LEVEL 1
-double AKA_FC_GLOBAL(ddot, DDOT)(int *, double *, int *, double *, int *);
-void AKA_FC_GLOBAL(daxpy, DAXPY)(int *, double *, double *, int *, double *,
- int *);
-
-// LEVEL 2
-void AKA_FC_GLOBAL(dgemv, DGEMV)(char *, int *, int *, double *, double *,
- int *, double *, int *, double *, double *,
- int *);
-// LEVEL 3
-void AKA_FC_GLOBAL(dgemm, DGEMM)(char *, char *, int *, int *, int *, double *,
- double *, int *, double *, int *, double *,
- double *, int *);
-/* ------------------------------------------------------------------------ */
-/* Simple precision */
-/* ------------------------------------------------------------------------ */
-// LEVEL 1
-float AKA_FC_GLOBAL(sdot, SDOT)(int *, float *, int *, float *, int *);
-void AKA_FC_GLOBAL(saxpy, SAXPY)(int *, float *, float *, int *, float *,
- int *);
-
-// LEVEL 2
-void AKA_FC_GLOBAL(sgemv, SGEMV)(char *, int *, int *, float *, float *, int *,
- float *, int *, float *, float *, int *);
-// LEVEL 3
-void AKA_FC_GLOBAL(sgemm, SGEMM)(char *, char *, int *, int *, int *, float *,
- float *, int *, float *, int *, float *,
- float *, int *);
-}
-#endif
-
-namespace akantu {
-
-#define AKANTU_WARNING_IGNORE_UNUSED_PARAMETER
-#include "aka_warning.hh"
-
-/// Wrapper around the S/DDOT BLAS function that returns the dot product of two
-/// vectors
-template <typename T>
-inline T aka_dot(int * n, T * x, int * incx, T * y, int * incy) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "BLAS in the compilation options!");
-}
-
-/// Wrapper around the S/DAXPY BLAS function that computes \f$y := \alpha x +
-/// y\f$
-template <typename T>
-inline void aka_axpy(int * n, T * alpha, T * x, int * incx, T * y, int * incy) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "BLAS in the compilation options!");
-}
-
-/// Wrapper around the S/DGEMV BLAS function that computes matrix-vector product
-/// \f$y := \alpha A^{(T)}x + \beta y \f$
-template <typename T>
-inline void aka_gemv(char * trans, int * m, int * n, T * alpha, T * a,
- int * lda, T * x, int * incx, T * beta, T * y,
- int * incy) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "BLAS in the compilation options!");
-}
-
-/// Wrapper around the S/DGEMM BLAS function that computes the product of two
-/// matrices \f$C := \alpha A^{(T)} B^{(T)} + \beta C \f$
-template <typename T>
-inline void aka_gemm(char * transa, char * transb, int * m, int * n, int * k,
- T * alpha, T * a, int * lda, T * b, int * ldb, T * beta,
- T * c, int * ldc) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "BLAS in the compilation options!");
-}
-
-#if defined(AKANTU_USE_BLAS)
-template <>
-inline double aka_dot<double>(int * n, double * x, int * incx, double * y,
- int * incy) {
- return AKA_FC_GLOBAL(ddot, DDOT)(n, x, incx, y, incy);
-}
-
-template <>
-inline void aka_axpy(int * n, double * alpha, double * x, int * incx,
- double * y, int * incy) {
- return AKA_FC_GLOBAL(daxpy, DAXPY)(n, alpha, x, incx, y, incy);
-}
-
-template <>
-inline void aka_gemv<double>(char * trans, int * m, int * n, double * alpha,
- double * a, int * lda, double * x, int * incx,
- double * beta, double * y, int * incy) {
- return AKA_FC_GLOBAL(dgemv, DGEMV)(trans, m, n, alpha, a, lda, x, incx, beta,
- y, incy);
-}
-
-template <>
-inline void aka_gemm<double>(char * transa, char * transb, int * m, int * n,
- int * k, double * alpha, double * a, int * lda,
- double * b, int * ldb, double * beta, double * c,
- int * ldc) {
- AKA_FC_GLOBAL(dgemm, DGEMM)
- (transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc);
-}
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-template <>
-inline float aka_dot<float>(int * n, float * x, int * incx, float * y,
- int * incy) {
- return AKA_FC_GLOBAL(sdot, SDOT)(n, x, incx, y, incy);
-}
-
-template <>
-inline void aka_axpy(int * n, float * alpha, float * x, int * incx, float * y,
- int * incy) {
- return AKA_FC_GLOBAL(daxpy, DAXPY)(n, alpha, x, incx, y, incy);
-}
-
-template <>
-inline void aka_gemv<float>(char * trans, int * m, int * n, float * alpha,
- float * a, int * lda, float * x, int * incx,
- float * beta, float * y, int * incy) {
- AKA_FC_GLOBAL(sgemv, SGEMV)
- (trans, m, n, alpha, a, lda, x, incx, beta, y, incy);
-}
-
-template <>
-inline void aka_gemm<float>(char * transa, char * transb, int * m, int * n,
- int * k, float * alpha, float * a, int * lda,
- float * b, int * ldb, float * beta, float * c,
- int * ldc) {
- AKA_FC_GLOBAL(sgemm, SGEMM)
- (transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc);
-}
-
-#endif
-
-} // namespace akantu
-
-#ifdef AKANTU_USE_LAPACK
-#include "aka_fortran_mangling.hh"
-extern "C" {
-/* ------------------------------------------------------------------------ */
-/* Double general matrix */
-/* ------------------------------------------------------------------------ */
-/// compute the eigenvalues/vectors
-void AKA_FC_GLOBAL(dgeev, DGEEV)(char * jobvl, char * jobvr, int * n,
- double * a, int * lda, double * wr,
- double * wi, double * vl, int * ldvl,
- double * vr, int * ldvr, double * work,
- int * lwork, int * info);
-
-/// LU decomposition of a general matrix
-void AKA_FC_GLOBAL(dgetrf, DGETRF)(int * m, int * n, double * a, int * lda,
- int * ipiv, int * info);
-
-/// generate inverse of a matrix given its LU decomposition
-void AKA_FC_GLOBAL(dgetri, DGETRI)(int * n, double * a, int * lda, int * ipiv,
- double * work, int * lwork, int * info);
-
-/// solving A x = b using a LU factorization
-void AKA_FC_GLOBAL(dgetrs, DGETRS)(char * trans, int * n, int * nrhs,
- double * A, int * lda, int * ipiv,
- double * b, int * ldb, int * info);
-
-/* ------------------------------------------------------------------------ */
-/* Simple general matrix */
-/* ------------------------------------------------------------------------ */
-/// compute the eigenvalues/vectors
-void AKA_FC_GLOBAL(sgeev, SGEEV)(char * jobvl, char * jobvr, int * n, float * a,
- int * lda, float * wr, float * wi, float * vl,
- int * ldvl, float * vr, int * ldvr,
- float * work, int * lwork, int * info);
-
-/// LU decomposition of a general matrix
-void AKA_FC_GLOBAL(sgetrf, SGETRF)(int * m, int * n, float * a, int * lda,
- int * ipiv, int * info);
-
-/// generate inverse of a matrix given its LU decomposition
-void AKA_FC_GLOBAL(sgetri, SGETRI)(int * n, float * a, int * lda, int * ipiv,
- float * work, int * lwork, int * info);
-
-/// solving A x = b using a LU factorization
-void AKA_FC_GLOBAL(sgetrs, SGETRS)(char * trans, int * n, int * nrhs, float * A,
- int * lda, int * ipiv, float * b, int * ldb,
- int * info);
-}
-#endif // AKANTU_USE_LAPACK
-
-namespace akantu {
-
-/// Wrapper around the S/DGEEV BLAS function that computes the eigenvalues and
-/// eigenvectors of a matrix
-template <typename T>
-inline void aka_geev(char * jobvl, char * jobvr, int * n, T * a, int * lda,
- T * wr, T * wi, T * vl, int * ldvl, T * vr, int * ldvr,
- T * work, int * lwork, int * info) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "LAPACK in the compilation options!");
-}
-
-/// Wrapper around the S/DGETRF BLAS function that computes the LU decomposition
-/// of a matrix
-template <typename T>
-inline void aka_getrf(int * m, int * n, T * a, int * lda, int * ipiv,
- int * info) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "LAPACK in the compilation options!");
-}
-
-/// Wrapper around the S/DGETRI BLAS function that computes the inverse of a
-/// matrix given its LU decomposition
-template <typename T>
-inline void aka_getri(int * n, T * a, int * lda, int * ipiv, T * work,
- int * lwork, int * info) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "LAPACK in the compilation options!");
-}
-
-/// Wrapper around the S/DGETRS BLAS function that solves \f$A^{(T)}x = b\f$
-/// using LU decomposition
-template <typename T>
-inline void aka_getrs(char * trans, int * n, int * nrhs, T * A, int * lda,
- int * ipiv, T * b, int * ldb, int * info) {
- AKANTU_ERROR(debug::demangle(typeid(T).name())
- << "is not a type recognized, or you didn't activated "
- "LAPACK in the compilation options!");
-}
-
-#include "aka_warning_restore.hh"
-
-#ifdef AKANTU_USE_LAPACK
-template <>
-inline void aka_geev<double>(char * jobvl, char * jobvr, int * n, double * a,
- int * lda, double * wr, double * wi, double * vl,
- int * ldvl, double * vr, int * ldvr, double * work,
- int * lwork, int * info) {
- AKA_FC_GLOBAL(dgeev, DGEEV)
- (jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info);
-}
-
-template <>
-inline void aka_getrf<double>(int * m, int * n, double * a, int * lda,
- int * ipiv, int * info) {
- AKA_FC_GLOBAL(dgetrf, DGETRF)(m, n, a, lda, ipiv, info);
-}
-
-template <>
-inline void aka_getri<double>(int * n, double * a, int * lda, int * ipiv,
- double * work, int * lwork, int * info) {
- AKA_FC_GLOBAL(dgetri, DGETRI)(n, a, lda, ipiv, work, lwork, info);
-}
-
-template <>
-inline void aka_getrs<double>(char * trans, int * n, int * nrhs, double * A,
- int * lda, int * ipiv, double * b, int * ldb,
- int * info) {
- AKA_FC_GLOBAL(dgetrs, DGETRS)(trans, n, nrhs, A, lda, ipiv, b, ldb, info);
-}
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-template <>
-inline void aka_geev<float>(char * jobvl, char * jobvr, int * n, float * a,
- int * lda, float * wr, float * wi, float * vl,
- int * ldvl, float * vr, int * ldvr, float * work,
- int * lwork, int * info) {
- AKA_FC_GLOBAL(sgeev, SGEEV)
- (jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info);
-}
-
-template <>
-inline void aka_getrf<float>(int * m, int * n, float * a, int * lda, int * ipiv,
- int * info) {
- AKA_FC_GLOBAL(sgetrf, SGETRF)(m, n, a, lda, ipiv, info);
-}
-
-template <>
-inline void aka_getri<float>(int * n, float * a, int * lda, int * ipiv,
- float * work, int * lwork, int * info) {
- AKA_FC_GLOBAL(sgetri, SGETRI)(n, a, lda, ipiv, work, lwork, info);
-}
-
-template <>
-inline void aka_getrs<float>(char * trans, int * n, int * nrhs, float * A,
- int * lda, int * ipiv, float * b, int * ldb,
- int * info) {
- AKA_FC_GLOBAL(sgetrs, SGETRS)(trans, n, nrhs, A, lda, ipiv, b, ldb, info);
-}
-#endif
-
-} // namespace akantu
-
-#endif /* AKANTU_AKA_BLAS_LAPACK_HH_ */
diff --git a/src/common/aka_circular_array.hh b/src/common/aka_circular_array.hh
index db95bc240..507a8c53c 100644
--- a/src/common/aka_circular_array.hh
+++ b/src/common/aka_circular_array.hh
@@ -1,123 +1,123 @@
/**
* @file aka_circular_array.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief class of circular array
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <typeinfo>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_CIRCULAR_ARRAY_HH_
#define AKANTU_AKA_CIRCULAR_ARRAY_HH_
namespace akantu {
template <class T> class CircularArray : protected Array<T> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
typedef typename Array<T>::value_type value_type;
typedef typename Array<T>::reference reference;
typedef typename Array<T>::pointer_type pointer_type;
typedef typename Array<T>::const_reference const_reference;
/// Allocation of a new array with a default value
- CircularArray(UInt size, UInt nb_component = 1,
+ CircularArray(Int size, Int nb_component = 1,
const_reference value = value_type(), const ID & id = "")
: Array<T>(size, nb_component, value, id), start_position(0),
end_position(size - 1) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
};
virtual ~CircularArray() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/**
advance start and end position by one:
the first element is now at the end of the array
**/
inline void makeStep();
/// function to print the contain of the class
virtual void printself(std::ostream & stream, int indent = 0) const;
private:
/* ------------------------------------------------------------------------ */
/* Operators */
/* ------------------------------------------------------------------------ */
public:
- inline reference operator()(UInt i, UInt j = 0);
- inline const_reference operator()(UInt i, UInt j = 0) const;
+ inline reference operator()(Idx i, Idx j = 0);
+ inline const_reference operator()(Idx i, Idx j = 0) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- UInt size() const { return this->size_; };
+ Int size() const { return this->size_; };
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// indice of first element in this circular array
- UInt start_position;
+ Idx start_position;
/// indice of last element in this circular array
- UInt end_position;
+ Idx end_position;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
/// standard output stream operator
template <typename T>
inline std::ostream & operator<<(std::ostream & stream,
const CircularArray<T> & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "aka_circular_array_inline_impl.hh"
#endif /* AKANTU_AKA_CIRCULAR_ARRAY_HH_ */
diff --git a/src/common/aka_circular_array_inline_impl.hh b/src/common/aka_circular_array_inline_impl.hh
index 66f2f6bbc..d5a78f3a5 100644
--- a/src/common/aka_circular_array_inline_impl.hh
+++ b/src/common/aka_circular_array_inline_impl.hh
@@ -1,103 +1,101 @@
/**
* @file aka_circular_array_inline_impl.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Nov 11 2011
* @date last modification: Fri Mar 16 2018
*
* @brief implementation of circular array
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_circular_array.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class T>
inline typename CircularArray<T>::reference
-CircularArray<T>::operator()(UInt i, UInt j) {
+CircularArray<T>::operator()(Idx i, Idx j) {
AKANTU_DEBUG_ASSERT(end_position != start_position,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT(
(i < (end_position - start_position + this->allocated_size) %
this->allocated_size +
1) &&
(j < this->nb_component),
"The value at position [" << i << "," << j
<< "] is out of range in array \"" << this->id
<< "\"");
return this->values[((i + start_position) % this->allocated_size) *
this->nb_component +
j];
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline typename CircularArray<T>::const_reference
-CircularArray<T>::operator()(UInt i, UInt j) const {
+CircularArray<T>::operator()(Idx i, Idx j) const {
AKANTU_DEBUG_ASSERT(end_position != start_position,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT(
(i < (end_position - start_position + this->allocated_size) %
this->allocated_size +
1) &&
(j < this->nb_component),
"The value at position [" << i << "," << j
<< "] is out of range in array \"" << this->id
<< "\"");
return this->values[((i + start_position) % this->allocated_size) *
this->nb_component +
j];
}
/* -------------------------------------------------------------------------- */
template <class T> inline void CircularArray<T>::makeStep() {
AKANTU_DEBUG_IN();
start_position = (start_position + 1) % this->allocated_size;
end_position = (end_position + 1) % this->allocated_size;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class T>
void CircularArray<T>::printself(std::ostream & stream, int indent) const {
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
- ;
+ std::string space(AKANTU_INDENT, indent);
stream << space << "CircularArray<" << debug::demangle(typeid(T).name())
<< "> [" << std::endl;
stream << space << " + start_position : " << this->start_position
<< std::endl;
stream << space << " + end_position : " << this->end_position << std::endl;
Array<T>::printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
} // namespace akantu
diff --git a/src/common/aka_common.cc b/src/common/aka_common.cc
index f15de9893..72a275c7b 100644
--- a/src/common/aka_common.cc
+++ b/src/common/aka_common.cc
@@ -1,160 +1,165 @@
/**
* @file aka_common.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jun 14 2010
* @date last modification: Wed Dec 09 2020
*
* @brief Initialization of global variables
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_random_generator.hh"
#include "communicator.hh"
#include "cppargparse.hh"
#include "parser.hh"
#include "communication_tag.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <cstdlib>
#include <ctime>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
void initialize(int & argc, char **& argv) {
AKANTU_DEBUG_IN();
initialize("", argc, argv);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void initialize(const std::string & input_file, int & argc, char **& argv) {
AKANTU_DEBUG_IN();
Communicator & comm = Communicator::getStaticCommunicator(argc, argv);
Tag::setMaxTag(comm.getMaxTag());
debug::debugger.setParallelContext(comm.whoAmI(), comm.getNbProc());
debug::setDebugLevel(dblError);
static_argparser.setParallelContext(comm.whoAmI(), comm.getNbProc());
static_argparser.setExternalExitFunction(debug::exit);
static_argparser.addArgument("--aka_input_file", "Akantu's input file", 1,
cppargparse::_string, std::string());
static_argparser.addArgument(
"--aka_debug_level",
std::string("Akantu's overall debug level") +
std::string(" (0: error, 1: exceptions, 4: warnings, 5: info, ..., "
"100: dump") +
- std::string(" more info on levels can be foind in aka_error.hh)"),
+ std::string(" more info on levels can be found in aka_error.hh)"),
1, cppargparse::_integer, (long int)(dblWarning));
static_argparser.addArgument(
"--aka_print_backtrace",
"Should Akantu print a backtrace in case of error", 0,
cppargparse::_boolean, false, true);
static_argparser.addArgument("--aka_seed", "The seed to use on prank 0", 1,
cppargparse::_integer);
static_argparser.parse(argc, argv, cppargparse::_remove_parsed);
std::string infile = static_argparser["aka_input_file"];
if (infile.empty()) {
infile = input_file;
}
debug::debugger.printBacktrace(static_argparser["aka_print_backtrace"]);
if (not infile.empty()) {
readInputFile(infile);
}
long int seed;
char * env_seed = std::getenv("AKA_SEED");
if (env_seed != nullptr) {
seed = std::atol(env_seed);
} else if (static_argparser.has("aka_seed")) {
seed = static_argparser["aka_seed"];
} else {
seed =
static_parser.getParameter("seed", time(nullptr), _ppsc_current_scope);
}
seed *= (comm.whoAmI() + 1);
- RandomGenerator<UInt>::seed(seed);
+ RandomGenerator<Idx>::seed(seed);
long int dbl_level = static_argparser["aka_debug_level"];
debug::setDebugLevel(DebugLevel(dbl_level));
+ char * env_debug_level = std::getenv("AKA_DEBUG_LEVEL");
+ if (env_debug_level != nullptr) {
+ debug::setDebugLevel(DebugLevel(std::atoi(env_debug_level)));
+ }
+
AKANTU_DEBUG_INFO("Random seed set to " << seed);
std::atexit(finalize);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void finalize() {}
/* -------------------------------------------------------------------------- */
void readInputFile(const std::string & input_file) {
static_parser.parse(input_file);
}
/* -------------------------------------------------------------------------- */
cppargparse::ArgumentParser & getStaticArgumentParser() {
return static_argparser;
}
/* -------------------------------------------------------------------------- */
Parser & getStaticParser() { return static_parser; }
/* -------------------------------------------------------------------------- */
const ParserSection & getUserParser() {
return *(static_parser.getSubSections(ParserType::_user).first);
}
std::unique_ptr<Communicator> Communicator::static_communicator;
std::ostream & operator<<(std::ostream & stream, NodeFlag flag) {
using under = std::underlying_type_t<NodeFlag>;
auto digits = static_cast<int>(
std::log(std::numeric_limits<under>::max() + 1) / std::log(16));
std::ios_base::fmtflags ff;
ff = stream.flags();
auto value = static_cast<std::common_type_t<under, unsigned int>>(flag);
stream << "0x" << std::hex << std::setw(digits) << std::setfill('0') << value;
stream.flags(ff);
return stream;
}
} // namespace akantu
diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh
index d3a804c90..b414061f8 100644
--- a/src/common/aka_common.hh
+++ b/src/common/aka_common.hh
@@ -1,709 +1,716 @@
/**
* @file aka_common.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jun 14 2010
* @date last modification: Sat May 01 2021
*
* @brief common type descriptions for akantu
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COMMON_HH_
#define AKANTU_COMMON_HH_
#include "aka_compatibilty_with_cpp_standard.hh"
/* -------------------------------------------------------------------------- */
#if defined(WIN32)
#define __attribute__(x)
#endif
/* -------------------------------------------------------------------------- */
#include "aka_config.hh"
#include "aka_error.hh"
#include "aka_safe_enum.hh"
/* -------------------------------------------------------------------------- */
#include <boost/preprocessor.hpp>
#include <limits>
#include <list>
#include <memory>
#include <string>
#include <type_traits>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Constants */
/* -------------------------------------------------------------------------- */
namespace {
- [[gnu::unused]] constexpr UInt _all_dimensions{
- std::numeric_limits<UInt>::max()};
+ [[gnu::unused]] constexpr Int _all_dimensions{
+ std::numeric_limits<Int>::max()};
#ifdef AKANTU_NDEBUG
[[gnu::unused]] constexpr Real REAL_INIT_VALUE{0.};
#else
[[gnu::unused]] constexpr Real REAL_INIT_VALUE{
std::numeric_limits<Real>::quiet_NaN()};
#endif
} // namespace
-/* -------------------------------------------------------------------------- */
-/* Common types */
-/* -------------------------------------------------------------------------- */
+using dim_1_t = std::integral_constant<Int, 1>;
+using dim_2_t = std::integral_constant<Int, 2>;
+using dim_3_t = std::integral_constant<Int, 3>;
+using AllSpatialDimensions = std::tuple<dim_1_t, dim_2_t, dim_3_t>;
+/* --------------------------------------------------------------------------
+ */
+/* Common types */
+/* --------------------------------------------------------------------------
+ */
using ID = std::string;
} // namespace akantu
/* -------------------------------------------------------------------------- */
#include "aka_enum_macros.hh"
/* -------------------------------------------------------------------------- */
#include "aka_element_classes_info.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Mesh/FEM/Model types */
/* -------------------------------------------------------------------------- */
/// small help to use names for directions
enum SpatialDirection { _x = 0, _y = 1, _z = 2 };
/// enum MeshIOType type of mesh reader/writer
enum MeshIOType {
_miot_auto, ///< Auto guess of the reader to use based on the extension
_miot_gmsh, ///< Gmsh files
_miot_gmsh_struct, ///< Gsmh reader with reintpretation of elements has
/// structures elements
_miot_diana, ///< TNO Diana mesh format
_miot_abaqus ///< Abaqus mesh format
};
/// enum MeshEventHandlerPriority defines relative order of execution of
/// events
enum EventHandlerPriority {
_ehp_highest = 0,
_ehp_mesh = 5,
_ehp_fe_engine = 9,
_ehp_synchronizer = 10,
_ehp_dof_manager = 20,
_ehp_model = 94,
_ehp_non_local_manager = 100,
_ehp_lowest = 100
};
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_MODEL_TYPES \
(model) \
(solid_mechanics_model) \
(solid_mechanics_model_cohesive) \
(heat_transfer_model) \
(structural_mechanics_model) \
(embedded_model) \
(contact_mechanics_model) \
(coupler_solid_contact) \
(coupler_solid_cohesive_contact) \
(phase_field_model) \
(coupler_solid_phasefield)
// clang-format on
/// enum ModelType defines which type of physics is solved
AKANTU_CLASS_ENUM_DECLARE(ModelType, AKANTU_MODEL_TYPES)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(ModelType, AKANTU_MODEL_TYPES)
AKANTU_CLASS_ENUM_INPUT_STREAM(ModelType, AKANTU_MODEL_TYPES)
#else
enum class ModelType {
model,
solid_mechanics_model,
solid_mechanics_model_cohesive,
heat_transfer_model,
structural_mechanics_model,
embedded_model,
};
#endif
/// enum AnalysisMethod type of solving method used to solve the equation of
/// motion
enum AnalysisMethod {
_static = 0,
_implicit_dynamic = 1,
_explicit_lumped_mass = 2,
_explicit_lumped_capacity = 2,
_explicit_consistent_mass = 3,
_explicit_contact = 4,
_implicit_contact = 5
};
/// enum DOFSupportType defines which kind of dof that can exists
enum DOFSupportType { _dst_nodal, _dst_generic };
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_NON_LINEAR_SOLVER_TYPES \
(linear) \
(newton_raphson) \
(newton_raphson_modified) \
(lumped) \
(gmres) \
(bfgs) \
(cg) \
(newton_raphson_contact) \
(auto)
// clang-format on
AKANTU_CLASS_ENUM_DECLARE(NonLinearSolverType, AKANTU_NON_LINEAR_SOLVER_TYPES)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(NonLinearSolverType,
AKANTU_NON_LINEAR_SOLVER_TYPES)
AKANTU_CLASS_ENUM_INPUT_STREAM(NonLinearSolverType,
AKANTU_NON_LINEAR_SOLVER_TYPES)
#else
/// Type of non linear resolution available in akantu
enum class NonLinearSolverType {
_linear, ///< No non linear convergence loop
_newton_raphson, ///< Regular Newton-Raphson
_newton_raphson_modified, ///< Newton-Raphson with initial tangent
_lumped, ///< Case of lumped mass or equivalent matrix
_gmres,
_bfgs,
_cg,
_newton_raphson_contact, ///< Regular Newton-Raphson modified
/// for contact problem
_auto, ///< This will take a default value that make sense in case of
/// model::getNewSolver
};
#endif
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_TIME_STEP_SOLVER_TYPE \
(static) \
(dynamic) \
(dynamic_lumped) \
(not_defined)
// clang-format on
AKANTU_CLASS_ENUM_DECLARE(TimeStepSolverType, AKANTU_TIME_STEP_SOLVER_TYPE)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(TimeStepSolverType,
AKANTU_TIME_STEP_SOLVER_TYPE)
AKANTU_CLASS_ENUM_INPUT_STREAM(TimeStepSolverType, AKANTU_TIME_STEP_SOLVER_TYPE)
#else
/// Type of time stepping solver
enum class TimeStepSolverType {
_static, ///< Static solution
_dynamic, ///< Dynamic solver
_dynamic_lumped, ///< Dynamic solver with lumped mass
_not_defined, ///< For not defined cases
};
#endif
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_INTEGRATION_SCHEME_TYPE \
(pseudo_time) \
(forward_euler) \
(trapezoidal_rule_1) \
(backward_euler) \
(central_difference) \
(fox_goodwin) \
(trapezoidal_rule_2) \
(linear_acceleration) \
(newmark_beta) \
(generalized_trapezoidal)
// clang-format on
AKANTU_CLASS_ENUM_DECLARE(IntegrationSchemeType, AKANTU_INTEGRATION_SCHEME_TYPE)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(IntegrationSchemeType,
AKANTU_INTEGRATION_SCHEME_TYPE)
AKANTU_CLASS_ENUM_INPUT_STREAM(IntegrationSchemeType,
AKANTU_INTEGRATION_SCHEME_TYPE)
#else
/// Type of integration scheme
enum class IntegrationSchemeType {
_pseudo_time, ///< Pseudo Time
_forward_euler, ///< GeneralizedTrapezoidal(0)
_trapezoidal_rule_1, ///< GeneralizedTrapezoidal(1/2)
_backward_euler, ///< GeneralizedTrapezoidal(1)
_central_difference, ///< NewmarkBeta(0, 1/2)
_fox_goodwin, ///< NewmarkBeta(1/6, 1/2)
_trapezoidal_rule_2, ///< NewmarkBeta(1/2, 1/2)
_linear_acceleration, ///< NewmarkBeta(1/3, 1/2)
_newmark_beta, ///< generic NewmarkBeta with user defined
/// alpha and beta
_generalized_trapezoidal ///< generic GeneralizedTrapezoidal with user
/// defined alpha
};
#endif
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_SOLVE_CONVERGENCE_CRITERIA \
(residual) \
(solution) \
(residual_mass_wgh)
// clang-format on
AKANTU_CLASS_ENUM_DECLARE(SolveConvergenceCriteria,
AKANTU_SOLVE_CONVERGENCE_CRITERIA)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(SolveConvergenceCriteria,
AKANTU_SOLVE_CONVERGENCE_CRITERIA)
AKANTU_CLASS_ENUM_INPUT_STREAM(SolveConvergenceCriteria,
AKANTU_SOLVE_CONVERGENCE_CRITERIA)
#else
/// enum SolveConvergenceCriteria different convergence criteria
enum class SolveConvergenceCriteria {
_residual, ///< Use residual to test the convergence
_solution, ///< Use solution to test the convergence
_residual_mass_wgh ///< Use residual weighted by inv. nodal mass to
///< testb
};
#endif
/// enum CohesiveMethod type of insertion of cohesive elements
enum CohesiveMethod { _intrinsic, _extrinsic };
/// @enum MatrixType type of sparse matrix used
enum MatrixType { _unsymmetric, _symmetric, _mt_not_defined };
/// @enum Type of contact detection
enum DetectionType { _explicit, _implicit };
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_CONTACT_STATE \
(no_contact) \
(stick) \
(slip)
// clang-format on
AKANTU_CLASS_ENUM_DECLARE(ContactState, AKANTU_CONTACT_STATE)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(ContactState, AKANTU_CONTACT_STATE)
AKANTU_CLASS_ENUM_INPUT_STREAM(ContactState, AKANTU_CONTACT_STATE)
#else
/// @enum no contact or stick or slip state
enum class ContactState {
_no_contact = 0,
_stick = 1,
_slip = 2,
};
#endif
/* -------------------------------------------------------------------------- */
/* Ghosts handling */
/* -------------------------------------------------------------------------- */
/// @enum CommunicatorType type of communication method to use
enum CommunicatorType { _communicator_mpi, _communicator_dummy };
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_SYNCHRONIZATION_TAG \
(whatever) \
(update) \
(ask_nodes) \
(size) \
(smm_mass) \
(smm_for_gradu) \
(smm_boundary) \
(smm_uv) \
(smm_res) \
(smm_init_mat) \
(smm_stress) \
(smmc_facets) \
(smmc_facets_conn) \
(smmc_facets_stress) \
(smmc_damage) \
(giu_global_conn) \
(ce_groups) \
(ce_insertion_order) \
(gm_clusters) \
(htm_temperature) \
(htm_gradient_temperature) \
(htm_phi) \
(htm_gradient_phi) \
(pfm_damage) \
(pfm_driving) \
(pfm_history) \
(pfm_energy) \
(csp_damage) \
(csp_strain) \
(mnl_for_average) \
(mnl_weight) \
(nh_criterion) \
(test) \
(user_1) \
(user_2) \
(material_id) \
(for_dump) \
(cf_nodal) \
(cf_incr) \
(solver_solution)
// clang-format on
AKANTU_CLASS_ENUM_DECLARE(SynchronizationTag, AKANTU_SYNCHRONIZATION_TAG)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(SynchronizationTag, AKANTU_SYNCHRONIZATION_TAG)
#else
/// @enum SynchronizationTag type of synchronizations
enum class SynchronizationTag {
//--- Generic tags ---
_whatever,
_update,
_ask_nodes,
_size,
//--- SolidMechanicsModel tags ---
_smm_mass, ///< synchronization of the SolidMechanicsModel.mass
_smm_for_gradu, ///< synchronization of the
/// SolidMechanicsModel.displacement
_smm_boundary, ///< synchronization of the boundary, forces, velocities
/// and displacement
_smm_uv, ///< synchronization of the nodal velocities and displacement
_smm_res, ///< synchronization of the nodal residual
_smm_init_mat, ///< synchronization of the data to initialize materials
_smm_stress, ///< synchronization of the stresses to compute the
///< internal
/// forces
_smmc_facets, ///< synchronization of facet data to setup facet synch
_smmc_facets_conn, ///< synchronization of facet global connectivity
_smmc_facets_stress, ///< synchronization of facets' stress to setup
///< facet
/// synch
_smmc_damage, ///< synchronization of damage
// --- GlobalIdsUpdater tags ---
_giu_global_conn, ///< synchronization of global connectivities
// --- CohesiveElementInserter tags ---
_ce_groups, ///< synchronization of cohesive element insertion depending
/// on facet groups
_ce_insertion_order, ///< synchronization of the order of insertion of
/// cohesive elements
// --- GroupManager tags ---
_gm_clusters, ///< synchronization of clusters
// --- HeatTransfer tags ---
_htm_temperature, ///< synchronization of the nodal temperature
_htm_gradient_temperature, ///< synchronization of the element gradient
/// temperature
// --- PhaseFieldModel tags ---
_pfm_damage, ///< synchronization of the nodal damage
_pfm_driving, ///< synchronization of the driving forces to
/// compute the internal
_pfm_history, ///< synchronization of the damage history to
/// compute the internal
_pfm_energy, ///< synchronization of the damage energy
/// density to compute the internal
// --- CouplerSolidPhaseField tags ---
_csp_damage, ///< synchronization of the damage from phase
/// model to solid model
_csp_strain, ///< synchronization of the strain from solid
/// model to phase model
// --- LevelSet tags ---
_htm_phi, ///< synchronization of the nodal level set value phi
_htm_gradient_phi, ///< synchronization of the element gradient phi
//--- Material non local ---
_mnl_for_average, ///< synchronization of data to average in non local
/// material
_mnl_weight, ///< synchronization of data for the weight computations
// --- NeighborhoodSynchronization tags ---
_nh_criterion,
// --- General tags ---
_test, ///< Test tag
_user_1, ///< tag for user simulations
_user_2, ///< tag for user simulations
_material_id, ///< synchronization of the material ids
_for_dump, ///< everything that needs to be synch before dump
// --- Contact & Friction ---
_cf_nodal, ///< synchronization of disp, velo, and current position
_cf_incr, ///< synchronization of increment
// --- Solver tags ---
_solver_solution ///< synchronization of the solution obained with the
/// PETSc solver
};
#endif
/// @enum GhostType type of ghost
enum GhostType {
_not_ghost = 0,
_ghost = 1,
_casper // not used but a real cute ghost
};
/// Define the flag that can be set to a node
enum class NodeFlag : std::uint8_t {
_normal = 0x00,
_distributed = 0x01,
_master = 0x03,
_slave = 0x05,
_pure_ghost = 0x09,
_shared_mask = 0x0F,
_periodic = 0x10,
_periodic_master = 0x30,
_periodic_slave = 0x50,
_periodic_mask = 0xF0,
_local_master_mask = 0xCC, // ~(_master & _periodic_mask)
};
inline NodeFlag operator&(const NodeFlag & a, const NodeFlag & b) {
using under = std::underlying_type_t<NodeFlag>;
return NodeFlag(under(a) & under(b));
}
inline NodeFlag operator|(const NodeFlag & a, const NodeFlag & b) {
using under = std::underlying_type_t<NodeFlag>;
return NodeFlag(under(a) | under(b));
}
inline NodeFlag & operator|=(NodeFlag & a, const NodeFlag & b) {
a = a | b;
return a;
}
inline NodeFlag & operator&=(NodeFlag & a, const NodeFlag & b) {
a = a & b;
return a;
}
inline NodeFlag operator~(const NodeFlag & a) {
using under = std::underlying_type_t<NodeFlag>;
return NodeFlag(~under(a));
}
std::ostream & operator<<(std::ostream & stream, NodeFlag flag);
} // namespace akantu
AKANTU_ENUM_HASH(GhostType)
namespace akantu {
/* -------------------------------------------------------------------------- */
struct GhostType_def {
using type = GhostType;
static const type _begin_ = _not_ghost;
static const type _end_ = _casper;
};
using ghost_type_t = safe_enum<GhostType_def>;
namespace {
constexpr ghost_type_t ghost_types{_casper};
}
/// standard output stream operator for GhostType
// inline std::ostream & operator<<(std::ostream & stream, GhostType type);
/* -------------------------------------------------------------------------- */
/* Global defines */
/* -------------------------------------------------------------------------- */
#define AKANTU_MIN_ALLOCATION 2000
#define AKANTU_INDENT ' '
#define AKANTU_INCLUDE_INLINE_IMPL
/* -------------------------------------------------------------------------- */
#define AKANTU_SET_MACRO(name, variable, type) \
inline void set##name(type variable) { this->variable = variable; }
#define AKANTU_GET_MACRO(name, variable, type) \
- inline type get##name() const { return variable; }
+ inline auto get##name() const->type { return variable; }
+
+#define AKANTU_GET_MACRO_AUTO(name, variable) \
+ inline decltype(auto) get##name() const { return (variable); }
+
+#define AKANTU_GET_MACRO_AUTO_NOT_CONST(name, variable) \
+ inline decltype(auto) get##name() { return (variable); }
#define AKANTU_GET_MACRO_NOT_CONST(name, variable, type) \
- inline type get##name() { return variable; }
+ inline auto get##name()->type { return variable; }
#define AKANTU_GET_MACRO_DEREF_PTR(name, ptr) \
inline const auto & get##name() const { \
if (not(ptr)) { \
AKANTU_EXCEPTION("The member " << #ptr << " is not initialized"); \
} \
return (*(ptr)); \
}
#define AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(name, ptr) \
- inline auto & get##name() { \
+ inline decltype(auto) get##name() { \
if (not(ptr)) { \
AKANTU_EXCEPTION("The member " << #ptr << " is not initialized"); \
} \
return (*(ptr)); \
}
#define AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, support, con) \
- inline con Array<type> & get##name(const support & el_type, \
- GhostType ghost_type = _not_ghost) \
- con { /* NOLINT */ \
+ inline auto get##name(const support & el_type, \
+ GhostType ghost_type = _not_ghost) \
+ con->con Array<type> & { \
return variable(el_type, ghost_type); \
} // NOLINT
#define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \
AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, )
#define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type) \
AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, const)
#define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE(name, variable, type) \
AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, )
#define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE_CONST(name, variable, type) \
AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, const)
/* -------------------------------------------------------------------------- */
/// initialize the static part of akantu
void initialize(int & argc, char **& argv);
/// initialize the static part of akantu and read the global input_file
void initialize(const std::string & input_file, int & argc, char **& argv);
/* -------------------------------------------------------------------------- */
/// finilize correctly akantu and clean the memory
void finalize();
/* -------------------------------------------------------------------------- */
/// Read an new input file
void readInputFile(const std::string & input_file);
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* string manipulation */
/* -------------------------------------------------------------------------- */
-inline std::string to_lower(const std::string & str);
+inline auto to_lower(const std::string & str) -> std::string;
/* -------------------------------------------------------------------------- */
-inline std::string trim(const std::string & to_trim);
-inline std::string trim(const std::string & to_trim, char c);
+inline auto trim(const std::string & to_trim) -> std::string;
+inline auto trim(const std::string & to_trim, char c) -> std::string;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/// give a string representation of the a human readable size in bit
-template <typename T> std::string printMemorySize(UInt size);
+template <typename T> auto printMemorySize(UInt size) -> std::string;
/* -------------------------------------------------------------------------- */
-struct TensorTrait {};
-struct TensorProxyTrait {};
-
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* Type traits */
/* -------------------------------------------------------------------------- */
namespace aka {
-/* ------------------------------------------------------------------------ */
-template <typename T> using is_tensor = std::is_base_of<akantu::TensorTrait, T>;
-template <typename T>
-using is_tensor_proxy = std::is_base_of<akantu::TensorProxyTrait, T>;
/* ------------------------------------------------------------------------ */
template <typename T> using is_scalar = std::is_arithmetic<T>;
/* ------------------------------------------------------------------------ */
template <typename R, typename T,
- std::enable_if_t<std::is_reference<T>::value> * = nullptr>
-bool is_of_type(T && t) {
- return (
- dynamic_cast<std::add_pointer_t<
- std::conditional_t<std::is_const<std::remove_reference_t<T>>::value,
- std::add_const_t<R>, R>>>(&t) != nullptr);
+ std::enable_if_t<std::is_reference_v<T>> * = nullptr>
+auto is_of_type(T && t) -> bool {
+ return (dynamic_cast<std::add_pointer_t<
+ std::conditional_t<std::is_const_v<std::remove_reference_t<T>>,
+ std::add_const_t<R>, R>>>(&t) != nullptr);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename R, typename T>
+auto is_of_type(std::unique_ptr<T> & t) -> bool {
+ return (dynamic_cast<std::add_pointer_t<
+ std::conditional_t<std::is_const_v<T>, std::add_const_t<R>, R>>>(
+ t.get()) != nullptr);
}
/* -------------------------------------------------------------------------- */
-template <typename R, typename T> bool is_of_type(std::unique_ptr<T> & t) {
- return (
- dynamic_cast<std::add_pointer_t<
- std::conditional_t<std::is_const<T>::value, std::add_const_t<R>, R>>>(
- t.get()) != nullptr);
+template <typename R, typename T>
+decltype(auto) as_type(const std::shared_ptr<T> & t) {
+ return std::dynamic_pointer_cast<R>(t);
}
/* ------------------------------------------------------------------------ */
template <typename R, typename T,
- std::enable_if_t<std::is_reference<T>::value> * = nullptr>
+ std::enable_if_t<std::is_reference_v<T>> * = nullptr>
decltype(auto) as_type(T && t) {
static_assert(
disjunction<
std::is_base_of<std::decay_t<T>, std::decay_t<R>>, // down-cast
std::is_base_of<std::decay_t<R>, std::decay_t<T>> // up-cast
>::value,
"Type T and R are not valid for a as_type conversion");
return dynamic_cast<std::add_lvalue_reference_t<
std::conditional_t<std::is_const<std::remove_reference_t<T>>::value,
std::add_const_t<R>, R>>>(t);
}
/* -------------------------------------------------------------------------- */
template <typename R, typename T,
std::enable_if_t<std::is_pointer<T>::value> * = nullptr>
decltype(auto) as_type(T && t) {
return &as_type<R>(*t);
}
-/* -------------------------------------------------------------------------- */
-template <typename R, typename T>
-decltype(auto) as_type(const std::shared_ptr<T> & t) {
- return std::dynamic_pointer_cast<R>(t);
-}
+template <class T> inline constexpr auto decay_v = std::decay_t<T>::value;
} // namespace aka
#include "aka_common_inline_impl.hh"
#include "aka_fwd.hh"
namespace akantu {
/// get access to the internal argument parser
cppargparse::ArgumentParser & getStaticArgumentParser();
/// get access to the internal input file parser
Parser & getStaticParser();
/// get access to the user part of the internal input file parser
const ParserSection & getUserParser();
#define AKANTU_CURRENT_FUNCTION \
(std::string(__func__) + "():" + std::to_string(__LINE__))
} // namespace akantu
/* -------------------------------------------------------------------------- */
#if AKANTU_INTEGER_SIZE == 4
#define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b9
#elif AKANTU_INTEGER_SIZE == 8
#define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b97f4a7c13LL
#endif
namespace std {
/**
* Hashing function for pairs based on hash_combine from boost The magic
* number is coming from the golden number @f[\phi = \frac{1 + \sqrt5}{2}@f]
* @f[\frac{2^32}{\phi} = 0x9e3779b9@f]
* http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine
* http://burtleburtle.net/bob/hash/doobs.html
*/
template <typename a, typename b> struct hash<std::pair<a, b>> {
hash() = default;
- size_t operator()(const std::pair<a, b> & p) const {
+ auto operator()(const std::pair<a, b> & p) const -> std::size_t {
size_t seed = ah(p.first);
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
return bh(p.second) + AKANTU_HASH_COMBINE_MAGIC_NUMBER + (seed << 6) +
(seed >> 2);
}
private:
const hash<a> ah{};
const hash<b> bh{};
};
} // namespace std
#endif // AKANTU_COMMON_HH_
diff --git a/src/common/aka_config.hh.in b/src/common/aka_config.hh.in
index a1d0cabbf..38f623e88 100644
--- a/src/common/aka_config.hh.in
+++ b/src/common/aka_config.hh.in
@@ -1,101 +1,114 @@
/**
* @file aka_config.hh.in
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Sep 26 2010
* @date last modification: Thu Jan 25 2018
*
* @brief Compilation time configuration of Akantu
*
*
* Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <string>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_CONFIG_HH_
#define AKANTU_AKA_CONFIG_HH_
// clang-format off
#define AKANTU_VERSION_MAJOR @AKANTU_MAJOR_VERSION@
#define AKANTU_VERSION_MINOR @AKANTU_MINOR_VERSION@
#define AKANTU_VERSION_PATCH @AKANTU_PATCH_VERSION@
#define AKANTU_VERSION_PRERELEASE "@AKANTU_PRERELEASE_VERSION@"
#define AKANTU_VERSION (AKANTU_VERSION_MAJOR * 10000 \
+ AKANTU_VERSION_MINOR * 100 \
+ AKANTU_VERSION_PATCH)
namespace akantu {
std::string getVersion();
}
@AKANTU_TYPES_EXTRA_INCLUDES@
namespace akantu {
using Real = @AKANTU_FLOAT_TYPE@;
using Int = @AKANTU_SIGNED_INTEGER_TYPE@;
+using Idx = @AKANTU_SIGNED_INTEGER_TYPE@;
using UInt = @AKANTU_UNSIGNED_INTEGER_TYPE@;
} // akantu
#define AKANTU_INTEGER_SIZE @AKANTU_INTEGER_SIZE@
#define AKANTU_FLOAT_SIZE @AKANTU_FLOAT_SIZE@
+
// clang-format on
+#cmakedefine AKANTU_CAN_COMPILE_CONSTEXPR_MAP
+#cmakedefine AKANTU_HAS_GNU_UNLIKELY
+#cmakedefine AKANTU_HAS_BUILTIN_EXPECT
+
+#if defined(AKANTU_HAS_GNU_UNLIKELY)
+#define AKANTU_UNLIKELY(x) (x) [[gnu::unlikely]]
+#elif defined(AKANTU_HAS_BUILTIN_EXPECT)
+#define AKANTU_UNLIKELY(x) (__builtin_expect(!!(x), 0))
+#else
+#define AKANTU_UNLIKELY(x) (x)
+#endif
#cmakedefine AKANTU_USE_BLAS
#cmakedefine AKANTU_USE_LAPACK
#cmakedefine AKANTU_PARALLEL
#cmakedefine AKANTU_USE_MPI
#cmakedefine AKANTU_USE_SCOTCH
#cmakedefine AKANTU_USE_PTSCOTCH
#cmakedefine AKANTU_SCOTCH_NO_EXTERN
#cmakedefine AKANTU_IMPLICIT
#cmakedefine AKANTU_USE_MUMPS
#cmakedefine AKANTU_USE_PETSC
#cmakedefine AKANTU_USE_PYBIND11
#cmakedefine AKANTU_EXTRA_MATERIALS
#cmakedefine AKANTU_STUDENTS_EXTRA_PACKAGE
#cmakedefine AKANTU_DAMAGE_NON_LOCAL
#cmakedefine AKANTU_SOLID_MECHANICS
#cmakedefine AKANTU_STRUCTURAL_MECHANICS
#cmakedefine AKANTU_HEAT_TRANSFER
#cmakedefine AKANTU_PHASE_FIELD
#cmakedefine AKANTU_COHESIVE_ELEMENT
#cmakedefine AKANTU_CONTACT_MECHANICS
#cmakedefine AKANTU_MODEL_COUPLERS
#cmakedefine AKANTU_IGFEM
#cmakedefine AKANTU_EMBEDDED
// clang-format off
// Debug tools
//#cmakedefine AKANTU_NDEBUG
#cmakedefine AKANTU_DEBUG_TOOLS
#cmakedefine READLINK_COMMAND @READLINK_COMMAND@
#cmakedefine ADDR2LINE_COMMAND @ADDR2LINE_COMMAND@
// clang-format on
#endif /* AKANTU_AKA_CONFIG_HH_ */
diff --git a/src/common/aka_constexpr_map.hh b/src/common/aka_constexpr_map.hh
new file mode 100644
index 000000000..42058a7bb
--- /dev/null
+++ b/src/common/aka_constexpr_map.hh
@@ -0,0 +1,84 @@
+
+#include <array>
+#include <tuple>
+#include <type_traits>
+
+#ifndef AKANTU_CONSTEXPR_MAP_HH
+#define AKANTU_CONSTEXPR_MAP_HH
+
+namespace akantu {
+namespace details {
+ template <class InputIt, class UnaryPredicate>
+ constexpr InputIt my_find_if(InputIt first, InputIt last,
+ UnaryPredicate && p) {
+ for (; first != last; ++first) {
+ if (std::forward<UnaryPredicate>(p)(*first)) {
+ return first;
+ }
+ }
+ return last;
+ }
+
+ // Author Jason Turner C++ Weekly ep 233
+ template <typename Key, typename Value, std::size_t Size>
+ struct ConstexprMap {
+ std::array<std::pair<Key, Value>, Size> data;
+
+ [[nodiscard]] constexpr Value at(const Key & key) const {
+ const auto it =
+ my_find_if(data.begin(), data.end(),
+ [&key](const auto & val) { return val.first == key; });
+
+ if (it != data.end()) {
+ return it->second;
+ } else {
+ throw std::range_error("Key out of range");
+ }
+ }
+
+ [[nodiscard]] constexpr auto find(const Key & key) const {
+ const auto it =
+ my_find_if(data.begin(), data.end(),
+ [&key](const auto & val) { return val.first == key; });
+
+ return it;
+ }
+
+ [[nodiscard]] constexpr auto begin() const { return data.begin(); }
+ [[nodiscard]] constexpr auto end() const { return data.end(); }
+ };
+
+ // magic_switch from
+ // https://stackoverflow.com/questions/39915986/solutions-for-dynamic-dispatch-on-unrelated-types
+ template <class Function, class DynamicType, class Tuple,
+ class DefaultFunction, std::size_t... Is>
+ [[gnu::visibility("hidden")]] constexpr decltype(auto) static_switch_dispatch(
+ const Tuple &, Function && function, const DynamicType & type,
+ DefaultFunction && default_function, std::index_sequence<Is...> /*is*/) {
+ auto * function_pointer = std::addressof(function);
+ using FunctionPointer = decltype(function_pointer);
+ using Ret = decltype(function(std::tuple_element_t<0, Tuple>{}));
+ using TableEntry = Ret (*)(FunctionPointer);
+
+ constexpr std::array<std::pair<DynamicType, std::size_t>, sizeof...(Is)>
+ data{{{std::tuple_element_t<Is, Tuple>::value, Is}...}};
+
+ constexpr auto map =
+ ConstexprMap<DynamicType, std::size_t, data.size()>{{data}};
+
+ constexpr TableEntry table[] = {
+ [](FunctionPointer function_pointer) -> Ret {
+ return (*function_pointer)(std::tuple_element_t<Is, Tuple>{});
+ }...};
+
+ auto it = map.find(type);
+ if (it != map.end()) {
+ return table[it->second](function_pointer);
+ } else {
+ return default_function(type);
+ }
+ }
+} // namespace details
+} // namespace akantu
+
+#endif // AKANTU_CONSTEXPR_MAP_HH
diff --git a/src/common/aka_csr.hh b/src/common/aka_csr.hh
index 0ed83138c..2f1b1c7c3 100644
--- a/src/common/aka_csr.hh
+++ b/src/common/aka_csr.hh
@@ -1,287 +1,286 @@
/**
* @file aka_csr.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Apr 20 2011
* @date last modification: Tue Sep 29 2020
*
* @brief A compresed sparse row structure based on akantu Arrays
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_CSR_HH_
#define AKANTU_AKA_CSR_HH_
namespace akantu {
/**
* This class can be used to store the structure of a sparse matrix or for
* vectors with variable number of component per element
*
* @param nb_rows number of rows of a matrix or size of a vector.
*/
template <typename T> class CSR {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- explicit CSR(UInt nb_rows = 0)
+ explicit CSR(Int nb_rows = 0)
: nb_rows(nb_rows), rows_offsets(nb_rows + 1, 1, "rows_offsets"),
rows(0, 1, "rows") {
rows_offsets.zero();
};
virtual ~CSR() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// does nothing
inline void beginInsertions(){};
/// insert a new entry val in row row
- inline UInt insertInRow(UInt row, const T & val) {
- UInt pos = rows_offsets(row)++;
+ inline Idx insertInRow(Idx row, const T & val) {
+ Idx pos = rows_offsets(row)++;
rows(pos) = val;
return pos;
}
/// access an element of the matrix
- inline const T & operator()(UInt row, UInt col) const {
+ inline const T & operator()(Idx row, Idx col) const {
AKANTU_DEBUG_ASSERT(rows_offsets(row + 1) - rows_offsets(row) > col,
"This element is not present in this CSR");
return rows(rows_offsets(row) + col);
}
/// access an element of the matrix
- inline T & operator()(UInt row, UInt col) {
+ inline T & operator()(Idx row, Idx col) {
AKANTU_DEBUG_ASSERT(rows_offsets(row + 1) - rows_offsets(row) > col,
"This element is not present in this CSR");
return rows(rows_offsets(row) + col);
}
inline void endInsertions() {
- for (UInt i = nb_rows; i > 0; --i) {
+ for (Int i = nb_rows; i > 0; --i) {
rows_offsets(i) = rows_offsets(i - 1);
}
rows_offsets(0) = 0;
}
inline void countToCSR() {
- for (UInt i = 1; i < nb_rows; ++i) {
+ for (Int i = 1; i < nb_rows; ++i) {
rows_offsets(i) += rows_offsets(i - 1);
}
- for (UInt i = nb_rows; i >= 1; --i) {
+ for (Int i = nb_rows; i >= 1; --i) {
rows_offsets(i) = rows_offsets(i - 1);
}
rows_offsets(0) = 0;
}
inline void clearRows() {
rows_offsets.zero();
rows.resize(0);
};
- inline void resizeRows(UInt nb_rows) {
+ inline void resizeRows(Int nb_rows) {
this->nb_rows = nb_rows;
rows_offsets.resize(nb_rows + 1);
rows_offsets.zero();
}
inline void resizeCols() { rows.resize(rows_offsets(nb_rows)); }
- inline void copy(Array<UInt> & offsets, Array<T> & values) {
+ inline void copy(Array<Idx> & offsets, Array<T> & values) {
offsets.copy(rows_offsets);
values.copy(rows);
}
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// returns the number of rows
- inline UInt getNbRows() const { return rows_offsets.size() - 1; };
+ inline Int getNbRows() const { return rows_offsets.size() - 1; };
/// returns the number of non-empty columns in a given row
- inline UInt getNbCols(UInt row) const {
+ inline Int getNbCols(Idx row) const {
return rows_offsets(row + 1) - rows_offsets(row);
};
/// returns the offset (start of columns) for a given row
- inline UInt & rowOffset(UInt row) { return rows_offsets(row); };
+ inline Idx & rowOffset(Idx row) { return rows_offsets(row); };
// /// iterator on a row
// template <class array_iterator>
// class iterator_internal
// : public std::iterator<std::bidirectional_iterator_tag, typename
// array_iterator::value_type> {
// public:
// using _parent = std::iterator<std::bidirectional_iterator_tag, R>;
// using pointer = typename _parent::pointer;
// using reference = typename _parent::reference;
// explicit iterator_internal(array_iterator ait) : pos(std::move(ait)){};
// iterator_internal(const iterator_internal & it) : pos(it.pos){};
// iterator_internal & operator++() {
// ++pos;
// return *this;
// };
// iterator_internal operator++(int) {
// iterator tmp(*this);
// operator++();
// return tmp;
// };
// iterator_internal & operator--() {
// --pos;
// return *this;
// };
// iterator_internal operator--(int) {
// iterator_internal tmp(*this);
// operator--();
// return tmp;
// };
// bool operator==(const iterator_internal & rhs) { return pos == rhs.pos;
// }; bool operator!=(const iterator_internal & rhs) { return pos !=
// rhs.pos; }; reference operator*() { return *pos; }; pointer operator->()
// const { return pos; };
// private:
// array_iterator pos;
// };
using iterator = typename Array<T>::scalar_iterator;
using const_iterator = typename Array<T>::const_scalar_iterator;
template <typename iterator_internal> class CSRRow {
public:
+ using size_type = Idx;
CSRRow(iterator_internal begin, iterator_internal end)
: begin_(std::move(begin)), end_(std::move(end)) {}
inline auto begin() const { return begin_; }
inline auto end() const { return end_; }
private:
iterator_internal begin_, end_;
};
- inline iterator begin(UInt row) { return rows.begin() + rows_offsets(row); };
- inline iterator end(UInt row) {
- return rows.begin() + rows_offsets(row + 1);
- };
+ inline iterator begin(Idx row) { return rows.begin() + rows_offsets(row); };
+ inline iterator end(Idx row) { return rows.begin() + rows_offsets(row + 1); };
- inline const_iterator begin(UInt row) const {
+ inline const_iterator begin(Idx row) const {
return rows.begin() + rows_offsets(row);
};
- inline const_iterator end(UInt row) const {
+ inline const_iterator end(Idx row) const {
return rows.begin() + rows_offsets(row + 1);
};
private:
template <typename iterator_internal>
decltype(auto) make_row(iterator_internal begin, iterator_internal end) {
return CSRRow<iterator_internal>(std::move(begin), std::move(end));
}
public:
- inline decltype(auto) getRow(UInt row) {
+ inline decltype(auto) getRow(Idx row) {
return make_row(begin(row), end(row));
}
- inline decltype(auto) getRow(UInt row) const {
+ inline decltype(auto) getRow(Idx row) const {
return make_row(begin(row), end(row));
}
- inline iterator rbegin(UInt row) {
+ inline iterator rbegin(Idx row) {
return rows.begin() + rows_offsets(row + 1) - 1;
};
- inline iterator rend(UInt row) {
+ inline iterator rend(Idx row) {
return rows.begin() + rows_offsets(row) - 1;
};
- inline const Array<UInt> & getRowsOffset() const { return rows_offsets; };
+ inline const Array<Idx> & getRowsOffset() const { return rows_offsets; };
inline const Array<T> & getRows() const { return rows; };
inline Array<T> & getRows() { return rows; };
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
- UInt nb_rows;
+ Int nb_rows;
/// array of size nb_rows containing the offset where the values are stored in
- Array<UInt> rows_offsets;
+ Array<Idx> rows_offsets;
/// compressed row values, values of row[i] are stored between rows_offsets[i]
/// and rows_offsets[i+1]
Array<T> rows;
};
/* -------------------------------------------------------------------------- */
/* Data CSR */
/* -------------------------------------------------------------------------- */
/**
- * Inherits from CSR<UInt> and can contain information such as matrix values
+ * Inherits from CSR<Idx> and can contain information such as matrix values
* where the mother class would be a CSR structure for row and cols
*
* @return nb_rows
*/
-template <class T> class DataCSR : public CSR<UInt> {
+template <class T> class DataCSR : public CSR<Idx> {
public:
- DataCSR(UInt nb_rows = 0) : CSR<UInt>(nb_rows), data(0, 1){};
+ DataCSR(Int nb_rows = 0) : CSR<Idx>(nb_rows), data(0, 1){};
inline void resizeCols() {
- CSR<UInt>::resizeCols();
+ CSR<Idx>::resizeCols();
data.resize(rows_offsets(nb_rows));
}
inline const Array<T> & getData() const { return data; };
private:
Array<T> data;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
//#include "aka_csr_inline_impl.hh"
/// standard output stream operator
// inline std::ostream & operator <<(std::ostream & stream, const CSR & _this)
// {
// _this.printself(stream);
// return stream;
// }
} // namespace akantu
#endif /* AKANTU_AKA_CSR_HH_ */
diff --git a/src/common/aka_element_classes_info.hh b/src/common/aka_element_classes_info.hh
new file mode 100644
index 000000000..12dda7492
--- /dev/null
+++ b/src/common/aka_element_classes_info.hh
@@ -0,0 +1,249 @@
+/**
+ * @file aka_element_classes_info.hh.in
+ *
+ * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ *
+ * @date creation: Sun Jul 19 2015
+ * @date last modification: Tue Feb 20 2018
+ *
+ * @brief Declaration of the enums for the element classes
+ *
+ *
+ * Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#include "aka_safe_enum.hh"
+/* -------------------------------------------------------------------------- */
+#include <boost/preprocessor.hpp>
+/* -------------------------------------------------------------------------- */
+
+// clang-format off
+#ifndef AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_
+#define AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+/* Element Types */
+/* -------------------------------------------------------------------------- */
+// clang-format off
+#define AKANTU_ek_regular_ELEMENT_TYPE \
+ (_point_1) \
+ (_segment_2) \
+ (_segment_3) \
+ (_triangle_3) \
+ (_triangle_6) \
+ (_quadrangle_4) \
+ (_quadrangle_8) \
+ (_tetrahedron_4) \
+ (_tetrahedron_10) \
+ (_pentahedron_6) \
+ (_pentahedron_15) \
+ (_hexahedron_8) \
+ (_hexahedron_20)
+
+#if defined(AKANTU_COHESIVE_ELEMENT)
+#define AKANTU_ek_cohesive_ELEMENT_TYPE \
+ (_cohesive_1d_2) \
+ (_cohesive_2d_4) \
+ (_cohesive_2d_6) \
+ (_cohesive_3d_12) \
+ (_cohesive_3d_16) \
+ (_cohesive_3d_6) \
+ (_cohesive_3d_8)
+#else
+#define AKANTU_ek_cohesive_ELEMENT_TYPE
+#endif
+
+#if defined(AKANTU_STRUCTURAL_MECHANICS)
+#define AKANTU_ek_structural_ELEMENT_TYPE \
+ (_bernoulli_beam_2) \
+ (_bernoulli_beam_3) \
+ (_discrete_kirchhoff_triangle_18)
+#else
+#define AKANTU_ek_structural_ELEMENT_TYPE
+#endif
+
+#if defined(AKANTU_IGFEM)
+#define AKANTU_ek_igfem_ELEMENT_TYPE \
+ (_igfem_segment_3) \
+ (_igfem_triangle_4) \
+ (_igfem_triangle_5)
+#else
+#define AKANTU_ek_igfem_ELEMENT_TYPE
+#endif
+
+#define AKANTU_ALL_ELEMENT_TYPE \
+ AKANTU_ek_regular_ELEMENT_TYPE \
+ AKANTU_ek_cohesive_ELEMENT_TYPE \
+ AKANTU_ek_structural_ELEMENT_TYPE \
+ AKANTU_ek_igfem_ELEMENT_TYPE
+// clang-format on
+
+/// @enum ElementType type of elements
+enum ElementType {
+ _not_defined,
+ BOOST_PP_SEQ_ENUM(AKANTU_ALL_ELEMENT_TYPE),
+ _max_element_type
+};
+
+/* -------------------------------------------------------------------------- */
+/* Element Kinds */
+/* -------------------------------------------------------------------------- */
+#define AKANTU_ELEMENT_KIND (_ek_regular)(_ek_cohesive)(_ek_structural)
+
+enum ElementKind { BOOST_PP_SEQ_ENUM(AKANTU_ELEMENT_KIND), _ek_not_defined };
+
+/* -------------------------------------------------------------------------- */
+struct ElementKind_def {
+ using type = ElementKind;
+ static const type _begin_ = BOOST_PP_SEQ_HEAD(AKANTU_ELEMENT_KIND);
+ static const type _end_ = _ek_not_defined;
+};
+
+using element_kind_t = safe_enum<ElementKind_def>;
+
+/* -------------------------------------------------------------------------- */
+/// @enum GeometricalType type of element potentially contained in a Mesh
+/// @enum GeometricalType type of element potentially contained in a Mesh
+enum GeometricalType {
+ _gt_point,
+ _gt_segment_2,
+ _gt_segment_3,
+ _gt_triangle_3,
+ _gt_triangle_6,
+ _gt_quadrangle_4,
+ _gt_quadrangle_8,
+ _gt_tetrahedron_4,
+ _gt_tetrahedron_10,
+ _gt_hexahedron_8,
+ _gt_hexahedron_20,
+ _gt_pentahedron_6,
+ _gt_pentahedron_15,
+#if defined(AKANTU_COHESIVE_ELEMENT)
+ _gt_cohesive_1d_2,
+ _gt_cohesive_2d_4,
+ _gt_cohesive_2d_6,
+ _gt_cohesive_3d_12,
+ _gt_cohesive_3d_16,
+ _gt_cohesive_3d_6,
+ _gt_cohesive_3d_8,
+#endif
+#if defined(AKANTU_IGFEM)
+ _gt_igfem_segment_3,
+ _gt_igfem_triangle_4,
+ _gt_igfem_triangle_5,
+#endif
+ _gt_not_defined
+};
+
+/* -------------------------------------------------------------------------- */
+/* Interpolation Types */
+/* -------------------------------------------------------------------------- */
+// clang-format off
+#define AKANTU_itp_regular_INTERPOLATION_TYPES \
+ (_itp_lagrange_point_1) \
+ (_itp_lagrange_segment_2) \
+ (_itp_lagrange_segment_3) \
+ (_itp_lagrange_triangle_3) \
+ (_itp_lagrange_triangle_6) \
+ (_itp_lagrange_quadrangle_4) \
+ (_itp_serendip_quadrangle_8) \
+ (_itp_lagrange_tetrahedron_4) \
+ (_itp_lagrange_tetrahedron_10) \
+ (_itp_lagrange_hexahedron_8) \
+ (_itp_serendip_hexahedron_20) \
+ (_itp_lagrange_pentahedron_6) \
+ (_itp_lagrange_pentahedron_15)
+
+#if defined(AKANTU_STRUCTURAL_MECHANICS)
+#define AKANTU_itp_structural_INTERPOLATION_TYPES \
+ (_itp_hermite_2) \
+ (_itp_bernoulli_beam_2) \
+ (_itp_bernoulli_beam_3) \
+ (_itp_discrete_kirchhoff_triangle_18)
+#else
+#define AKANTU_itp_structural_INTERPOLATION_TYPES
+#endif
+
+#if defined(AKANTU_IGFEM)
+#define AKANTU_itp_igfem_INTERPOLATION_TYPES \
+ (_itp_igfem_segment_3) \
+ (_itp_igfem_triangle_4) \
+ (_itp_igfem_triangle_5)
+#else
+#define AKANTU_itp_igfem_INTERPOLATION_TYPES
+#endif
+
+#define AKANTU_INTERPOLATION_TYPES \
+ AKANTU_itp_regular_INTERPOLATION_TYPES \
+ AKANTU_itp_structural_INTERPOLATION_TYPES \
+ AKANTU_itp_igfem_INTERPOLATION_TYPES
+// clang-format on
+
+/// @enum InterpolationType type of elements
+enum InterpolationType {
+ BOOST_PP_SEQ_ENUM(AKANTU_INTERPOLATION_TYPES),
+ _itp_not_defined
+};
+
+/* -------------------------------------------------------------------------- */
+/* Some sub types less probable to change */
+/* -------------------------------------------------------------------------- */
+/// @enum GeometricalShapeType types of shapes to define the contains
+/// function in the element classes
+enum GeometricalShapeType {
+ _gst_point,
+ _gst_triangle,
+ _gst_square,
+ _gst_prism,
+ _gst_not_defined
+};
+
+/* -------------------------------------------------------------------------- */
+/// @enum GaussIntegrationType classes of types using common
+/// description of the gauss point position and weights
+enum GaussIntegrationType {
+ _git_point,
+ _git_segment,
+ _git_triangle,
+ _git_tetrahedron,
+ _git_pentahedron,
+ _git_not_defined
+};
+
+/* -------------------------------------------------------------------------- */
+/// @enum InterpolationKind the family of interpolation types
+enum InterpolationKind {
+ _itk_lagrangian,
+#if defined(AKANTU_STRUCTURAL_MECHANICS)
+ _itk_structural,
+#endif
+#if defined(AKANTU_IGFEM)
+ _itk_igfem,
+#endif
+ _itk_not_defined
+};
+
+} // namespace akantu
+
+#endif /* AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_ */
+// clang-format on
+
+#include "aka_element_classes_info_inline_impl.hh"
diff --git a/src/common/aka_element_classes_info.hh.in b/src/common/aka_element_classes_info.hh.in
index 2b34cddb3..8eb2018e8 100644
--- a/src/common/aka_element_classes_info.hh.in
+++ b/src/common/aka_element_classes_info.hh.in
@@ -1,209 +1,140 @@
/**
* @file aka_element_classes_info.hh.in
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Jul 19 2015
* @date last modification: Tue Feb 20 2018
*
* @brief Declaration of the enums for the element classes
*
*
* Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_safe_enum.hh"
/* -------------------------------------------------------------------------- */
#include <boost/preprocessor.hpp>
/* -------------------------------------------------------------------------- */
+// clang-format off
#ifndef AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_
#define AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Element Types */
/* -------------------------------------------------------------------------- */
-
/// @enum ElementType type of elements
enum ElementType {
_not_defined,
@AKANTU_ELEMENT_TYPES_ENUM@
_max_element_type
};
@AKANTU_ELEMENT_TYPES_BOOST_SEQ@
@AKANTU_ALL_ELEMENT_BOOST_SEQ@
/* -------------------------------------------------------------------------- */
/* Element Kinds */
/* -------------------------------------------------------------------------- */
-@AKANTU_ELEMENT_KINDS_BOOST_SEQ@
-
-@AKANTU_ELEMENT_KIND_BOOST_SEQ@
+#define AKANTU_ELEMENT_KIND (_ek_regular)(_ek_cohesive)(_ek_structural)
enum ElementKind {
BOOST_PP_SEQ_ENUM(AKANTU_ELEMENT_KIND),
_ek_not_defined
};
/* -------------------------------------------------------------------------- */
struct ElementKind_def {
using type = ElementKind;
static const type _begin_ = BOOST_PP_SEQ_HEAD(AKANTU_ELEMENT_KIND);
static const type _end_ = _ek_not_defined;
};
using element_kind_t = safe_enum<ElementKind_def> ;
/* -------------------------------------------------------------------------- */
/// @enum GeometricalType type of element potentially contained in a Mesh
enum GeometricalType {
@AKANTU_GEOMETRICAL_TYPES_ENUM@
_gt_not_defined
};
/* -------------------------------------------------------------------------- */
/* Interpolation Types */
/* -------------------------------------------------------------------------- */
@AKANTU_INTERPOLATION_TYPES_BOOST_SEQ@
/// @enum InterpolationType type of elements
enum InterpolationType {
BOOST_PP_SEQ_ENUM(AKANTU_INTERPOLATION_TYPES),
_itp_not_defined
};
/* -------------------------------------------------------------------------- */
/* Some sub types less probable to change */
/* -------------------------------------------------------------------------- */
/// @enum GeometricalShapeType types of shapes to define the contains
/// function in the element classes
enum GeometricalShapeType {
@AKANTU_GEOMETRICAL_SHAPES_ENUM@
_gst_not_defined
};
/* -------------------------------------------------------------------------- */
/// @enum GaussIntegrationType classes of types using common
/// description of the gauss point position and weights
enum GaussIntegrationType {
@AKANTU_GAUSS_INTEGRATION_TYPES_ENUM@
_git_not_defined
};
/* -------------------------------------------------------------------------- */
/// @enum InterpolationKind the family of interpolation types
enum InterpolationKind {
@AKANTU_INTERPOLATION_KIND_ENUM@
_itk_not_defined
};
-/* -------------------------------------------------------------------------- */
-// BOOST PART: TOUCH ONLY IF YOU KNOW WHAT YOU ARE DOING
-#define AKANTU_BOOST_CASE_MACRO(r, macro, _type) \
- case _type: { \
- macro(_type); \
- break; \
- }
-
-#define AKANTU_BOOST_LIST_SWITCH(macro1, list1, var) \
- do { \
- switch (var) { \
- BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \
- default: { \
- AKANTU_ERROR("Type (" \
- << var /* NOLINT */ << ") not handled by this function"); \
- } \
- } \
- } while (0)
-
-#define AKANTU_BOOST_LIST_SWITCH_NO_DEFAULT(macro1, list1, var) \
- do { \
- switch (var) { \
- BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \
- case _not_defined: /* FALLTHRU */ \
- case _max_element_type: \
- break; \
- } \
- } while (0)
-
-#define AKANTU_BOOST_ELEMENT_SWITCH(macro1, list1) \
- AKANTU_BOOST_LIST_SWITCH(macro1, list1, type)
-
-#define AKANTU_BOOST_ELEMENT_SWITCH_NO_DEFAULT(macro1, list1) \
- AKANTU_BOOST_LIST_SWITCH_NO_DEFAULT(macro1, list1, type)
-
-#define AKANTU_BOOST_ALL_ELEMENT_SWITCH(macro) \
- AKANTU_BOOST_ELEMENT_SWITCH(macro, AKANTU_ALL_ELEMENT_TYPE)
-
-#define AKANTU_BOOST_ALL_ELEMENT_SWITCH_NO_DEFAULT(macro) \
- AKANTU_BOOST_ELEMENT_SWITCH_NO_DEFAULT(macro, AKANTU_ALL_ELEMENT_TYPE)
-
-#define AKANTU_BOOST_LIST_MACRO(r, macro, type) macro(type)
-
-#define AKANTU_BOOST_APPLY_ON_LIST(macro, list) \
- BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list)
-
-#define AKANTU_BOOST_ALL_ELEMENT_LIST(macro) \
- AKANTU_BOOST_APPLY_ON_LIST(macro, AKANTU_ALL_ELEMENT_TYPE)
-
-#define AKANTU_GET_ELEMENT_LIST(kind) AKANTU##kind##_ELEMENT_TYPE
-
-#define AKANTU_BOOST_KIND_ELEMENT_SWITCH(macro, kind) \
- AKANTU_BOOST_ELEMENT_SWITCH(macro, AKANTU_GET_ELEMENT_LIST(kind))
-
-// BOOST_PP_SEQ_TO_LIST does not exists in Boost < 1.49
-#define AKANTU_GENERATE_KIND_LIST(seq) \
- BOOST_PP_TUPLE_TO_LIST(BOOST_PP_SEQ_SIZE(seq), BOOST_PP_SEQ_TO_TUPLE(seq))
-
-#define AKANTU_ELEMENT_KIND_BOOST_LIST \
- AKANTU_GENERATE_KIND_LIST(AKANTU_ELEMENT_KIND)
-
-#define AKANTU_BOOST_ALL_KIND_LIST(macro, list) \
- BOOST_PP_LIST_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list)
-
-#define AKANTU_BOOST_ALL_KIND(macro) \
- AKANTU_BOOST_ALL_KIND_LIST(macro, AKANTU_ELEMENT_KIND_BOOST_LIST)
-
-#define AKANTU_BOOST_ALL_KIND_SWITCH(macro) \
- AKANTU_BOOST_LIST_SWITCH(macro, AKANTU_ELEMENT_KIND, kind)
@AKANTU_ELEMENT_KINDS_BOOST_MACROS@
// /// define kept for compatibility reasons (they are most probably not needed
// /// anymore) \todo check if they can be removed
// #define AKANTU_REGULAR_ELEMENT_TYPE AKANTU_ek_regular_ELEMENT_TYPE
// #define AKANTU_COHESIVE_ELEMENT_TYPE AKANTU_ek_cohesive_ELEMENT_TYPE
// #define AKANTU_STRUCTURAL_ELEMENT_TYPE AKANTU_ek_structural_ELEMENT_TYPE
// #define AKANTU_IGFEM_ELEMENT_TYPE AKANTU_ek_igfem_ELEMENT_TYPE
+
/* -------------------------------------------------------------------------- */
/* Lists of interests for FEEngineTemplate functions */
/* -------------------------------------------------------------------------- */
@AKANTU_FE_ENGINE_LISTS@
} // akantu
#endif /* AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_ */
+// clang-format on
#include "aka_element_classes_info_inline_impl.hh"
diff --git a/src/common/aka_element_classes_info_inline_impl.hh b/src/common/aka_element_classes_info_inline_impl.hh
index 33d64d7ae..4fb125902 100644
--- a/src/common/aka_element_classes_info_inline_impl.hh
+++ b/src/common/aka_element_classes_info_inline_impl.hh
@@ -1,55 +1,344 @@
/**
* @file aka_element_classes_info_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Jun 18 2015
* @date last modification: Tue Sep 29 2020
*
* @brief Implementation of the streaming fonction for the element classes
* enums
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
/* -------------------------------------------------------------------------- */
+#include "aka_config.hh"
+#include "aka_tuple_tools.hh"
+#if defined(AKANTU_CAN_COMPILE_CONSTEXPR_MAP)
+#include "aka_constexpr_map.hh"
+#endif
+/* -------------------------------------------------------------------------- */
+#include <tuple>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_ELEMENT_CLASSES_INFO_INLINE_IMPL_HH_
#define AKANTU_AKA_ELEMENT_CLASSES_INFO_INLINE_IMPL_HH_
namespace akantu {
+/* -------------------------------------------------------------------------- */
+// BOOST PART: TOUCH ONLY IF YOU KNOW WHAT YOU ARE DOING
+#define AKANTU_BOOST_CASE_MACRO(r, macro, _type) \
+ case _type: { \
+ macro(_type); \
+ break; \
+ }
+
+#define AKANTU_BOOST_LIST_SWITCH(macro1, list1, var) \
+ do { \
+ switch (var) { \
+ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \
+ default: { \
+ AKANTU_ERROR("Type (" << var << ") not handled by this function"); \
+ } \
+ } \
+ } while (0)
+
+#define AKANTU_BOOST_LIST_SWITCH_NO_DEFAULT(macro1, list1, var) \
+ do { \
+ switch (var) { \
+ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \
+ case _not_defined: \
+ break; \
+ case _max_element_type: \
+ break; \
+ } \
+ } while (0)
+
+#define AKANTU_BOOST_LIST_SWITCH_CONSTEXPR(macro1, list1, var) \
+ do { \
+ switch (var) { \
+ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \
+ default: { \
+ macro1(_not_defined); \
+ } \
+ } \
+ } while (0)
+
+#define AKANTU_BOOST_LIST_SWITCH_WITH_DEFAULT_MACRO(macro1, def_macro, list1, \
+ var) \
+ do { \
+ switch (var) { \
+ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \
+ default: { \
+ def_macro(var); \
+ } \
+ } \
+ } while (0)
+
+#define AKANTU_BOOST_ELEMENT_SWITCH(macro1, list1) \
+ AKANTU_BOOST_LIST_SWITCH(macro1, list1, type)
+
+#define AKANTU_BOOST_ELEMENT_SWITCH_NO_DEFAULT(macro1, list1) \
+ AKANTU_BOOST_LIST_SWITCH_NO_DEFAULT(macro1, list1, type)
+
+#define AKANTU_BOOST_ELEMENT_SWITCH_CONSTEXPR(macro1, list1) \
+ AKANTU_BOOST_LIST_SWITCH_CONSTEXPR(macro1, list1, type)
+
+#define AKANTU_BOOST_ELEMENT_SWITCH_WITH_DEFAULT_MACRO(macro1, def_macro, \
+ list1) \
+ AKANTU_BOOST_LIST_SWITCH_WITH_DEFAULT_MACRO(macro1, def_macro, list1, type)
+
+#define AKANTU_BOOST_ALL_ELEMENT_SWITCH(macro) \
+ AKANTU_BOOST_ELEMENT_SWITCH(macro, AKANTU_ALL_ELEMENT_TYPE)
+
+#define AKANTU_BOOST_ALL_ELEMENT_SWITCH_NO_DEFAULT(macro) \
+ AKANTU_BOOST_ELEMENT_SWITCH_NO_DEFAULT(macro, AKANTU_ALL_ELEMENT_TYPE)
+
+#define AKANTU_BOOST_ALL_ELEMENT_SWITCH_CONSTEXPR(macro) \
+ AKANTU_BOOST_ELEMENT_SWITCH_CONSTEXPR(macro, AKANTU_ALL_ELEMENT_TYPE)
+
+#define AKANTU_BOOST_LIST_MACRO(r, macro, type) macro(type)
+
+#define AKANTU_BOOST_APPLY_ON_LIST(macro, list) \
+ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list)
+
+#define AKANTU_BOOST_ALL_ELEMENT_LIST(macro) \
+ AKANTU_BOOST_APPLY_ON_LIST(macro, AKANTU_ALL_ELEMENT_TYPE)
+
+#define AKANTU_GET_ELEMENT_LIST(kind) AKANTU##kind##_ELEMENT_TYPE
+
+#define AKANTU_BOOST_KIND_ELEMENT_SWITCH(macro, kind) \
+ AKANTU_BOOST_ELEMENT_SWITCH(macro, AKANTU_GET_ELEMENT_LIST(kind))
+
+// BOOST_PP_SEQ_TO_LIST does not exists in Boost < 1.49
+#define AKANTU_GENERATE_KIND_LIST(seq) \
+ BOOST_PP_TUPLE_TO_LIST(BOOST_PP_SEQ_SIZE(seq), BOOST_PP_SEQ_TO_TUPLE(seq))
+
+#define AKANTU_ELEMENT_KIND_BOOST_LIST \
+ AKANTU_GENERATE_KIND_LIST(AKANTU_ELEMENT_KIND)
+
+#define AKANTU_BOOST_ALL_KIND_LIST(macro, list) \
+ BOOST_PP_LIST_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list)
+
+#define AKANTU_BOOST_ALL_KIND(macro) \
+ AKANTU_BOOST_ALL_KIND_LIST(macro, AKANTU_ELEMENT_KIND_BOOST_LIST)
+
+#define AKANTU_BOOST_ALL_KIND_SWITCH(macro) \
+ AKANTU_BOOST_LIST_SWITCH(macro, AKANTU_ELEMENT_KIND, kind)
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
AKANTU_ENUM_OUTPUT_STREAM(
ElementType, AKANTU_ALL_ELEMENT_TYPE(_not_defined)(_max_element_type))
AKANTU_ENUM_INPUT_STREAM(ElementType, AKANTU_ALL_ELEMENT_TYPE)
AKANTU_ENUM_OUTPUT_STREAM(InterpolationType, AKANTU_INTERPOLATION_TYPES)
AKANTU_ENUM_INPUT_STREAM(InterpolationType, AKANTU_INTERPOLATION_TYPES)
AKANTU_ENUM_OUTPUT_STREAM(ElementKind, AKANTU_ELEMENT_KIND)
AKANTU_ENUM_INPUT_STREAM(ElementKind, AKANTU_ELEMENT_KIND)
+template <::akantu::ElementType t>
+using element_type_t = std::integral_constant<::akantu::ElementType, t>;
+
+#define OP_CAT(s, data, elem) BOOST_PP_CAT(_element_type, elem)
+
+// creating a type instead of a using helps to debug
+#define AKANTU_DECLARE_ELEMENT_TYPE_STRUCT(r, data, elem) \
+ struct BOOST_PP_CAT(_element_type, elem) \
+ : public element_type_t<::akantu::elem> {};
+
+BOOST_PP_SEQ_FOR_EACH(AKANTU_DECLARE_ELEMENT_TYPE_STRUCT, _,
+ AKANTU_ALL_ELEMENT_TYPE)
+
+#undef AKANTU_DECLARE_ELEMENT_TYPE_STRUCT
+
+template <ElementKind kind> struct ElementTypes;
+
+template <> struct ElementTypes<_ek_regular> {
+ using type = std::tuple<BOOST_PP_SEQ_ENUM(
+ BOOST_PP_SEQ_TRANSFORM(OP_CAT, _, AKANTU_ek_regular_ELEMENT_TYPE))>;
+};
+
+#if defined(AKANTU_COHESIVE_ELEMENT)
+template <> struct ElementTypes<_ek_cohesive> {
+ using type = std::tuple<BOOST_PP_SEQ_ENUM(
+ BOOST_PP_SEQ_TRANSFORM(OP_CAT, _, AKANTU_ek_cohesive_ELEMENT_TYPE))>;
+};
+#else
+template <> struct ElementTypes<_ek_cohesive> { using type = std::tuple<>; };
+#endif
+
+#if defined(AKANTU_STRUCTURAL_MECHANICS)
+template <> struct ElementTypes<_ek_structural> {
+ using type = std::tuple<BOOST_PP_SEQ_ENUM(
+ BOOST_PP_SEQ_TRANSFORM(OP_CAT, _, AKANTU_ek_structural_ELEMENT_TYPE))>;
+};
+#else
+template <> struct ElementTypes<_ek_structural> { using type = std::tuple<>; };
+#endif
+
+#undef OP_CAT
+
+template <ElementKind kind>
+using ElementTypes_t = typename ElementTypes<kind>::type;
+
+#define OP_CAT(s, data, elem) ElementTypes_t<elem>
+using AllElementTypes = tuple::cat_t<BOOST_PP_SEQ_ENUM(
+ BOOST_PP_SEQ_TRANSFORM(OP_CAT, _, AKANTU_ELEMENT_KIND))>;
+#undef OP_CAT
+
+namespace details {
+
+#if !defined(AKANTU_CAN_COMPILE_CONSTEXPR_MAP)
+ template <class Function, class DynamicType, class DefaultFunction,
+ std::size_t... Is>
+ constexpr decltype(auto)
+ static_switch_dispatch(const AllSpatialDimensions &, Function && function,
+ const DynamicType & type,
+ DefaultFunction && default_function,
+ std::index_sequence<Is...> /*is*/) {
+ switch (type) {
+ case 1: {
+ return function(dim_1_t{});
+ }
+ case 2: {
+ return function(dim_2_t{});
+ }
+ case 3: {
+ return function(dim_3_t{});
+ }
+ default:
+ return default_function(type);
+ }
+ }
+
+#define AKANTU_STATIC_SWITCH_DISPATCH_FUNCTION(type) \
+ return function(element_type_t<type>{})
+#define AKANTU_STATIC_SWITCH_DISPATCH_DEFAULT(type) \
+ return default_function(type)
+ template <class Function, class DynamicType, class DefaultFunction,
+ std::size_t... Is>
+ constexpr decltype(auto) static_switch_dispatch(
+ const AllElementTypes &, Function && function, const DynamicType & type,
+ DefaultFunction && default_function, std::index_sequence<Is...> /*is*/) {
+
+ AKANTU_BOOST_ELEMENT_SWITCH_WITH_DEFAULT_MACRO(
+ AKANTU_STATIC_SWITCH_DISPATCH_FUNCTION,
+ AKANTU_STATIC_SWITCH_DISPATCH_DEFAULT, AKANTU_ALL_ELEMENT_TYPE);
+ }
+
+ template <class Function, class DynamicType, class DefaultFunction,
+ std::size_t... Is>
+ constexpr decltype(auto)
+ static_switch_dispatch(const ElementTypes_t<_ek_regular> &,
+ Function && function, const DynamicType & type,
+ DefaultFunction && default_function,
+ std::index_sequence<Is...> /*is*/) {
+ AKANTU_BOOST_ELEMENT_SWITCH_WITH_DEFAULT_MACRO(
+ AKANTU_STATIC_SWITCH_DISPATCH_FUNCTION,
+ AKANTU_STATIC_SWITCH_DISPATCH_DEFAULT, AKANTU_ek_regular_ELEMENT_TYPE);
+ }
+
+#if defined(AKANTU_STRUCTURAL_MECHANICS)
+ template <class Function, class DynamicType, class DefaultFunction,
+ std::size_t... Is>
+ constexpr decltype(auto)
+ static_switch_dispatch(const ElementTypes_t<_ek_structural> &,
+ Function && function, const DynamicType & type,
+ DefaultFunction && default_function,
+ std::index_sequence<Is...> /*is*/) {
+ AKANTU_BOOST_ELEMENT_SWITCH_WITH_DEFAULT_MACRO(
+ AKANTU_STATIC_SWITCH_DISPATCH_FUNCTION,
+ AKANTU_STATIC_SWITCH_DISPATCH_DEFAULT,
+ AKANTU_ek_structural_ELEMENT_TYPE);
+ }
+#endif
+
+#if defined(AKANTU_COHESIVE_ELEMENT)
+ template <class Function, class DynamicType, class DefaultFunction,
+ std::size_t... Is>
+ constexpr decltype(auto)
+ static_switch_dispatch(const ElementTypes_t<_ek_cohesive> &,
+ Function && function, const DynamicType & type,
+ DefaultFunction && default_function,
+ std::index_sequence<Is...> /*is*/) {
+ AKANTU_BOOST_ELEMENT_SWITCH_WITH_DEFAULT_MACRO(
+ AKANTU_STATIC_SWITCH_DISPATCH_FUNCTION,
+ AKANTU_STATIC_SWITCH_DISPATCH_DEFAULT, AKANTU_ek_cohesive_ELEMENT_TYPE);
+ }
+
+ template <class Function, class DynamicType, class DefaultFunction,
+ std::size_t... Is>
+ constexpr decltype(auto)
+ static_switch_dispatch(const tuple::cat_t<ElementTypes_t<_ek_regular>,
+ ElementTypes_t<_ek_cohesive>> &,
+ Function && function, const DynamicType & type,
+ DefaultFunction && default_function,
+ std::index_sequence<Is...> /*is*/) {
+#define AKANTU_REGULAR_AND_COHESIVE_ELEMENT_TYPE \
+ AKANTU_ek_regular_ELEMENT_TYPE AKANTU_ek_cohesive_ELEMENT_TYPE
+
+ AKANTU_BOOST_ELEMENT_SWITCH_WITH_DEFAULT_MACRO(
+ AKANTU_STATIC_SWITCH_DISPATCH_FUNCTION,
+ AKANTU_STATIC_SWITCH_DISPATCH_DEFAULT,
+ AKANTU_REGULAR_AND_COHESIVE_ELEMENT_TYPE);
+
+#undef AKANTU_REGULAR_AND_COHESIVE_ELEMENT_TYPE
+ }
+
+#endif
+
+#undef AKANTU_STATIC_SWITCH_DISPATCH_FUNCTION
+#undef AKANTU_STATIC_SWITCH_DISPATCH_DEFAULT
+
+#endif
+} // namespace details
+
+template <class Tuple, class Function, class DynamicType, class DefaultFunction>
+[[gnu::visibility("hidden")]] constexpr decltype(auto)
+tuple_dispatch_with_default(Function && function, const DynamicType & type,
+ DefaultFunction && default_function) {
+ return details::static_switch_dispatch(
+ Tuple{}, std::forward<Function>(function), type,
+ std::forward<DefaultFunction>(default_function),
+ std::make_index_sequence<std::tuple_size<Tuple>::value>{});
+}
+
+template <class Tuple, class Function, class DynamicType>
+[[gnu::visibility("hidden")]] constexpr decltype(auto)
+tuple_dispatch(Function && function, const DynamicType & type) {
+ return details::static_switch_dispatch(
+ Tuple{}, std::forward<Function>(function), type,
+ [](auto && type) -> decltype(function(std::tuple_element_t<0, Tuple>{})) {
+ throw std::range_error("Unknown type in dispatch: " +
+ std::to_string(type));
+ },
+ std::make_index_sequence<std::tuple_size<Tuple>::value>{});
+}
+
} // namespace akantu
#endif /* AKANTU_AKA_ELEMENT_CLASSES_INFO_INLINE_IMPL_HH_ */
diff --git a/src/common/aka_enum_macros.hh b/src/common/aka_enum_macros.hh
index 1c9c6594e..98d969468 100644
--- a/src/common/aka_enum_macros.hh
+++ b/src/common/aka_enum_macros.hh
@@ -1,137 +1,139 @@
/**
* @file aka_enum_macros.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Nov 05 2018
* @date last modification: Tue Sep 29 2020
*
* @brief Macros to help declare enums
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <algorithm>
+#include <cstdlib> // std::size_t
#include <string>
+
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_ENUM_MACROS_HH_
#define AKANTU_AKA_ENUM_MACROS_HH_
#define AKANTU_PP_ENUM(s, data, i, elem) \
BOOST_PP_TUPLE_REM() \
elem BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(i, BOOST_PP_DEC(data)))
#if (defined(__GNUC__) || defined(__GNUG__))
#define AKA_GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if AKA_GCC_VERSION < 60000
#define AKANTU_ENUM_HASH(type_name) \
namespace std { \
template <> struct hash<::akantu::type_name> { \
using argument_type = ::akantu::type_name; \
- size_t operator()(const argument_type & e) const noexcept { \
+ auto operator()(const argument_type &e) const noexcept { \
auto ue = underlying_type_t<argument_type>(e); \
return uh(ue); \
} \
\
private: \
const hash<underlying_type_t<argument_type>> uh{}; \
}; \
}
#else
#define AKANTU_ENUM_HASH(type_name)
#endif // AKA_GCC_VERSION
#endif // GNU
#define AKANTU_PP_CAT(s, data, elem) BOOST_PP_CAT(data, elem)
#define AKANTU_PP_TYPE_TO_STR(s, data, elem) \
({BOOST_PP_CAT(data, elem), BOOST_PP_STRINGIZE(elem)})
#define AKANTU_PP_STR_TO_TYPE(s, data, elem) \
({BOOST_PP_STRINGIZE(elem), BOOST_PP_CAT(data, elem)})
#define AKANTU_CLASS_ENUM_DECLARE(type_name, list) \
enum class type_name { \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_PP_CAT, _, list)) \
};
#define AKANTU_ENUM_OUTPUT_STREAM_(type_name, list, prefix) \
} \
AKANTU_ENUM_HASH(type_name) \
namespace std { \
- inline string to_string(const ::akantu::type_name & type) { \
+ inline auto to_string(const ::akantu::type_name &type) -> string { \
using namespace akantu; \
static unordered_map<::akantu::type_name, string> convert{ \
BOOST_PP_SEQ_FOR_EACH_I( \
AKANTU_PP_ENUM, BOOST_PP_SEQ_SIZE(list), \
BOOST_PP_SEQ_TRANSFORM(AKANTU_PP_TYPE_TO_STR, prefix, list))}; \
return convert.at(type); \
} \
- } \
+ } /* namespace std */ \
namespace akantu { \
- inline std::ostream & operator<<(std::ostream & stream, \
- const type_name & type) { \
+ inline auto operator<<(std::ostream &stream, const type_name &type) \
+ -> std::ostream & { \
stream << std::to_string(type); \
return stream; \
}
#define AKANTU_ENUM_INPUT_STREAM_(type_name, list, prefix) \
- inline std::istream & operator>>(std::istream & stream, \
- type_name & type) { /* NOLINT */ \
+ inline auto operator>>(std::istream &stream, type_name &type) \
+ ->std::istream & { \
std::string str; \
stream >> str; /* NOLINT */ \
static std::unordered_map<std::string, type_name> convert{ \
BOOST_PP_SEQ_FOR_EACH_I( \
AKANTU_PP_ENUM, BOOST_PP_SEQ_SIZE(list), \
BOOST_PP_SEQ_TRANSFORM(AKANTU_PP_STR_TO_TYPE, prefix, list))}; \
try { \
type = convert.at(str); \
} catch (std::out_of_range &) { \
std::ostringstream values; \
- std::for_each(convert.begin(), convert.end(), [&values](auto && pair) { \
+ std::for_each(convert.begin(), convert.end(), [&values](auto &&pair) { \
static bool first = true; \
if (not first) \
values << ", "; \
values << "\"" << pair.first << "\""; \
first = false; \
}); \
AKANTU_EXCEPTION("The value " << str << " is not a valid " \
<< BOOST_PP_STRINGIZE(type_name) << " valid values are " \
<< values.str()); \
} \
return stream; \
}
#define AKANTU_CLASS_ENUM_OUTPUT_STREAM(type_name, list) \
AKANTU_ENUM_OUTPUT_STREAM_(type_name, list, type_name::_)
#define AKANTU_ENUM_OUTPUT_STREAM(type_name, list) \
AKANTU_ENUM_OUTPUT_STREAM_(type_name, list, )
#define AKANTU_CLASS_ENUM_INPUT_STREAM(type_name, list) \
AKANTU_ENUM_INPUT_STREAM_(type_name, list, type_name::_)
#define AKANTU_ENUM_INPUT_STREAM(type_name, list) \
AKANTU_ENUM_INPUT_STREAM_(type_name, list, )
#endif /* AKANTU_AKA_ENUM_MACROS_HH_ */
diff --git a/src/common/aka_error.cc b/src/common/aka_error.cc
index 4ec7b92a6..681b879be 100644
--- a/src/common/aka_error.cc
+++ b/src/common/aka_error.cc
@@ -1,368 +1,367 @@
/**
* @file aka_error.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Sep 06 2010
* @date last modification: Wed Feb 24 2021
*
* @brief handling of errors
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_error.hh"
#include "aka_common.hh"
#include "aka_config.hh"
#include "aka_iterators.hh"
#include "aka_random_generator.hh"
/* -------------------------------------------------------------------------- */
#include <csignal>
#include <iostream>
#include <vector>
#if (defined(READLINK_COMMAND) || defined(ADDR2LINE_COMMAND)) && \
(!defined(_WIN32))
#include <execinfo.h>
#include <sys/wait.h>
#endif
#include <chrono>
#include <cmath>
#include <cstring>
#include <cxxabi.h>
#include <fstream>
#include <iomanip>
#include <map>
#include <sys/types.h>
#include <unistd.h>
#ifdef AKANTU_USE_MPI
#include <mpi.h>
#endif
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace debug {
-
/* ------------------------------------------------------------------------ */
std::string demangle(const char * symbol) {
int status;
std::string result;
char * demangled_name;
if ((demangled_name = abi::__cxa_demangle(symbol, nullptr, nullptr,
&status)) != nullptr) {
result = demangled_name;
free(demangled_name);
} else {
result = symbol;
}
return result;
}
/* ------------------------------------------------------------------------ */
#if (defined(READLINK_COMMAND) || defined(ADDR2LINK_COMMAND)) && \
(!defined(_WIN32))
std::string exec(const std::string & cmd) {
FILE * pipe = popen(cmd.c_str(), "r");
if (pipe == nullptr) {
return "";
}
char buffer[1024];
std::string result;
while (feof(pipe) == 0) {
if (fgets(buffer, 128, pipe) != nullptr) {
result += buffer;
}
}
result = result.substr(0, result.size() - 1);
pclose(pipe);
return result;
}
#endif
auto getBacktrace() -> std::vector<std::string> {
std::vector<std::string> backtrace_lines;
#if not defined(_WIN32)
#if defined(READLINK_COMMAND) && defined(ADDR2LINE_COMMAND)
std::string me;
char buf[1024];
/* The manpage says it won't null terminate. Let's zero the buffer. */
memset(buf, 0, sizeof(buf));
/* Note we use sizeof(buf)-1 since we may need an extra char for NUL. */
if (readlink("/proc/self/exe", buf, sizeof(buf) - 1) != 0) {
me = std::string(buf);
}
std::ifstream inmaps;
inmaps.open("/proc/self/maps");
std::map<std::string, size_t> addr_map;
std::string line;
while (inmaps.good()) {
std::getline(inmaps, line);
std::stringstream sstr(line);
size_t first = line.find('-');
std::stringstream sstra(line.substr(0, first));
size_t addr;
sstra >> std::hex >> addr;
std::string lib;
sstr >> lib;
sstr >> lib;
sstr >> lib;
sstr >> lib;
sstr >> lib;
sstr >> lib;
if (not lib.empty() and (addr_map.find(lib) == addr_map.end())) {
addr_map[lib] = addr;
}
}
if (not me.empty()) {
addr_map[me] = 0;
}
#endif
/// \todo for windows this part could be coded using CaptureStackBackTrace
/// and SymFromAddr
const size_t max_depth = 100;
size_t stack_depth;
void * stack_addrs[max_depth];
char ** stack_strings;
size_t i;
stack_depth = backtrace(stack_addrs, max_depth);
stack_strings = backtrace_symbols(stack_addrs, stack_depth);
/// -1 to remove the call to the printBacktrace function
for (i = 1; i < stack_depth; i++) {
std::string bt_line(stack_strings[i]);
size_t first;
size_t second;
if ((first = bt_line.find('(')) != std::string::npos &&
(second = bt_line.find('+')) != std::string::npos) {
std::string location = bt_line.substr(0, first);
#if defined(READLINK_COMMAND)
std::string location_cmd =
std::string(BOOST_PP_STRINGIZE(READLINK_COMMAND)) +
std::string(" -f ") + location;
location = exec(location_cmd);
#endif
std::string call =
demangle(bt_line.substr(first + 1, second - first - 1).c_str());
size_t f = bt_line.find('[');
size_t s = bt_line.find(']');
std::string address = bt_line.substr(f + 1, s - f - 1);
std::stringstream sstra(address);
size_t addr;
sstra >> std::hex >> addr;
std::string trace = location + " [" + call + "]";
#if defined(READLINK_COMMAND) && defined(ADDR2LINE_COMMAND)
auto it = addr_map.find(location);
if (it != addr_map.end()) {
std::stringstream syscom;
syscom << BOOST_PP_STRINGIZE(ADDR2LINE_COMMAND)
<< " 0x" << std::hex
<< (addr - it->second) << " -i -e "
<< location;
std::string line = exec(syscom.str());
trace += " (" + line + ")";
} else {
#endif
std::stringstream sstr_addr;
sstr_addr << std::hex << addr;
trace += " (0x" + sstr_addr.str() + ")";
#if defined(READLINK_COMMAND) && defined(ADDR2LINE_COMMAND)
}
#endif
backtrace_lines.push_back(trace);
} else {
backtrace_lines.push_back(bt_line);
}
}
free(stack_strings);
#endif
return backtrace_lines;
}
/* ------------------------------------------------------------------------ */
void printBacktrace(const std::vector<std::string> & backtrace) {
auto w = size_t(std::floor(std::log10(double(backtrace.size()))) + 1);
std::cerr << "BACKTRACE : " << backtrace.size() << " stack frames.\n";
for (auto && data : enumerate(backtrace)) {
std::cerr << " [" << std::setw(w) << (std::get<0>(data) + 1) << "] "
<< std::get<1>(data) << "\n";
}
std::cerr << "END BACKTRACE" << std::endl;
}
/* ------------------------------------------------------------------------ */
namespace {
void terminate_handler() {
auto eptr = std::current_exception();
auto * t = abi::__cxa_current_exception_type();
auto name = (t != nullptr) ? demangle(t->name()) : std::string("unknown");
try {
if (eptr) {
std::rethrow_exception(eptr);
} else {
printBacktrace();
std::cerr << AKANTU_LOCATION
<< "!! Execution terminated for unknown reasons !!"
<< std::endl;
}
} catch (Exception & e) {
printBacktrace(e.backtrace());
std::cerr << "!! Uncaught akantu::Exception of type " << name
<< " !!\nwhat(): \"" << e.what() << "\"" << std::endl;
} catch (std::exception & e) {
std::cerr << "!! Uncaught exception of type " << name
<< " !!\nwhat(): \"" << e.what() << "\"" << std::endl;
} catch (...) {
std::cerr << "!! Something strange of type \"" << name
<< "\" was thrown.... !!" << std::endl;
}
if (debugger.printBacktrace()) {
- std::cerr << "Random generator seed: " << RandomGenerator<UInt>::seed()
+ std::cerr << "Random generator seed: " << RandomGenerator<Int>::seed()
<< std::endl;
printBacktrace();
}
}
} // namespace
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
Debugger::Debugger() noexcept {
cout = &std::cerr;
level = dblWarning;
parallel_context = "";
file_open = false;
print_backtrace = false;
// initSignalHandler();
std::set_terminate(terminate_handler);
}
/* ------------------------------------------------------------------------ */
Debugger::~Debugger() {
if (file_open) {
dynamic_cast<std::ofstream *>(cout)->close();
delete cout;
}
}
/* ------------------------------------------------------------------------ */
void Debugger::exit(int status) {
if (status != 0) {
std::terminate();
}
std::exit(0);
}
/*------------------------------------------------------------------------- */
void Debugger::throwException(const std::string & info,
const std::string & file, unsigned int line,
__attribute__((unused)) bool silent,
__attribute__((unused))
const std::string & location,
const std::string & module) const
noexcept(false) {
#if !defined(AKANTU_NDEBUG)
if (not silent) {
printMessage("###", dblWarning, info + " " + location, module);
}
#endif
debug::Exception ex(info, file, line);
ex.setModule(module);
throw ex;
}
/* ------------------------------------------------------------------------ */
void Debugger::printMessage(const std::string & prefix,
const DebugLevel & level,
const std::string & info,
const std::string & module) const {
- if (testLevel(level, module)) {
+ if AKANTU_UNLIKELY (testLevel(level, module)) {
double timestamp =
std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(
std::chrono::system_clock::now().time_since_epoch())
.count();
*(cout) << parallel_context << "{" << (size_t)timestamp << "} " << prefix
<< " " << info << std::endl;
}
}
/* ------------------------------------------------------------------------ */
void Debugger::setDebugLevel(const DebugLevel & level) {
this->level = level;
}
/* ------------------------------------------------------------------------ */
const DebugLevel & Debugger::getDebugLevel() const { return this->level; }
/* ------------------------------------------------------------------------ */
void Debugger::setLogFile(const std::string & filename) {
if (file_open) {
dynamic_cast<std::ofstream *>(cout)->close();
delete cout;
}
auto * fileout = new std::ofstream(filename.c_str());
file_open = true;
cout = fileout;
}
std::ostream & Debugger::getOutputStream() { return *cout; }
/* ------------------------------------------------------------------------ */
void Debugger::setParallelContext(int rank, int size) {
std::stringstream sstr;
- UInt pad = std::ceil(std::log10(size));
+ Int pad = std::ceil(std::log10(size));
sstr << "<" << getpid() << ">[R" << std::setfill(' ') << std::right
<< std::setw(pad) << rank << "|S" << size << "] ";
parallel_context = sstr.str();
}
void setDebugLevel(const DebugLevel & level) {
debugger.setDebugLevel(level);
}
const DebugLevel & getDebugLevel() { return debugger.getDebugLevel(); }
/* ------------------------------------------------------------------------ */
void exit(int status) { Debugger::exit(status); }
} // namespace debug
} // namespace akantu
diff --git a/src/common/aka_error.hh b/src/common/aka_error.hh
index 89ecef3c8..65a102aa3 100644
--- a/src/common/aka_error.hh
+++ b/src/common/aka_error.hh
@@ -1,421 +1,422 @@
/**
* @file aka_error.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jun 14 2010
* @date last modification: Tue Feb 09 2021
*
* @brief error management and internal exceptions
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <set>
#include <sstream>
#include <typeinfo>
#include <utility>
#include <vector>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ERROR_HH_
#define AKANTU_ERROR_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
enum DebugLevel {
dbl0 = 0,
dblError = 0,
dblAssert = 0,
dbl1 = 1,
dblException = 1,
dblCritical = 1,
dbl2 = 2,
dblMajor = 2,
dbl3 = 3,
dblCall = 3,
dblSecondary = 3,
dblHead = 3,
dbl4 = 4,
dblWarning = 4,
dbl5 = 5,
dblInfo = 5,
dbl6 = 6,
dblIn = 6,
dblOut = 6,
dbl7 = 7,
dbl8 = 8,
dblTrace = 8,
dbl9 = 9,
dblAccessory = 9,
dbl10 = 10,
dblDebug = 42,
dbl100 = 100,
dblDump = 100,
dblTest = 1337
};
/* -------------------------------------------------------------------------- */
#define AKANTU_LOCATION \
"(" << std::string(__func__) << "(): " << std::string(__FILE__) << ":" \
<< std::to_string(__LINE__) \
<< ")" // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
/* -------------------------------------------------------------------------- */
namespace debug {
void setDebugLevel(const DebugLevel & level);
const DebugLevel & getDebugLevel();
void initSignalHandler();
std::string demangle(const char * symbol);
template <class T> std::string demangle() {
return demangle(typeid(T).name());
}
template <class T> std::string demangle(const T & t) {
return demangle(typeid(t).name());
}
auto exec(const std::string & cmd) -> std::string;
auto getBacktrace() -> std::vector<std::string>;
void
printBacktrace(const std::vector<std::string> & backtrace = getBacktrace());
void exit(int status) __attribute__((noreturn));
/* ------------------------------------------------------------------------ */
/// exception class that can be thrown by akantu
class Exception : public std::exception {
/* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
/* ---------------------------------------------------------------------- */
protected:
explicit Exception(const std::string & info = "") : _info(info) {}
public:
//! full constructor
Exception(const std::string & info, const std::string & file,
unsigned int line)
: _info(info), _file(file), _line(line) {}
/* ---------------------------------------------------------------------- */
/* Methods */
/* ---------------------------------------------------------------------- */
public:
const char * what() const noexcept override { return _info.c_str(); }
virtual std::string info() const noexcept {
std::stringstream stream;
stream << debug::demangle(typeid(*this).name()) << " : " << _info << " ["
<< _file << ":" << _line << "]";
return stream.str();
}
public:
void setInfo(const std::string & info) { _info = info; }
void setFile(const std::string & file) { _file = file; }
void setLine(unsigned int line) { _line = line; }
void setModule(const std::string & module) { _module = module; }
void setBacktrace(const std::vector<std::string> & backtrace) {
backtrace_ = backtrace;
}
decltype(auto) backtrace() const { return backtrace_; }
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
protected:
/// exception description and additionals
std::string _info;
private:
/// file it is thrown from
std::string _file;
/// line it is thrown from
unsigned int _line{0};
/// module in which exception was raised
std::string _module{"core"};
std::vector<std::string> backtrace_;
};
class CriticalError : public Exception {};
class AssertException : public Exception {};
class NotImplementedException : public Exception {};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const Exception & _this) {
stream << _this.what();
return stream;
}
/* ------------------------------------------------------------------------ */
class Debugger {
public:
Debugger() noexcept;
virtual ~Debugger();
Debugger(const Debugger &) = default;
Debugger & operator=(const Debugger &) = default;
Debugger(Debugger &&) noexcept = default;
Debugger & operator=(Debugger &&) noexcept = default;
static void exit(int status) __attribute__((noreturn));
void throwException(const std::string & info, const std::string & file,
unsigned int line, bool /*silent*/,
const std::string & /*location*/,
const std::string & module) const noexcept(false)
__attribute__((noreturn));
/*----------------------------------------------------------------------- */
template <class Except>
void throwCustomException(Except ex, const std::string & info,
const std::string & file, unsigned int line,
const std::string & module) const noexcept(false)
__attribute__((noreturn));
/*----------------------------------------------------------------------- */
template <class Except>
void throwCustomException(Except ex, const std::string & file,
unsigned int line,
const std::string & module_) const noexcept(false)
__attribute__((noreturn));
void printMessage(const std::string & prefix, const DebugLevel & level,
const std::string & info,
const std::string & module_) const;
void setOutStream(std::ostream & out) { cout = &out; }
std::ostream & getOutStream() { return *cout; }
public:
void setParallelContext(int rank, int size);
void setDebugLevel(const DebugLevel & level);
const DebugLevel & getDebugLevel() const;
void setLogFile(const std::string & filename);
std::ostream & getOutputStream();
inline bool testLevel(const DebugLevel & level,
const std::string & module = "core") const {
auto level_reached = (this->level >= (level));
auto correct_module =
(level <= dblCritical) or (modules_to_debug.empty()) or
(modules_to_debug.find(module) != modules_to_debug.end());
return level_reached and correct_module;
}
void printBacktrace(bool on_off) { this->print_backtrace = on_off; }
bool printBacktrace() const { return this->print_backtrace; }
void addModuleToDebug(const std::string & id) {
this->modules_to_debug.insert(id);
}
void removeModuleToDebug(const std::string & id) {
auto it = this->modules_to_debug.find(id);
if (it != this->modules_to_debug.end()) {
this->modules_to_debug.erase(it);
}
}
void listModules() {
for (const auto & module_ : modules_to_debug) {
(*cout) << module_ << std::endl;
}
}
private:
std::string parallel_context;
std::ostream * cout;
bool file_open;
DebugLevel level;
bool print_backtrace;
std::set<std::string> modules_to_debug;
};
extern Debugger debugger; // NOLINT
} // namespace debug
/* -------------------------------------------------------------------------- */
#define AKANTU_STRINGIZE_(str) #str
#define AKANTU_STRINGIZE(str) AKANTU_STRINGIZE_(str)
/* -------------------------------------------------------------------------- */
#define AKANTU_DEBUG_MODULE AKANTU_STRINGIZE(AKANTU_MODULE)
/* -------------------------------------------------------------------------- */
#define AKANTU_STRINGSTREAM_IN(_str, _sstr) \
; \
do { \
std::stringstream _dbg_s_info; \
_dbg_s_info << _sstr; /* NOLINT */ \
(_str) = _dbg_s_info.str(); \
} while (false)
/* -------------------------------------------------------------------------- */
#define AKANTU_EXCEPTION(info) AKANTU_EXCEPTION_(info, false)
#define AKANTU_SILENT_EXCEPTION(info) AKANTU_EXCEPTION_(info, true)
#define AKANTU_EXCEPTION_(info, silent) \
do { \
std::stringstream _dbg_str; \
_dbg_str << info; /* NOLINT */ \
std::stringstream _dbg_loc; \
_dbg_loc << AKANTU_LOCATION; \
::akantu::debug::debugger.throwException(_dbg_str.str(), __FILE__, \
__LINE__, silent, _dbg_loc.str(), \
AKANTU_DEBUG_MODULE); \
} while (false)
#define AKANTU_CUSTOM_EXCEPTION_INFO(ex, info) \
do { \
std::stringstream _dbg_str; \
_dbg_str << info; /* NOLINT */ \
::akantu::debug::debugger.throwCustomException( \
ex, _dbg_str.str(), __FILE__, __LINE__, AKANTU_DEBUG_MODULE); \
} while (false)
#define AKANTU_CUSTOM_EXCEPTION(ex) \
do { \
::akantu::debug::debugger.throwCustomException(ex, __FILE__, __LINE__, \
AKANTU_DEBUG_MODULE); \
} while (false)
/* -------------------------------------------------------------------------- */
#ifdef AKANTU_NDEBUG
#define AKANTU_DEBUG_TEST(level) (false)
#define AKANTU_DEBUG_LEVEL_IS_TEST() \
(::akantu::debug::debugger.testLevel(dblTest, AKANTU_DEBUG_MODULE))
#define AKANTU_DEBUG(level, info)
#define AKANTU_DEBUG_(pref, level, info)
#define AKANTU_DEBUG_IN()
#define AKANTU_DEBUG_OUT()
#define AKANTU_DEBUG_INFO(info)
#define AKANTU_DEBUG_WARNING(info)
#define AKANTU_DEBUG_TRACE(info)
#define AKANTU_DEBUG_ASSERT(test, info)
#define AKANTU_ERROR(info) \
AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), info)
/* -------------------------------------------------------------------------- */
#else
#define AKANTU_DEBUG(level, info) AKANTU_DEBUG_(" ", level, info)
#define AKANTU_DEBUG_(pref, level, info) \
do { \
std::string _dbg_str; \
AKANTU_STRINGSTREAM_IN(_dbg_str, \
info << " " << AKANTU_LOCATION); /* NOLINT */ \
::akantu::debug::debugger.printMessage(pref, level, _dbg_str, \
AKANTU_DEBUG_MODULE); \
} while (false)
#define AKANTU_DEBUG_TEST(level) \
(::akantu::debug::debugger.testLevel(level, AKANTU_DEBUG_MODULE))
#define AKANTU_DEBUG_LEVEL_IS_TEST() \
(::akantu::debug::debugger.testLevel(dblTest))
#define AKANTU_DEBUG_IN() \
AKANTU_DEBUG_( \
"==>", ::akantu::dblIn, \
__func__ \
<< "()") // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,
// bugprone-lambda-function-name)
#define AKANTU_DEBUG_OUT() \
AKANTU_DEBUG_( \
"<==", ::akantu::dblOut, \
__func__ \
<< "()") // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,
// bugprone-lambda-function-name)
#define AKANTU_DEBUG_INFO(info) AKANTU_DEBUG_("---", ::akantu::dblInfo, info)
#define AKANTU_DEBUG_WARNING(info) \
AKANTU_DEBUG_("/!\\", ::akantu::dblWarning, info)
#define AKANTU_DEBUG_TRACE(info) AKANTU_DEBUG_(">>>", ::akantu::dblTrace, info)
#define AKANTU_DEBUG_ASSERT(test, info) \
do { \
- if (not(test)) \
+ if AKANTU_UNLIKELY (not(test)) { \
AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::AssertException(), \
"assert [" << #test << "] " \
<< info); /* NOLINT */ \
+ } \
} while (false)
#define AKANTU_ERROR(info) \
do { \
AKANTU_DEBUG_("!!! ", ::akantu::dblError, info); \
AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), \
info); /* NOLINT */ \
} while (false)
#endif // AKANTU_NDEBUG
#define AKANTU_TO_IMPLEMENT() \
AKANTU_CUSTOM_EXCEPTION_INFO( \
::akantu::debug::NotImplementedException(), \
__func__ \
<< " : not implemented yet !") // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,
// bugprone-lambda-function-name)
/* -------------------------------------------------------------------------- */
namespace debug {
/* ------------------------------------------------------------------------ */
template <class Except>
void Debugger::throwCustomException(Except ex, const std::string & info,
const std::string & file,
unsigned int line,
const std::string & module_) const
noexcept(false) {
ex.setInfo(info);
ex.setFile(file);
ex.setLine(line);
ex.setModule(module_);
if (::akantu::debug::debugger.printBacktrace()) {
ex.setBacktrace(::akantu::debug::getBacktrace());
}
throw ex;
}
/* ------------------------------------------------------------------------ */
template <class Except>
void Debugger::throwCustomException(Except ex, const std::string & file,
unsigned int line,
const std::string & module_) const
noexcept(false) {
ex.setFile(file);
ex.setLine(line);
ex.setModule(module_);
if (::akantu::debug::debugger.printBacktrace()) {
ex.setBacktrace(::akantu::debug::getBacktrace());
}
throw ex;
}
} // namespace debug
} // namespace akantu
#endif /* AKANTU_ERROR_HH_ */
diff --git a/src/common/aka_event_handler_manager.hh b/src/common/aka_event_handler_manager.hh
index 453353665..9df4c83a0 100644
--- a/src/common/aka_event_handler_manager.hh
+++ b/src/common/aka_event_handler_manager.hh
@@ -1,128 +1,128 @@
/**
* @file aka_event_handler_manager.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Feb 09 2021
*
* @brief Base of Event Handler classes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_EVENT_HANDLER_MANAGER_HH_
#define AKANTU_AKA_EVENT_HANDLER_MANAGER_HH_
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <list>
/* -------------------------------------------------------------------------- */
namespace akantu {
template <class EventHandler> class EventHandlerManager {
private:
using priority_value = std::pair<EventHandlerPriority, EventHandler *>;
using priority_list = std::list<priority_value>;
struct KeyComp {
bool operator()(const priority_value & a, const priority_value & b) const {
return (a.first < b.first);
}
- bool operator()(const priority_value & a, UInt b) const {
+ bool operator()(const priority_value & a, Int b) const {
return (a.first < b);
}
};
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
virtual ~EventHandlerManager() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// register a new EventHandler to the Manager. The register object
/// will then be informed about the events the manager observes.
void registerEventHandler(EventHandler & event_handler,
EventHandlerPriority priority = _ehp_highest) {
auto it = this->searchEventHandler(event_handler);
if (it != this->event_handlers.end()) {
AKANTU_EXCEPTION("This event handler was already registered (priority: "
<< priority << ")");
}
auto pos =
std::lower_bound(this->event_handlers.begin(),
this->event_handlers.end(), priority, KeyComp());
this->event_handlers.insert(pos, std::make_pair(priority, &event_handler));
}
/// unregister a EventHandler object. This object will not be
/// notified anymore about the events this manager observes.
void unregisterEventHandler(EventHandler & event_handler) {
auto it = this->searchEventHandler(event_handler);
if (it == this->event_handlers.end()) {
AKANTU_EXCEPTION("This event handler is not registered");
}
this->event_handlers.erase(it);
}
/// Notify all the registered EventHandlers about the event that just occured.
template <class Event> void sendEvent(const Event & event) {
for (auto & pair : this->event_handlers) {
pair.second->sendEvent(event);
}
}
private:
typename priority_list::iterator searchEventHandler(EventHandler & handler) {
auto it = this->event_handlers.begin();
auto end = this->event_handlers.end();
for (; it != end && it->second != &handler; ++it) {
;
}
return it;
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// list of the event handlers
priority_list event_handlers;
};
} // namespace akantu
#endif /* AKANTU_AKA_EVENT_HANDLER_MANAGER_HH_ */
diff --git a/src/common/aka_extern.cc b/src/common/aka_extern.cc
index f1b930ddc..e5d0913c0 100644
--- a/src/common/aka_extern.cc
+++ b/src/common/aka_extern.cc
@@ -1,98 +1,101 @@
/**
* @file aka_extern.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jun 14 2010
* @date last modification: Tue Oct 27 2020
*
* @brief initialisation of all global variables
* to insure the order of creation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "aka_math.hh"
#include "aka_named_argument.hh"
#include "aka_random_generator.hh"
#include "communication_tag.hh"
#include "cppargparse.hh"
#include "parser.hh"
#include "solid_mechanics_model.hh"
#if defined(AKANTU_COHESIVE_ELEMENT)
#include "solid_mechanics_model_cohesive.hh"
#endif
/* -------------------------------------------------------------------------- */
#include <iostream>
#include <limits>
namespace akantu {
/* -------------------------------------------------------------------------- */
/* error.hpp variables */
/* -------------------------------------------------------------------------- */
namespace debug {
/** \todo write function to get this
* values from the environment or a config file
*/
/// standard output for debug messages
std::ostream * _akantu_debug_cout = &std::cerr;
/// standard output for normal messages
std::ostream & _akantu_cout = std::cout;
/// parallel context used in debug messages
std::string _parallel_context;
Debugger debugger;
} // namespace debug
/* -------------------------------------------------------------------------- */
/// Paser for commandline arguments
::cppargparse::ArgumentParser static_argparser;
/// Parser containing the information parsed by the input file given to initFull
Parser static_parser;
bool Parser::permissive_parser = false;
/* -------------------------------------------------------------------------- */
Real Math::tolerance = 1e2 * std::numeric_limits<Real>::epsilon();
/* -------------------------------------------------------------------------- */
-const UInt _all_dimensions [[gnu::unused]] = UInt(-1);
+const Int _all_dimensions [[gnu::unused]] = Int(-1);
/* -------------------------------------------------------------------------- */
-const Array<UInt> empty_filter(0, 1, "empty_filter");
+const Array<Int> empty_filter(0, 1, "empty_filter");
/* -------------------------------------------------------------------------- */
+template <> long int RandomGenerator<Idx>::_seed = 5489;
+template <> std::default_random_engine RandomGenerator<Idx>::generator(5489);
template <> long int RandomGenerator<UInt>::_seed = 5489U;
template <> std::default_random_engine RandomGenerator<UInt>::generator(5489U);
+
/* -------------------------------------------------------------------------- */
int Tag::max_tag = 0;
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/common/aka_fwd.hh b/src/common/aka_fwd.hh
index d4b7ba9a6..baf302b39 100644
--- a/src/common/aka_fwd.hh
+++ b/src/common/aka_fwd.hh
@@ -1,73 +1,77 @@
/**
* @file aka_fwd.hh
*
* @author Alejandro M. Aragón <alejandro.aragon@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Apr 13 2012
* @date last modification: Tue Sep 29 2020
*
* @brief File containing forward declarations in akantu.
* This file helps if circular #include would be needed because two classes
* refer both to each other. This file usually does not need any modification.
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_FWD_HH_
#define AKANTU_FWD_HH_
namespace cppargparse {
class ArgumentParser;
}
namespace akantu {
// forward declaration
template <int dim, class model_type> struct ContactData;
-template <typename T> class Matrix;
-template <typename T> class Vector;
-template <typename T> class Tensor3;
-
template <typename T, bool is_scal = aka::is_scalar<T>::value> class Array;
template <typename T, typename SupportType = ElementType>
class ElementTypeMapArray;
template <class T> class SpatialGrid;
// Model element
template <class ModelPolicy> class ModelElement;
-extern const Array<UInt> empty_filter;
+extern const Array<Int> empty_filter;
class Parser;
class ParserSection;
extern Parser static_parser; // NOLINT
extern cppargparse::ArgumentParser static_argparser; // NOLINT
class Mesh;
class SparseMatrix;
+
} // namespace akantu
+namespace aka {
+
+template <class T> struct is_array : public std::false_type {};
+template <class T> struct is_array<akantu::Array<T>> : public std::true_type {};
+
+} // namespace aka
+
#endif /* AKANTU_FWD_HH_ */
diff --git a/src/common/aka_grid_dynamic.hh b/src/common/aka_grid_dynamic.hh
index 668da3734..69425d4f5 100644
--- a/src/common/aka_grid_dynamic.hh
+++ b/src/common/aka_grid_dynamic.hh
@@ -1,530 +1,532 @@
/**
* @file aka_grid_dynamic.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Tue Feb 09 2021
*
* @brief Grid that is auto balanced
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "aka_types.hh"
#include "mesh_accessor.hh"
#include <iostream>
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_GRID_DYNAMIC_HH_
#define AKANTU_AKA_GRID_DYNAMIC_HH_
namespace akantu {
class Mesh;
template <typename T> class SpatialGrid {
public:
- explicit SpatialGrid(UInt dimension)
+ explicit SpatialGrid(Int dimension)
: dimension(dimension), spacing(dimension), center(dimension),
- lower(dimension), upper(dimension), empty_cell() {}
+ lower(dimension), upper(dimension), empty_cell() {
+ lower.fill(std::numeric_limits<Real>::max());
+ upper.fill(-std::numeric_limits<Real>::max());
+ }
- SpatialGrid(UInt dimension, const Vector<Real> & spacing,
+ SpatialGrid(Int dimension, const Vector<Real> & spacing,
const Vector<Real> & center)
- : dimension(dimension), spacing(spacing), center(center),
- lower(dimension), upper(dimension), empty_cell() {
- for (UInt i = 0; i < dimension; ++i) {
- lower(i) = std::numeric_limits<Real>::max();
- upper(i) = -std::numeric_limits<Real>::max();
- }
+ : SpatialGrid(dimension) {
+ this->spacing = spacing;
+ this->center = center;
}
virtual ~SpatialGrid() = default;
class neighbor_cells_iterator;
class cells_iterator;
class CellID {
public:
CellID() = default;
- explicit CellID(UInt dimention) : ids(dimention) {}
- void setID(UInt dir, Int id) { ids(dir) = id; }
- Int getID(UInt dir) const { return ids(dir); }
+ explicit CellID(Int dimention) : ids(dimention) {}
+ void setID(Int dir, Int id) { ids(dir) = id; }
+ Idx getID(Int dir) const { return ids(dir); }
+ const Vector<Idx> & getIDs() const { return ids; }
bool operator<(const CellID & id) const {
- return std::lexicographical_compare(
- ids.storage(), ids.storage() + ids.size(), id.ids.storage(),
- id.ids.storage() + id.ids.size());
+ return std::lexicographical_compare(ids.data(), ids.data() + ids.size(),
+ id.ids.data(),
+ id.ids.data() + id.ids.size());
}
bool operator==(const CellID & id) const {
- return std::equal(ids.storage(), ids.storage() + ids.size(),
- id.ids.storage());
+ return std::equal(ids.data(), ids.data() + ids.size(), id.ids.data());
}
bool operator!=(const CellID & id) const { return !(operator==(id)); }
class neighbor_cells_iterator {
public:
neighbor_cells_iterator(const CellID & cell_id, bool end)
- : cell_id(cell_id), position(cell_id.ids.size(), end ? 1 : -1) {
-
+ : cell_id(cell_id), position(cell_id.ids.size()) {
+ position.fill(end ? 1 : -1);
this->updateIt();
if (end) {
this->it++;
}
}
neighbor_cells_iterator & operator++() {
- UInt i = 0;
+ Int i = 0;
for (; i < position.size() && position(i) == 1; ++i) {
- ;
}
if (i == position.size()) {
++it;
return *this;
}
- for (UInt j = 0; j < i; ++j) {
+ for (decltype(i) j = 0; j < i; ++j) {
position(j) = -1;
}
position(i)++;
updateIt();
return *this;
}
neighbor_cells_iterator operator++(int) {
neighbor_cells_iterator tmp(*this);
operator++();
return tmp;
};
bool operator==(const neighbor_cells_iterator & rhs) const {
return cell_id == rhs.cell_id && it == rhs.it;
};
bool operator!=(const neighbor_cells_iterator & rhs) const {
return !operator==(rhs);
};
CellID operator*() const {
CellID cur_cell_id(cell_id);
cur_cell_id.ids += position;
return cur_cell_id;
};
private:
void updateIt() {
it = 0;
- for (UInt i = 0; i < position.size(); ++i) {
+ for (Int i = 0; i < position.size(); ++i) {
it = it * 3 + (position(i) + 1);
}
}
private:
/// central cell id
const CellID & cell_id;
// number representing the current neighbor in base 3;
- UInt it;
+ Int it{0};
// current cell shift
- Vector<Int> position;
+ Vector<Idx> position;
};
class Neighbors {
public:
explicit Neighbors(const CellID & cell_id) : cell_id(cell_id) {}
decltype(auto) begin() { return neighbor_cells_iterator(cell_id, false); }
decltype(auto) end() { return neighbor_cells_iterator(cell_id, true); }
private:
const CellID & cell_id;
};
decltype(auto) neighbors() { return Neighbors(*this); }
private:
friend class cells_iterator;
- Vector<Int> ids;
+ Vector<Idx> ids;
};
/* ------------------------------------------------------------------------ */
class Cell {
public:
using iterator = typename std::vector<T>::iterator;
using const_iterator = typename std::vector<T>::const_iterator;
Cell() : id(), data() {}
explicit Cell(const CellID & cell_id) : id(cell_id), data() {}
bool operator==(const Cell & cell) const { return id == cell.id; }
bool operator!=(const Cell & cell) const { return id != cell.id; }
Cell & add(const T & d) {
data.push_back(d);
return *this;
}
iterator begin() { return data.begin(); }
const_iterator begin() const { return data.begin(); }
iterator end() { return data.end(); }
const_iterator end() const { return data.end(); }
private:
CellID id;
std::vector<T> data;
};
private:
using cells_container = std::map<CellID, Cell>;
public:
const Cell & getCell(const CellID & cell_id) const {
auto it = cells.find(cell_id);
if (it != cells.end()) {
return it->second;
}
return empty_cell;
}
decltype(auto) beginCell(const CellID & cell_id) {
auto it = cells.find(cell_id);
if (it != cells.end()) {
return it->second.begin();
}
return empty_cell.begin();
}
decltype(auto) endCell(const CellID & cell_id) {
auto it = cells.find(cell_id);
if (it != cells.end()) {
return it->second.end();
}
return empty_cell.end();
}
decltype(auto) beginCell(const CellID & cell_id) const {
auto it = cells.find(cell_id);
if (it != cells.end()) {
return it->second.begin();
}
return empty_cell.begin();
}
decltype(auto) endCell(const CellID & cell_id) const {
auto it = cells.find(cell_id);
if (it != cells.end()) {
return it->second.end();
}
return empty_cell.end();
}
/* ------------------------------------------------------------------------ */
class cells_iterator {
public:
explicit cells_iterator(typename std::map<CellID, Cell>::const_iterator it)
: it(it) {}
cells_iterator & operator++() {
this->it++;
return *this;
}
cells_iterator operator++(int /*unused*/) {
cells_iterator tmp(*this);
operator++();
return tmp;
};
bool operator==(const cells_iterator & rhs) const { return it == rhs.it; };
bool operator!=(const cells_iterator & rhs) const {
return !operator==(rhs);
};
CellID operator*() const {
CellID cur_cell_id(this->it->first);
return cur_cell_id;
};
private:
/// map iterator
typename std::map<CellID, Cell>::const_iterator it;
};
public:
template <class vector_type>
Cell & insert(const T & d, const vector_type & position) {
auto && cell_id = getCellID(position);
auto && it = cells.find(cell_id);
if (it == cells.end()) {
Cell cell(cell_id);
auto & tmp = (cells[cell_id] = cell).add(d);
- for (UInt i = 0; i < dimension; ++i) {
- Real posl = center(i) + cell_id.getID(i) * spacing(i);
- Real posu = posl + spacing(i);
- if (posl <= lower(i)) {
- lower(i) = posl;
- }
- if (posu > upper(i)) {
- upper(i) = posu;
- }
- }
+ auto posl =
+ center.array() +
+ cell_id.getIDs().array().template cast<Real>() * spacing.array();
+ auto posu = posl + spacing.array();
+
+ lower = lower.array().min(posl);
+ upper = upper.array().max(posu);
return tmp;
}
return it->second.add(d);
}
/* ------------------------------------------------------------------------ */
inline decltype(auto) begin() const {
auto begin = this->cells.begin();
return cells_iterator(begin);
}
inline decltype(auto) end() const {
auto end = this->cells.end();
return cells_iterator(end);
}
template <class vector_type>
CellID getCellID(const vector_type & position) const {
CellID cell_id(dimension);
- for (UInt i = 0; i < dimension; ++i) {
+ for (Int i = 0; i < dimension; ++i) {
cell_id.setID(i, getCellID(position(i), i));
}
return cell_id;
}
+ template <class vector_type>
+ const Cell & getCell(const vector_type & position) const {
+ return this->getCell(this->getCellID(position));
+ }
+
void printself(std::ostream & stream, int indent = 0) const {
std::string space(indent, AKANTU_INDENT);
std::streamsize prec = stream.precision();
std::ios_base::fmtflags ff = stream.flags();
stream.setf(std::ios_base::showbase);
stream.precision(5);
stream << space << "SpatialGrid<" << debug::demangle(typeid(T).name())
<< "> [" << std::endl;
stream << space << " + dimension : " << this->dimension << std::endl;
stream << space << " + lower bounds : {";
- for (UInt i = 0; i < lower.size(); ++i) {
+ for (Int i = 0; i < lower.size(); ++i) {
if (i != 0) {
stream << ", ";
}
stream << lower(i);
};
stream << "}" << std::endl;
stream << space << " + upper bounds : {";
- for (UInt i = 0; i < upper.size(); ++i) {
+ for (Int i = 0; i < upper.size(); ++i) {
if (i != 0) {
stream << ", ";
}
stream << upper(i);
};
stream << "}" << std::endl;
stream << space << " + spacing : {";
- for (UInt i = 0; i < spacing.size(); ++i) {
+ for (Int i = 0; i < spacing.size(); ++i) {
if (i != 0) {
stream << ", ";
}
stream << spacing(i);
};
stream << "}" << std::endl;
stream << space << " + center : {";
- for (UInt i = 0; i < center.size(); ++i) {
+ for (Int i = 0; i < center.size(); ++i) {
if (i != 0) {
stream << ", ";
}
stream << center(i);
};
stream << "}" << std::endl;
stream << space << " + nb_cells : " << this->cells.size() << "/";
Vector<Real> dist(this->dimension);
dist = upper;
dist -= lower;
- for (UInt i = 0; i < this->dimension; ++i) {
+ for (Int i = 0; i < this->dimension; ++i) {
dist(i) /= spacing(i);
}
- UInt nb_cells = std::ceil(dist(0));
- for (UInt i = 1; i < this->dimension; ++i) {
+ auto nb_cells = std::ceil(dist(0));
+ for (Int i = 1; i < this->dimension; ++i) {
nb_cells *= std::ceil(dist(i));
}
stream << nb_cells << std::endl;
stream << space << "]" << std::endl;
stream.precision(prec);
stream.flags(ff);
}
void saveAsMesh(Mesh & mesh) const;
private:
/* --------------------------------------------------------------------------
*/
- inline UInt getCellID(Real position, UInt direction) const {
+ inline decltype(auto) getCellID(Real position, Int direction) const {
AKANTU_DEBUG_ASSERT(direction < center.size(), "The direction asked ("
<< direction
<< ") is out of range "
<< center.size());
Real dist_center = position - center(direction);
Int id = std::floor(dist_center / spacing(direction));
// if(dist_center < 0) id--;
return id;
}
friend class GridSynchronizer;
public:
AKANTU_GET_MACRO(LowerBounds, lower, const Vector<Real> &);
AKANTU_GET_MACRO(UpperBounds, upper, const Vector<Real> &);
AKANTU_GET_MACRO(Spacing, spacing, const Vector<Real> &);
AKANTU_SET_MACRO(Spacing, spacing, Vector<Real> &);
AKANTU_GET_MACRO(Center, center, const Vector<Real> &);
AKANTU_SET_MACRO(Center, center, Vector<Real> &);
-protected:
- UInt dimension;
+private:
+ Int dimension{0};
cells_container cells;
Vector<Real> spacing;
Vector<Real> center;
Vector<Real> lower;
Vector<Real> upper;
Cell empty_cell;
};
/// standard output stream operator
template <typename T>
inline std::ostream & operator<<(std::ostream & stream,
const SpatialGrid<T> & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
+
#include "mesh.hh"
+
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename T> void SpatialGrid<T>::saveAsMesh(Mesh & mesh) const {
-
ElementType type = _not_defined;
switch (dimension) {
case 1:
type = _segment_2;
break;
case 2:
type = _quadrangle_4;
break;
case 3:
type = _hexahedron_8;
break;
}
MeshAccessor mesh_accessor(mesh);
auto & connectivity = mesh_accessor.getConnectivity(type);
auto & nodes = mesh_accessor.getNodes();
- auto & uint_data = mesh.getDataPointer<UInt>("tag_1", type);
+ auto & uint_data = mesh.getDataPointer<Int>("tag_1", type);
Vector<Real> pos(dimension);
- UInt global_id = 0;
+ Int global_id = 0;
for (auto & cell_pair : cells) {
- UInt cur_node = nodes.size();
- UInt cur_elem = connectivity.size();
- const CellID & cell_id = cell_pair.first;
+ auto cur_node = nodes.size();
+ auto cur_elem = connectivity.size();
+ const auto & cell_id = cell_pair.first;
- for (UInt i = 0; i < dimension; ++i) {
+ for (Int i = 0; i < dimension; ++i) {
pos(i) = center(i) + cell_id.getID(i) * spacing(i);
}
nodes.push_back(pos);
- for (UInt i = 0; i < dimension; ++i) {
+ for (Int i = 0; i < dimension; ++i) {
pos(i) += spacing(i);
}
nodes.push_back(pos);
connectivity.push_back(cur_node);
switch (dimension) {
case 1:
connectivity(cur_elem, 1) = cur_node + 1;
break;
case 2:
pos(0) -= spacing(0);
nodes.push_back(pos);
pos(0) += spacing(0);
pos(1) -= spacing(1);
nodes.push_back(pos);
connectivity(cur_elem, 1) = cur_node + 3;
connectivity(cur_elem, 2) = cur_node + 1;
connectivity(cur_elem, 3) = cur_node + 2;
break;
case 3:
pos(1) -= spacing(1);
pos(2) -= spacing(2);
nodes.push_back(pos);
pos(1) += spacing(1);
nodes.push_back(pos);
pos(0) -= spacing(0);
nodes.push_back(pos);
pos(1) -= spacing(1);
pos(2) += spacing(2);
nodes.push_back(pos);
pos(0) += spacing(0);
nodes.push_back(pos);
pos(0) -= spacing(0);
pos(1) += spacing(1);
nodes.push_back(pos);
connectivity(cur_elem, 1) = cur_node + 2;
connectivity(cur_elem, 2) = cur_node + 3;
connectivity(cur_elem, 3) = cur_node + 4;
connectivity(cur_elem, 4) = cur_node + 5;
connectivity(cur_elem, 5) = cur_node + 6;
connectivity(cur_elem, 6) = cur_node + 1;
connectivity(cur_elem, 7) = cur_node + 7;
break;
}
uint_data.push_back(global_id);
++global_id;
}
}
} // namespace akantu
#endif /* AKANTU_AKA_GRID_DYNAMIC_HH_ */
diff --git a/src/common/aka_math.cc b/src/common/aka_math.cc
index 0d356c30d..857b16d23 100644
--- a/src/common/aka_math.cc
+++ b/src/common/aka_math.cc
@@ -1,271 +1,125 @@
/**
* @file aka_math.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Leonardo Snozzi <leonardo.snozzi@epfl.ch>
* @author Peter Spijker <peter.spijker@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Tue Sep 29 2020
*
* @brief Implementation of the math toolbox
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_math.hh"
#include "aka_array.hh"
#include "aka_iterators.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace Math {
- /* --------------------------------------------------------------------------
- */
- void matrix_vector(UInt m, UInt n, const Array<Real> & A,
- const Array<Real> & x, Array<Real> & y, Real alpha) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_ASSERT(A.size() == x.size(),
- "The vector A(" << A.getID() << ") and the vector x("
- << x.getID()
- << ") must have the same size");
-
- AKANTU_DEBUG_ASSERT(
- A.getNbComponent() == m * n,
- "The vector A(" << A.getID() << ") has the good number of component.");
-
- AKANTU_DEBUG_ASSERT(x.getNbComponent() == n,
- "The vector x("
- << x.getID()
- << ") do not the good number of component.");
-
- AKANTU_DEBUG_ASSERT(y.getNbComponent() == n,
- "The vector y("
- << y.getID()
- << ") do not the good number of component.");
-
- UInt nb_element = A.size();
- UInt offset_A = A.getNbComponent();
- UInt offset_x = x.getNbComponent();
-
- y.resize(nb_element);
-
- Real * A_val = A.storage();
- Real * x_val = x.storage();
- Real * y_val = y.storage();
-
- for (UInt el = 0; el < nb_element; ++el) {
- matrix_vector(m, n, A_val, x_val, y_val, alpha);
-
- A_val += offset_A;
- x_val += offset_x;
- y_val += offset_x;
- }
-
- AKANTU_DEBUG_OUT();
- }
-
- /* --------------------------------------------------------------------------
- */
- void matrix_matrix(UInt m, UInt n, UInt k, const Array<Real> & A,
- const Array<Real> & B, Array<Real> & C, Real alpha) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_ASSERT(A.size() == B.size(),
- "The vector A(" << A.getID() << ") and the vector B("
- << B.getID()
- << ") must have the same size");
-
- AKANTU_DEBUG_ASSERT(
- A.getNbComponent() == m * k,
- "The vector A(" << A.getID() << ") has the good number of component.");
-
- AKANTU_DEBUG_ASSERT(B.getNbComponent() == k * n,
- "The vector B("
- << B.getID()
- << ") do not the good number of component.");
-
- AKANTU_DEBUG_ASSERT(C.getNbComponent() == m * n,
- "The vector C("
- << C.getID()
- << ") do not the good number of component.");
-
- UInt nb_element = A.size();
- UInt offset_A = A.getNbComponent();
- UInt offset_B = B.getNbComponent();
- UInt offset_C = C.getNbComponent();
-
- C.resize(nb_element);
-
- Real * A_val = A.storage();
- Real * B_val = B.storage();
- Real * C_val = C.storage();
-
- for (UInt el = 0; el < nb_element; ++el) {
- matrix_matrix(m, n, k, A_val, B_val, C_val, alpha);
-
- A_val += offset_A;
- B_val += offset_B;
- C_val += offset_C;
- }
-
- AKANTU_DEBUG_OUT();
- }
-
- /* --------------------------------------------------------------------------
- */
- void matrix_matrixt(UInt m, UInt n, UInt k, const Array<Real> & A,
- const Array<Real> & B, Array<Real> & C, Real alpha) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_ASSERT(A.size() == B.size(),
- "The vector A(" << A.getID() << ") and the vector B("
- << B.getID()
- << ") must have the same size");
-
- AKANTU_DEBUG_ASSERT(
- A.getNbComponent() == m * k,
- "The vector A(" << A.getID() << ") has the good number of component.");
-
- AKANTU_DEBUG_ASSERT(B.getNbComponent() == k * n,
- "The vector B("
- << B.getID()
- << ") do not the good number of component.");
-
- AKANTU_DEBUG_ASSERT(C.getNbComponent() == m * n,
- "The vector C("
- << C.getID()
- << ") do not the good number of component.");
-
- UInt nb_element = A.size();
- UInt offset_A = A.getNbComponent();
- UInt offset_B = B.getNbComponent();
- UInt offset_C = C.getNbComponent();
-
- C.resize(nb_element);
-
- Real * A_val = A.storage();
- Real * B_val = B.storage();
- Real * C_val = C.storage();
-
- for (UInt el = 0; el < nb_element; ++el) {
- matrix_matrixt(m, n, k, A_val, B_val, C_val, alpha);
-
- A_val += offset_A;
- B_val += offset_B;
- C_val += offset_C;
- }
-
- AKANTU_DEBUG_OUT();
- }
-
- /* --------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
void compute_tangents(const Array<Real> & normals, Array<Real> & tangents) {
- AKANTU_DEBUG_IN();
-
if (normals.empty()) {
return;
}
auto spatial_dimension = normals.getNbComponent();
auto tangent_components = spatial_dimension * (spatial_dimension - 1);
if (tangent_components == 0) {
return;
}
AKANTU_DEBUG_ASSERT(
tangent_components == tangents.getNbComponent(),
"Cannot compute the tangents, the storage array for tangents"
<< " does not have the good amount of components.");
auto nb_normals = normals.size();
tangents.resize(nb_normals);
tangents.zero();
/// compute first tangent
- for (auto && data : zip(make_view(normals, spatial_dimension),
- make_view(tangents, tangent_components))) {
- const auto & normal = std::get<0>(data);
+ for (auto && data :
+ zip(make_view(normals, spatial_dimension),
+ make_view(tangents, spatial_dimension, spatial_dimension - 1))) {
+ const auto & normal_ = std::get<0>(data);
auto & tangent = std::get<1>(data);
- if (are_float_equal(norm2(normal.storage()), 0.)) {
- tangent(0) = 1.;
+ if (are_float_equal(normal_.norm(), 0.)) {
+ tangent(0, 0) = 1.;
} else {
- normal2(normal.storage(), tangent.storage());
+ tangent(0) = normal(normal_);
}
}
/// compute second tangent (3D case)
if (spatial_dimension == 3) {
- for (auto && data : zip(make_view(normals, spatial_dimension),
- make_view(tangents, tangent_components))) {
- const auto & normal = std::get<0>(data);
+ for (auto && data :
+ zip(make_view(normals, spatial_dimension),
+ make_view(tangents, spatial_dimension, spatial_dimension - 1))) {
+ const auto & normal_ = std::get<0>(data);
auto & tangent = std::get<1>(data);
- normal3(normal.storage(), tangent.storage(),
- tangent.storage() + spatial_dimension);
+ tangent(1) = normal(normal_, tangent(0));
}
}
+ }
- AKANTU_DEBUG_OUT();
- } // namespace akantu
-
- /* --------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
Real reduce(Array<Real> & array) {
UInt nb_values = array.size();
if (nb_values == 0) {
return 0.;
}
- UInt nb_values_to_sum = nb_values >> 1;
+ Int nb_values_to_sum = nb_values >> 1;
std::sort(array.begin(), array.end());
// as long as the half is not empty
- while (nb_values_to_sum != 0U) {
- UInt remaining = (nb_values - 2 * nb_values_to_sum);
+ while (nb_values_to_sum != 0) {
+ Int remaining = (nb_values - 2 * nb_values_to_sum);
if (remaining != 0U) {
array(nb_values - 2) += array(nb_values - 1);
}
// sum to consecutive values and store the sum in the first half
- for (UInt i = 0; i < nb_values_to_sum; ++i) {
+ for (Int i = 0; i < nb_values_to_sum; ++i) {
array(i) = array(2 * i) + array(2 * i + 1);
}
nb_values = nb_values_to_sum;
nb_values_to_sum >>= 1;
}
return array(0);
}
-
} // namespace Math
} // namespace akantu
diff --git a/src/common/aka_math.hh b/src/common/aka_math.hh
index 5e399db67..b31d33078 100644
--- a/src/common/aka_math.hh
+++ b/src/common/aka_math.hh
@@ -1,287 +1,169 @@
/**
* @file aka_math.hh
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Leonardo Snozzi <leonardo.snozzi@epfl.ch>
* @author Peter Spijker <peter.spijker@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Tue Feb 09 2021
*
* @brief mathematical operations
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
+#include "aka_types.hh"
/* -------------------------------------------------------------------------- */
#include <utility>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_MATH_H_
#define AKANTU_AKA_MATH_H_
namespace akantu {
/* -------------------------------------------------------------------------- */
namespace Math {
/// tolerance for functions that need one
extern Real tolerance; // NOLINT
- /* ------------------------------------------------------------------------ */
- /* Matrix algebra */
- /* ------------------------------------------------------------------------ */
- /// @f$ y = A*x @f$
- void matrix_vector(UInt m, UInt n, const Array<Real> & A,
- const Array<Real> & x, Array<Real> & y, Real alpha = 1.);
-
- /// @f$ y = A*x @f$
- inline void matrix_vector(UInt m, UInt n, Real * A, Real * x, Real * y,
- Real alpha = 1.);
-
- /// @f$ y = A^t*x @f$
- inline void matrixt_vector(UInt m, UInt n, Real * A, Real * x, Real * y,
- Real alpha = 1.);
-
- /// @f$ C = A*B @f$
- void matrix_matrix(UInt m, UInt n, UInt k, const Array<Real> & A,
- const Array<Real> & B, Array<Real> & C, Real alpha = 1.);
-
- /// @f$ C = A*B^t @f$
- void matrix_matrixt(UInt m, UInt n, UInt k, const Array<Real> & A,
- const Array<Real> & B, Array<Real> & C, Real alpha = 1.);
-
- /// @f$ C = A*B @f$
- inline void matrix_matrix(UInt m, UInt n, UInt k, Real * A, Real * B,
- Real * C, Real alpha = 1.);
-
- /// @f$ C = A^t*B @f$
- inline void matrixt_matrix(UInt m, UInt n, UInt k, Real * A, Real * B,
- Real * C, Real alpha = 1.);
-
- /// @f$ C = A*B^t @f$
- inline void matrix_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B,
- Real * C, Real alpha = 1.);
-
- /// @f$ C = A^t*B^t @f$
- inline void matrixt_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B,
- Real * C, Real alpha = 1.);
-
- template <bool tr_A, bool tr_B>
- inline void matMul(UInt m, UInt n, UInt k, Real alpha, Real * A, Real * B,
- Real beta, Real * C);
-
- template <bool tr_A>
- inline void matVectMul(UInt m, UInt n, Real alpha, Real * A, Real * x,
- Real beta, Real * y);
-
- inline void aXplusY(UInt n, Real alpha, Real * x, Real * y);
-
- inline void matrix33_eigenvalues(Real * A, Real * Adiag);
-
- inline void matrix22_eigenvalues(Real * A, Real * Adiag);
- template <UInt dim> inline void eigenvalues(Real * A, Real * d);
-
- /// solve @f$ A x = \Lambda x @f$ and return d and V such as @f$ A V[i:] =
- /// d[i] V[i:]@f$
- template <typename T> void matrixEig(UInt n, T * A, T * d, T * V = nullptr);
-
- /// determinent of a 2x2 matrix
- Real det2(const Real * mat);
- /// determinent of a 3x3 matrix
- Real det3(const Real * mat);
- /// determinent of a nxn matrix
- template <UInt n> Real det(const Real * mat);
- /// determinent of a nxn matrix
- template <typename T> T det(UInt n, const T * A);
-
- /// inverse a nxn matrix
- template <UInt n> inline void inv(const Real * A, Real * inv);
- /// inverse a nxn matrix
- template <typename T> inline void inv(UInt n, const T * A, T * inv);
- /// inverse a 3x3 matrix
- inline void inv3(const Real * mat, Real * inv);
- /// inverse a 2x2 matrix
- inline void inv2(const Real * mat, Real * inv);
-
- /// solve A x = b using a LU factorization
- template <typename T>
- inline void solve(UInt n, const T * A, T * x, const T * b);
-
- /// return the double dot product between 2 tensors in 2d
- inline Real matrixDoubleDot22(Real * A, Real * B);
-
- /// return the double dot product between 2 tensors in 3d
- inline Real matrixDoubleDot33(Real * A, Real * B);
-
- /// extension of the double dot product to two 2nd order tensor in dimension n
- inline Real matrixDoubleDot(UInt n, Real * A, Real * B);
-
- /* ------------------------------------------------------------------------ */
- /* Array algebra */
- /* ------------------------------------------------------------------------ */
- /// vector cross product
- inline void vectorProduct3(const Real * v1, const Real * v2, Real * res);
-
- /// normalize a vector
- inline void normalize2(Real * v);
-
- /// normalize a vector
- inline void normalize3(Real * v);
-
- /// return norm of a 2-vector
- inline Real norm2(const Real * v);
-
- /// return norm of a 3-vector
- inline Real norm3(const Real * v);
-
- /// return norm of a vector
- inline Real norm(UInt n, const Real * v);
-
- /// return the dot product between 2 vectors in 2d
- inline Real vectorDot2(const Real * v1, const Real * v2);
-
- /// return the dot product between 2 vectors in 3d
- inline Real vectorDot3(const Real * v1, const Real * v2);
-
- /// return the dot product between 2 vectors
- inline Real vectorDot(Real * v1, Real * v2, UInt n);
-
/* ------------------------------------------------------------------------ */
/* Geometry */
/* ------------------------------------------------------------------------ */
/// compute normal a normal to a vector
- inline void normal2(const Real * vec, Real * normal);
+ template <class D1, std::enable_if_t<aka::is_vector_v<D1>> * = nullptr>
+ inline Vector<Real> normal(const Eigen::MatrixBase<D1> & vec);
+
+ template <class D1, aka::enable_if_t<not aka::is_vector_v<D1>> * = nullptr>
+ inline Vector<Real> normal(const Eigen::MatrixBase<D1> & /*vec*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
/// compute normal a normal to a vector
- inline void normal3(const Real * vec1, const Real * vec2, Real * normal);
+ template <class D1, class D2,
+ std::enable_if_t<aka::are_vectors<D1, D2>::value> * = nullptr>
+ inline Vector<Real, 3> normal(const Eigen::MatrixBase<D1> & vec1,
+ const Eigen::MatrixBase<D2> & vec2);
/// compute the tangents to an array of normal vectors
void compute_tangents(const Array<Real> & normals, Array<Real> & tangents);
- /// distance in 2D between x and y
- inline Real distance_2d(const Real * x, const Real * y);
-
- /// distance in 3D between x and y
- inline Real distance_3d(const Real * x, const Real * y);
-
/// radius of the in-circle of a triangle in 2d space
- static inline Real triangle_inradius(const Vector<Real> & coord1,
- const Vector<Real> & coord2,
- const Vector<Real> & coord3);
+ template <class D1, class D2, class D3>
+ static inline Real triangle_inradius(const Eigen::MatrixBase<D1> & coord1,
+ const Eigen::MatrixBase<D2> & coord2,
+ const Eigen::MatrixBase<D3> & coord3);
/// radius of the in-circle of a tetrahedron
- inline Real tetrahedron_inradius(const Real * coord1, const Real * coord2,
- const Real * coord3, const Real * coord4);
-
+ template <class D1, class D2, class D3, class D4>
+ static inline Real tetrahedron_inradius(const Eigen::MatrixBase<D1> & coord1,
+ const Eigen::MatrixBase<D2> & coord2,
+ const Eigen::MatrixBase<D3> & coord3,
+ const Eigen::MatrixBase<D4> & coord4);
/// volume of a tetrahedron
- inline Real tetrahedron_volume(const Real * coord1, const Real * coord2,
- const Real * coord3, const Real * coord4);
+ template <class D1, class D2, class D3, class D4>
+ static inline Real tetrahedron_volume(const Eigen::MatrixBase<D1> & coord1,
+ const Eigen::MatrixBase<D2> & coord2,
+ const Eigen::MatrixBase<D3> & coord3,
+ const Eigen::MatrixBase<D4> & coord4);
/// compute the barycenter of n points
- inline void barycenter(const Real * coord, UInt nb_points,
- UInt spatial_dimension, Real * barycenter);
-
- /// vector between x and y
- inline void vector_2d(const Real * x, const Real * y, Real * res);
-
- /// vector pointing from x to y in 3 spatial dimension
- inline void vector_3d(const Real * x, const Real * y, Real * res);
+ template <class D1, class D2>
+ inline void barycenter(const Eigen::MatrixBase<D1> & coord,
+ Eigen::MatrixBase<D2> & barycenter);
/// test if two scalar are equal within a given tolerance
inline bool are_float_equal(Real x, Real y);
/// test if two vectors are equal within a given tolerance
- inline bool are_vector_equal(UInt n, Real * x, Real * y);
+ inline bool are_vector_equal(Int n, Real * x, Real * y);
#ifdef isnan
#error \
"You probably included <math.h> which is incompatible with aka_math please use\
<cmath> or add a \"#undef isnan\" before akantu includes"
#endif
/// test if a real is a NaN
inline bool isnan(Real x);
/// test if the line x and y intersects each other
inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max);
/// test if a is in the range [x_min, x_max]
inline bool is_in_range(Real a, Real x_min, Real x_max);
inline Real getTolerance() { return Math::tolerance; }
inline void setTolerance(Real tol) { Math::tolerance = tol; }
- template <UInt p, typename T> inline T pow(T x);
+ template <Int p, typename T> inline T pow(T x);
template <class T1, class T2,
std::enable_if_t<std::is_integral<T1>::value and
std::is_integral<T2>::value> * = nullptr>
inline Real kronecker(T1 i, T2 j) {
return static_cast<Real>(i == j);
}
+ /* --------------------------------------------------------------------------
+ */
+ template <typename T> static inline constexpr T pow(T x, int p) {
+ return p == 0 ? T(1) : (pow(x, p - 1) * x);
+ }
/// reduce all the values of an array, the summation is done in place and the
/// array is modified
Real reduce(Array<Real> & array);
- class NewtonRaphson {
+ template <class T> class NewtonRaphson {
public:
- NewtonRaphson(Real tolerance, Real max_iteration)
+ NewtonRaphson(Real tolerance, Int max_iteration)
: tolerance(tolerance), max_iteration(max_iteration) {}
- template <class Functor> Real solve(const Functor & funct, Real x_0);
+ template <class Functor> T solve(const Functor & funct, const T & x_0);
private:
Real tolerance;
- Real max_iteration;
+ Int max_iteration;
};
- struct NewtonRaphsonFunctor {
+ template <class T> struct NewtonRaphsonFunctor {
explicit NewtonRaphsonFunctor(const std::string & name) : name(name) {}
- virtual ~NewtonRaphsonFunctor() = default;
-
- NewtonRaphsonFunctor(const NewtonRaphsonFunctor & other) = default;
- NewtonRaphsonFunctor(NewtonRaphsonFunctor && other) noexcept = default;
- NewtonRaphsonFunctor &
- operator=(const NewtonRaphsonFunctor & other) = default;
- NewtonRaphsonFunctor &
- operator=(NewtonRaphsonFunctor && other) noexcept = default;
+ virtual T f(const T & x) const = 0;
+ virtual T f_prime(const T & x) const = 0;
- virtual Real f(Real x) const = 0;
- virtual Real f_prime(Real x) const = 0;
std::string name;
};
} // namespace Math
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "aka_math_tmpl.hh"
#endif /* AKANTU_AKA_MATH_H_ */
diff --git a/src/common/aka_math_tmpl.hh b/src/common/aka_math_tmpl.hh
index d5b37876f..d584e7da7 100644
--- a/src/common/aka_math_tmpl.hh
+++ b/src/common/aka_math_tmpl.hh
@@ -1,843 +1,233 @@
/**
* @file aka_math_tmpl.hh
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Alejandro M. Aragón <alejandro.aragon@epfl.ch>
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Mathilde Radiguet <mathilde.radiguet@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Leonardo Snozzi <leonardo.snozzi@epfl.ch>
* @author Peter Spijker <peter.spijker@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Fri Dec 11 2020
*
* @brief Implementation of the inline functions of the math toolkit
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_blas_lapack.hh"
#include "aka_math.hh"
#include "aka_types.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <typeinfo>
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace Math {
/* ------------------------------------------------------------------------ */
- inline void matrix_vector(UInt im, UInt in,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * x, // NOLINT(readability-non-const-parameter)
- Real * y, Real alpha) {
-#ifdef AKANTU_USE_BLAS
- /// y = alpha*op(A)*x + beta*y
- char tran_A = 'N';
- int incx = 1;
- int incy = 1;
- double beta = 0.;
- int m = im;
- int n = in;
-
- aka_gemv(&tran_A, &m, &n, &alpha, A, &m, x, &incx, &beta, y, &incy);
-
-#else
- std::fill_n(y, im, 0.);
- for (UInt i = 0; i < im; ++i) {
- for (UInt j = 0; j < in; ++j) {
- y[i] += A[i + j * im] * x[j];
- }
- y[i] *= alpha;
- }
-#endif
- }
-
- /* ------------------------------------------------------------------------ */
- inline void
- matrixt_vector(UInt im, UInt in,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * x, // NOLINT(readability-non-const-parameter)
- Real * y, Real alpha) {
-#ifdef AKANTU_USE_BLAS
- /// y = alpha*op(A)*x + beta*y
- char tran_A = 'T';
- int incx = 1;
- int incy = 1;
- double beta = 0.;
- int m = im;
- int n = in;
-
- aka_gemv(&tran_A, &m, &n, &alpha, A, &m, x, &incx, &beta, y, &incy);
-#else
- std::fill_n(y, in, 0.);
- for (UInt i = 0; i < im; ++i) {
- for (UInt j = 0; j < in; ++j) {
- y[j] += alpha * A[j * im + i] * x[i];
- }
- }
-#endif
- }
-
- /* ------------------------------------------------------------------------ */
- inline void matrix_matrix(UInt im, UInt in, UInt ik,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * B, // NOLINT(readability-non-const-parameter)
- Real * C, Real alpha) {
-#ifdef AKANTU_USE_BLAS
- /// C := alpha*op(A)*op(B) + beta*C
- char trans_a = 'N';
- char trans_b = 'N';
- double beta = 0.;
- int m = im, n = in, k = ik;
-
- aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &m, B, &k, &beta, C,
- &m);
-#else
- std::fill_n(C, im * in, 0.);
- for (UInt j = 0; j < in; ++j) {
- UInt _jb = j * ik;
- UInt _jc = j * im;
- for (UInt i = 0; i < im; ++i) {
- for (UInt l = 0; l < ik; ++l) {
- UInt _la = l * im;
- C[i + _jc] += A[i + _la] * B[l + _jb];
- }
- C[i + _jc] *= alpha;
- }
- }
-#endif
- }
-
- /* ------------------------------------------------------------------------ */
- inline void
- matrixt_matrix(UInt im, UInt in, UInt ik,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * B, // NOLINT(readability-non-const-parameter)
- Real * C, Real alpha) {
-#ifdef AKANTU_USE_BLAS
- /// C := alpha*op(A)*op(B) + beta*C
- char trans_a = 'T';
- char trans_b = 'N';
- double beta = 0.;
- int m = im, n = in, k = ik;
-
- aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &k, B, &k, &beta, C,
- &m);
-#else
- std::fill_n(C, im * in, 0.);
- for (UInt j = 0; j < in; ++j) {
- UInt _jc = j * im;
- UInt _jb = j * ik;
- for (UInt i = 0; i < im; ++i) {
- UInt _ia = i * ik;
- for (UInt l = 0; l < ik; ++l) {
- C[i + _jc] += A[l + _ia] * B[l + _jb];
- }
- C[i + _jc] *= alpha;
- }
- }
-#endif
- }
-
- /* ------------------------------------------------------------------------ */
- inline void
- matrix_matrixt(UInt im, UInt in, UInt ik,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * B, // NOLINT(readability-non-const-parameter)
- Real * C, Real alpha) {
-#ifdef AKANTU_USE_BLAS
- /// C := alpha*op(A)*op(B) + beta*C
- char trans_a = 'N';
- char trans_b = 'T';
- double beta = 0.;
- int m = im, n = in, k = ik;
-
- aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &m, B, &n, &beta, C,
- &m);
-#else
- std::fill_n(C, im * in, 0.);
- for (UInt j = 0; j < in; ++j) {
- UInt _jc = j * im;
- for (UInt i = 0; i < im; ++i) {
- for (UInt l = 0; l < ik; ++l) {
- UInt _la = l * im;
- UInt _lb = l * in;
- C[i + _jc] += A[i + _la] * B[j + _lb];
- }
- C[i + _jc] *= alpha;
- }
- }
-#endif
- }
-
- /* ------------------------------------------------------------------------ */
- inline void
- matrixt_matrixt(UInt im, UInt in, UInt ik,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * B, // NOLINT(readability-non-const-parameter)
- Real * C, Real alpha) {
-#ifdef AKANTU_USE_BLAS
- /// C := alpha*op(A)*op(B) + beta*C
- char trans_a = 'T';
- char trans_b = 'T';
- double beta = 0.;
- int m = im, n = in, k = ik;
-
- aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &k, B, &n, &beta, C,
- &m);
-#else
- std::fill_n(C, im * in, 0.);
- for (UInt j = 0; j < in; ++j) {
- UInt _jc = j * im;
- for (UInt i = 0; i < im; ++i) {
- UInt _ia = i * ik;
- for (UInt l = 0; l < ik; ++l) {
- UInt _lb = l * in;
- C[i + _jc] += A[l + _ia] * B[j + _lb];
- }
- C[i + _jc] *= alpha;
- }
- }
-#endif
- }
-
- /* ------------------------------------------------------------------------ */
- inline void aXplusY(UInt n, Real alpha,
- Real * x, // NOLINT(readability-non-const-parameter)
- Real * y) {
-#ifdef AKANTU_USE_BLAS
- /// y := alpha x + y
- int incx = 1, incy = 1;
- aka_axpy(&n, &alpha, x, &incx, y, &incy);
-#else
- for (UInt i = 0; i < n; ++i) {
- *(y++) += alpha * *(x++);
- }
-#endif
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real vectorDot(Real * v1, // NOLINT(readability-non-const-parameter)
- Real * v2, // NOLINT(readability-non-const-parameter)
- UInt in) {
-#ifdef AKANTU_USE_BLAS
- /// d := v1 . v2
- int incx = 1, incy = 1, n = in;
- Real d = aka_dot(&n, v1, &incx, v2, &incy);
-#else
- Real d = 0;
- for (UInt i = 0; i < in; ++i) {
- d += v1[i] * v2[i];
- }
-#endif
- return d;
- }
-
- /* ------------------------------------------------------------------------ */
- template <bool tr_A, bool tr_B>
- inline void matMul(UInt m, UInt n, UInt k, Real alpha,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * B, // NOLINT(readability-non-const-parameter)
- Real /*beta*/, Real * C) {
- if (tr_A) {
- if (tr_B) {
- matrixt_matrixt(m, n, k, A, B, C, alpha);
- } else {
- matrixt_matrix(m, n, k, A, B, C, alpha);
- }
- } else {
- if (tr_B) {
- matrix_matrixt(m, n, k, A, B, C, alpha);
- } else {
- matrix_matrix(m, n, k, A, B, C, alpha);
- }
- }
- }
-
- /* ------------------------------------------------------------------------ */
- template <bool tr_A>
- inline void matVectMul(UInt m, UInt n, Real alpha,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * x, // NOLINT(readability-non-const-parameter)
- Real /*beta*/, Real * y) {
- if (tr_A) {
- matrixt_vector(m, n, A, x, y, alpha);
- } else {
- matrix_vector(m, n, A, x, y, alpha);
- }
- }
-
- /* ------------------------------------------------------------------------ */
- template <typename T>
- inline void matrixEig(UInt n,
- T * A, // NOLINT(readability-non-const-parameter)
- T * d, T * V) {
-
- // Matrix A is row major, so the lapack function in fortran will
- // process A^t. Asking for the left eigenvectors of A^t will give the
- // transposed right eigenvectors of A so in the C++ code the right
- // eigenvectors.
- char jobvr{'N'};
- if (V != nullptr) {
- jobvr = 'V'; // compute left eigenvectors
- }
-
- char jobvl{'N'}; // compute right eigenvectors
-
- auto * di = new T[n]; // imaginary part of the eigenvalues
-
- int info;
- int N = n;
-
- T wkopt;
- int lwork = -1;
- // query and allocate the optimal workspace
- aka_geev<T>(&jobvl, &jobvr, &N, A, &N, d, di, nullptr, &N, V, &N, &wkopt,
- &lwork, &info);
-
- lwork = int(wkopt);
- auto * work = new T[lwork];
- // solve the eigenproblem
- aka_geev<T>(&jobvl, &jobvr, &N, A, &N, d, di, nullptr, &N, V, &N, work,
- &lwork, &info);
-
- AKANTU_DEBUG_ASSERT(
- info == 0,
- "Problem computing eigenvalues/vectors. DGEEV exited with the value "
- << info);
-
- delete[] work;
- delete[] di; // I hope for you that there was no complex eigenvalues !!!
- }
-
- /* ------------------------------------------------------------------------ */
- inline void
- matrix22_eigenvalues(Real * A, // NOLINT(readability-non-const-parameter)
- Real * Adiag) {
- /// d = determinant of Matrix A
- Real d = det2(A);
- /// b = trace of Matrix A
- Real b = A[0] + A[3];
-
- Real c = std::sqrt(b * b - 4 * d);
- Adiag[0] = .5 * (b + c);
- Adiag[1] = .5 * (b - c);
- }
-
- /* ------------------------------------------------------------------------ */
- inline void
- matrix33_eigenvalues(Real * A, // NOLINT(readability-non-const-parameter)
- Real * Adiag) {
- matrixEig(3, A, Adiag);
- }
-
- /* ------------------------------------------------------------------------ */
- template <UInt dim>
- inline void eigenvalues(Real * A, // NOLINT(readability-non-const-parameter)
- Real * d) {
- if (dim == 1) {
- d[0] = A[0];
- } else if (dim == 2) {
- matrix22_eigenvalues(A, d);
- }
- // else if(dim == 3) { matrix33_eigenvalues(A, d); }
- else {
- matrixEig(dim, A, d);
- }
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real det2(const Real * mat) {
- return mat[0] * mat[3] - mat[1] * mat[2];
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real det3(const Real * mat) {
- return mat[0] * (mat[4] * mat[8] - mat[7] * mat[5]) -
- mat[3] * (mat[1] * mat[8] - mat[7] * mat[2]) +
- mat[6] * (mat[1] * mat[5] - mat[4] * mat[2]);
- }
-
- /* ------------------------------------------------------------------------ */
- template <UInt n> inline Real det(const Real * mat) {
- if (n == 1) {
- return *mat;
- }
- if (n == 2) {
- return det2(mat);
- }
- if (n == 3) {
- return det3(mat);
- }
- return det(n, mat);
- }
-
- /* ------------------------------------------------------------------------ */
- template <typename T> inline T det(UInt n, const T * A) {
- int N = n;
- int info;
- auto * ipiv = new int[N + 1];
-
- auto * LU = new T[N * N];
- std::copy(A, A + N * N, LU);
-
- // LU factorization of A
- aka_getrf(&N, &N, LU, &N, ipiv, &info);
- if (info > 0) {
- AKANTU_ERROR("Singular matrix - cannot factorize it (info: " << info
- << " )");
- }
-
- // det(A) = det(L) * det(U) = 1 * det(U) = product_i U_{ii}
- T det = 1.;
- for (int i = 0; i < N; ++i) {
- det *= (2 * (ipiv[i] == i) - 1) * LU[i * n + i];
- }
-
- delete[] ipiv;
- delete[] LU;
- return det;
+ template <class D1, aka::enable_if_t<aka::is_vector_v<D1>> *>
+ inline Vector<Real> normal(const Eigen::MatrixBase<D1> & vec) {
+ Vector<Real> normal_(vec);
+ normal_[0] = vec[1];
+ normal_[1] = -vec[0];
+ normal_.normalize();
+ return normal_;
}
/* ------------------------------------------------------------------------ */
- inline void normal2(const Real * vec, Real * normal) {
- normal[0] = vec[1];
- normal[1] = -vec[0];
- normalize2(normal);
+ template <class D1, class D2, aka::enable_if_vectors_t<D1, D2> *>
+ inline Vector<Real, 3> normal(const Eigen::MatrixBase<D1> & vec1,
+ const Eigen::MatrixBase<D2> & vec2) {
+ AKANTU_DEBUG_ASSERT(vec1.cols() == 1 and vec1.rows() == 3,
+ "Vec is not of the proper size");
+ AKANTU_DEBUG_ASSERT(vec2.cols() == 1 and vec2.rows() == 3,
+ "Vec is not of the proper size");
+ Vector<Real, 3> vec1_(vec1);
+ Vector<Real, 3> vec2_(vec2);
+ Vector<Real, 3> normal_ = (vec1_.cross(vec2_)).normalized();
+ return normal_;
}
/* ------------------------------------------------------------------------ */
- inline void normal3(const Real * vec1, const Real * vec2, Real * normal) {
- vectorProduct3(vec1, vec2, normal);
- normalize3(normal);
- }
-
- /* ------------------------------------------------------------------------ */
- inline void normalize2(Real * vec) {
- Real norm = norm2(vec);
- vec[0] /= norm;
- vec[1] /= norm;
- }
-
- /* ------------------------------------------------------------------------ */
- inline void normalize3(Real * vec) {
- Real norm = norm3(vec);
- vec[0] /= norm;
- vec[1] /= norm;
- vec[2] /= norm;
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real norm2(const Real * vec) {
- return sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real norm3(const Real * vec) {
- return sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real norm(UInt n, const Real * vec) {
- Real norm = 0.;
- for (UInt i = 0; i < n; ++i) {
- norm += vec[i] * vec[i];
- }
- return sqrt(norm);
- }
-
- /* ------------------------------------------------------------------------ */
- inline void inv2(const Real * mat, Real * inv) {
- Real det_mat = det2(mat);
-
- inv[0] = mat[3] / det_mat;
- inv[1] = -mat[1] / det_mat;
- inv[2] = -mat[2] / det_mat;
- inv[3] = mat[0] / det_mat;
- }
-
- /* ------------------------------------------------------------------------ */
- inline void inv3(const Real * mat, Real * inv) {
- Real det_mat = det3(mat);
-
- inv[0] = (mat[4] * mat[8] - mat[7] * mat[5]) / det_mat;
- inv[1] = (mat[2] * mat[7] - mat[8] * mat[1]) / det_mat;
- inv[2] = (mat[1] * mat[5] - mat[4] * mat[2]) / det_mat;
- inv[3] = (mat[5] * mat[6] - mat[8] * mat[3]) / det_mat;
- inv[4] = (mat[0] * mat[8] - mat[6] * mat[2]) / det_mat;
- inv[5] = (mat[2] * mat[3] - mat[5] * mat[0]) / det_mat;
- inv[6] = (mat[3] * mat[7] - mat[6] * mat[4]) / det_mat;
- inv[7] = (mat[1] * mat[6] - mat[7] * mat[0]) / det_mat;
- inv[8] = (mat[0] * mat[4] - mat[3] * mat[1]) / det_mat;
- }
-
- /* ------------------------------------------------------------------------ */
- template <UInt n> inline void inv(const Real * A, Real * Ainv) {
- if (n == 1) {
- *Ainv = 1. / *A;
- } else if (n == 2) {
- inv2(A, Ainv);
- } else if (n == 3) {
- inv3(A, Ainv);
- } else {
- inv(n, A, Ainv);
- }
- }
-
- /* ------------------------------------------------------------------------ */
- template <typename T> inline void inv(UInt n, const T * A, T * invA) {
- int N = n;
- int info;
- auto * ipiv = new int[N + 1];
- int lwork = N * N;
- auto * work = new T[lwork];
-
- std::copy(A, A + n * n, invA);
-
- aka_getrf(&N, &N, invA, &N, ipiv, &info);
- if (info > 0) {
- AKANTU_ERROR("Singular matrix - cannot factorize it (info: " << info
- << " )");
- }
-
- aka_getri(&N, invA, &N, ipiv, work, &lwork, &info);
- if (info != 0) {
- AKANTU_ERROR("Cannot invert the matrix (info: " << info << " )");
- }
-
- delete[] ipiv;
- delete[] work;
- }
-
- /* ------------------------------------------------------------------------ */
- template <typename T>
- inline void solve(UInt n, const T * A, T * x, const T * b) {
- int N = n;
- int info;
- auto * ipiv = new int[N];
- auto * lu_A = new T[N * N];
-
- std::copy(A, A + N * N, lu_A);
-
- aka_getrf(&N, &N, lu_A, &N, ipiv, &info);
- if (info > 0) {
- AKANTU_ERROR("Singular matrix - cannot factorize it (info: " << info
- << " )");
- }
-
- char trans = 'N';
- int nrhs = 1;
+ template <class D1, class D2, class D3>
+ inline Real triangle_inradius(const Eigen::MatrixBase<D1> & coord1,
+ const Eigen::MatrixBase<D2> & coord2,
+ const Eigen::MatrixBase<D3> & coord3) {
+ auto a = coord1.distance(coord2);
+ auto b = coord2.distance(coord3);
+ auto c = coord1.distance(coord3);
- std::copy(b, b + N, x);
+ auto s = (a + b + c) / 2.;
- aka_getrs(&trans, &N, &nrhs, lu_A, &N, ipiv, x, &N, &info);
- if (info != 0) {
- AKANTU_ERROR("Cannot solve the system (info: " << info << " )");
- }
-
- delete[] ipiv;
- delete[] lu_A;
- }
-
- /* ------------------------------------------------------------------------ */
- /* ------------------------------------------------------------------------ */
- inline Real
- matrixDoubleDot22(Real * A, // NOLINT(readability-non-const-parameter)
- Real * B // NOLINT(readability-non-const-parameter)
- ) {
- Real d;
- d = A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3];
- return d;
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real
- matrixDoubleDot33(Real * A, // NOLINT(readability-non-const-parameter)
- Real * B // NOLINT(readability-non-const-parameter)
- ) {
- Real d;
- d = A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3] + A[4] * B[4] +
- A[5] * B[5] + A[6] * B[6] + A[7] * B[7] + A[8] * B[8];
- return d;
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real
- matrixDoubleDot(UInt n,
- Real * A, // NOLINT(readability-non-const-parameter)
- Real * B // NOLINT(readability-non-const-parameter)
- ) {
- Real d = 0.;
- for (UInt i = 0; i < n; ++i) {
- for (UInt j = 0; j < n; ++j) {
- d += A[i * n + j] * B[i * n + j];
- }
- }
- return d;
- }
-
- /* ------------------------------------------------------------------------ */
- inline void vectorProduct3(const Real * v1, const Real * v2, Real * res) {
- res[0] = v1[1] * v2[2] - v1[2] * v2[1];
- res[1] = v1[2] * v2[0] - v1[0] * v2[2];
- res[2] = v1[0] * v2[1] - v1[1] * v2[0];
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real vectorDot2(const Real * v1, const Real * v2) {
- return (v1[0] * v2[0] + v1[1] * v2[1]);
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real vectorDot3(const Real * v1, const Real * v2) {
- return (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]);
+ return std::sqrt((s - a) * (s - b) * (s - c) / s);
}
/* ------------------------------------------------------------------------ */
- inline Real distance_2d(const Real * x, const Real * y) {
- return std::sqrt((y[0] - x[0]) * (y[0] - x[0]) +
- (y[1] - x[1]) * (y[1] - x[1]));
- }
+ template <class D1, class D2, class D3, class D4>
+ inline Real tetrahedron_volume(const Eigen::MatrixBase<D1> & coord1,
+ const Eigen::MatrixBase<D2> & coord2,
+ const Eigen::MatrixBase<D3> & coord3,
+ const Eigen::MatrixBase<D4> & coord4) {
+ Matrix<Real, 3, 3> xx;
- /* ------------------------------------------------------------------------ */
- inline Real triangle_inradius(const Vector<Real> & coord1,
- const Vector<Real> & coord2,
- const Vector<Real> & coord3) {
- /**
- * @f{eqnarray*}{
- * r &=& A / s \\
- * A &=& 1/4 * \sqrt{(a + b + c) * (a - b + c) * (a + b - c) (-a + b + c)}
- * \\ s &=& \frac{a + b + c}{2}
- * @f}
- */
-
- Real a, b, c;
-
- a = coord1.distance(coord2);
- b = coord2.distance(coord3);
- c = coord1.distance(coord3);
-
- Real s;
- s = (a + b + c) * 0.5;
+ xx.col(0) = coord2;
+ xx.col(1) = coord3;
+ xx.col(2) = coord4;
+ auto vol = xx.determinant();
- return std::sqrt((s - a) * (s - b) * (s - c) / s);
- }
+ xx.col(0) = coord1;
+ vol -= xx.determinant();
- /* ------------------------------------------------------------------------ */
- inline Real distance_3d(const Real * x, const Real * y) {
- return std::sqrt((y[0] - x[0]) * (y[0] - x[0]) +
- (y[1] - x[1]) * (y[1] - x[1]) +
- (y[2] - x[2]) * (y[2] - x[2]));
- }
+ xx.col(1) = coord2;
+ vol += xx.determinant();
- /* ------------------------------------------------------------------------ */
- inline Real tetrahedron_volume(const Real * coord1, const Real * coord2,
- const Real * coord3, const Real * coord4) {
- Real xx[9];
-
- xx[0] = coord2[0];
- xx[1] = coord2[1];
- xx[2] = coord2[2];
- xx[3] = coord3[0];
- xx[4] = coord3[1];
- xx[5] = coord3[2];
- xx[6] = coord4[0];
- xx[7] = coord4[1];
- xx[8] = coord4[2];
- auto vol = det3(xx);
-
- xx[0] = coord1[0];
- xx[1] = coord1[1];
- xx[2] = coord1[2];
- xx[3] = coord3[0];
- xx[4] = coord3[1];
- xx[5] = coord3[2];
- xx[6] = coord4[0];
- xx[7] = coord4[1];
- xx[8] = coord4[2];
- vol -= det3(xx);
-
- xx[0] = coord1[0];
- xx[1] = coord1[1];
- xx[2] = coord1[2];
- xx[3] = coord2[0];
- xx[4] = coord2[1];
- xx[5] = coord2[2];
- xx[6] = coord4[0];
- xx[7] = coord4[1];
- xx[8] = coord4[2];
- vol += det3(xx);
-
- xx[0] = coord1[0];
- xx[1] = coord1[1];
- xx[2] = coord1[2];
- xx[3] = coord2[0];
- xx[4] = coord2[1];
- xx[5] = coord2[2];
- xx[6] = coord3[0];
- xx[7] = coord3[1];
- xx[8] = coord3[2];
- vol -= det3(xx);
+ xx.col(2) = coord3;
+ vol -= xx.determinant();
vol /= 6;
return vol;
}
/* ------------------------------------------------------------------------ */
- inline Real tetrahedron_inradius(const Real * coord1, const Real * coord2,
- const Real * coord3, const Real * coord4) {
- auto l12 = distance_3d(coord1, coord2);
- auto l13 = distance_3d(coord1, coord3);
- auto l14 = distance_3d(coord1, coord4);
- auto l23 = distance_3d(coord2, coord3);
- auto l24 = distance_3d(coord2, coord4);
- auto l34 = distance_3d(coord3, coord4);
+ template <class D1, class D2, class D3, class D4>
+ inline Real tetrahedron_inradius(const Eigen::MatrixBase<D1> & coord1,
+ const Eigen::MatrixBase<D2> & coord2,
+ const Eigen::MatrixBase<D3> & coord3,
+ const Eigen::MatrixBase<D4> & coord4) {
+ auto l12 = coord1.distance(coord2);
+ auto l13 = coord1.distance(coord3);
+ auto l14 = coord1.distance(coord4);
+ auto l23 = coord2.distance(coord3);
+ auto l24 = coord2.distance(coord4);
+ auto l34 = coord3.distance(coord4);
auto s1 = (l12 + l23 + l13) * 0.5;
s1 = std::sqrt(s1 * (s1 - l12) * (s1 - l23) * (s1 - l13));
auto s2 = (l12 + l24 + l14) * 0.5;
s2 = std::sqrt(s2 * (s2 - l12) * (s2 - l24) * (s2 - l14));
auto s3 = (l23 + l34 + l24) * 0.5;
s3 = std::sqrt(s3 * (s3 - l23) * (s3 - l34) * (s3 - l24));
auto s4 = (l13 + l34 + l14) * 0.5;
s4 = std::sqrt(s4 * (s4 - l13) * (s4 - l34) * (s4 - l14));
- auto volume = tetrahedron_volume(coord1, coord2, coord3, coord4);
+ auto volume = Math::tetrahedron_volume(coord1, coord2, coord3, coord4);
return 3 * volume / (s1 + s2 + s3 + s4);
}
/* ------------------------------------------------------------------------ */
- inline void barycenter(const Real * coord, UInt nb_points,
- UInt spatial_dimension, Real * barycenter) {
- std::fill_n(barycenter, spatial_dimension, 0.);
- for (UInt n = 0; n < nb_points; ++n) {
- UInt offset = n * spatial_dimension;
- for (UInt i = 0; i < spatial_dimension; ++i) {
- barycenter[i] += coord[offset + i] / (Real)nb_points;
- }
+ template <class D1, class D2>
+ inline void barycenter(const Eigen::MatrixBase<D1> & coord,
+ Eigen::MatrixBase<D2> & barycenter) {
+ barycenter.zero();
+ for (auto && x : coord) {
+ barycenter += x;
}
- }
-
- /* ------------------------------------------------------------------------ */
- inline void vector_2d(const Real * x, const Real * y, Real * res) {
- res[0] = y[0] - x[0];
- res[1] = y[1] - x[1];
- }
-
- /* ------------------------------------------------------------------------ */
- inline void vector_3d(const Real * x, const Real * y, Real * res) {
- res[0] = y[0] - x[0];
- res[1] = y[1] - x[1];
- res[2] = y[2] - x[2];
+ barycenter /= (Real)coord.cols();
}
/* ------------------------------------------------------------------------ */
/// Combined absolute and relative tolerance test proposed in
/// Real-time collision detection by C. Ericson (2004)
inline bool are_float_equal(const Real x, const Real y) {
Real abs_max = std::max(std::abs(x), std::abs(y));
abs_max = std::max(abs_max, Real(1.));
return std::abs(x - y) <= (tolerance * abs_max);
}
/* ------------------------------------------------------------------------ */
inline bool isnan(Real x) {
#if defined(__INTEL_COMPILER)
#pragma warning(push)
#pragma warning(disable : 1572)
#endif // defined(__INTEL_COMPILER)
// x = x return false means x = quiet_NaN
return !(x == x);
#if defined(__INTEL_COMPILER)
#pragma warning(pop)
#endif // defined(__INTEL_COMPILER)
}
/* ------------------------------------------------------------------------ */
- inline bool are_vector_equal(UInt n, Real * x, Real * y) {
+ inline bool are_vector_equal(Int n, Real * x, Real * y) {
bool test = true;
- for (UInt i = 0; i < n; ++i) {
+ for (Int i = 0; i < n; ++i) {
test &= are_float_equal(x[i], y[i]);
}
return test;
}
/* ------------------------------------------------------------------------ */
inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max) {
return not((x_max < y_min) or (x_min > y_max));
}
/* ------------------------------------------------------------------------ */
inline bool is_in_range(Real a, Real x_min, Real x_max) {
return ((a >= x_min) and (a <= x_max));
}
/* ------------------------------------------------------------------------ */
- template <UInt p, typename T> inline T pow(T x) {
+ template <Int p, typename T> inline T pow(T x) {
return (pow<p - 1, T>(x) * x);
}
- template <> inline UInt pow<0, UInt>(__attribute__((unused)) UInt x) {
- return (1);
- }
- template <> inline Real pow<0, Real>(__attribute__((unused)) Real x) {
- return (1.);
- }
+ template <> inline Int pow<0, Int>(Int /*x*/) { return (1); }
+ template <> inline Real pow<0, Real>(Real /*x*/) { return (1.); }
/* ------------------------------------------------------------------------ */
-
+ template <class T>
template <class Functor>
- Real NewtonRaphson::solve(const Functor & funct, Real x_0) {
- Real x = x_0;
- Real f_x = funct.f(x);
- UInt iter = 0;
+ T NewtonRaphson<T>::solve(const Functor & funct, const T & x_0) {
+ T x = x_0;
+ T f_x = funct.f(x);
+ Int iter = 0;
while (std::abs(f_x) > this->tolerance && iter < this->max_iteration) {
x -= f_x / funct.f_prime(x);
f_x = funct.f(x);
iter++;
}
AKANTU_DEBUG_ASSERT(iter < this->max_iteration,
"Newton Raphson ("
<< funct.name << ") solve did not converge in "
<< this->max_iteration << " iterations (tolerance: "
<< this->tolerance << ")");
return x;
}
} // namespace Math
} // namespace akantu
diff --git a/src/common/aka_named_argument.hh b/src/common/aka_named_argument.hh
index 4fa9ba58d..00dddc336 100644
--- a/src/common/aka_named_argument.hh
+++ b/src/common/aka_named_argument.hh
@@ -1,169 +1,173 @@
/**
* @file aka_named_argument.hh
*
* @author Marco Arena <None>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 16 2017
* @date last modification: Tue Sep 29 2020
*
* @brief tool to use named arguments in functions
*
*
* @section LICENSE
*
* Public Domain ? https://gist.github.com/ilpropheta/7576dce4c3249df89f85
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_compatibilty_with_cpp_standard.hh"
/* -------------------------------------------------------------------------- */
#include <tuple>
#include <type_traits>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_NAMED_ARGUMENT_HH_
#define AKANTU_AKA_NAMED_ARGUMENT_HH_
namespace akantu {
namespace named_argument {
struct param_t_trait {};
/* -- Pack utils (proxy version) ------------------------------------------ */
/// Proxy containing [tag, value]
template <typename tag, typename type> struct param_t : param_t_trait {
using _tag = tag;
using _type = type;
template <typename T>
explicit param_t(T && value) // NOLINT
: _value(std::forward<T>(value)) {}
type _value;
};
/*
* Tagged proxy that allows syntax _name = value
* operator=(T&&) returns a param_t instance
**/
template <typename tag> struct param_proxy {
using _tag = tag;
- template <typename T> decltype(auto) operator=(T && value) {
+ // NOLINTNEXTLINE(cppcoreguidelines-c-copy-assignment-signature)
+ template <typename T> constexpr decltype(auto) operator=(T && value) const {
return param_t<tag, decltype(value)>{std::forward<T>(value)};
}
};
/* Same as type_at but it's supposed to be used by passing
a pack of param_t (_tag is looked for instead of a
plain type). This and type_at should be refactored.
*/
template <typename T, typename head, typename... tail> struct type_at_p {
enum {
_tmp = (std::is_same<T, typename std::decay_t<head>::_tag>::value)
? 0
: type_at_p<T, tail...>::_pos
};
enum { _pos = _tmp == -1 ? -1 : 1 + _tmp };
};
template <typename T, typename head> struct type_at_p<T, head> {
enum {
_pos =
(std::is_same<T, typename std::decay<head>::type::_tag>::value ? 1
: -1)
};
};
template <typename... Ts> struct type_at {
enum { _pos = -1 };
};
template <typename T, typename head, typename... tail>
struct type_at<T, head, tail...> {
enum { _tmp = type_at_p<T, head, tail...>::_pos };
enum { _pos = _tmp == 1 ? 0 : (_tmp == -1 ? -1 : _tmp - 1) };
};
/* Same as get_at but it's supposed to be used by passing
a pack of param_t (_type is retrieved instead)
This and get_at should be refactored.
*/
template <int pos, int curr> struct get_at {
static_assert(pos >= 0, "Required parameter");
template <typename head, typename... tail>
- static decltype(auto) get(head && /*unused*/, tail &&... t) {
- return get_at<pos, curr + 1>::get(std::forward<tail>(t)...);
+ static decltype(auto) get(head && /*unused*/, tail &&... tail_) {
+ return get_at<pos, curr + 1>::get(std::forward<tail>(tail_)...);
}
};
template <int pos> struct get_at<pos, pos> {
static_assert(pos >= 0, "Required parameter");
template <typename head, typename... tail>
- static decltype(auto) get(head && h, tail &&... /*unused*/) {
- return std::forward<decltype(h._value)>(h._value);
+ static decltype(auto) get(head && head_, tail &&... /*unused*/) {
+ return std::forward<decltype(head_._value)>(head_._value);
}
};
// Optional version
template <int pos, int curr> struct get_optional {
template <typename T, typename... pack>
static decltype(auto) get(T && /*unused*/, pack &&... _pack) {
return get_at<pos, curr>::get(std::forward<pack>(_pack)...);
}
};
template <int curr> struct get_optional<-1, curr> {
template <typename T, typename... pack>
static decltype(auto) get(T && _default, pack &&... /*unused*/) {
return std::forward<T>(_default);
}
};
} // namespace named_argument
// CONVENIENCE MACROS FOR CLASS DESIGNERS ==========
+// // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define TAG_OF_ARGUMENT(_name) p_##_name
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define TAG_OF_ARGUMENT_WNS(_name) TAG_OF_ARGUMENT(_name)
-
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define REQUIRED_NAMED_ARG(_name) \
named_argument::get_at< \
named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \
0>::get(std::forward<pack>(_pack)...)
-
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define REQUIRED_NAMED_ARG(_name) \
named_argument::get_at< \
named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \
0>::get(std::forward<pack>(_pack)...)
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define OPTIONAL_NAMED_ARG(_name, _defaultVal) \
named_argument::get_optional< \
named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \
0>::get(_defaultVal, std::forward<pack>(_pack)...)
-
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define DECLARE_NAMED_ARGUMENT(name) \
struct TAG_OF_ARGUMENT(name) {}; \
- named_argument::param_proxy<TAG_OF_ARGUMENT_WNS(name)> _##name \
+ const named_argument::param_proxy<TAG_OF_ARGUMENT_WNS(name)> _##name \
__attribute__((unused))
namespace {
struct use_named_args_t {};
- use_named_args_t use_named_args __attribute__((unused));
+ const use_named_args_t use_named_args __attribute__((unused));
} // namespace
template <typename T> struct is_named_argument : public std::false_type {};
template <typename... type>
struct is_named_argument<named_argument::param_t<type...>>
: public std::true_type {};
template <typename... pack>
using are_named_argument =
aka::conjunction<is_named_argument<std::decay_t<pack>>...>;
} // namespace akantu
#endif /* AKANTU_AKA_NAMED_ARGUMENT_HH_ */
diff --git a/src/common/aka_random_generator.hh b/src/common/aka_random_generator.hh
index 0312f2bd8..28e8bdb12 100644
--- a/src/common/aka_random_generator.hh
+++ b/src/common/aka_random_generator.hh
@@ -1,285 +1,285 @@
/**
* @file aka_random_generator.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Tue Sep 29 2020
*
* @brief generic random generator
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
/* -------------------------------------------------------------------------- */
#include <random>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_RANDOM_GENERATOR_HH_
#define AKANTU_AKA_RANDOM_GENERATOR_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* List of available distributions */
/* -------------------------------------------------------------------------- */
// clang-format off
#define AKANTU_RANDOM_DISTRIBUTION_TYPES \
((uniform , std::uniform_real_distribution )) \
((exponential , std::exponential_distribution )) \
((gamma , std::gamma_distribution )) \
((weibull , std::weibull_distribution )) \
((extreme_value, std::extreme_value_distribution)) \
((normal , std::normal_distribution )) \
((lognormal , std::lognormal_distribution )) \
((chi_squared , std::chi_squared_distribution )) \
((cauchy , std::cauchy_distribution )) \
((fisher_f , std::fisher_f_distribution )) \
((student_t , std::student_t_distribution ))
// clang-format on
#define AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(elem) BOOST_PP_CAT(_rdt_, elem)
#define AKANTU_RANDOM_DISTRIBUTION_PREFIX(s, data, elem) \
AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(BOOST_PP_TUPLE_ELEM(2, 0, elem))
enum RandomDistributionType {
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_RANDOM_DISTRIBUTION_PREFIX, _,
AKANTU_RANDOM_DISTRIBUTION_TYPES)),
_rdt_not_defined
};
/* -------------------------------------------------------------------------- */
/* Generator */
/* -------------------------------------------------------------------------- */
template <typename T> class RandomGenerator {
/* ------------------------------------------------------------------------ */
private:
static long int _seed; // NOLINT
static std::default_random_engine generator; // NOLINT
/* ------------------------------------------------------------------------ */
public:
inline T operator()() { return generator(); }
/// function to print the contain of the class
void printself(std::ostream & stream, int /* indent */) const {
stream << "RandGenerator [seed=" << _seed << "]";
}
/* ------------------------------------------------------------------------ */
public:
static void seed(long int s) {
_seed = s;
generator.seed(_seed);
}
static long int seed() { return _seed; }
static constexpr T min() { return std::default_random_engine::min(); }
static constexpr T max() { return std::default_random_engine::max(); }
};
#if defined(__clang__)
template <typename T> long int RandomGenerator<T>::_seed; // NOLINT
template <typename T> std::default_random_engine RandomGenerator<T>::generator;
#endif
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#undef AKANTU_RANDOM_DISTRIBUTION_PREFIX
#define AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE(r, data, elem) \
case AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \
BOOST_PP_TUPLE_ELEM(2, 0, elem)): { \
stream << BOOST_PP_STRINGIZE(AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \
BOOST_PP_TUPLE_ELEM(2, 0, elem))); \
break; \
}
inline std::ostream & operator<<(std::ostream & stream,
RandomDistributionType type) {
switch (type) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE, _,
AKANTU_RANDOM_DISTRIBUTION_TYPES)
default:
stream << UInt(type) << " not a RandomDistributionType";
break;
}
return stream;
}
#undef AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE
/* -------------------------------------------------------------------------- */
/* Some Helper */
/* -------------------------------------------------------------------------- */
template <typename T, class Distribution> class RandomDistributionTypeHelper {
enum { value = _rdt_not_defined };
};
/* -------------------------------------------------------------------------- */
#define AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE(r, data, elem) \
template <typename T> \
struct RandomDistributionTypeHelper<T, BOOST_PP_TUPLE_ELEM(2, 1, elem) < \
T> > { \
enum { \
value = AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \
BOOST_PP_TUPLE_ELEM(2, 0, elem)) \
}; \
\
static void printself(std::ostream & stream) { \
stream << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem)); \
} \
};
BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE, _,
AKANTU_RANDOM_DISTRIBUTION_TYPES)
#undef AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE
/* -------------------------------------------------------------------------- */
template <class T> class RandomDistribution {
public:
virtual ~RandomDistribution() = default;
RandomDistribution() = default;
RandomDistribution(const RandomDistribution & other) = default;
RandomDistribution(RandomDistribution && other) noexcept = default;
RandomDistribution & operator=(const RandomDistribution & other) = default;
RandomDistribution &
operator=(RandomDistribution && other) noexcept = default;
- virtual T operator()(RandomGenerator<UInt> & gen) = 0;
+ virtual T operator()(RandomGenerator<Idx> & gen) = 0;
virtual std::unique_ptr<RandomDistribution<T>> make_unique() const = 0;
virtual void printself(std::ostream & stream, int = 0) const = 0;
};
template <class T, class Distribution>
class RandomDistributionProxy : public RandomDistribution<T> {
public:
explicit RandomDistributionProxy(Distribution dist)
: distribution(std::move(dist)) {}
- T operator()(RandomGenerator<UInt> & gen) override {
+ T operator()(RandomGenerator<Idx> & gen) override {
return distribution(gen);
}
std::unique_ptr<RandomDistribution<T>> make_unique() const override {
return std::make_unique<RandomDistributionProxy<T, Distribution>>(
distribution);
}
void printself(std::ostream & stream, int /* indent */ = 0) const override {
RandomDistributionTypeHelper<T, Distribution>::printself(stream);
stream << " [ " << distribution << " ]";
}
private:
Distribution distribution;
};
/* -------------------------------------------------------------------------- */
/* RandomParameter */
/* -------------------------------------------------------------------------- */
template <typename T> class RandomParameter {
public:
template <class Distribution>
explicit RandomParameter(T base_value, Distribution dist)
: base_value(base_value),
type(RandomDistributionType(
RandomDistributionTypeHelper<T, Distribution>::value)),
distribution_proxy(
std::make_unique<RandomDistributionProxy<T, Distribution>>(
std::move(dist))) {}
explicit RandomParameter(T base_value)
: base_value(base_value),
type(RandomDistributionType(
RandomDistributionTypeHelper<
T, std::uniform_real_distribution<T>>::value)),
distribution_proxy(
std::make_unique<
RandomDistributionProxy<T, std::uniform_real_distribution<T>>>(
std::uniform_real_distribution<T>(0., 0.))) {}
RandomParameter(const RandomParameter & other)
: base_value(other.base_value), type(other.type),
distribution_proxy(other.distribution_proxy->make_unique()) {}
RandomParameter & operator=(const RandomParameter & other) {
distribution_proxy = other.distribution_proxy->make_unique();
base_value = other.base_value;
type = other.type;
return *this;
}
RandomParameter(RandomParameter && other) noexcept = default;
RandomParameter & operator=(RandomParameter && other) noexcept = default;
virtual ~RandomParameter() = default;
inline void setBaseValue(const T & value) { this->base_value = value; }
inline T getBaseValue() const { return this->base_value; }
template <template <typename> class Generator, class iterator>
void setValues(iterator it, iterator end) {
- RandomGenerator<UInt> gen;
+ RandomGenerator<Idx> gen;
for (; it != end; ++it) {
*it = this->base_value + (*distribution_proxy)(gen);
}
}
virtual void printself(std::ostream & stream,
__attribute__((unused)) int indent = 0) const {
stream << base_value;
stream << " + " << *distribution_proxy;
}
private:
/// Value with no random variations
T base_value;
/// Random distribution type
RandomDistributionType type;
/// Proxy to store a std random distribution
std::unique_ptr<RandomDistribution<T>> distribution_proxy;
};
/* -------------------------------------------------------------------------- */
template <typename T>
inline std::ostream & operator<<(std::ostream & stream,
RandomDistribution<T> & _this) {
_this.printself(stream);
return stream;
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline std::ostream & operator<<(std::ostream & stream,
RandomParameter<T> & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#endif /* AKANTU_AKA_RANDOM_GENERATOR_HH_ */
diff --git a/src/common/aka_tensor.hh b/src/common/aka_tensor.hh
new file mode 100644
index 000000000..74dfdcc29
--- /dev/null
+++ b/src/common/aka_tensor.hh
@@ -0,0 +1,463 @@
+/**
+ * @file aka_tensor.hh
+ *
+ * @author Nicolas Richart
+ *
+ * @date creation dim jan 23 2022
+ *
+ * @brief A Documented file.
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKA_TENSOR_HH_
+#define AKA_TENSOR_HH_
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+/* TensorBase */
+/* -------------------------------------------------------------------------- */
+template <typename T, Int ndim> class TensorBase : public TensorTrait<ndim> {
+ using RetType = TensorBase<T, ndim>;
+ static_assert(ndim > 2, "TensorBase cannot by used for dimensions < 3");
+
+protected:
+ using idx_t = Idx;
+
+ template <typename... Args>
+ using valid_args_t = typename std::enable_if<
+ aka::conjunction<aka::disjunction<std::is_integral<Args>,
+ std::is_enum<Args>>...>::value and
+ ndim == sizeof...(Args),
+ int>::type;
+
+public:
+ using proxy = TensorBase<T, ndim>;
+ using size_type = Idx;
+ template <Int _ndim = ndim,
+ std::enable_if_t<_ndim == 1 or _ndim == 2, int> = 0>
+ TensorBase() {
+ n.fill(0);
+ }
+
+ TensorBase() { n.fill(0); }
+
+ template <typename... Args, valid_args_t<Args...> = 0>
+ constexpr TensorBase(Args... args)
+ : n{idx_t(args)...}, _size(detail::product_all(args...)) {}
+
+ constexpr TensorBase(const TensorBase & other)
+ : n(other.n), _size(other._size), values(other.values) {}
+
+ constexpr TensorBase(TensorBase && other) noexcept
+ : n(std::move(other.n)), _size(std::exchange(other._size, 0)),
+ values(std::exchange(other.values, nullptr)) {}
+
+protected:
+ template <typename Array, idx_t... I>
+ constexpr auto check_indices(
+ const Array & idx,
+ std::integer_sequence<idx_t, I...> /* for_template_deduction */) const {
+ bool result = true;
+ (void)std::initializer_list<int>{(result &= idx[I] < n[I], 0)...};
+ return result;
+ }
+
+ template <typename... Args> constexpr auto compute_index(Args... args) const {
+ std::array<idx_t, sizeof...(Args)> idx{idx_t(args)...};
+ assert(check_indices(
+ idx, std::make_integer_sequence<idx_t, sizeof...(Args)>{}) &&
+ "The indexes are out of bound");
+ idx_t index = 0, i = (sizeof...(Args)) - 1;
+ for (; i > 0; i--) {
+ index += idx[i];
+ if (i > 0) {
+ index *= n[i - 1];
+ }
+ }
+ return index + idx[0];
+ }
+
+ template <typename S, int... I>
+ constexpr auto get_slice(idx_t s, std::index_sequence<I...>) {
+ return S(this->values + s * detail::product_all(n[I]...), n[I]...);
+ }
+
+ template <typename S, std::size_t... I>
+ constexpr auto get_slice(idx_t s, std::index_sequence<I...>) const {
+ return S(this->values + s * detail::product_all(n[I]...), n[I]...);
+ }
+
+public:
+ template <typename... Args, valid_args_t<Args...> = 0>
+ inline auto operator()(Args... args) -> T & {
+ return *(this->values + compute_index(std::move(args)...));
+ }
+
+ template <typename... Args, valid_args_t<Args...> = 0>
+ inline auto operator()(Args... args) const -> const T & {
+ return *(this->values + compute_index(std::move(args)...));
+ }
+
+ template <
+ class R = T, idx_t _ndim = ndim,
+ std::enable_if_t<(_ndim > 3) and not std::is_const<R>::value> * = nullptr>
+ inline auto operator()(idx_t s) {
+ return get_slice<TensorProxy<T, ndim - 1>>(
+ s, std::make_index_sequence<ndim - 1>());
+ }
+
+ template <idx_t _ndim = ndim, std::enable_if_t<(_ndim > 3)> * = nullptr>
+ inline auto operator()(idx_t s) const {
+ return get_slice<TensorProxy<T, ndim - 1>>(
+ s, std::make_index_sequence<ndim - 1>());
+ }
+
+ template <class R = T, idx_t _ndim = ndim,
+ std::enable_if_t<(_ndim == 3) and not std::is_const<R>::value> * =
+ nullptr>
+ inline auto operator()(idx_t s) {
+ return get_slice<
+ Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>>(
+ s, std::make_index_sequence<ndim - 1>());
+ }
+
+ template <idx_t _ndim = ndim, std::enable_if_t<_ndim == 3> * = nullptr>
+ inline auto operator()(idx_t s) const {
+ return get_slice<Eigen::Map<const Eigen::Matrix<
+ std::remove_const_t<T>, Eigen::Dynamic, Eigen::Dynamic>>>(
+ s, std::make_index_sequence<ndim - 1>());
+ }
+
+protected:
+ template <class Operator> auto transform(Operator && op) -> RetType & {
+ std::transform(this->values, this->values + this->_size, this->values,
+ std::forward<Operator>(op));
+ return *(static_cast<RetType *>(this));
+ }
+
+ template <class Other, class Operator>
+ auto transform(Other && other, Operator && op) -> RetType & {
+ AKANTU_DEBUG_ASSERT(_size == other.size(),
+ "The two tensors do not have the same size "
+ << this->_size << " != " << other._size);
+
+ std::transform(this->values, this->values + this->_size, other.values,
+ this->values, std::forward<Operator>(op));
+ return *(static_cast<RetType *>(this));
+ }
+
+ template <class Operator> auto accumulate(T init, Operator && op) -> T {
+ return std::accumulate(this->values, this->values + this->_size,
+ std::move(init), std::forward<Operator>(op));
+ }
+
+ template <class Other, class Init, class Accumulate, class Operator>
+ auto transform_reduce(Other && other, T init, Accumulate && acc,
+ Operator && op) -> T {
+ return std::inner_product(
+ this->values, this->values + this->_size, other.data(), std::move(init),
+ std::forward<Accumulate>(acc), std::forward<Operator>(op));
+ }
+
+ // element wise arithmetic operators -----------------------------------------
+public:
+ inline decltype(auto) operator+=(const TensorBase & other) {
+ return transform(other, [](auto && a, auto && b) { return a + b; });
+ }
+
+ /* ------------------------------------------------------------------------ */
+ inline auto operator-=(const TensorBase & other) -> TensorBase & {
+ return transform(other, [](auto && a, auto && b) { return a - b; });
+ }
+
+ /* ------------------------------------------------------------------------ */
+ inline auto operator+=(const T & x) -> TensorBase & {
+ return transform([&x](auto && a) { return a + x; });
+ }
+
+ /* ------------------------------------------------------------------------ */
+ inline auto operator-=(const T & x) -> TensorBase & {
+ return transform([&x](auto && a) { return a - x; });
+ }
+
+ /* ------------------------------------------------------------------------ */
+ inline auto operator*=(const T & x) -> TensorBase & {
+ return transform([&x](auto && a) { return a * x; });
+ }
+
+ /* ---------------------------------------------------------------------- */
+ inline auto operator/=(const T & x) -> TensorBase & {
+ return transform([&x](auto && a) { return a / x; });
+ }
+
+ /// Y = \alpha X + Y
+ inline auto aXplusY(const TensorBase & other, const T alpha = 1.)
+ -> TensorBase & {
+ return transform(other,
+ [&alpha](auto && a, auto && b) { return alpha * a + b; });
+ }
+
+ /* ------------------------------------------------------------------------ */
+ auto data() -> T * { return values; }
+ auto data() const -> const T * { return values; }
+
+ // clang-format off
+ [[deprecated("use data instead to be stl compatible")]]
+ auto storage() -> T*{
+ return values;
+ }
+
+ [[deprecated("use data instead to be stl compatible")]]
+ auto storage() const -> const T * {
+ return values;
+ }
+ // clang-format on
+
+ auto size() const { return _size; }
+ auto size(idx_t i) const {
+ AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim
+ << " dimensions, not "
+ << (i + 1));
+ return n[i];
+ };
+
+ inline void set(const T & t) { std::fill_n(values, _size, t); };
+ inline void zero() { set(T()); };
+
+public:
+ /// "Entrywise" norm norm<L_p> @f[ \|\boldsymbol{T}\|_p = \left(
+ /// \sum_i^{n[0]}\sum_j^{n[1]}\sum_k^{n[2]} |T_{ijk}|^p \right)^{\frac{1}{p}}
+ /// @f]
+ template <Int norm_type,
+ std::enable_if_t<norm_type == Eigen::Infinity> * = nullptr>
+ auto lpNorm() const -> T {
+ return accumulate(
+ T(), [](auto && init, auto && a) { return init + std::abs(a); });
+ }
+
+ template <Int norm_type, std::enable_if_t<norm_type == 1> * = nullptr>
+ auto lpNorm() const -> T {
+ return accumulate(T(), [](auto && init, auto && a) {
+ return std::max(init, std::abs(a));
+ });
+ }
+
+ template <Int norm_type, std::enable_if_t<norm_type == 2> * = nullptr>
+ auto norm() const -> T {
+ return std::sqrt(
+ accumulate(T(), [](auto && init, auto && a) { return init + a * a; }));
+ }
+
+ template <Int norm_type, std::enable_if_t<(norm_type > 2)> * = nullptr>
+ auto norm() const -> T {
+ return std::pow(accumulate(T(),
+ [](auto && init, auto && a) {
+ return init + std::pow(a, norm_type);
+ }),
+ 1. / norm_type);
+ }
+
+ auto norm() const -> T { return lpNorm<2>(); }
+
+protected:
+ template <Int N, typename... Args,
+ std::enable_if_t<(sizeof...(Args) == ndim), int> = 0>
+ void serialize(std::ostream & stream, Args... args) const {
+ stream << this->operator()(std::move(args)...);
+ }
+
+ template <Int N, typename... Args,
+ std::enable_if_t<(sizeof...(Args) < ndim), int> = 0>
+ void serialize(std::ostream & stream, Args... args) const {
+ stream << "[";
+ for (idx_t i = 0; i < n[N]; ++i) {
+ if (i != 0) {
+ stream << ",";
+ }
+ serialize<N + 1>(stream, std::move(args)..., i);
+ }
+ stream << "]";
+ }
+
+public:
+ void printself(std::ostream & stream) const { serialize<0>(stream); };
+
+protected:
+ template <std::size_t... I>
+ constexpr decltype(auto) begin(std::index_sequence<I...>) {
+ return view_iterator<ViewIteratorHelper_t<sizeof...(I), T>>(values,
+ n[I]...);
+ }
+
+ template <std::size_t... I>
+ constexpr decltype(auto) end(std::index_sequence<I...>) {
+ return view_iterator<ViewIteratorHelper_t<sizeof...(I), T>>(values + _size,
+ n[I]...);
+ }
+
+ template <std::size_t... I>
+ constexpr decltype(auto) begin(std::index_sequence<I...>) const {
+ return const_view_iterator<ViewIteratorHelper_t<sizeof...(I), T>>(values,
+ n[I]...);
+ }
+
+ template <std::size_t... I>
+ constexpr decltype(auto) end(std::index_sequence<I...>) const {
+ return const_view_iterator<ViewIteratorHelper_t<sizeof...(I), T>>(
+ values + _size, n[I]...);
+ }
+
+public:
+ decltype(auto) begin() { return begin(std::make_index_sequence<ndim - 1>{}); }
+ decltype(auto) end() { return end(std::make_index_sequence<ndim - 1>{}); }
+
+ decltype(auto) begin() const {
+ return begin(std::make_index_sequence<ndim - 1>{});
+ }
+ decltype(auto) end() const {
+ return end(std::make_index_sequence<ndim - 1>{});
+ }
+
+protected:
+ // size per dimension
+ std::array<idx_t, ndim> n;
+
+ // total storage size
+ idx_t _size{0};
+
+ // actual data location
+ T * values{nullptr};
+};
+
+/* -------------------------------------------------------------------------- */
+/* TensorProxy */
+/* -------------------------------------------------------------------------- */
+template <typename T, Int ndim> class TensorProxy : public TensorBase<T, ndim> {
+private:
+ using parent = TensorBase<T, ndim>;
+
+public:
+ // proxy constructor
+ template <typename... Args>
+ constexpr TensorProxy(T * data = reinterpret_cast<T *>(0xdeadbeef),
+ Args... args)
+ : parent(args...) {
+ this->values = data;
+ }
+
+ constexpr TensorProxy(const TensorProxy<T, ndim> & other) : parent(other) {
+ this->values = other.values;
+ }
+
+ constexpr TensorProxy(const Tensor<T, ndim> & other) : parent(other) {
+ this->values = other.values;
+ }
+
+ // move constructors ---------------------------------------------------------
+ // proxy -> proxy
+ TensorProxy(TensorProxy && other) noexcept : parent(other) {}
+
+ auto operator=(const TensorBase<T, ndim> & other) -> TensorProxy & {
+ AKANTU_DEBUG_ASSERT(
+ other.size() == this->size(),
+ "You are trying to copy too a tensors proxy with the wrong size "
+ << this->_size << " != " << other._size);
+
+ static_assert(std::is_trivially_copyable<T>{},
+ "Cannot copy a tensor on non trivial types");
+
+ std::copy(other.values, other.values + this->_size, this->values);
+ return *this;
+ }
+};
+
+/* -------------------------------------------------------------------------- */
+/* Tensor */
+/* -------------------------------------------------------------------------- */
+template <typename T, Int ndim> class Tensor : public TensorBase<T, ndim> {
+private:
+ using parent = TensorBase<T, ndim>;
+
+public:
+ template <typename... Args> constexpr Tensor(Args... args) : parent(args...) {
+ static_assert(
+ std::is_trivially_constructible<T>{},
+ "Cannot create a tensor on non trivially constructible types");
+ this->values = new T[this->_size];
+ }
+
+ /* ------------------------------------------------------------------------ */
+ virtual ~Tensor() { delete[] this->values; }
+
+ // copy constructors ---------------------------------------------------------
+ constexpr Tensor(const Tensor & other) : parent(other) {
+ this->values = new T[this->_size];
+ std::copy(other.values, other.values + this->_size, this->values);
+ }
+
+ constexpr explicit Tensor(const TensorProxy<T, ndim> & other)
+ : parent(other) {
+ // static_assert(false, "Copying data are you sure");
+ this->values = new T[this->_size];
+ std::copy(other.values, other.values + this->_size, this->values);
+ }
+
+ // move constructors ---------------------------------------------------------
+ // proxy -> proxy, non proxy -> non proxy
+ Tensor(Tensor && other) noexcept : parent(other) {}
+
+ // copy operator -------------------------------------------------------------
+ /// operator= copy-and-swap
+ auto operator=(const TensorBase<T, ndim> & other) -> Tensor & {
+ if (&other == this)
+ return *this;
+
+ std::cout << "Warning: operator= delete data" << std::endl;
+ delete[] this->values;
+ this->n = other.n;
+ this->_size = other._size;
+
+ static_assert(
+ std::is_trivially_constructible<T>{},
+ "Cannot create a tensor on non trivially constructible types");
+
+ this->values = new T[this->_size];
+
+ static_assert(std::is_trivially_copyable<T>{},
+ "Cannot copy a tensor on non trivial types");
+
+ std::copy(other.values, other.values + this->_size, this->values);
+
+ return *this;
+ }
+};
+
+/* -------------------------------------------------------------------------- */
+template <typename T> using Tensor3 = Tensor<T, 3>;
+template <typename T> using Tensor3Proxy = TensorProxy<T, 3>;
+template <typename T> using Tensor3Base = TensorBase<T, 3>;
+
+} // namespace akantu
+
+#endif // AKA_TENSOR_HH_
diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh
index 3c55c2604..c9e62e945 100644
--- a/src/common/aka_types.hh
+++ b/src/common/aka_types.hh
@@ -1,1558 +1,549 @@
/**
* @file aka_types.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 17 2011
* @date last modification: Wed Dec 09 2020
*
* @brief description of the "simple" types
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
-#include "aka_math.hh"
+#include "aka_compatibilty_with_cpp_standard.hh"
+#include "aka_error.hh"
/* -------------------------------------------------------------------------- */
+#include <algorithm>
+#include <array>
#include <initializer_list>
-#include <iomanip>
+#include <numeric>
#include <type_traits>
-/* -------------------------------------------------------------------------- */
-
-#ifndef AKANTU_AKA_TYPES_HH_
-#define AKANTU_AKA_TYPES_HH_
-
-namespace akantu {
-
-enum NormType { L_1 = 1, L_2 = 2, L_inf = UInt(-1) };
-/**
- * DimHelper is a class to generalize the setup of a dim array from 3
- * values. This gives a common interface in the TensorStorage class
- * independently of its derived inheritance (Vector, Matrix, Tensor3)
- * @tparam dim
- */
-template <UInt dim> struct DimHelper {
- static inline void setDims(UInt m, UInt n, UInt p,
- std::array<UInt, dim> & dims);
-};
+#ifndef AKANTU_AKA_TYPES_HH
+#define AKANTU_AKA_TYPES_HH
/* -------------------------------------------------------------------------- */
-template <> struct DimHelper<1> {
- static inline void setDims(UInt m, UInt /*n*/, UInt /*p*/,
- std::array<UInt, 1> & dims) {
- dims[0] = m;
- }
-};
-
+#define EIGEN_DEFAULT_DENSE_INDEX_TYPE akantu::Idx
+#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION Eigen::ColMajor
+#define EIGEN_DEFAULT_IO_FORMAT \
+ Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ", ", \
+ "[", "]", "[", "]")
/* -------------------------------------------------------------------------- */
-template <> struct DimHelper<2> {
- static inline void setDims(UInt m, UInt n, UInt /*p*/,
- std::array<UInt, 2> & dims) {
- dims[0] = m;
- dims[1] = n;
- }
-};
+#define EIGEN_MATRIXBASE_PLUGIN "aka_types_eigen_matrix_base_plugin.hh"
+#define EIGEN_MATRIX_PLUGIN "aka_types_eigen_matrix_plugin.hh"
+#define EIGEN_PLAINOBJECTBASE_PLUGIN \
+ "aka_types_eigen_plain_object_base_plugin.hh"
+#include <Eigen/Dense>
+#include <Eigen/Eigenvalues>
/* -------------------------------------------------------------------------- */
-template <> struct DimHelper<3> {
- static inline void setDims(UInt m, UInt n, UInt p,
- std::array<UInt, 3> & dims) {
- dims[0] = m;
- dims[1] = n;
- dims[2] = p;
- }
-};
-
-/* -------------------------------------------------------------------------- */
-template <typename T, UInt ndim, class RetType> class TensorStorage;
-
-/* -------------------------------------------------------------------------- */
-/* Proxy classes */
-/* -------------------------------------------------------------------------- */
-namespace tensors {
- template <class A, class B> struct is_copyable {
- enum : bool { value = false };
- };
-
- template <class A> struct is_copyable<A, A> {
- enum : bool { value = true };
- };
- template <class A> struct is_copyable<A, typename A::RetType> {
- enum : bool { value = true };
- };
+namespace aka {
- template <class A> struct is_copyable<A, typename A::RetType::proxy> {
- enum : bool { value = true };
- };
+template <typename T> struct is_eigen_map : public std::false_type {};
-} // namespace tensors
+template <typename PlainObjectType, int MapOptions, typename StrideType>
+struct is_eigen_map<Eigen::Map<PlainObjectType, MapOptions, StrideType>>
+ : public std::true_type {};
/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-namespace types {
- namespace details {
- template <typename reference_> class vector_iterator {
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = std::decay_t<reference_>;
- using pointer = value_type *;
- using reference = reference_;
- using iterator_category = std::input_iterator_tag;
-
- vector_iterator(pointer ptr) : ptr(ptr) {}
-
- // input iterator ++it
- vector_iterator & operator++() {
- ++ptr;
- return *this;
- }
- // input iterator it++
- vector_iterator operator++(int) {
- auto cpy = *this;
- ++ptr;
- return cpy;
- }
- vector_iterator & operator+=(int n) {
- ptr += n;
- return *this;
- }
-
- vector_iterator operator+(int n) {
- vector_iterator cpy(*this);
- cpy += n;
- return cpy;
- }
-
- // input iterator it != other_it
- bool operator!=(const vector_iterator & other) const {
- return ptr != other.ptr;
- }
- bool operator==(const vector_iterator & other) const {
- return ptr == other.ptr;
- }
-
- difference_type operator-(const vector_iterator & other) const {
- return this->ptr - other.ptr;
- }
-
- // input iterator dereference *it
- reference operator*() { return *ptr; }
- pointer operator->() { return ptr; }
-
- private:
- pointer ptr;
- };
- } // namespace details
-} // namespace types
-
-/**
- * @class TensorProxy aka_types.hh
- * The TensorProxy class is a proxy class to the
- * TensorStorage it handles the wrapped case. That is to say if an accessor
- * should give access to a Tensor wrapped on some data, like the
- * Array<T>::iterator they can return a TensorProxy that will be automatically
- * transformed as a TensorStorage wrapped on the same data
- * @tparam T stored type
- * @tparam ndim order of the tensor
- * @tparam _RetType real derived type
- */
-template <typename T, UInt ndim, class RetType_>
-class TensorProxy : public TensorProxyTrait {
-protected:
- using RetTypeProxy = typename RetType_::proxy;
-
- constexpr TensorProxy(T * data, UInt m, UInt n, UInt p) {
- DimHelper<ndim>::setDims(m, n, p, this->n);
- this->values = data;
- }
-
- template <class Other, typename = std::enable_if_t<
- tensors::is_copyable<TensorProxy, Other>::value>>
- explicit TensorProxy(const Other & other) {
- this->values = other.storage();
- for (UInt i = 0; i < ndim; ++i) {
- this->n[i] = other.size(i);
- }
- }
+template <typename T> struct is_eigen_matrix : public std::false_type {};
-public:
- using RetType = RetType_;
-
- UInt size(UInt i) const {
- AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim
- << " dimensions, not "
- << (i + 1));
- return n[i];
- }
-
- inline UInt size() const {
- UInt _size = 1;
- for (UInt d = 0; d < ndim; ++d) {
- _size *= this->n[d];
- }
- return _size;
- }
-
- T * storage() const { return values; }
-
- template <class Other, typename = std::enable_if_t<
- tensors::is_copyable<TensorProxy, Other>::value>>
- inline TensorProxy & operator=(const Other & other) {
- AKANTU_DEBUG_ASSERT(
- other.size() == this->size(),
- "You are trying to copy two tensors with different sizes");
- std::copy_n(other.storage(), this->size(), this->values);
- return *this;
- }
- // template <class Other, typename = std::enable_if_t<
- // tensors::is_copyable<TensorProxy, Other>::value>>
- // inline TensorProxy & operator=(const Other && other) {
- // AKANTU_DEBUG_ASSERT(
- // other.size() == this->size(),
- // "You are trying to copy two tensors with different sizes");
- // memcpy(this->values, other.storage(), this->size() * sizeof(T));
- // return *this;
- // }
-
- template <typename O> inline RetTypeProxy & operator*=(const O & o) {
- RetType(*this) *= o;
- return static_cast<RetTypeProxy &>(*this);
- }
+template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
+ int _MaxCols>
+struct is_eigen_matrix<
+ Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>>
+ : public std::true_type {};
- template <typename O> inline RetTypeProxy & operator/=(const O & o) {
- RetType(*this) /= o;
- return static_cast<RetTypeProxy &>(*this);
- }
-
-protected:
- T * values;
- std::array<UInt, ndim> n;
-};
-
-/* -------------------------------------------------------------------------- */
-template <typename T> class VectorProxy : public TensorProxy<T, 1, Vector<T>> {
- using parent = TensorProxy<T, 1, Vector<T>>;
- using type = Vector<T>;
-
-public:
- constexpr VectorProxy(T * data, UInt n) : parent(data, n, 0, 0) {}
- template <class Other> explicit VectorProxy(Other & src) : parent(src) {}
-
- /* ---------------------------------------------------------------------- */
- template <class Other>
- inline VectorProxy<T> & operator=(const Other & other) {
- parent::operator=(other);
- return *this;
- }
-
- // inline VectorProxy<T> & operator=(const VectorProxy && other) {
- // parent::operator=(other);
- // return *this;
- // }
- using iterator = types::details::vector_iterator<T &>;
- using const_iterator = types::details::vector_iterator<const T &>;
-
- iterator begin() { return iterator(this->storage()); }
- iterator end() { return iterator(this->storage() + this->size()); }
-
- const_iterator begin() const { return const_iterator(this->storage()); }
- const_iterator end() const {
- return const_iterator(this->storage() + this->size());
- }
-
- /* ------------------------------------------------------------------------ */
- T & operator()(UInt index) { return this->values[index]; };
- const T & operator()(UInt index) const { return this->values[index]; };
-};
-
-template <typename T> class MatrixProxy : public TensorProxy<T, 2, Matrix<T>> {
- using parent = TensorProxy<T, 2, Matrix<T>>;
- using type = Matrix<T>;
-
-public:
- MatrixProxy(T * data, UInt m, UInt n) : parent(data, m, n, 0) {}
- template <class Other> explicit MatrixProxy(Other & src) : parent(src) {}
-
- /* ---------------------------------------------------------------------- */
- template <class Other>
- inline MatrixProxy<T> & operator=(const Other & other) {
- parent::operator=(other);
- return *this;
- }
-};
-
-template <typename T>
-class Tensor3Proxy : public TensorProxy<T, 3, Tensor3<T>> {
- using parent = TensorProxy<T, 3, Tensor3<T>>;
- using type = Tensor3<T>;
-
-public:
- Tensor3Proxy(const T * data, UInt m, UInt n, UInt k)
- : parent(data, m, n, k) {}
- Tensor3Proxy(const Tensor3Proxy & src) : parent(src) {}
- Tensor3Proxy(const Tensor3<T> & src) : parent(src) {}
-
- /* ---------------------------------------------------------------------- */
- template <class Other>
- inline Tensor3Proxy<T> & operator=(const Other & other) {
- parent::operator=(other);
- return *this;
- }
-};
-
-/* -------------------------------------------------------------------------- */
-/* Tensor base class */
/* -------------------------------------------------------------------------- */
-template <typename T, UInt ndim, class RetType>
-class TensorStorage : public TensorTrait {
-public:
- using value_type = T;
+template <typename T> struct is_eigen_matrix_base : public std::false_type {};
- friend class Array<T>;
+template <typename Derived>
+struct is_eigen_matrix_base<Eigen::MatrixBase<Derived>>
+ : public std::true_type {};
+} // namespace aka
-protected:
- template <class TensorType> void copySize(const TensorType & src) {
- for (UInt d = 0; d < ndim; ++d) {
- this->n[d] = src.size(d); // NOLINT
- }
- this->_size = src.size();
- }
-
- TensorStorage() = default;
- TensorStorage(const TensorProxy<T, ndim, RetType> & proxy) {
- this->copySize(proxy);
- this->values = proxy.storage();
- this->wrapped = true;
- }
-
-public:
- TensorStorage(const TensorStorage & src) = delete;
+namespace akantu {
- TensorStorage(const TensorStorage & src, bool deep_copy) : values(nullptr) {
- if (deep_copy) {
- this->deepCopy(src);
- } else {
- this->shallowCopy(src);
- }
- }
+using Eigen::Ref;
-protected:
- TensorStorage(UInt m, UInt n, UInt p, const T & def) {
- static_assert(std::is_trivially_constructible<T>{},
- "Cannot create a tensor on non trivial types");
- DimHelper<ndim>::setDims(m, n, p, this->n);
+template <typename T, Eigen::Index n = Eigen::Dynamic>
+using Vector = Eigen::Matrix<T, n, 1>;
- this->computeSize();
- this->values = new T[this->_size]; // NOLINT
- this->set(def);
- this->wrapped = false;
- }
+template <typename T, Eigen::Index m = Eigen::Dynamic,
+ Eigen::Index n = Eigen::Dynamic>
+using Matrix = Eigen::Matrix<T, m, n>;
- TensorStorage(T * data, UInt m, UInt n, UInt p) {
- DimHelper<ndim>::setDims(m, n, p, this->n);
+template <typename T, Eigen::Index n = Eigen::Dynamic>
+using VectorProxy =
+ Eigen::Map<std::conditional_t<std::is_const<T>::value,
+ const Vector<std::remove_const_t<T>, n>,
+ Vector<std::remove_const_t<T>, n>>>;
- this->computeSize();
- this->values = data;
- this->wrapped = true;
- }
+template <typename T, Eigen::Index m = Eigen::Dynamic,
+ Eigen::Index n = Eigen::Dynamic>
+using MatrixProxy =
+ Eigen::Map<std::conditional_t<std::is_const<T>::value,
+ const Matrix<std::remove_const_t<T>, m, n>,
+ Matrix<std::remove_const_t<T>, m, n>>>;
-public:
- /* ------------------------------------------------------------------------ */
- template <class TensorType> inline void shallowCopy(const TensorType & src) {
- this->copySize(src);
- if (!this->wrapped) {
- delete[] this->values;
- }
- this->values = src.storage();
- this->wrapped = true;
- }
+using VectorXr = Vector<Real>;
+using MatrixXr = Matrix<Real>;
- /* ------------------------------------------------------------------------ */
- template <class TensorType> inline void deepCopy(const TensorType & src) {
- this->copySize(src);
+enum NormType : int8_t { L_1 = 1, L_2 = 2, L_inf = -1 };
- if (!this->wrapped) {
- delete[] this->values;
- }
+struct TensorTraitBase {};
- static_assert(std::is_trivially_constructible<T>{},
- "Cannot create a tensor on non trivial types");
- this->values = new T[this->_size]; // NOLINT
+template <size_t n> struct TensorTrait : public TensorTraitBase {};
- static_assert(std::is_trivially_copyable<T>{},
- "Cannot copy a tensor on non trivial types");
- std::copy_n(src.storage(), this->_size, this->values);
+} // namespace akantu
- this->wrapped = false;
- }
+namespace aka {
+template <typename Derived>
+using is_vector = aka::bool_constant<
+ std::remove_reference_t<std::decay_t<Derived>>::IsVectorAtCompileTime>;
+template <class V> inline constexpr bool is_vector_v = is_vector<V>::value;
- virtual ~TensorStorage() {
- if (!this->wrapped) {
- delete[] this->values;
- }
- }
+template <typename Derived> using is_matrix = aka::negation<is_vector<Derived>>;
+template <class M> inline constexpr bool is_matrix_v = is_matrix<M>::value;
- /* ------------------------------------------------------------------------ */
- inline TensorStorage & operator=(const TensorStorage & other) {
- if (this == &other) {
- return *this;
- }
- this->operator=(aka::as_type<RetType>(other));
- return *this;
- }
+template <typename... Ds>
+using are_vectors = aka::conjunction<is_vector<Ds>...>;
- // inline TensorStorage & operator=(TensorStorage && other) noexcept {
- // std::swap(n, other.n);
- // std::swap(_size, other._size);
- // std::swap(values, other.values);
- // std::swap(wrapped, other.wrapped);
- // return *this;
- // }
-
- /* ------------------------------------------------------------------------ */
- inline TensorStorage & operator=(const RetType & src) {
- if (this != &src) {
- if (this->wrapped) {
- static_assert(std::is_trivially_copyable<T>{},
- "Cannot copy a tensor on non trivial types");
- // this test is not sufficient for Tensor of order higher than 1
- AKANTU_DEBUG_ASSERT(this->_size == src.size(),
- "Tensors of different size ("
- << this->_size << " != " << src.size() << ")");
- std::copy_n(src.storage(), this->_size, this->values);
- } else {
- deepCopy(src);
- }
- }
- return *this;
- }
+template <class... Vs>
+inline constexpr bool are_vectors_v = are_vectors<Vs...>::value;
- /* ------------------------------------------------------------------------ */
- template <class R>
- inline RetType & operator+=(const TensorStorage<T, ndim, R> & other) {
- T * a = this->storage();
- T * b = other.storage();
- AKANTU_DEBUG_ASSERT(
- _size == other.size(),
- "The two tensors do not have the same size, they cannot be subtracted");
- for (UInt i = 0; i < _size; ++i) {
- *(a++) += *(b++);
- }
- return *(static_cast<RetType *>(this));
- }
+template <typename... Ds>
+using are_matrices = aka::conjunction<is_matrix<Ds>...>;
- /* ------------------------------------------------------------------------ */
- template <class R>
- inline RetType & operator-=(const TensorStorage<T, ndim, R> & other) {
- T * a = this->storage();
- T * b = other.storage();
- AKANTU_DEBUG_ASSERT(
- _size == other.size(),
- "The two tensors do not have the same size, they cannot be subtracted");
- for (UInt i = 0; i < _size; ++i) {
- *(a++) -= *(b++);
- }
- return *(static_cast<RetType *>(this));
- }
+template <class... Ms>
+inline constexpr bool are_matrices_v = are_matrices<Ms...>::value;
- /* ------------------------------------------------------------------------ */
- inline RetType & operator+=(const T & x) {
- T * a = this->values;
- for (UInt i = 0; i < _size; ++i) {
- *(a++) += x;
- }
- return *(static_cast<RetType *>(this));
- }
+template <typename... Ds>
+using enable_if_matrices_t = std::enable_if_t<are_matrices<Ds...>::value>;
- /* ------------------------------------------------------------------------ */
- inline RetType & operator-=(const T & x) {
- T * a = this->values;
- for (UInt i = 0; i < _size; ++i) {
- *(a++) -= x;
- }
- return *(static_cast<RetType *>(this));
- }
+template <typename... Ds>
+using enable_if_vectors_t = std::enable_if_t<are_vectors<Ds...>::value>;
- /* ------------------------------------------------------------------------ */
- inline RetType & operator*=(const T & x) {
- T * a = this->storage();
- for (UInt i = 0; i < _size; ++i) {
- *(a++) *= x;
- }
- return *(static_cast<RetType *>(this));
- }
+/* -------------------------------------------------------------------------- */
- /* ---------------------------------------------------------------------- */
- inline RetType & operator/=(const T & x) {
- T * a = this->values;
- for (UInt i = 0; i < _size; ++i) {
- *(a++) /= x;
- }
- return *(static_cast<RetType *>(this));
- }
+template <typename T>
+struct is_tensor : public std::is_base_of<akantu::TensorTraitBase, T> {};
- /// \f[Y = \alpha X + Y\f]
- inline RetType & aXplusY(const TensorStorage & other, const T & alpha = 1.) {
- AKANTU_DEBUG_ASSERT(
- _size == other.size(),
- "The two tensors do not have the same size, they cannot be subtracted");
+template <typename PlainObjectType, int MapOptions, typename StrideType>
+struct is_tensor<Eigen::Map<PlainObjectType, MapOptions, StrideType>>
+ : public std::true_type {};
- Math::aXplusY(this->_size, alpha, other.storage(), this->storage());
- return *(static_cast<RetType *>(this));
- }
+template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
+struct is_tensor<Eigen::Block<XprType, BlockRows, BlockCols, InnerPanel>>
+ : public std::true_type {};
- /* ------------------------------------------------------------------------ */
- T * storage() const { return values; }
- UInt size() const { return _size; }
- UInt size(UInt i) const {
- AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim
- << " dimensions, not "
- << (i + 1));
- return n[i];
- };
- /* ------------------------------------------------------------------------ */
- inline void set(const T & t) { std::fill_n(values, _size, t); };
- inline void zero() { this->set(0.); };
-
- template <class TensorType> inline void copy(const TensorType & other) {
- AKANTU_DEBUG_ASSERT(
- _size == other.size(),
- "The two tensors do not have the same size, they cannot be copied");
- std::copy_n(other.storage(), _size, values);
- }
+template <typename T, Eigen::Index m, Eigen::Index n>
+struct is_tensor<Eigen::Matrix<T, m, n>> : public std::true_type {};
- bool isWrapped() const { return this->wrapped; }
+template <typename T, size_t n>
+using is_tensor_n = std::is_base_of<akantu::TensorTrait<n>, T>;
-protected:
- inline void computeSize() {
- _size = 1;
- for (UInt d = 0; d < ndim; ++d) {
- _size *= this->n[d];
- }
- }
+template <class T> inline constexpr bool is_tensor_v = is_tensor<T>::value;
-protected:
- template <typename R, NormType norm_type> struct NormHelper {
- template <class Ten> static R norm(const Ten & ten) {
- R _norm = 0.;
- R * it = ten.storage();
- R * end = ten.storage() + ten.size();
- for (; it < end; ++it) {
- _norm += std::pow(std::abs(*it), norm_type);
- }
- return std::pow(_norm, 1. / norm_type);
- }
- }; // namespace akantu
-
- template <typename R> struct NormHelper<R, L_1> {
- template <class Ten> static R norm(const Ten & ten) {
- R _norm = 0.;
- R * it = ten.storage();
- R * end = ten.storage() + ten.size();
- for (; it < end; ++it) {
- _norm += std::abs(*it);
- }
- return _norm;
- }
- };
+template <class T, size_t n>
+inline constexpr bool is_tensor_n_v = is_tensor_n<T, n>::value;
- template <typename R> struct NormHelper<R, L_2> {
- template <class Ten> static R norm(const Ten & ten) {
- R _norm = 0.;
- R * it = ten.storage();
- R * end = ten.storage() + ten.size();
- for (; it < end; ++it) {
- _norm += *it * *it;
- }
- return sqrt(_norm);
- }
- };
+template <std::size_t n, typename T = void, typename... Ts>
+using enable_if_tensors_n = std::enable_if<
+ aka::conjunction<
+ is_tensor_n<Ts, n>...,
+ std::is_same<
+ std::common_type_t<std::decay_t<typename Ts::value_type>...>,
+ std::decay_t<typename Ts::value_type>>...>::value,
+ T>;
- template <typename R> struct NormHelper<R, L_inf> {
- template <class Ten> static R norm(const Ten & ten) {
- R _norm = 0.;
- R * it = ten.storage();
- R * end = ten.storage() + ten.size();
- for (; it < end; ++it) {
- _norm = std::max(std::abs(*it), _norm);
- }
- return _norm;
- }
- };
+template <std::size_t n, typename T = void, typename... Ts>
+using enable_if_tensors_n_t = typename enable_if_tensors_n<n, T, Ts...>::type;
-public:
- /*----------------------------------------------------------------------- */
- /// "Entrywise" norm norm<L_p> @f[ \|\boldsymbol{T}\|_p = \left(
- /// \sum_i^{n[0]}\sum_j^{n[1]}\sum_k^{n[2]} |T_{ijk}|^p \right)^{\frac{1}{p}}
- /// @f]
- template <NormType norm_type> inline T norm() const {
- return NormHelper<T, norm_type>::norm(*this);
- }
+} // namespace aka
-protected:
- std::array<UInt, ndim> n{};
- UInt _size{0};
- T * values{nullptr};
- bool wrapped{false};
-};
+namespace akantu { // fwd declaration
+template <typename T, Int ndim> class TensorBase;
+template <typename T, Int ndim> class TensorProxy;
+template <typename T, Int ndim> class Tensor;
+} // namespace akantu
/* -------------------------------------------------------------------------- */
-/* Vector */
+#include "aka_view_iterators.hh"
/* -------------------------------------------------------------------------- */
-template <typename T> class Vector : public TensorStorage<T, 1, Vector<T>> {
- using parent = TensorStorage<T, 1, Vector<T>>;
-
-public:
- using value_type = typename parent::value_type;
- using proxy = VectorProxy<T>;
-
-public:
- Vector() : parent() {}
- explicit Vector(UInt n, const T & def = T()) : parent(n, 0, 0, def) {}
- Vector(T * data, UInt n) : parent(data, n, 0, 0) {}
- Vector(const Vector & src, bool deep_copy = true) : parent(src, deep_copy) {}
- Vector(const TensorProxy<T, 1, Vector> & src) : parent(src) {}
-
- Vector(std::initializer_list<T> list) : parent(list.size(), 0, 0, T()) {
- UInt i = 0;
- for (auto val : list) {
- operator()(i++) = val;
- }
- }
-
-public:
- using iterator = types::details::vector_iterator<T &>;
- using const_iterator = types::details::vector_iterator<const T &>;
-
- iterator begin() { return iterator(this->storage()); }
- iterator end() { return iterator(this->storage() + this->size()); }
-
- const_iterator begin() const { return const_iterator(this->storage()); }
- const_iterator end() const {
- return const_iterator(this->storage() + this->size());
- }
-
-public:
- ~Vector() override = default;
-
- /* ------------------------------------------------------------------------ */
- inline Vector & operator=(const Vector & src) {
- parent::operator=(src);
- return *this;
- }
-
- inline Vector & operator=(Vector && src) noexcept = default;
-
- /* ------------------------------------------------------------------------ */
- inline T & operator()(UInt i) {
- AKANTU_DEBUG_ASSERT((i < this->n[0]),
- "Access out of the vector! "
- << "Index (" << i
- << ") is out of the vector of size (" << this->n[0]
- << ")");
- return *(this->values + i);
- }
-
- inline const T & operator()(UInt i) const {
- AKANTU_DEBUG_ASSERT((i < this->n[0]),
- "Access out of the vector! "
- << "Index (" << i
- << ") is out of the vector of size (" << this->n[0]
- << ")");
- return *(this->values + i);
- }
-
- inline T & operator[](UInt i) { return this->operator()(i); }
- inline const T & operator[](UInt i) const { return this->operator()(i); }
-
- /* ------------------------------------------------------------------------ */
- inline Vector<T> & operator*=(Real x) { return parent::operator*=(x); }
- inline Vector<T> & operator/=(Real x) { return parent::operator/=(x); }
- /* ------------------------------------------------------------------------ */
- inline Vector<T> & operator*=(const Vector<T> & vect) {
- AKANTU_DEBUG_ASSERT(this->_size == vect._size,
- "The vectors have non matching sizes");
- T * a = this->storage();
- T * b = vect.storage();
- for (UInt i = 0; i < this->_size; ++i) {
- *(a++) *= *(b++);
- }
- return *this;
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real dot(const Vector<T> & vect) const {
- return Math::vectorDot(this->values, vect.storage(), this->_size);
- }
-
- /* ------------------------------------------------------------------------ */
- inline Real mean() const {
- Real mean = 0;
- T * a = this->storage();
- for (UInt i = 0; i < this->_size; ++i) {
- mean += *(a++);
- }
- return mean / this->_size;
- }
-
- /* ------------------------------------------------------------------------ */
- inline Vector & crossProduct(const Vector<T> & v1, const Vector<T> & v2) {
- AKANTU_DEBUG_ASSERT(this->size() == 3,
- "crossProduct is only defined in 3D (n=" << this->size()
- << ")");
- AKANTU_DEBUG_ASSERT(
- this->size() == v1.size() && this->size() == v2.size(),
- "crossProduct is not a valid operation non matching size vectors");
- Math::vectorProduct3(v1.storage(), v2.storage(), this->values);
- return *this;
- }
-
- inline Vector crossProduct(const Vector<T> & v) {
- Vector<T> tmp(this->size());
- tmp.crossProduct(*this, v);
- return tmp;
- }
-
- /* ------------------------------------------------------------------------ */
- inline void solve(const Matrix<T> & A, const Vector<T> & b) {
- AKANTU_DEBUG_ASSERT(
- this->size() == A.rows() && this->_size == A.cols(),
- "The size of the solution vector mismatches the size of the matrix");
- AKANTU_DEBUG_ASSERT(
- this->_size == b._size,
- "The rhs vector has a mismatch in size with the matrix");
- Math::solve(this->_size, A.storage(), this->values, b.storage());
- }
-
- /* ------------------------------------------------------------------------ */
- template <bool tr_A>
- inline void mul(const Matrix<T> & A, const Vector<T> & x, T alpha = T(1));
- /* ------------------------------------------------------------------------ */
- inline Real norm() const { return parent::template norm<L_2>(); }
-
- template <NormType nt> inline Real norm() const {
- return parent::template norm<nt>();
- }
-
- /* ------------------------------------------------------------------------ */
- inline Vector<Real> & normalize() {
- Real n = norm();
- operator/=(n);
- return *this;
- }
-
- /* ------------------------------------------------------------------------ */
- /// norm of (*this - x)
- inline Real distance(const Vector<T> & y) const {
- Real * vx = this->values;
- Real * vy = y.storage();
- Real sum_2 = 0;
- for (UInt i = 0; i < this->_size; ++i, ++vx, ++vy) { // NOLINT
- sum_2 += (*vx - *vy) * (*vx - *vy);
- }
- return sqrt(sum_2);
- }
-
- /* ------------------------------------------------------------------------ */
- inline bool equal(const Vector<T> & v,
- Real tolerance = Math::getTolerance()) const {
- T * a = this->storage();
- T * b = v.storage();
- UInt i = 0;
- while (i < this->_size && (std::abs(*(a++) - *(b++)) < tolerance)) {
- ++i;
- }
- return i == this->_size;
- }
-
- /* ------------------------------------------------------------------------ */
- inline short compare(const Vector<T> & v,
- Real tolerance = Math::getTolerance()) const {
- T * a = this->storage();
- T * b = v.storage();
- for (UInt i(0); i < this->_size; ++i, ++a, ++b) {
- if (std::abs(*a - *b) > tolerance) {
- return (((*a - *b) > tolerance) ? 1 : -1);
- }
- }
- return 0;
- }
-
- /* ------------------------------------------------------------------------ */
- inline bool operator==(const Vector<T> & v) const { return equal(v); }
- inline bool operator!=(const Vector<T> & v) const { return !operator==(v); }
- inline bool operator<(const Vector<T> & v) const { return compare(v) == -1; }
- inline bool operator>(const Vector<T> & v) const { return compare(v) == 1; }
-
- template <typename Func, typename Acc>
- decltype(auto) accumulate(const Vector<T> & v, Acc && accumulator,
- Func && func) const {
- T * a = this->storage();
- T * b = v.storage();
- for (UInt i(0); i < this->_size; ++i, ++a, ++b) {
- accumulator = func(*a, *b, std::forward<Acc>(accumulator));
- }
- return accumulator;
- }
-
- inline bool operator<=(const Vector<T> & v) const {
- bool res = true;
- return accumulate(v, res, [](auto && a, auto && b, auto && accumulator) {
- return accumulator & (a <= b);
- });
- }
-
- inline bool operator>=(const Vector<T> & v) const {
- bool res = true;
- return accumulate(v, res, [](auto && a, auto && b, auto && accumulator) {
- return accumulator & (a >= b);
- });
- }
-
- /* ------------------------------------------------------------------------ */
- /// function to print the containt of the class
- virtual void printself(std::ostream & stream, int indent = 0) const {
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
-
- stream << "[";
- for (UInt i = 0; i < this->_size; ++i) {
- if (i != 0) {
- stream << ", ";
- }
- stream << this->values[i];
- }
- stream << "]";
- }
-
- /* ---------------------------------------------------------------------- */
- static inline Vector<T> zeros(UInt n) {
- Vector<T> tmp(n);
- tmp.set(T());
- return tmp;
- }
-};
-
-using RVector = Vector<Real>;
-
-/* ------------------------------------------------------------------------ */
-template <>
-inline bool Vector<UInt>::equal(const Vector<UInt> & v,
- __attribute__((unused)) Real tolerance) const {
- UInt * a = this->storage();
- UInt * b = v.storage();
- UInt i = 0;
- while (i < this->_size && (*(a++) == *(b++))) {
- ++i;
- }
- return i == this->_size;
-}
-
+#include "aka_tensor.hh"
/* -------------------------------------------------------------------------- */
-namespace types {
- namespace details {
- template <typename Mat> class column_iterator {
- public:
- using difference_type = std::ptrdiff_t;
- using value_type = decltype(std::declval<Mat>().operator()(0));
- using pointer = value_type *;
- using reference = value_type &;
- using iterator_category = std::input_iterator_tag;
-
- column_iterator(Mat & mat, UInt col) : mat(mat), col(col) {}
- decltype(auto) operator*() { return mat(col); }
- decltype(auto) operator++() {
- ++col;
- AKANTU_DEBUG_ASSERT(col <= mat.cols(), "The iterator is out of bound");
- return *this;
- }
- decltype(auto) operator++(int) {
- auto tmp = *this;
- ++col;
- AKANTU_DEBUG_ASSERT(col <= mat.cols(), "The iterator is out of bound");
- return tmp;
- }
- bool operator!=(const column_iterator & other) const {
- return col != other.col;
- }
-
- bool operator==(const column_iterator & other) const {
- return not operator!=(other);
- }
-
- private:
- Mat & mat;
- UInt col;
- };
- } // namespace details
-} // namespace types
-
-/* ------------------------------------------------------------------------ */
-/* Matrix */
-/* ------------------------------------------------------------------------ */
-template <typename T> class Matrix : public TensorStorage<T, 2, Matrix<T>> {
- using parent = TensorStorage<T, 2, Matrix<T>>;
-
-public:
- using value_type = typename parent::value_type;
- using proxy = MatrixProxy<T>;
-
-public:
- Matrix() : parent() {}
- Matrix(UInt m, UInt n, const T & def = T()) : parent(m, n, 0, def) {}
- Matrix(T * data, UInt m, UInt n) : parent(data, m, n, 0) {}
- Matrix(const Matrix & src, bool deep_copy = true) : parent(src, deep_copy) {}
- Matrix(const MatrixProxy<T> & src) : parent(src) {}
- Matrix(std::initializer_list<std::initializer_list<T>> list) {
- static_assert(std::is_trivially_copyable<T>{},
- "Cannot create a tensor on non trivial types");
- std::size_t n = 0;
- std::size_t m = list.size();
- for (auto row : list) {
- n = std::max(n, row.size());
- }
-
- DimHelper<2>::setDims(m, n, 0, this->n);
- this->computeSize();
- this->values = new T[this->_size];
- this->set(0);
-
- UInt i{0};
- UInt j{0};
- for (auto & row : list) {
- for (auto & val : row) {
- at(i, j++) = val;
- }
- ++i;
- j = 0;
- }
- }
-
- ~Matrix() override = default;
- /* ------------------------------------------------------------------------ */
- inline Matrix & operator=(const Matrix & src) {
- parent::operator=(src);
- return *this;
- }
-
- inline Matrix & operator=(Matrix && src) noexcept = default;
-
-public:
- /* ---------------------------------------------------------------------- */
- UInt rows() const { return this->n[0]; }
- UInt cols() const { return this->n[1]; }
-
- /* ---------------------------------------------------------------------- */
- inline T & at(UInt i, UInt j) {
- AKANTU_DEBUG_ASSERT(((i < this->n[0]) && (j < this->n[1])),
- "Access out of the matrix! "
- << "Index (" << i << ", " << j
- << ") is out of the matrix of size (" << this->n[0]
- << ", " << this->n[1] << ")");
- return *(this->values + i + j * this->n[0]);
- }
- inline const T & at(UInt i, UInt j) const {
- AKANTU_DEBUG_ASSERT(((i < this->n[0]) && (j < this->n[1])),
- "Access out of the matrix! "
- << "Index (" << i << ", " << j
- << ") is out of the matrix of size (" << this->n[0]
- << ", " << this->n[1] << ")");
- return *(this->values + i + j * this->n[0]);
- }
+namespace akantu {
- /* ------------------------------------------------------------------------ */
- inline T & operator()(UInt i, UInt j) { return this->at(i, j); }
- inline const T & operator()(UInt i, UInt j) const { return this->at(i, j); }
-
- /// give a line vector wrapped on the column i
- inline VectorProxy<T> operator()(UInt j) {
- AKANTU_DEBUG_ASSERT(j < this->n[1],
- "Access out of the matrix! "
- << "You are trying to access the column vector "
- << j << " in a matrix of size (" << this->n[0]
- << ", " << this->n[1] << ")");
- return VectorProxy<T>(this->values + j * this->n[0], this->n[0]);
- }
+class ArrayBase;
- inline VectorProxy<T> operator()(UInt j) const {
- AKANTU_DEBUG_ASSERT(j < this->n[1],
- "Access out of the matrix! "
- << "You are trying to access the column vector "
- << j << " in a matrix of size (" << this->n[0]
- << ", " << this->n[1] << ")");
- return VectorProxy<T>(this->values + j * this->n[0], this->n[0]);
- }
+/* -------------------------------------------------------------------------- */
+namespace details {
+ template <typename T> struct MapPlainObjectType { using type = T; };
-public:
- decltype(auto) begin() {
- return types::details::column_iterator<Matrix<T>>(*this, 0);
- }
- decltype(auto) begin() const {
- return types::details::column_iterator<const Matrix<T>>(*this, 0);
- }
+ template <typename PlainObjectType, int MapOptions, typename StrideType>
+ struct MapPlainObjectType<
+ Eigen::Map<PlainObjectType, MapOptions, StrideType>> {
+ using type = PlainObjectType;
+ };
- decltype(auto) end() {
- return types::details::column_iterator<Matrix<T>>(*this, this->cols());
- }
- decltype(auto) end() const {
- return types::details::column_iterator<const Matrix<T>>(*this,
- this->cols());
- }
+ template <typename T>
+ using MapPlainObjectType_t = typename MapPlainObjectType<T>::type;
- /* ------------------------------------------------------------------------ */
- inline void block(const Matrix & block, UInt pos_i, UInt pos_j) {
- AKANTU_DEBUG_ASSERT(pos_i + block.rows() <= rows(),
- "The block size or position are not correct");
- AKANTU_DEBUG_ASSERT(pos_i + block.cols() <= cols(),
- "The block size or position are not correct");
- for (UInt i = 0; i < block.rows(); ++i) {
- for (UInt j = 0; j < block.cols(); ++j) {
- this->at(i + pos_i, j + pos_j) = block(i, j);
- }
- }
- }
+ template <typename Scalar, Idx...> struct EigenMatrixViewHelper {};
- inline Matrix block(UInt pos_i, UInt pos_j, UInt block_rows,
- UInt block_cols) const {
- AKANTU_DEBUG_ASSERT(pos_i + block_rows <= rows(),
- "The block size or position are not correct");
- AKANTU_DEBUG_ASSERT(pos_i + block_cols <= cols(),
- "The block size or position are not correct");
- Matrix block(block_rows, block_cols);
- for (UInt i = 0; i < block_rows; ++i) {
- for (UInt j = 0; j < block_cols; ++j) {
- block(i, j) = this->at(i + pos_i, j + pos_j);
- }
- }
- return block;
- }
-
- inline T & operator[](UInt idx) { return *(this->values + idx); };
- inline const T & operator[](UInt idx) const { return *(this->values + idx); };
+ template <typename Scalar, Idx RowsAtCompileTime>
+ struct EigenMatrixViewHelper<Scalar, RowsAtCompileTime> {
+ using type = Eigen::Matrix<Scalar, RowsAtCompileTime, 1>;
+ };
- /* ---------------------------------------------------------------------- */
- inline Matrix operator*(const Matrix & B) const {
- Matrix C(this->rows(), B.cols());
- C.mul<false, false>(*this, B);
- return C;
- }
+ template <typename Scalar, Idx RowsAtCompileTime, Idx ColsAtCompileTime>
+ struct EigenMatrixViewHelper<Scalar, RowsAtCompileTime, ColsAtCompileTime> {
+ using type = Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>;
+ };
- /* ----------------------------------------------------------------------- */
- inline Matrix & operator*=(const T & x) { return parent::operator*=(x); }
+ template <typename Scalar, Idx... sizes>
+ using EigenMatrixViewHelper_t =
+ typename EigenMatrixViewHelper<Scalar, sizes...>::type;
- inline Matrix & operator*=(const Matrix & B) {
- Matrix C(*this);
- this->mul<false, false>(C, B);
- return *this;
- }
+ template <typename Array, Idx... sizes> class EigenView {
+ static_assert(sizeof...(sizes) == 1 or sizeof...(sizes) == 2,
+ "Eigen only supports Vector and Matrices");
- /* ---------------------------------------------------------------------- */
- template <bool tr_A, bool tr_B>
- inline void mul(const Matrix & A, const Matrix & B, T alpha = 1.0) {
- UInt k = A.cols();
- if (tr_A) {
- k = A.rows();
+ private:
+ template <
+ class A = Array,
+ std::enable_if_t<aka::is_array<std::decay_t<A>>::value> * = nullptr>
+ auto array_size() const {
+ return array.get().size() * array.get().getNbComponent();
}
-#ifndef AKANTU_NDEBUG
- if (tr_B) {
- AKANTU_DEBUG_ASSERT(k == B.cols(),
- "matrices to multiply have no fit dimensions");
- AKANTU_DEBUG_ASSERT(this->cols() == B.rows(),
- "matrices to multiply have no fit dimensions");
- } else {
- AKANTU_DEBUG_ASSERT(k == B.rows(),
- "matrices to multiply have no fit dimensions");
- AKANTU_DEBUG_ASSERT(this->cols() == B.cols(),
- "matrices to multiply have no fit dimensions");
- }
- if (tr_A) {
- AKANTU_DEBUG_ASSERT(this->rows() == A.cols(),
- "matrices to multiply have no fit dimensions");
- } else {
- AKANTU_DEBUG_ASSERT(this->rows() == A.rows(),
- "matrices to multiply have no fit dimensions");
+ template <
+ class A = Array,
+ std::enable_if_t<not aka::is_array<std::decay_t<A>>::value> * = nullptr>
+ auto array_size() const {
+ return array.get().size();
}
-#endif // AKANTU_NDEBUG
- Math::matMul<tr_A, tr_B>(this->rows(), this->cols(), k, alpha, A.storage(),
- B.storage(), 0., this->storage());
- }
+ using ArrayRef_t = decltype(std::ref(std::declval<Array>()));
- /* ---------------------------------------------------------------------- */
- inline void outerProduct(const Vector<T> & A, const Vector<T> & B) {
- AKANTU_DEBUG_ASSERT(
- A.size() == this->rows() && B.size() == this->cols(),
- "A and B are not compatible with the size of the matrix");
- for (UInt i = 0; i < this->rows(); ++i) {
- for (UInt j = 0; j < this->cols(); ++j) {
- this->values[i + j * this->rows()] += A[i] * B[j];
- }
- }
- }
-
-private:
- class EigenSorter {
public:
- EigenSorter(const Vector<T> & eigs) : eigs(eigs) {}
+ using size_type = typename std::decay_t<Array>::size_type;
+ using value_type = typename std::decay_t<Array>::value_type;
- bool operator()(const UInt & a, const UInt & b) const {
- return (eigs(a) > eigs(b));
- }
+ EigenView(Array && array, decltype(sizes)... sizes_)
+ : array(std::ref(array)), sizes_(sizes_...) {}
- private:
- const Vector<T> & eigs;
- };
+ EigenView(Array && array) : array(array), sizes_(sizes...) {}
-public:
- /* ---------------------------------------------------------------------- */
- inline void eig(Vector<T> & eigenvalues, Matrix<T> & eigenvectors,
- bool sort = true) const {
- AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
- "eig is not a valid operation on a rectangular matrix");
- AKANTU_DEBUG_ASSERT(eigenvalues.size() == this->cols(),
- "eigenvalues should be of size " << this->cols()
- << ".");
-#ifndef AKANTU_NDEBUG
- if (eigenvectors.storage() != nullptr) {
- AKANTU_DEBUG_ASSERT((eigenvectors.rows() == eigenvectors.cols()) &&
- (eigenvectors.rows() == this->cols()),
- "Eigenvectors needs to be a square matrix of size "
- << this->cols() << " x " << this->cols() << ".");
- }
-#endif
+ EigenView(const EigenView & other) = default;
+ EigenView(EigenView && other) noexcept = default;
- Matrix<T> tmp = *this;
- Vector<T> tmp_eigs(eigenvalues.size());
- Matrix<T> tmp_eig_vects(eigenvectors.rows(), eigenvectors.cols());
+ auto operator=(const EigenView & other) -> EigenView & = default;
+ auto operator=(EigenView && other) noexcept -> EigenView & = default;
- if (tmp_eig_vects.rows() == 0 || tmp_eig_vects.cols() == 0) {
- Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage());
- } else {
- Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage(),
- tmp_eig_vects.storage());
+ template <typename T = value_type,
+ std::enable_if_t<not std::is_const<T>::value> * = nullptr>
+ decltype(auto) begin() {
+ return aka::make_from_tuple<::akantu::view_iterator<
+ Eigen::Map<EigenMatrixViewHelper_t<value_type, sizes...>>>>(
+ std::tuple_cat(std::make_tuple(array.get().data()), sizes_));
}
- if (not sort) {
- eigenvalues = tmp_eigs;
- eigenvectors = tmp_eig_vects;
- return;
+ template <typename T = value_type,
+ std::enable_if_t<not std::is_const<T>::value> * = nullptr>
+ decltype(auto) end() {
+ return aka::make_from_tuple<::akantu::view_iterator<
+ Eigen::Map<EigenMatrixViewHelper_t<value_type, sizes...>>>>(
+ std::tuple_cat(std::make_tuple(array.get().data() + array_size()),
+ sizes_));
}
- Vector<UInt> perm(eigenvalues.size());
- for (UInt i = 0; i < perm.size(); ++i) {
- perm(i) = i;
+ decltype(auto) begin() const {
+ return aka::make_from_tuple<::akantu::view_iterator<
+ Eigen::Map<const EigenMatrixViewHelper_t<value_type, sizes...>>>>(
+ std::tuple_cat(std::make_tuple(array.get().data()), sizes_));
}
-
- std::sort(perm.storage(), perm.storage() + perm.size(),
- EigenSorter(tmp_eigs));
-
- for (UInt i = 0; i < perm.size(); ++i) {
- eigenvalues(i) = tmp_eigs(perm(i));
+ decltype(auto) end() const {
+ return aka::make_from_tuple<::akantu::view_iterator<
+ Eigen::Map<const EigenMatrixViewHelper_t<value_type, sizes...>>>>(
+ std::tuple_cat(std::make_tuple(array.get().data() + array_size()),
+ sizes_));
}
- if (tmp_eig_vects.rows() != 0 && tmp_eig_vects.cols() != 0) {
- for (UInt i = 0; i < perm.size(); ++i) {
- for (UInt j = 0; j < eigenvectors.rows(); ++j) {
- eigenvectors(j, i) = tmp_eig_vects(j, perm(i));
- }
- }
- }
- }
-
- /* ---------------------------------------------------------------------- */
- inline void eig(Vector<T> & eigenvalues) const {
- Matrix<T> empty;
- eig(eigenvalues, empty);
- }
+ private:
+ ArrayRef_t array;
+ std::tuple<decltype(sizes)...> sizes_;
+ };
- /* ---------------------------------------------------------------------- */
- inline void eye(T alpha = 1.) {
- AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
- "eye is not a valid operation on a rectangular matrix");
- this->zero();
- for (UInt i = 0; i < this->cols(); ++i) {
- this->values[i + i * this->rows()] = alpha;
- }
- }
+} // namespace details
- /* ---------------------------------------------------------------------- */
- static inline Matrix<T> eye(UInt m, T alpha = 1.) {
- Matrix<T> tmp(m, m);
- tmp.eye(alpha);
- return tmp;
- }
+template <Idx RowsAtCompileTime, typename Array>
+decltype(auto) make_view(Array && array, Idx rows = RowsAtCompileTime) {
+ return details::EigenView<Array, RowsAtCompileTime>(
+ std::forward<Array>(array), rows);
+}
- /* ---------------------------------------------------------------------- */
- inline T trace() const {
- AKANTU_DEBUG_ASSERT(
- this->cols() == this->rows(),
- "trace is not a valid operation on a rectangular matrix");
- T trace = 0.;
- for (UInt i = 0; i < this->rows(); ++i) {
- trace += this->values[i + i * this->rows()];
- }
- return trace;
- }
+template <Idx RowsAtCompileTime, Idx ColsAtCompileTime, typename Array>
+decltype(auto) make_view(Array && array, Idx rows = RowsAtCompileTime,
+ Idx cols = ColsAtCompileTime) {
+ return details::EigenView<Array, RowsAtCompileTime, ColsAtCompileTime>(
+ std::forward<Array>(array), rows, cols);
+}
- /* ---------------------------------------------------------------------- */
- inline Matrix transpose() const {
- Matrix tmp(this->cols(), this->rows());
- for (UInt i = 0; i < this->rows(); ++i) {
- for (UInt j = 0; j < this->cols(); ++j) {
- tmp(j, i) = operator()(i, j);
- }
- }
- return tmp;
- }
+template <Idx RowsAtCompileTime, typename Array>
+decltype(auto) make_const_view(const Array & array,
+ Idx rows = RowsAtCompileTime) {
+ return make_view<RowsAtCompileTime>(array, rows);
+}
- /* ---------------------------------------------------------------------- */
- inline void inverse(const Matrix & A) {
- AKANTU_DEBUG_ASSERT(A.cols() == A.rows(),
- "inv is not a valid operation on a rectangular matrix");
- AKANTU_DEBUG_ASSERT(this->cols() == A.cols(),
- "the matrix should have the same size as its inverse");
-
- if (this->cols() == 1) {
- *this->values = 1. / *A.storage();
- } else if (this->cols() == 2) {
- Math::inv2(A.storage(), this->values);
- } else if (this->cols() == 3) {
- Math::inv3(A.storage(), this->values);
- } else {
- Math::inv(this->cols(), A.storage(), this->values);
- }
- }
+template <Idx RowsAtCompileTime, Idx ColsAtCompileTime, typename Array>
+decltype(auto) make_const_view(const Array & array,
+ Idx rows = RowsAtCompileTime,
+ Idx cols = ColsAtCompileTime) {
+ return make_view<RowsAtCompileTime, ColsAtCompileTime>(array, rows, cols);
+}
- inline Matrix inverse() {
- Matrix inv(this->rows(), this->cols());
- inv.inverse(*this);
- return inv;
- }
+} // namespace akantu
- /* --------------------------------------------------------------------- */
- inline T det() const {
- AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
- "inv is not a valid operation on a rectangular matrix");
- if (this->cols() == 1) {
- return *(this->values);
- }
- if (this->cols() == 2) {
- return Math::det2(this->values);
- }
- if (this->cols() == 3) {
- return Math::det3(this->values);
- }
- return Math::det(this->cols(), this->values);
- }
+namespace Eigen {
- /* --------------------------------------------------------------------- */
- inline T doubleDot(const Matrix<T> & other) const {
- AKANTU_DEBUG_ASSERT(
- this->cols() == this->rows(),
- "doubleDot is not a valid operation on a rectangular matrix");
- if (this->cols() == 1) {
- return *(this->values) * *(other.storage());
- }
- if (this->cols() == 2) {
- return Math::matrixDoubleDot22(this->values, other.storage());
- }
- if (this->cols() == 3) {
- return Math::matrixDoubleDot33(this->values, other.storage());
- }
+template <typename Derived>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::zero() {
+ return this->fill(0.);
+}
- AKANTU_ERROR("doubleDot is not defined for other spatial dimensions"
- << " than 1, 2 or 3.");
- }
+/* -------------------------------------------------------------------------- */
+/* Vector */
+/* -------------------------------------------------------------------------- */
+template <typename Derived>
+template <typename ED, typename T,
+ std::enable_if_t<not std::is_const<T>::value and
+ ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::begin() {
+ return ::akantu::view_iterator<typename Derived::Scalar>(
+ this->derived().data());
+}
- /* ---------------------------------------------------------------------- */
- /// function to print the containt of the class
- virtual void printself(std::ostream & stream, int indent = 0) const {
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+template <typename Derived>
+template <typename ED, typename T,
+ std::enable_if_t<not std::is_const<T>::value and
+ ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::end() {
+ return ::akantu::view_iterator<typename Derived::Scalar>(
+ this->derived().data() + this->size());
+}
- stream << "[";
- for (UInt i = 0; i < this->n[0]; ++i) {
- if (i != 0) {
- stream << ", ";
- }
- stream << "[";
- for (UInt j = 0; j < this->n[1]; ++j) {
- if (j != 0) {
- stream << ", ";
- }
- stream << operator()(i, j);
- }
- stream << "]";
- }
- stream << "]";
- };
-};
+template <typename Derived>
+template <typename ED, std::enable_if_t<ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::begin() const {
+ using Scalar = typename Derived::Scalar;
+ return ::akantu::const_view_iterator<Scalar>(this->derived().data());
+}
-/* ------------------------------------------------------------------------ */
-template <typename T>
-template <bool tr_A>
-inline void Vector<T>::mul(const Matrix<T> & A, const Vector<T> & x, T alpha) {
-#ifndef AKANTU_NDEBUG
- UInt n = x.size();
- if (tr_A) {
- AKANTU_DEBUG_ASSERT(n == A.rows(),
- "matrix and vector to multiply have no fit dimensions");
- AKANTU_DEBUG_ASSERT(this->size() == A.cols(),
- "matrix and vector to multiply have no fit dimensions");
- } else {
- AKANTU_DEBUG_ASSERT(n == A.cols(),
- "matrix and vector to multiply have no fit dimensions");
- AKANTU_DEBUG_ASSERT(this->size() == A.rows(),
- "matrix and vector to multiply have no fit dimensions");
- }
-#endif
- Math::matVectMul<tr_A>(A.rows(), A.cols(), alpha, A.storage(), x.storage(),
- 0., this->storage());
+template <typename Derived>
+template <typename ED, std::enable_if_t<ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::end() const {
+ using Scalar = typename Derived::Scalar;
+ return ::akantu::const_view_iterator<Scalar>(this->derived().data() +
+ this->size());
}
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline std::ostream & operator<<(std::ostream & stream,
- const Matrix<T> & _this) {
- _this.printself(stream);
- return stream;
+/* Matrix */
+/* -------------------------------------------------------------------------- */
+template <typename Derived>
+template <typename ED, typename T,
+ std::enable_if_t<not std::is_const<T>::value and
+ not ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::begin() {
+ return ::akantu::view_iterator<
+ Map<Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, 1>>>(
+ this->derived().data(), this->rows());
}
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline std::ostream & operator<<(std::ostream & stream,
- const Vector<T> & _this) {
- _this.printself(stream);
- return stream;
+template <typename Derived>
+template <typename ED, typename T,
+ std::enable_if_t<not std::is_const<T>::value and
+ not ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::end() {
+ return ::akantu::view_iterator<
+ Map<Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, 1>>>(
+ this->derived().data() + this->size(), this->rows());
}
-/* ------------------------------------------------------------------------ */
-/* Tensor3 */
-/* ------------------------------------------------------------------------ */
-template <typename T> class Tensor3 : public TensorStorage<T, 3, Tensor3<T>> {
- using parent = TensorStorage<T, 3, Tensor3<T>>;
+template <typename Derived>
+template <typename ED, std::enable_if_t<not ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::begin() const {
+ using Scalar = typename Derived::Scalar;
+ return ::akantu::const_view_iterator<
+ Map<const Matrix<Scalar, Derived::RowsAtCompileTime, 1>>>(
+ const_cast<Scalar *>(this->derived().data()), this->rows());
+}
-public:
- using value_type = typename parent::value_type;
- using proxy = Tensor3Proxy<T>;
+template <typename Derived>
+template <typename ED, std::enable_if_t<not ED::IsVectorAtCompileTime> *>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto)
+MatrixBase<Derived>::end() const {
+ using Scalar = typename Derived::Scalar;
+ return ::akantu::const_view_iterator<
+ Map<const Matrix<Scalar, Derived::RowsAtCompileTime, 1>>>(
+ const_cast<Scalar *>(this->derived().data()) + this->size(),
+ this->rows());
+}
-public:
- Tensor3() : parent(){};
+template <typename Derived>
+template <typename OtherDerived>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
+MatrixBase<Derived>::eig(MatrixBase<OtherDerived> & values) const {
+ EigenSolver<akantu::details::MapPlainObjectType_t<std::decay_t<Derived>>>
+ solver(*this, false);
+ using OtherScalar = typename OtherDerived::Scalar;
+
+ // as advised by the Eigen developers even though this is a UB
+ // auto & values = const_cast<MatrixBase<OtherDerived> &>(values_);
+ if constexpr (std::is_floating_point<OtherScalar>{}) {
+ values = solver.eigenvalues().real();
+ } else {
+ values = solver.eigenvalues();
+ }
+}
- Tensor3(UInt m, UInt n, UInt p, const T & def = T()) : parent(m, n, p, def) {}
+template <typename Derived>
+template <typename D1, typename D2>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
+MatrixBase<Derived>::eig(MatrixBase<D1> & values, MatrixBase<D2> & vectors,
+ bool sort) const {
+ EigenSolver<akantu::details::MapPlainObjectType_t<std::decay_t<Derived>>>
+ solver(*this, true);
- Tensor3(T * data, UInt m, UInt n, UInt p) : parent(data, m, n, p) {}
+ // as advised by the Eigen developers even though this is a UB
+ // auto & values = const_cast<MatrixBase<D1> &>(values_);
+ // auto & vectors = const_cast<MatrixBase<D2> &>(vectors_);
- Tensor3(const Tensor3 & src, bool deep_copy = true)
- : parent(src, deep_copy) {}
+ auto norm = this->norm();
- Tensor3(const proxy & src) : parent(src) {}
+ using OtherScalar = typename D1::Scalar;
-public:
- /* ------------------------------------------------------------------------ */
- inline Tensor3 & operator=(const Tensor3 & src) {
- parent::operator=(src);
- return *this;
+ if ((solver.eigenvectors().imag().template lpNorm<Infinity>() >
+ 1e-15 * norm) and
+ std::is_floating_point<OtherScalar>::value) {
+ AKANTU_EXCEPTION("This matrix has complex eigenvectors()");
}
- /* ---------------------------------------------------------------------- */
- inline T & operator()(UInt i, UInt j, UInt k) {
- AKANTU_DEBUG_ASSERT(
- (i < this->n[0]) && (j < this->n[1]) && (k < this->n[2]),
- "Access out of the tensor3! "
- << "You are trying to access the element "
- << "(" << i << ", " << j << ", " << k << ") in a tensor of size ("
- << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")");
- return *(this->values + (k * this->n[0] + i) * this->n[1] + j);
+ if (not sort) {
+ if constexpr (std::is_floating_point<OtherScalar>{}) {
+ values = solver.eigenvalues().real();
+ vectors = solver.eigenvectors().real();
+ } else {
+ values = solver.eigenvalues();
+ vectors = solver.eigenvectors();
+ }
+ return;
}
- inline const T & operator()(UInt i, UInt j, UInt k) const {
- AKANTU_DEBUG_ASSERT(
- (i < this->n[0]) && (j < this->n[1]) && (k < this->n[2]),
- "Access out of the tensor3! "
- << "You are trying to access the element "
- << "(" << i << ", " << j << ", " << k << ") in a tensor of size ("
- << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")");
- return *(this->values + (k * this->n[0] + i) * this->n[1] + j);
+ if (not std::is_floating_point<OtherScalar>::value) {
+ AKANTU_EXCEPTION("Cannot sort complex eigen values");
}
- inline MatrixProxy<T> operator()(UInt k) {
- AKANTU_DEBUG_ASSERT((k < this->n[2]),
- "Access out of the tensor3! "
- << "You are trying to access the slice " << k
- << " in a tensor3 of size (" << this->n[0] << ", "
- << this->n[1] << ", " << this->n[2] << ")");
- return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
- this->n[0], this->n[1]);
- }
+ values = solver.eigenvalues().real();
- inline MatrixProxy<T> operator()(UInt k) const {
- AKANTU_DEBUG_ASSERT((k < this->n[2]),
- "Access out of the tensor3! "
- << "You are trying to access the slice " << k
- << " in a tensor3 of size (" << this->n[0] << ", "
- << this->n[1] << ", " << this->n[2] << ")");
- return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
- this->n[0], this->n[1]);
- }
+ PermutationMatrix<Dynamic> P(values.size());
+ P.setIdentity();
- inline MatrixProxy<T> operator[](UInt k) {
- return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
- this->n[0], this->n[1]);
- }
+ std::sort(P.indices().data(), P.indices().data() + P.indices().size(),
+ [&values](const Index & a, const Index & b) {
+ return (values(a) - values(b)) > 0;
+ });
- inline MatrixProxy<T> operator[](UInt k) const {
- return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
- this->n[0], this->n[1]);
+ if constexpr (std::is_floating_point<OtherScalar>{}) {
+ values = P.transpose() * values;
+ vectors = solver.eigenvectors().real() * P;
}
-};
-
-/* -------------------------------------------------------------------------- */
-// support operations for the creation of other vectors
-/* -------------------------------------------------------------------------- */
-template <typename T>
-Vector<T> operator*(const T & scalar, const Vector<T> & a) {
- Vector<T> r(a);
- r *= scalar;
- return r;
+ return;
}
-template <typename T>
-Vector<T> operator*(const Vector<T> & a, const T & scalar) {
- Vector<T> r(a);
- r *= scalar;
- return r;
+template <typename Derived>
+template <typename OtherDerived>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
+MatrixBase<Derived>::eigh(const MatrixBase<OtherDerived> & values_) const {
+ SelfAdjointEigenSolver<
+ akantu::details::MapPlainObjectType_t<std::decay_t<Derived>>>
+ solver(*this, EigenvaluesOnly);
+ // as advised by the Eigen developers even though this is a UB
+ auto & values = const_cast<MatrixBase<OtherDerived> &>(values_);
+ values = solver.eigenvalues();
}
-template <typename T>
-Vector<T> operator/(const Vector<T> & a, const T & scalar) {
- Vector<T> r(a);
- r /= scalar;
- return r;
-}
+template <typename Derived>
+template <typename D1, typename D2>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
+MatrixBase<Derived>::eigh(const MatrixBase<D1> & values_,
+ const MatrixBase<D2> & vectors_, bool sort) const {
+ SelfAdjointEigenSolver<
+ akantu::details::MapPlainObjectType_t<std::decay_t<Derived>>>
+ solver(*this, ComputeEigenvectors);
-template <typename T>
-Vector<T> operator*(const Vector<T> & a, const Vector<T> & b) {
- Vector<T> r(a);
- r *= b;
- return r;
-}
-
-template <typename T>
-Vector<T> operator+(const Vector<T> & a, const Vector<T> & b) {
- Vector<T> r(a);
- r += b;
- return r;
-}
-
-template <typename T>
-Vector<T> operator-(const Vector<T> & a, const Vector<T> & b) {
- Vector<T> r(a);
- r -= b;
- return r;
-}
+ // as advised by the Eigen developers, even though this is a UB
+ auto & values = const_cast<MatrixBase<D1> &>(values_);
+ auto & vectors = const_cast<MatrixBase<D2> &>(vectors_);
-template <typename T>
-Vector<T> operator*(const Matrix<T> & A, const Vector<T> & b) {
- Vector<T> r(b.size());
- r.template mul<false>(A, b);
- return r;
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-Matrix<T> operator*(const T & scalar, const Matrix<T> & a) {
- Matrix<T> r(a);
- r *= scalar;
- return r;
-}
-
-template <typename T>
-Matrix<T> operator*(const Matrix<T> & a, const T & scalar) {
- Matrix<T> r(a);
- r *= scalar;
- return r;
-}
+ if (not sort) {
+ values = solver.eigenvalues();
+ vectors = solver.eigenvectors();
+ return;
+ }
-template <typename T>
-Matrix<T> operator/(const Matrix<T> & a, const T & scalar) {
- Matrix<T> r(a);
- r /= scalar;
- return r;
-}
+ values = solver.eigenvalues();
+ PermutationMatrix<Dynamic> P(values.size());
+ P.setIdentity();
-template <typename T>
-Matrix<T> operator+(const Matrix<T> & a, const Matrix<T> & b) {
- Matrix<T> r(a);
- r += b;
- return r;
-}
+ std::sort(P.indices().data(), P.indices().data() + P.indices().size(),
+ [&values](const Index & a, const Index & b) {
+ return (values(a) - values(b)) > 0;
+ });
-template <typename T>
-Matrix<T> operator-(const Matrix<T> & a, const Matrix<T> & b) {
- Matrix<T> r(a);
- r -= b;
- return r;
+ values = P.transpose() * values;
+ vectors = solver.eigenvectors() * P; // permutes the columns (eigen vectors)
}
-} // namespace akantu
-
-#include <iterator>
+} // namespace Eigen
namespace std {
-template <typename R>
-struct iterator_traits<::akantu::types::details::vector_iterator<R>> {
-protected:
- using iterator = ::akantu::types::details::vector_iterator<R>;
-
-public:
- using iterator_category = typename iterator::iterator_category;
- using value_type = typename iterator::value_type;
- using difference_type = typename iterator::difference_type;
- using pointer = typename iterator::pointer;
- using reference = typename iterator::reference;
-};
-
-template <typename Mat>
-struct iterator_traits<::akantu::types::details::column_iterator<Mat>> {
-protected:
- using iterator = ::akantu::types::details::column_iterator<Mat>;
-
-public:
- using iterator_category = typename iterator::iterator_category;
- using value_type = typename iterator::value_type;
- using difference_type = typename iterator::difference_type;
- using pointer = typename iterator::pointer;
- using reference = typename iterator::reference;
-};
-
+template <typename POD1, typename POD2, int MapOptions, typename StrideType>
+struct is_convertible<Eigen::Map<POD1, MapOptions, StrideType>,
+ Eigen::Map<POD2, MapOptions, StrideType>>
+ : aka::bool_constant<is_convertible<POD1, POD2>::value> {};
} // namespace std
-#endif /* AKANTU_AKA_TYPES_HH_ */
+#endif /* AKANTU_AKA_TYPES_HH */
diff --git a/src/common/aka_types_eigen_matrix_base_plugin.hh b/src/common/aka_types_eigen_matrix_base_plugin.hh
new file mode 100644
index 000000000..2783d9a13
--- /dev/null
+++ b/src/common/aka_types_eigen_matrix_base_plugin.hh
@@ -0,0 +1,169 @@
+using size_type = Index;
+
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void zero();
+
+template <bool _is_vector = IsVectorAtCompileTime,
+ std::enable_if_t<not _is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) operator()(Index c) {
+ auto & d = this->derived();
+ return d.col(c);
+}
+
+template <bool _is_vector = IsVectorAtCompileTime,
+ std::enable_if_t<not _is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) operator()(Index c) const {
+ const auto & d = this->derived();
+ return d.col(c);
+}
+
+template <bool _is_vector = IsVectorAtCompileTime,
+ std::enable_if_t<_is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) operator()(Index c) {
+ return Base::operator()(c);
+}
+
+template <bool _is_vector = IsVectorAtCompileTime,
+ std::enable_if_t<_is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) operator()(Index c) const {
+ return Base::operator()(c);
+}
+
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) operator()(Index i,
+ Index j) {
+ return Base::operator()(i, j);
+}
+
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) operator()(Index i,
+ Index j) const {
+ return Base::operator()(i, j);
+}
+
+template <
+ typename ED = Derived,
+ typename T = std::remove_reference_t<decltype(*std::declval<ED>().data())>,
+ std::enable_if_t<not std::is_const<T>::value and
+ ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) begin();
+template <
+ typename ED = Derived,
+ typename T = std::remove_reference_t<decltype(*std::declval<ED>().data())>,
+ std::enable_if_t<not std::is_const<T>::value and
+ ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) end();
+
+template <typename ED = Derived,
+ std::enable_if_t<ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) begin() const;
+template <typename ED = Derived,
+ std::enable_if_t<ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) end() const;
+
+template <
+ typename ED = Derived,
+ typename T = std::remove_reference_t<decltype(*std::declval<ED>().data())>,
+ std::enable_if_t<not std::is_const<T>::value and
+ not ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) begin();
+template <
+ typename ED = Derived,
+ typename T = std::remove_reference_t<decltype(*std::declval<ED>().data())>,
+ std::enable_if_t<not std::is_const<T>::value and
+ not ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) end();
+
+template <typename ED = Derived,
+ std::enable_if_t<not ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) begin() const;
+template <typename ED = Derived,
+ std::enable_if_t<not ED::IsVectorAtCompileTime> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) end() const;
+
+// clang-format off
+[[deprecated("use data instead to be stl compatible")]]
+Scalar * storage() {
+ return this->data();
+}
+
+[[deprecated("use data instead to be stl compatible")]]
+const Scalar * storage() const {
+ return this->data();
+}
+// clang-format on
+
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const {
+ return this->rows() * this->cols();
+}
+
+template <bool _is_vector = IsVectorAtCompileTime,
+ std::enable_if_t<not _is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size(Index i) const {
+ AKANTU_DEBUG_ASSERT(i < 2, "This tensor has only " << 2 << " dimensions, not "
+ << (i + 1));
+ return (i == 0) ? this->rows() : this->cols();
+}
+
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void set(const Scalar & t) {
+ this->fill(t);
+}
+
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void eye(const Scalar & t = 1.) {
+ (*this).noalias() =
+ t *
+ Matrix<Scalar, Derived::RowsAtCompileTime,
+ Derived::ColsAtCompileTime>::Identity(this->rows(), this->cols());
+}
+
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void clear() { this->fill(Scalar()); };
+
+template <typename OtherDerived>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE auto
+distance(const MatrixBase<OtherDerived> & other) const {
+ return (*this - other).norm();
+}
+
+template <typename OtherDerived>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar
+doubleDot(const MatrixBase<OtherDerived> & other) const {
+ eigen_assert(rows() == cols() and rows() == other.rows() and
+ cols() == other.cols());
+
+ return this->cwiseProduct(other).sum();
+}
+
+template <typename OtherDerived>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
+eig(MatrixBase<OtherDerived> & other) const;
+
+template <typename D1, typename D2>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
+eig(MatrixBase<D1> & values, MatrixBase<D2> & vectors,
+ bool sort = std::is_floating_point<typename D1::Scalar>::value) const;
+
+template <typename OtherDerived>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
+eigh(const MatrixBase<OtherDerived> & other) const;
+
+template <typename D1, typename D2>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void eigh(const MatrixBase<D1> & values,
+ const MatrixBase<D2> & vectors,
+ bool sort = true) const;
+
+template <typename OtherDerived>
+inline bool operator<=(const MatrixBase<OtherDerived> & v) const {
+ return this->isMuchSmallerThan(v);
+}
+
+template <typename OtherDerived>
+inline bool operator>=(const MatrixBase<OtherDerived> & v) const {
+ return v.isMuchSmallerThan(*this);
+}
+
+template <typename OtherDerived>
+inline bool operator<(const MatrixBase<OtherDerived> & v) const {
+ return (*this <= v) and (*this != v);
+}
+
+template <typename OtherDerived>
+inline bool operator>(const MatrixBase<OtherDerived> & v) const {
+ return (*this >= v) and (*this != v);
+}
diff --git a/src/common/aka_types_eigen_matrix_plugin.hh b/src/common/aka_types_eigen_matrix_plugin.hh
new file mode 100644
index 000000000..a4a33c92a
--- /dev/null
+++ b/src/common/aka_types_eigen_matrix_plugin.hh
@@ -0,0 +1,38 @@
+#define AKANTU_EIGEN_VERSION \
+ (EIGEN_WORLD_VERSION * 10000 + EIGEN_MAJOR_VERSION * 1000 + \
+ EIGEN_MAJOR_VERSION)
+
+using size_type = Index;
+
+template <typename PlainObjectType, int MapOptions, typename StrideType>
+EIGEN_STRONG_INLINE
+Matrix(const Map<PlainObjectType, MapOptions, StrideType> & other)
+ : Base(other.derived().rows() * other.derived().cols(),
+ other.derived().rows(), other.derived().cols()) {
+ // AKANTU_DEBUG_WARNING("copy operator Map in matrix");
+ Base::_check_template_params();
+ Base::_resize_to_match(other);
+ // FIXME/CHECK: isn't *this = other.derived() more efficient. it allows to
+ // go for pure _set() implementations, right?
+ *this = other;
+}
+
+template <typename PlainObjectType, int MapOptions, typename StrideType>
+EIGEN_STRONG_INLINE Matrix &
+operator=(const Map<PlainObjectType, MapOptions, StrideType> & map) {
+ // AKANTU_DEBUG_WARNING("operator= Map in matrix");
+ return Base::_set(map);
+}
+
+template <bool _is_vector = IsVectorAtCompileTime,
+ std::enable_if_t<_is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix(std::initializer_list<Scalar> list)
+ : Base(list) {}
+
+#if AKANTU_EIGEN_VERSION <= 34000
+template <bool _is_vector = IsVectorAtCompileTime,
+ std::enable_if_t<not _is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+Matrix(std::initializer_list<std::initializer_list<Scalar>> list)
+ : Base(list) {}
+#endif
diff --git a/src/common/aka_types_eigen_plain_object_base_plugin.hh b/src/common/aka_types_eigen_plain_object_base_plugin.hh
new file mode 100644
index 000000000..150c1f550
--- /dev/null
+++ b/src/common/aka_types_eigen_plain_object_base_plugin.hh
@@ -0,0 +1,55 @@
+#define AKANTU_EIGEN_VERSION \
+ (EIGEN_WORLD_VERSION * 10000 + EIGEN_MAJOR_VERSION * 1000 + \
+ EIGEN_MAJOR_VERSION)
+template <bool _is_vector = IsVectorAtCompileTime, typename _Derived = Derived,
+ std::enable_if_t<_is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE
+PlainObjectBase(std::initializer_list<Scalar> list) {
+ static_assert(std::is_trivially_copyable<Scalar>{},
+ "Cannot create a tensor on non trivial types");
+ _check_template_params();
+ this->template _init1<Index>(list.size());
+
+ Index i = 0;
+ for (auto val : list) {
+ this->operator()(i++) = val;
+ }
+}
+
+#if AKANTU_EIGEN_VERSION < 34000
+template <bool _is_vector = IsVectorAtCompileTime, typename _Derived = Derived,
+ std::enable_if_t<not _is_vector> * = nullptr>
+EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE
+PlainObjectBase(std::initializer_list<std::initializer_list<Scalar>> list) {
+ static_assert(std::is_trivially_copyable<Scalar>{},
+ "Cannot create a tensor on non trivial types");
+ Index m = list.size();
+ Index n = 0;
+ for (auto row : list) {
+ n = std::max(n, Index(row.size()));
+ }
+
+ if (RowsAtCompileTime != -1 and RowsAtCompileTime != m) {
+ throw std::range_error(
+ "The size of the matrix does not correspond to the initializer_list");
+ }
+
+ if (ColsAtCompileTime != -1 and ColsAtCompileTime != n) {
+ throw std::range_error(
+ "The size of the matrix does not correspond to the initializer_list");
+ }
+
+ _check_template_params();
+ this->template _init2<Index, Index>(m, n);
+ this->fill(Scalar{});
+
+ Index i = 0, j = 0;
+ for (auto & row : list) {
+ for (auto & val : row) {
+ this->operator()(i, j++) = val;
+ }
+ ++i;
+ j = 0;
+ }
+}
+#endif
diff --git a/src/common/aka_view_iterators.hh b/src/common/aka_view_iterators.hh
new file mode 100644
index 000000000..1ab77251f
--- /dev/null
+++ b/src/common/aka_view_iterators.hh
@@ -0,0 +1,615 @@
+/**
+ * @file aka_view_iterators.hh
+ *
+ * @author Nicolas Richart
+ *
+ * @date creation Thu Nov 15 2018
+ *
+ * @brief View iterators
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#include "aka_common.hh"
+//#include "aka_types.hh"
+/* -------------------------------------------------------------------------- */
+#include <memory>
+/* -------------------------------------------------------------------------- */
+
+#ifndef __AKANTU_AKA_VIEW_ITERATORS_HH__
+#define __AKANTU_AKA_VIEW_ITERATORS_HH__
+
+namespace akantu {
+template <typename T, Int ndim> class TensorBase;
+}
+
+namespace akantu {
+/* -------------------------------------------------------------------------- */
+/* Iterators */
+/* -------------------------------------------------------------------------- */
+namespace detail {
+ template <typename... V> constexpr auto product_all(V &&... v) {
+ std::common_type_t<int, V...> result = 1;
+ (void)std::initializer_list<int>{(result *= v, 0)...};
+ return result;
+ }
+
+ template <class R> struct IteratorHelper { static constexpr Int dim = 0; };
+
+ template <class Derived> struct IteratorHelper<Eigen::MatrixBase<Derived>> {
+ private:
+ using T = typename Derived::Scalar;
+ static constexpr Int m = Derived::RowsAtCompileTime;
+ static constexpr Int n = Derived::ColsAtCompileTime;
+
+ public:
+ static constexpr Int dim =
+ Eigen::MatrixBase<Derived>::IsVectorAtCompileTime ? 1 : 2;
+ using pointer = T *;
+ using proxy = Eigen::Map<Eigen::Matrix<T, m, n>>;
+ using const_proxy = Eigen::Map<const Eigen::Matrix<T, m, n>>;
+ };
+
+ template <class Derived> struct IteratorHelper<Eigen::Map<Derived>> {
+ private:
+ using T = typename Derived::Scalar;
+ static constexpr Int m = Derived::RowsAtCompileTime;
+ static constexpr Int n = Derived::ColsAtCompileTime;
+
+ public:
+ static constexpr Int dim =
+ Derived::IsVectorAtCompileTime and m != 1 ? 1 : 2;
+ using pointer = T *;
+ using proxy = Eigen::Map<Derived>;
+ using const_proxy = Eigen::Map<const Derived>;
+ };
+
+ template <typename T, Int _dim> struct IteratorHelper<TensorBase<T, _dim>> {
+ static constexpr Int dim = _dim;
+ using pointer = T *;
+ using proxy = TensorProxy<T, _dim>;
+ using const_proxy = TensorProxy<const T, _dim>;
+ };
+
+ template <typename T, Int _dim> struct IteratorHelper<TensorProxy<T, _dim>> {
+ static constexpr Int dim = _dim;
+ using pointer = T *;
+ using proxy = TensorProxy<T, _dim>;
+ using const_proxy = TensorProxy<const T, _dim>;
+ };
+
+ /* ------------------------------------------------------------------------ */
+ template <class R, class daughter, class IR = R,
+ Int dim = IteratorHelper<std::decay_t<R>>::dim>
+ class internal_view_iterator {
+ protected:
+ using helper = IteratorHelper<std::decay_t<R>>;
+ using internal_value_type = IR;
+ using internal_pointer = IR *;
+ using scalar_pointer = typename helper::pointer;
+ using proxy_t = typename helper::proxy;
+ static constexpr int dim_ = dim;
+
+ public:
+ using pointer = proxy_t *;
+ using value_type = proxy_t;
+ using reference = proxy_t &;
+ using difference_type = Int;
+ using iterator_category = std::random_access_iterator_tag;
+
+ private:
+ template <class ProxyType, std::size_t... I>
+ constexpr auto get_new_proxy(scalar_pointer data,
+ std::index_sequence<I...>) const {
+ return ProxyType(data, dims[I]...);
+ }
+
+ constexpr auto get_new_proxy(scalar_pointer data) {
+ return this->template get_new_proxy<proxy_t>(
+ data, std::make_index_sequence<dim>());
+ }
+
+ constexpr auto get_new_proxy(scalar_pointer data) const {
+ return this->template get_new_proxy<proxy_t>(
+ data, std::make_index_sequence<dim>());
+ }
+
+ template <std::size_t... I>
+ constexpr void reset_proxy(std::index_sequence<I...>) {
+ new (&proxy) proxy_t(ret_ptr, dims[I]...);
+ }
+
+ constexpr auto reset_proxy() {
+ return reset_proxy(std::make_index_sequence<dim>());
+ }
+
+ protected:
+ template <typename OR, typename OD, typename OIR,
+ std::enable_if_t<std::is_convertible<
+ decltype(std::declval<OIR>().data()),
+ decltype(std::declval<IR>().data())>::value> * = nullptr>
+ explicit internal_view_iterator(
+ internal_view_iterator<OR, OD, OIR, dim> & it)
+ : dims(it.dims), _offset(it._offset), initial(it.initial),
+ ret_ptr(it.ret_ptr), proxy(get_new_proxy(it.ret_ptr)) {}
+
+ template <typename OR, typename OD, typename OIR, Int _dim>
+ friend class internal_view_iterator;
+
+ template <typename... Args>
+ using valid_args_t = std::enable_if_t<
+ aka::conjunction<aka::disjunction<std::is_integral<Args>,
+ std::is_enum<Args>>...>::value and
+ dim == sizeof...(Args),
+ int>;
+
+ public:
+ /// Generic constructor dor any tensor dimension
+ template <typename... Ns, valid_args_t<Ns...> = 0>
+ internal_view_iterator(scalar_pointer data, Ns... ns)
+ : dims({Int(ns)...}),
+ _offset(detail::product_all(std::forward<Ns>(ns)...)), initial(data),
+ ret_ptr(data), proxy(data, ns...) {}
+
+ // Specific constructor for Vector of static size 1
+ template <typename RD = std::decay_t<R>,
+ std::enable_if_t<aka::is_eigen_map<RD>::value and
+ RD::RowsAtCompileTime == 1 and
+ RD::ColsAtCompileTime == 1> * = nullptr>
+ constexpr internal_view_iterator(scalar_pointer data, Idx rows)
+ : dims({rows, 1}), _offset(rows), initial(data), ret_ptr(data),
+ proxy(data, rows, 1) {
+ assert(rows == 1 && "1x1 Matrix");
+ }
+
+ /// Specific constructor for Eigen::Map<Matrix> that look like
+ /// Eigen::Map<Vector>
+ template <typename RD = std::decay_t<R>,
+ std::enable_if_t<(RD::RowsAtCompileTime != 1) and
+ RD::ColsAtCompileTime == 1> * = nullptr>
+ constexpr internal_view_iterator(scalar_pointer data, Idx rows,
+ [[gnu::unused]] Idx cols)
+ : dims({rows}), _offset(rows), initial(data), ret_ptr(data),
+ proxy(data, rows, 1) {
+ assert(cols == 1 && "nx1 Matrix");
+ }
+
+ /// Default constructor for Eigen::Map<Vector>
+ template <Int _dim = dim, typename RD = std::decay_t<R>,
+ std::enable_if_t<_dim == 1> * = nullptr>
+ internal_view_iterator()
+ : proxy(reinterpret_cast<scalar_pointer>(0xdeadbeaf),
+ RD::RowsAtCompileTime == Eigen::Dynamic
+ ? 1
+ : RD::RowsAtCompileTime) {
+ // initialized to a fake pointer to pass the static_assert in Eigen
+ // this proxy should not be returned
+ }
+
+ /// Default constructor for Eigen::Map<Matrix>
+ template <Int _dim = dim, typename RD = std::decay_t<R>,
+ std::enable_if_t<_dim == 2> * = nullptr>
+ internal_view_iterator()
+ : proxy(reinterpret_cast<scalar_pointer>(0xdeadbeaf),
+ RD::RowsAtCompileTime == Eigen::Dynamic ? 1
+ : RD::RowsAtCompileTime,
+ RD::ColsAtCompileTime == Eigen::Dynamic
+ ? 1
+ : RD::ColsAtCompileTime) {
+ // initialized to a fake pointer to pass the `static_assert` in `Eigen
+ // this proxy should not be returned
+ }
+
+ template <Int _dim = dim, typename RD = std::decay_t<R>,
+ std::enable_if_t<(_dim > 2)> * = nullptr>
+ internal_view_iterator() {}
+
+ internal_view_iterator(const internal_view_iterator & it)
+ : dims(it.dims), _offset(it._offset), initial(it.initial),
+ ret_ptr(it.ret_ptr), proxy(get_new_proxy(it.ret_ptr)) {}
+
+ internal_view_iterator &
+ operator=(internal_view_iterator && it) noexcept = default;
+ internal_view_iterator(internal_view_iterator && it) noexcept = default;
+
+ virtual ~internal_view_iterator() = default;
+
+ template <typename OR, typename OD, typename OIR,
+ std::enable_if_t<std::is_convertible<
+ decltype(std::declval<OIR>().data()),
+ decltype(std::declval<IR>().data())>::value> * = nullptr>
+ inline internal_view_iterator &
+ operator=(const internal_view_iterator<OR, OD, OIR, dim> & it) {
+ this->dims = it.dims;
+ this->_offset = it._offset;
+ this->initial = it.initial;
+ this->ret_ptr = it.ret_ptr;
+ reset_proxy();
+ return *this;
+ }
+
+ inline internal_view_iterator &
+ operator=(const internal_view_iterator & it) {
+ if (this != &it) {
+ this->dims = it.dims;
+ this->_offset = it._offset;
+ this->initial = it.initial;
+ this->ret_ptr = it.ret_ptr;
+ reset_proxy();
+ }
+ return *this;
+ }
+
+ public:
+ Idx getCurrentIndex() {
+ return (this->ret_ptr - this->initial) / this->_offset;
+ }
+
+ inline reference operator*() {
+ this->reset_proxy();
+ return proxy;
+ }
+
+ inline pointer operator->() {
+ reset_proxy();
+ return &proxy;
+ }
+
+ inline daughter & operator++() {
+ ret_ptr += _offset;
+ return static_cast<daughter &>(*this);
+ }
+
+ inline daughter & operator--() {
+ ret_ptr -= _offset;
+ return static_cast<daughter &>(*this);
+ }
+
+ inline daughter & operator+=(Idx n) {
+ ret_ptr += _offset * n;
+ return static_cast<daughter &>(*this);
+ }
+
+ inline daughter & operator-=(Idx n) {
+ ret_ptr -= _offset * n;
+ return static_cast<daughter &>(*this);
+ }
+
+ inline auto operator[](Idx n) {
+ return get_new_proxy(ret_ptr + n * _offset);
+ }
+
+ inline auto operator[](Idx n) const {
+ return get_new_proxy(ret_ptr + n * _offset);
+ }
+
+ inline bool operator==(const internal_view_iterator & other) const {
+ return this->ret_ptr == other.ret_ptr;
+ }
+
+ inline bool operator!=(const internal_view_iterator & other) const {
+ return this->ret_ptr != other.ret_ptr;
+ }
+
+ inline bool operator<(const internal_view_iterator & other) const {
+ return this->ret_ptr < other.ret_ptr;
+ }
+
+ inline bool operator<=(const internal_view_iterator & other) const {
+ return this->ret_ptr <= other.ret_ptr;
+ }
+
+ inline bool operator>(const internal_view_iterator & other) const {
+ return this->ret_ptr > other.ret_ptr;
+ }
+
+ inline bool operator>=(const internal_view_iterator & other) const {
+ return this->ret_ptr >= other.ret_ptr;
+ }
+
+ inline auto operator+(difference_type n) const {
+ daughter tmp(static_cast<const daughter &>(*this));
+ tmp += n;
+ return tmp;
+ }
+
+ inline auto operator-(difference_type n) const {
+ daughter tmp(static_cast<const daughter &>(*this));
+ tmp -= n;
+ return tmp;
+ }
+
+ inline difference_type operator-(const internal_view_iterator & b) const {
+ return (this->ret_ptr - b.ret_ptr) / _offset;
+ }
+
+ inline scalar_pointer data() const { return ret_ptr; }
+ inline difference_type offset() const { return _offset; }
+ inline decltype(auto) getDims() const { return dims; }
+
+ protected:
+ std::array<Int, dim> dims;
+ difference_type _offset{0};
+ scalar_pointer initial{nullptr};
+ scalar_pointer ret_ptr{nullptr};
+ proxy_t proxy;
+ };
+
+ /* ------------------------------------------------------------------------ */
+ /**
+ * Specialization for scalar types
+ */
+ template <class R, class daughter, class IR>
+ class internal_view_iterator<R, daughter, IR, 0> {
+ public:
+ using value_type = R;
+ using pointer = R *;
+ using reference = R &;
+ using const_reference = const R &;
+ using difference_type = Idx; // std::ptrdiff_t;
+ using iterator_category = std::random_access_iterator_tag;
+ static constexpr int dim_ = 0;
+
+ protected:
+ using internal_value_type = IR;
+ using internal_pointer = IR *;
+
+ public:
+ internal_view_iterator(pointer data = nullptr) : ret(data), initial(data){};
+ internal_view_iterator(const internal_view_iterator & it) = default;
+ internal_view_iterator(internal_view_iterator && it) = default;
+
+ virtual ~internal_view_iterator() = default;
+
+ inline internal_view_iterator &
+ operator=(const internal_view_iterator & it) = default;
+
+ Idx getCurrentIndex() { return (this->ret - this->initial); };
+
+ inline reference operator*() { return *ret; }
+ inline pointer operator->() { return ret; };
+
+ inline daughter & operator++() {
+ ++ret;
+ return static_cast<daughter &>(*this);
+ }
+ inline daughter & operator--() {
+ --ret;
+ return static_cast<daughter &>(*this);
+ }
+
+ inline daughter & operator+=(const Idx n) {
+ ret += n;
+ return static_cast<daughter &>(*this);
+ }
+ inline daughter & operator-=(const Idx n) {
+ ret -= n;
+ return static_cast<daughter &>(*this);
+ }
+
+ inline reference operator[](const Idx n) { return ret[n]; }
+
+ inline bool operator==(const internal_view_iterator & other) const {
+ return ret == other.ret;
+ }
+ inline bool operator!=(const internal_view_iterator & other) const {
+ return ret != other.ret;
+ }
+ inline bool operator<(const internal_view_iterator & other) const {
+ return ret < other.ret;
+ }
+ inline bool operator<=(const internal_view_iterator & other) const {
+ return ret <= other.ret;
+ }
+ inline bool operator>(const internal_view_iterator & other) const {
+ return ret > other.ret;
+ }
+ inline bool operator>=(const internal_view_iterator & other) const {
+ return ret >= other.ret;
+ }
+
+ inline daughter operator-(difference_type n) const {
+ return daughter(ret - n);
+ }
+ inline daughter operator+(difference_type n) const {
+ return daughter(ret + n);
+ }
+
+ inline difference_type operator-(const internal_view_iterator & b) const {
+ return ret - b.ret;
+ }
+
+ inline pointer data() const { return ret; }
+ inline decltype(auto) getDims() const { return dims; }
+
+ protected:
+ std::array<int, 0> dims;
+ pointer ret{nullptr};
+ pointer initial{nullptr};
+ };
+} // namespace detail
+
+/* -------------------------------------------------------------------------- */
+template <typename R> class view_iterator;
+
+template <typename R>
+class const_view_iterator
+ : public detail::internal_view_iterator<const R, const_view_iterator<R>,
+ R> {
+public:
+ using parent =
+ detail::internal_view_iterator<const R, const_view_iterator, R>;
+ using value_type = typename parent::value_type;
+ using pointer = typename parent::pointer;
+ using reference = typename parent::reference;
+ using difference_type = typename parent::difference_type;
+ using iterator_category = typename parent::iterator_category;
+
+protected:
+ template <typename Iterator, std::size_t... I>
+ static inline auto convert_helper(const Iterator & it,
+ std::index_sequence<I...>) {
+ return const_view_iterator(it.data(), it.getDims()[I]...);
+ }
+ template <typename Iterator> static inline auto convert(const Iterator & it) {
+ return convert_helper(it, std::make_index_sequence<parent::dim_>());
+ }
+
+public:
+ const_view_iterator() : parent(){};
+ const_view_iterator(const const_view_iterator & it) = default;
+ const_view_iterator(const_view_iterator && it) noexcept = default;
+
+ template <typename P, typename... Ns>
+ const_view_iterator(P * data, Ns... ns) : parent(data, ns...) {}
+
+ const_view_iterator & operator=(const const_view_iterator & it) = default;
+
+ template <typename OR,
+ std::enable_if_t<not std::is_same<R, OR>::value> * = nullptr>
+ const_view_iterator(const const_view_iterator<OR> & it)
+ : parent(convert(it)) {}
+
+ template <typename OR,
+ std::enable_if_t<std::is_convertible<R, OR>::value> * = nullptr>
+ const_view_iterator(const view_iterator<OR> & it) : parent(convert(it)) {}
+
+ template <typename OR,
+ std::enable_if_t<not std::is_same<R, OR>::value and
+ std::is_convertible<R, OR>::value> * = nullptr>
+ const_view_iterator & operator=(const const_view_iterator<OR> & it) {
+ return dynamic_cast<const_view_iterator &>(parent::operator=(it));
+ }
+
+ template <typename OR,
+ std::enable_if_t<std::is_convertible<R, OR>::value> * = nullptr>
+ const_view_iterator operator=(const view_iterator<OR> & it) {
+ return convert(it);
+ }
+};
+
+template <class R, bool is_tensor_ = aka::is_tensor<R>::value>
+struct ConstConverterIteratorHelper {
+protected:
+ template <std::size_t... I>
+ static inline auto convert_helper(const view_iterator<R> & it,
+ std::index_sequence<I...>) {
+ return const_view_iterator<R>(it.data(), it.getDims()[I]...);
+ }
+
+public:
+ static inline auto convert(const view_iterator<R> & it) {
+ return convert_helper(
+ it, std::make_index_sequence<
+ std::tuple_size<decltype(it.getDims())>::value>());
+ }
+};
+
+template <class R> struct ConstConverterIteratorHelper<R, false> {
+ static inline auto convert(const view_iterator<R> & it) {
+ return const_view_iterator<R>(it.data());
+ }
+};
+
+template <typename R>
+class view_iterator
+ : public detail::internal_view_iterator<R, view_iterator<R>> {
+public:
+ using parent = detail::internal_view_iterator<R, view_iterator>;
+ using value_type = typename parent::value_type;
+ using pointer = typename parent::pointer;
+ using reference = typename parent::reference;
+ using difference_type = typename parent::difference_type;
+ using iterator_category = typename parent::iterator_category;
+
+public:
+ view_iterator() : parent(){};
+ view_iterator(const view_iterator & it) = default;
+ view_iterator(view_iterator && it) = default;
+
+ template <typename P, typename... Ns>
+ view_iterator(P * data, Ns... ns) : parent(data, ns...) {}
+
+ view_iterator & operator=(const view_iterator & it) = default;
+
+ operator const_view_iterator<R>() {
+ return ConstConverterIteratorHelper<R>::convert(*this);
+ }
+};
+
+namespace {
+ template <std::size_t dim, typename T> struct ViewIteratorHelper {
+ using type = TensorProxy<T, dim>;
+ };
+
+ template <typename T> struct ViewIteratorHelper<0, T> { using type = T; };
+ template <typename T> struct ViewIteratorHelper<1, T> {
+ using type = Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1>>;
+ };
+ template <typename T> struct ViewIteratorHelper<1, const T> {
+ using type = Eigen::Map<const Eigen::Matrix<T, Eigen::Dynamic, 1>>;
+ };
+
+ template <typename T> struct ViewIteratorHelper<2, T> {
+ using type = Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>;
+ };
+
+ template <typename T> struct ViewIteratorHelper<2, const T> {
+ using type =
+ Eigen::Map<const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>;
+ };
+
+ template <std::size_t dim, typename T>
+ using ViewIteratorHelper_t = typename ViewIteratorHelper<dim, T>::type;
+} // namespace
+
+} // namespace akantu
+
+#include <iterator>
+
+namespace std {
+
+template <typename R> struct iterator_traits<::akantu::const_view_iterator<R>> {
+protected:
+ using iterator = ::akantu::const_view_iterator<R>;
+
+public:
+ using iterator_category = typename iterator::iterator_category;
+ using value_type = typename iterator::value_type;
+ using difference_type = typename iterator::difference_type;
+ using pointer = typename iterator::pointer;
+ using reference = typename iterator::reference;
+};
+
+template <typename R> struct iterator_traits<::akantu::view_iterator<R>> {
+protected:
+ using iterator = ::akantu::view_iterator<R>;
+
+public:
+ using iterator_category = typename iterator::iterator_category;
+ using value_type = typename iterator::value_type;
+ using difference_type = typename iterator::difference_type;
+ using pointer = typename iterator::pointer;
+ using reference = typename iterator::reference;
+};
+
+} // namespace std
+
+#endif /* !__AKANTU_AKA_VIEW_ITERATORS_HH__ */
diff --git a/src/common/aka_voigthelper.cc b/src/common/aka_voigthelper.cc
index efb6517b1..9f082873b 100644
--- a/src/common/aka_voigthelper.cc
+++ b/src/common/aka_voigthelper.cc
@@ -1,69 +1,69 @@
/**
* @file aka_voigthelper.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Till Junge <till.junge@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 20 2013
* @date last modification: Fri Jul 24 2020
*
* @brief Voigt indices
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_voigthelper.hh"
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/* clang-format off */
-template <> const UInt VoigtHelper<1>::mat[][1] = {{0}};
-template <> const UInt VoigtHelper<2>::mat[][2] = {{0, 2},
- {3, 1}};
-template <> const UInt VoigtHelper<3>::mat[][3] = {{0, 5, 4},
- {8, 1, 3},
- {7, 6, 2}};
-template <> const UInt VoigtHelper<1>::vec[][2] = {{0, 0}};
-template <> const UInt VoigtHelper<2>::vec[][2] = {{0, 0},
- {1, 1},
- {0, 1},
- {1, 0}};
-template <> const UInt VoigtHelper<3>::vec[][2] = {{0, 0},
- {1, 1},
- {2, 2},
- {1, 2},
- {0, 2},
- {0, 1},
- {2, 1},
- {2, 0},
- {1, 0}};
+template <> const Int VoigtHelper<1>::mat[][1] = {{0}};
+template <> const Int VoigtHelper<2>::mat[][2] = {{0, 2},
+ {3, 1}};
+template <> const Int VoigtHelper<3>::mat[][3] = {{0, 5, 4},
+ {8, 1, 3},
+ {7, 6, 2}};
+template <> const Int VoigtHelper<1>::vec[][2] = {{0, 0}};
+template <> const Int VoigtHelper<2>::vec[][2] = {{0, 0},
+ {1, 1},
+ {0, 1},
+ {1, 0}};
+template <> const Int VoigtHelper<3>::vec[][2] = {{0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 2},
+ {0, 2},
+ {0, 1},
+ {2, 1},
+ {2, 0},
+ {1, 0}};
template <> const Real VoigtHelper<1>::factors[] = {1.};
template <> const Real VoigtHelper<2>::factors[] = {1., 1., 2.};
template <> const Real VoigtHelper<3>::factors[] = {1., 1., 1.,
2., 2., 2.};
/* clang-format on */
} // namespace akantu
diff --git a/src/common/aka_voigthelper.hh b/src/common/aka_voigthelper.hh
index 61021db3b..07f50d113 100644
--- a/src/common/aka_voigthelper.hh
+++ b/src/common/aka_voigthelper.hh
@@ -1,103 +1,111 @@
/**
* @file aka_voigthelper.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Till Junge <till.junge@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 20 2013
* @date last modification: Tue Sep 29 2020
*
* @brief Helper file for Voigt notation
* Wikipedia convention: @f[2*\epsilon_{ij} (i!=j) = voigt_\epsilon_{I}@f]
* http://en.wikipedia.org/wiki/Voigt_notation
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_types.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKA_VOIGTHELPER_HH_
#define AKA_VOIGTHELPER_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim> class VoigtHelper {
+template <Int dim> class VoigtHelper {
static_assert(dim > 0U, "Cannot be < 1D");
static_assert(dim < 4U, "Cannot be > 3D");
public:
/* ------------------------------------------------------------------------ */
template <class M, class V>
- static inline void matrixToVoigt(M && matrix, V && vector);
+ static constexpr inline void matrixToVoigt(M && matrix, V && vector);
- template <class M> static inline decltype(auto) matrixToVoigt(M && matrix);
+ template <class M>
+ static constexpr inline decltype(auto) matrixToVoigt(M && matrix);
template <class M, class V>
- static inline void matrixToVoigtWithFactors(M && matrix, V && vector);
+ static constexpr inline void matrixToVoigtWithFactors(M && matrix,
+ V && vector);
template <class M>
- static inline decltype(auto) matrixToVoigtWithFactors(M && matrix);
+ static constexpr inline decltype(auto) matrixToVoigtWithFactors(M && matrix);
template <class M, class V>
- static inline void voigtToMatrix(V && vector, M && matrix);
+ static constexpr inline void voigtToMatrix(V && vector, M && matrix);
- template <class V> static inline decltype(auto) voigtToMatrix(V && vector);
+ template <class V>
+ static constexpr inline decltype(auto) voigtToMatrix(V && vector);
/* ------------------------------------------------------------------------ */
/// transfer the B matrix to a Voigt notation B matrix
- inline static void transferBMatrixToSymVoigtBMatrix(
- const Matrix<Real> & B, Matrix<Real> & Bvoigt, UInt nb_nodes_per_element);
+ template <typename D1, typename D2>
+ static constexpr inline void
+ transferBMatrixToSymVoigtBMatrix(const Eigen::MatrixBase<D1> & B,
+ Eigen::MatrixBase<D2> & Bvoigt,
+ Int nb_nodes_per_element);
/// transfer the BNL matrix to a Voigt notation B matrix (See Bathe et al.
/// IJNME vol 9, 1975)
- inline static void transferBMatrixToBNL(const Matrix<Real> & B,
- Matrix<Real> & Bvoigt,
- UInt nb_nodes_per_element);
+ template <typename D1, typename D2>
+ static constexpr inline void
+ transferBMatrixToBNL(const Eigen::MatrixBase<D1> & B,
+ Eigen::MatrixBase<D2> & Bvoigt,
+ Int nb_nodes_per_element);
/// transfer the BL2 matrix to a Voigt notation B matrix (See Bathe et al.
/// IJNME vol 9, 1975)
- inline static void transferBMatrixToBL2(const Matrix<Real> & B,
- const Matrix<Real> & grad_u,
- Matrix<Real> & Bvoigt,
- UInt nb_nodes_per_element);
+ template <typename D1, typename D2, typename D3>
+ static constexpr inline void transferBMatrixToBL2(
+ const Eigen::MatrixBase<D1> & B, const Eigen::MatrixBase<D2> & grad_u,
+ Eigen::MatrixBase<D3> & Bvoigt, Int nb_nodes_per_element);
public:
- static constexpr UInt size{(dim * (dim - 1)) / 2 + dim};
+ static constexpr Int size{(dim * (dim - 1)) / 2 + dim};
// matrix of vector index I as function of tensor indices i,j
- static const UInt mat[dim][dim];
+ static const Idx mat[dim][dim];
// array of matrix indices ij as function of vector index I
- static const UInt vec[dim * dim][2];
+ static const Idx vec[dim * dim][2];
// factors to multiply the strain by for voigt notation
static const Real factors[size];
};
} // namespace akantu
#include "aka_voigthelper_tmpl.hh"
#endif
diff --git a/src/common/aka_voigthelper_tmpl.hh b/src/common/aka_voigthelper_tmpl.hh
index f15c12ad6..b06dec9bf 100644
--- a/src/common/aka_voigthelper_tmpl.hh
+++ b/src/common/aka_voigthelper_tmpl.hh
@@ -1,243 +1,247 @@
/**
* @file aka_voigthelper_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 20 2013
* @date last modification: Tue Sep 29 2020
*
* @brief implementation of the voight helper
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_voigthelper.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_AKA_VOIGTHELPER_TMPL_HH_
-#define AKANTU_AKA_VOIGTHELPER_TMPL_HH_
+// #ifndef __AKANTU_AKA_VOIGTHELPER_TMPL_HH__
+// #define __AKANTU_AKA_VOIGTHELPER_TMPL_HH__
namespace akantu {
-template <UInt dim> constexpr UInt VoigtHelper<dim>::size;
+template <Int dim> constexpr Int VoigtHelper<dim>::size;
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
template <class M, class V>
-inline void VoigtHelper<dim>::matrixToVoigt(M && matrix, V && vector) {
- for (UInt I = 0; I < size; ++I) {
+constexpr inline void VoigtHelper<dim>::matrixToVoigt(M && matrix, V && vector) {
+ for (Int I = 0; I < size; ++I) {
auto i = vec[I][0];
auto j = vec[I][1];
vector(I) = matrix(i, j);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
template <class M>
-inline decltype(auto) VoigtHelper<dim>::matrixToVoigt(M && matrix) {
- Vector<Real> vector(size);
+constexpr inline decltype(auto) VoigtHelper<dim>::matrixToVoigt(M && matrix) {
+ Vector<Real, size> vector;
matrixToVoigt(std::forward<M>(matrix), vector);
return vector;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
template <class M, class V>
-inline void VoigtHelper<dim>::matrixToVoigtWithFactors(M && matrix,
+constexpr inline void VoigtHelper<dim>::matrixToVoigtWithFactors(M && matrix,
V && vector) {
- for (UInt I = 0; I < size; ++I) {
+ for (Int I = 0; I < size; ++I) {
auto i = vec[I][0];
auto j = vec[I][1];
vector(I) = factors[I] * matrix(i, j);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
template <class M>
-inline decltype(auto) VoigtHelper<dim>::matrixToVoigtWithFactors(M && matrix) {
- Vector<Real> vector(size);
+constexpr inline decltype(auto) VoigtHelper<dim>::matrixToVoigtWithFactors(M && matrix) {
+ Vector<Real, size> vector;
matrixToVoigtWithFactors(std::forward<M>(matrix), vector);
return vector;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
template <class M, class V>
-inline void VoigtHelper<dim>::voigtToMatrix(V && vector, M && matrix) {
- for (UInt I = 0; I < size; ++I) {
+constexpr inline void VoigtHelper<dim>::voigtToMatrix(V && vector, M && matrix) {
+ for (Int I = 0; I < size; ++I) {
auto i = vec[I][0];
auto j = vec[I][1];
matrix(i, j) = matrix(j, i) = vector(I);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
template <class V>
-inline decltype(auto) VoigtHelper<dim>::voigtToMatrix(V && vector) {
- Matrix<Real> matrix(dim, dim);
+constexpr inline decltype(auto) VoigtHelper<dim>::voigtToMatrix(V && vector) {
+ Matrix<Real, dim, dim> matrix;
voigtToMatrix(std::forward<V>(vector), matrix);
return matrix;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(
- const Matrix<Real> & B, Matrix<Real> & Bvoigt, UInt nb_nodes_per_element) {
+template <Int dim>
+template <typename D1, typename D2>
+constexpr inline void VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(
+ const Eigen::MatrixBase<D1> & B, Eigen::MatrixBase<D2> & Bvoigt,
+ Int nb_nodes_per_element) {
Bvoigt.zero();
- for (UInt i = 0; i < dim; ++i) {
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int i = 0; i < dim; ++i) {
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
Bvoigt(i, i + n * dim) = B(i, n);
}
}
if (dim == 2) {
/// in 2D, fill the @f$ [\frac{\partial N_i}{\partial x}, \frac{\partial
/// N_i}{\partial y}]@f$ row
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
Bvoigt(2, 1 + n * 2) = B(0, n);
Bvoigt(2, 0 + n * 2) = B(1, n);
}
}
if (dim == 3) {
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- Real dndx = B(0, n);
- Real dndy = B(1, n);
- Real dndz = B(2, n);
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
+ auto dndx = B(0, n);
+ auto dndy = B(1, n);
+ auto dndz = B(2, n);
/// in 3D, fill the @f$ [0, \frac{\partial N_i}{\partial y},
/// \frac{N_i}{\partial z}]@f$ row
Bvoigt(3, 1 + n * 3) = dndz;
Bvoigt(3, 2 + n * 3) = dndy;
/// in 3D, fill the @f$ [\frac{\partial N_i}{\partial x}, 0,
/// \frac{N_i}{\partial z}]@f$ row
Bvoigt(4, 0 + n * 3) = dndz;
Bvoigt(4, 2 + n * 3) = dndx;
/// in 3D, fill the @f$ [\frac{\partial N_i}{\partial x},
/// \frac{N_i}{\partial y}, 0]@f$ row
Bvoigt(5, 0 + n * 3) = dndy;
Bvoigt(5, 1 + n * 3) = dndx;
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void VoigtHelper<dim>::transferBMatrixToBNL(const Matrix<Real> & B,
- Matrix<Real> & Bvoigt,
- UInt nb_nodes_per_element) {
+template <Int dim>
+template <typename D1, typename D2>
+constexpr inline void
+VoigtHelper<dim>::transferBMatrixToBNL(const Eigen::MatrixBase<D1> & B,
+ Eigen::MatrixBase<D2> & Bvoigt,
+ Int nb_nodes_per_element) {
Bvoigt.zero();
// see Finite element formulations for large deformation dynamic analysis,
// Bathe et al. IJNME vol 9, 1975, page 364 B_{NL}
- for (UInt i = 0; i < dim; ++i) {
- for (UInt m = 0; m < nb_nodes_per_element; ++m) {
- for (UInt n = 0; n < dim; ++n) {
+ for (Int i = 0; i < dim; ++i) {
+ for (Int m = 0; m < nb_nodes_per_element; ++m) {
+ for (Int n = 0; n < dim; ++n) {
// std::cout << B(n, m) << std::endl;
Bvoigt(i * dim + n, m * dim + i) = B(n, m);
}
}
}
// TODO: Verify the 2D and 1D case
}
/* -------------------------------------------------------------------------- */
template <>
-inline void VoigtHelper<1>::transferBMatrixToBL2(const Matrix<Real> & B,
- const Matrix<Real> & grad_u,
- Matrix<Real> & Bvoigt,
- UInt nb_nodes_per_element) {
+template <typename D1, typename D2, typename D3>
+constexpr inline void VoigtHelper<1>::transferBMatrixToBL2(
+ const Eigen::MatrixBase<D1> & B, const Eigen::MatrixBase<D2> & grad_u,
+ Eigen::MatrixBase<D3> & Bvoigt, Int nb_nodes_per_element) {
Bvoigt.zero();
- for (UInt j = 0; j < nb_nodes_per_element; ++j) {
+ for (Int j = 0; j < nb_nodes_per_element; ++j) {
Bvoigt(0, j) = grad_u(0, 0) * B(0, j);
}
}
/* -------------------------------------------------------------------------- */
template <>
-inline void VoigtHelper<3>::transferBMatrixToBL2(const Matrix<Real> & dNdX,
- const Matrix<Real> & grad_u,
- Matrix<Real> & Bvoigt,
- UInt nb_nodes_per_element) {
+template <typename D1, typename D2, typename D3>
+constexpr inline void VoigtHelper<3>::transferBMatrixToBL2(
+ const Eigen::MatrixBase<D1> & dNdX, const Eigen::MatrixBase<D2> & grad_u,
+ Eigen::MatrixBase<D3> & Bvoigt, Int nb_nodes_per_element) {
Bvoigt.zero();
- for (UInt I = 0; I < 3; ++I) {
- for (UInt a = 0; a < nb_nodes_per_element; ++a) {
- for (UInt i = 0; i < 3; ++i) {
+ for (Int I = 0; I < 3; ++I) {
+ for (Int a = 0; a < nb_nodes_per_element; ++a) {
+ for (Int i = 0; i < 3; ++i) {
Bvoigt(I, a * 3 + i) = grad_u(i, I) * dNdX(I, a);
}
}
}
- for (UInt Iv = 3; Iv < 6; ++Iv) {
- for (UInt a = 0; a < nb_nodes_per_element; ++a) {
- for (UInt k = 0; k < 3; ++k) {
- UInt aux = Iv - 3;
- for (UInt m = 0; m < 3; ++m) {
+ for (Int Iv = 3; Iv < 6; ++Iv) {
+ for (Int a = 0; a < nb_nodes_per_element; ++a) {
+ for (Int k = 0; k < 3; ++k) {
+ auto aux = Iv - 3;
+ for (Int m = 0; m < 3; ++m) {
if (m != aux) {
- UInt index1 = m;
- UInt index2 = 3 - m - aux;
+ auto index1 = m;
+ auto index2 = 3 - m - aux;
Bvoigt(Iv, a * 3 + k) += grad_u(k, index1) * dNdX(index2, a);
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
template <>
-inline void VoigtHelper<2>::transferBMatrixToBL2(const Matrix<Real> & B,
- const Matrix<Real> & grad_u,
- Matrix<Real> & Bvoigt,
- UInt nb_nodes_per_element) {
+template <typename D1, typename D2, typename D3>
+constexpr inline void VoigtHelper<2>::transferBMatrixToBL2(
+ const Eigen::MatrixBase<D1> & B, const Eigen::MatrixBase<D2> & grad_u,
+ Eigen::MatrixBase<D3> & Bvoigt, Int nb_nodes_per_element) {
Bvoigt.zero();
- for (UInt i = 0; i < 2; ++i) {
- for (UInt j = 0; j < nb_nodes_per_element; ++j) {
- for (UInt k = 0; k < 2; ++k) {
+ for (Int i = 0; i < 2; ++i) {
+ for (Int j = 0; j < nb_nodes_per_element; ++j) {
+ for (Int k = 0; k < 2; ++k) {
Bvoigt(i, j * 2 + k) = grad_u(k, i) * B(i, j);
}
}
}
- for (UInt j = 0; j < nb_nodes_per_element; ++j) {
- for (UInt k = 0; k < 2; ++k) {
- for (UInt m = 0; m < 2; ++m) {
- UInt index1 = m;
- UInt index2 = (2 - 1) - m;
+ for (Int j = 0; j < nb_nodes_per_element; ++j) {
+ for (Int k = 0; k < 2; ++k) {
+ for (Int m = 0; m < 2; ++m) {
+ auto index1 = m;
+ auto index2 = (2 - 1) - m;
Bvoigt(2, j * 2 + k) += grad_u(k, index1) * B(index2, j);
}
}
}
}
} // namespace akantu
-#endif /* AKANTU_AKA_VOIGTHELPER_TMPL_HH_ */
+//#endif /* __AKANTU_AKA_VOIGTHELPER_TMPL_HH__ */
diff --git a/src/common/aka_warning.hh b/src/common/aka_warning.hh
index 3e13c380f..9218cd685 100644
--- a/src/common/aka_warning.hh
+++ b/src/common/aka_warning.hh
@@ -1,69 +1,73 @@
/**
* @file aka_warning.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Tue Nov 17 2020
*
* @brief file to include to remove some warnings
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
AKANTU_WARNING_IGNORE_UNUSED_PARAMETER
AKANTU_WARNING_IGNORE_VARIADIC_MACRO_ARGUMENTS
**/
// --- Intel warnings ----------------------------------------------------------
#if defined(__INTEL_COMPILER)
#if defined(AKANTU_WARNING_IGNORE_UNUSED_PARAMETER)
#endif
// --- Clang Warnings ----------------------------------------------------------
#elif defined(__clang__) // test clang to be sure that when we test for gnu it
// is only gnu
#pragma clang diagnostic push
#if defined(AKANTU_WARNING_IGNORE_UNUSED_PARAMETER)
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
#if defined(AKANTU_WARNING_IGNORE_VARIADIC_MACRO_ARGUMENTS)
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
// --- GCC warnings ------------------------------------------------------------
#elif (defined(__GNUC__) || defined(__GNUG__))
#define GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION > 40600
#pragma GCC diagnostic push
#endif
#if defined(AKANTU_WARNING_IGNORE_UNUSED_PARAMETER)
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#if defined(AKANTU_WARNING_IGNORE_VARIADIC_MACRO_ARGUMENTS)
#pragma GCC diagnostic ignored "-Wvariadic-macros"
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
+#if defined(AKANTU_EIGEN_WARNING_IGNORE_BOUNDS) && (GCC_VERSION > 120000)
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#pragma GCC diagnostic ignored "-Wuse-after-free"
+#endif
#endif
diff --git a/src/common/aka_warning_restore.hh b/src/common/aka_warning_restore.hh
index 7fa0ae320..75081fadb 100644
--- a/src/common/aka_warning_restore.hh
+++ b/src/common/aka_warning_restore.hh
@@ -1,56 +1,57 @@
/**
* @file aka_warning_restore.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Tue Nov 17 2020
*
* @brief file to include to reactivate the previously deactivatied warnings
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
// --- Intel -------------------------------------------------------------------
#if defined(__INTEL_COMPILER)
//#pragma warning ( disable : 383 )
// --- Clang -------------------------------------------------------------------
#elif defined(__clang__) // test clang to be sure that when we test for gnu it
// is only gnu
#pragma clang diagnostic pop
// --- GCC ---------------------------------------------------------------------
#elif defined(__GNUG__)
#if GCC_VERSION > 40600
#pragma GCC diagnostic pop
#else
#if defined(AKANTU_WARNING_IGNORE_UNUSED_PARAMETER)
#pragma GCC diagnostic warning "-Wunused-parameter"
#endif
#if defined(AKANTU_WARNING_IGNORE_VARIADIC_MACRO_ARGUMENTS)
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
#endif
#endif
#undef AKANTU_WARNING_IGNORE_UNUSED_PARAMETER
#undef AKANTU_WARNING_IGNORE_VARIADIC_MACRO_ARGUMENTS
+#undef AKANTU_EIGEN_WARNING_IGNORE_BOUNDS
diff --git a/src/fe_engine/cohesive_element.hh b/src/fe_engine/cohesive_element.hh
index 2f3a7e9f9..2e3accb0e 100644
--- a/src/fe_engine/cohesive_element.hh
+++ b/src/fe_engine/cohesive_element.hh
@@ -1,91 +1,91 @@
/**
* @file cohesive_element.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief Generates the cohesive element structres (defined in
* element_class.hh)
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COHESIVE_ELEMENT_HH_
#define AKANTU_COHESIVE_ELEMENT_HH_
namespace akantu {
+AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_1d_2, _gt_cohesive_1d_2,
+ _itp_lagrange_point_1, _ek_cohesive, 1,
+ _git_point, 1);
+
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_2d_4, _gt_cohesive_2d_4,
_itp_lagrange_segment_2, _ek_cohesive, 2,
_git_segment, 2);
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_2d_6, _gt_cohesive_2d_6,
_itp_lagrange_segment_3, _ek_cohesive, 2,
_git_segment, 3);
-AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_1d_2, _gt_cohesive_1d_2,
- _itp_lagrange_point_1, _ek_cohesive, 1,
- _git_point, 1);
-
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_6, _gt_cohesive_3d_6,
_itp_lagrange_triangle_3, _ek_cohesive, 3,
_git_triangle, 2);
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_12, _gt_cohesive_3d_12,
_itp_lagrange_triangle_6, _ek_cohesive, 3,
_git_triangle, 3);
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_8, _gt_cohesive_3d_8,
_itp_lagrange_quadrangle_4, _ek_cohesive,
3, _git_segment, 2);
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_cohesive_3d_16, _gt_cohesive_3d_16,
_itp_serendip_quadrangle_8, _ek_cohesive,
3, _git_segment, 3);
template <ElementType> struct CohesiveFacetProperty {
static const ElementType cohesive_type = _not_defined;
};
#define AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(ftype, ctype) \
template <> struct CohesiveFacetProperty<ftype> { \
static const ElementType cohesive_type = ctype; \
}
AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_point_1, _cohesive_1d_2);
AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_segment_2, _cohesive_2d_4);
AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_segment_3, _cohesive_2d_6);
AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_triangle_3, _cohesive_3d_6);
AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_triangle_6, _cohesive_3d_12);
AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_quadrangle_4, _cohesive_3d_8);
AKANTU_DEFINE_COHESIVE_FACET_PROPERTY(_quadrangle_8, _cohesive_3d_16);
} // namespace akantu
#endif /* AKANTU_COHESIVE_ELEMENT_HH_ */
diff --git a/src/fe_engine/element.hh b/src/fe_engine/element.hh
index ccf5f8589..c78eaa880 100644
--- a/src/fe_engine/element.hh
+++ b/src/fe_engine/element.hh
@@ -1,129 +1,108 @@
/**
* @file element.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Tue Sep 29 2020
*
* @brief Element helper class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_HH_
#define AKANTU_ELEMENT_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Element */
/* -------------------------------------------------------------------------- */
class Element {
public:
ElementType type;
- UInt element;
+ Idx element;
GhostType ghost_type;
- // ElementKind kind;
- // ElementType type{_not_defined};
- // UInt element{0};
- // GhostType ghost_type{_not_ghost};
- // ElementKind kind{_ek_regular};
-
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- inline ElementKind kind() const;
+ inline constexpr ElementKind kind() const;
- inline bool operator==(const Element & elem) const {
- return std::tie(type, element, ghost_type) ==
- std::tie(elem.type, elem.element, elem.ghost_type);
+ inline constexpr bool operator==(const Element &elem) const {
+ return std::make_tuple(type, element, ghost_type) ==
+ std::make_tuple(elem.type, elem.element, elem.ghost_type);
}
- inline bool operator!=(const Element & elem) const {
- return std::tie(type, element, ghost_type) !=
- std::tie(elem.type, elem.element, elem.ghost_type);
+ inline constexpr bool operator!=(const Element &elem) const {
+ return std::make_tuple(type, element, ghost_type) !=
+ std::make_tuple(elem.type, elem.element, elem.ghost_type);
}
- // inline bool operator==(const Element & elem) const {
- // return ((element == elem.element) && (type == elem.type) &&
- // (ghost_type == elem.ghost_type) && (kind == elem.kind));
- // }
-
- // inline bool operator!=(const Element & elem) const {
- // return ((element != elem.element) || (type != elem.type) ||
- // (ghost_type != elem.ghost_type) || (kind != elem.kind));
- // }
-
- inline bool operator<(const Element & rhs) const;
+ inline constexpr bool operator<(const Element &rhs) const;
};
+#if __cplusplus < 201703L
namespace {
- const Element ElementNull{_not_defined, UInt(-1), _casper};
- // Element{_not_defined, 0, _casper, _ek_not_defined};
+const Element ElementNull{_not_defined, -1, _casper};
} // namespace
+#else
+inline constexpr Element ElementNull{_not_defined, -1, _casper};
+#endif
/* -------------------------------------------------------------------------- */
-inline bool Element::operator<(const Element & rhs) const {
- // bool res =
- // (rhs == ElementNull) ||
- // ((this->kind < rhs.kind) ||
- // ((this->kind == rhs.kind) &&
- // ((this->ghost_type < rhs.ghost_type) ||
- // ((this->ghost_type == rhs.ghost_type) &&
- // ((this->type < rhs.type) ||
- // ((this->type == rhs.type) && (this->element < rhs.element)))))));
+inline constexpr bool Element::operator<(const Element &rhs) const {
return ((rhs == ElementNull) ||
std::tie(ghost_type, type, element) <
std::tie(rhs.ghost_type, rhs.type, rhs.element));
}
} // namespace akantu
namespace std {
-inline string to_string(const akantu::Element & _this) {
+inline string to_string(const akantu::Element &_this) {
if (_this == akantu::ElementNull) {
return "ElementNull";
}
string str = "Element [" + to_string(_this.type) + ", " +
to_string(_this.element) + ", " + to_string(_this.ghost_type) +
"]";
return str;
}
} // namespace std
namespace akantu {
/// standard output stream operator
-inline std::ostream & operator<<(std::ostream & stream, const Element & _this) {
+inline std::ostream &operator<<(std::ostream &stream, const Element &_this) {
stream << std::to_string(_this);
return stream;
}
} // namespace akantu
#endif /* AKANTU_ELEMENT_HH_ */
diff --git a/src/fe_engine/element_class.hh b/src/fe_engine/element_class.hh
index e13009524..658c8438a 100644
--- a/src/fe_engine/element_class.hh
+++ b/src/fe_engine/element_class.hh
@@ -1,436 +1,494 @@
/**
* @file element_class.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Dec 11 2020
*
* @brief Declaration of the ElementClass main class and the
* Integration and Interpolation elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_types.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_CLASS_HH_
#define AKANTU_ELEMENT_CLASS_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/// default element class structure
template <ElementType element_type> struct ElementClassProperty {
- static const GeometricalType geometrical_type{_gt_not_defined};
- static const InterpolationType interpolation_type{_itp_not_defined};
- static const ElementKind element_kind{_ek_regular};
- static const UInt spatial_dimension{0};
- static const GaussIntegrationType gauss_integration_type{_git_not_defined};
- static const UInt polynomial_degree{0};
+ static constexpr GeometricalType geometrical_type{_gt_not_defined};
+ static constexpr InterpolationType interpolation_type{_itp_not_defined};
+ static constexpr ElementKind element_kind{_ek_regular};
+ static constexpr Int spatial_dimension{0};
+ static constexpr GaussIntegrationType gauss_itegration_type{_git_not_defined};
+ static constexpr Int polynomial_degree{0};
};
#if !defined(DOXYGEN)
/// Macro to generate the element class structures for different element types
#define AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(elem_type, geom_type, \
interp_type, elem_kind, sp, \
gauss_int_type, min_int_order) \
template <> struct ElementClassProperty<elem_type> { \
- static const GeometricalType geometrical_type{geom_type}; \
- static const InterpolationType interpolation_type{interp_type}; \
- static const ElementKind element_kind{elem_kind}; \
- static const UInt spatial_dimension{sp}; \
- static const GaussIntegrationType gauss_integration_type{gauss_int_type}; \
- static const UInt polynomial_degree{min_int_order}; \
+ static constexpr GeometricalType geometrical_type{geom_type}; \
+ static constexpr InterpolationType interpolation_type{interp_type}; \
+ static constexpr ElementKind element_kind{elem_kind}; \
+ static constexpr Int spatial_dimension{sp}; \
+ static constexpr GaussIntegrationType gauss_integration_type{ \
+ gauss_int_type}; \
+ static constexpr Int polynomial_degree{min_int_order}; \
}
#else
#define AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(elem_type, geom_type, \
interp_type, elem_kind, sp, \
gauss_int_type, min_int_order)
#endif
/* -------------------------------------------------------------------------- */
/* Geometry */
/* -------------------------------------------------------------------------- */
/// Default GeometricalShape structure
template <GeometricalType geometrical_type> struct GeometricalShape {
- static const GeometricalShapeType shape{_gst_point};
+ static constexpr GeometricalShapeType shape{_gst_point};
};
/// Templated GeometricalShape with function contains
template <GeometricalShapeType shape> struct GeometricalShapeContains {
- /// Check if the point (vector in 2 and 3D) at natural coordinate coor
- template <class vector_type>
- static inline bool contains(const vector_type & coord);
+ /// Check if the point (vector in 2 and 3D) at natural coordinate coord
+ template <class D>
+ static inline bool contains(const Eigen::MatrixBase<D> & coord);
};
#if !defined(DOXYGEN)
/// Macro to generate the GeometricalShape structures for different geometrical
/// types
#define AKANTU_DEFINE_SHAPE(geom_type, geom_shape) \
template <> struct GeometricalShape<geom_type> { \
- static const GeometricalShapeType shape{geom_shape}; \
+ static constexpr GeometricalShapeType shape{geom_shape}; \
}
AKANTU_DEFINE_SHAPE(_gt_hexahedron_20, _gst_square);
AKANTU_DEFINE_SHAPE(_gt_hexahedron_8, _gst_square);
AKANTU_DEFINE_SHAPE(_gt_pentahedron_15, _gst_prism);
AKANTU_DEFINE_SHAPE(_gt_pentahedron_6, _gst_prism);
AKANTU_DEFINE_SHAPE(_gt_point, _gst_point);
AKANTU_DEFINE_SHAPE(_gt_quadrangle_4, _gst_square);
AKANTU_DEFINE_SHAPE(_gt_quadrangle_8, _gst_square);
AKANTU_DEFINE_SHAPE(_gt_segment_2, _gst_square);
AKANTU_DEFINE_SHAPE(_gt_segment_3, _gst_square);
AKANTU_DEFINE_SHAPE(_gt_tetrahedron_10, _gst_triangle);
AKANTU_DEFINE_SHAPE(_gt_tetrahedron_4, _gst_triangle);
AKANTU_DEFINE_SHAPE(_gt_triangle_3, _gst_triangle);
AKANTU_DEFINE_SHAPE(_gt_triangle_6, _gst_triangle);
#endif
/* -------------------------------------------------------------------------- */
template <GeometricalType geometrical_type>
struct GeometricalElementProperty {};
template <ElementType element_type>
struct ElementClassExtraGeometryProperties {};
/* -------------------------------------------------------------------------- */
/// Templated GeometricalElement with function getInradius
template <GeometricalType geometrical_type,
GeometricalShapeType shape =
GeometricalShape<geometrical_type>::shape>
class GeometricalElement {
using geometrical_property = GeometricalElementProperty<geometrical_type>;
public:
/// compute the in-radius: \todo should be renamed for characteristic length
- static inline Real getInradius(const Matrix<Real> & /*coord*/) {
- AKANTU_TO_IMPLEMENT();
+ template <class D>
+ static inline Real getInradius(const Eigen::MatrixBase<D> & /*X*/) {
+ return 0.;
+ }
+
+ /// compute the normal to the element
+ template <class D1, class D2>
+ static inline void getNormal(const Eigen::MatrixBase<D1> & /*X*/,
+ Eigen::MatrixBase<D2> & n) {
+ n.zero();
}
/// true if the natural coordinates are in the element
- template <class vector_type>
- static inline bool contains(const vector_type & coord);
+ template <class D>
+ static inline bool contains(const Eigen::MatrixBase<D> & coord);
public:
- static AKANTU_GET_MACRO_NOT_CONST(SpatialDimension,
- geometrical_property::spatial_dimension,
- UInt);
- static AKANTU_GET_MACRO_NOT_CONST(NbNodesPerElement,
- geometrical_property::nb_nodes_per_element,
- UInt);
+ static constexpr auto getSpatialDimension() {
+ return geometrical_property::spatial_dimension;
+ }
+ static constexpr auto getNbNodesPerElement() {
+ return geometrical_property::nb_nodes_per_element;
+ }
static inline constexpr auto getNbFacetTypes() {
return geometrical_property::nb_facet_types;
};
- static inline UInt getNbFacetsPerElement(UInt t);
- static inline UInt getNbFacetsPerElement();
- static inline constexpr auto getFacetLocalConnectivityPerElement(UInt t = 0);
+ static inline constexpr Int getNbFacetsPerElement(Idx t);
+ static inline constexpr Int getNbFacetsPerElement();
+
+ static inline constexpr decltype(auto)
+ getFacetLocalConnectivityPerElement(Idx t = 0);
+
+ template <Idx t,
+ std::size_t size = std::tuple_size<
+ decltype(geometrical_property::nb_facets)>::value,
+ std::enable_if_t<(t < size)> * = nullptr>
+ static inline constexpr decltype(auto) getFacetLocalConnectivityPerElement();
+
+ template <Idx t,
+ std::size_t size = std::tuple_size<
+ decltype(geometrical_property::nb_facets)>::value,
+ std::enable_if_t<not(t < size)> * = nullptr>
+ static inline constexpr decltype(auto) getFacetLocalConnectivityPerElement();
};
/* -------------------------------------------------------------------------- */
/* Interpolation */
/* -------------------------------------------------------------------------- */
/// default InterpolationProperty structure
template <InterpolationType interpolation_type> struct InterpolationProperty {};
#if !defined(DOXYGEN)
/// Macro to generate the InterpolationProperty structures for different
/// interpolation types
#define AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(itp_type, itp_kind, \
nb_nodes, ndim) \
template <> struct InterpolationProperty<itp_type> { \
static constexpr InterpolationKind kind{itp_kind}; \
- static constexpr UInt nb_nodes_per_element{nb_nodes}; \
- static constexpr UInt natural_space_dimension{ndim}; \
+ static constexpr Int nb_nodes_per_element{nb_nodes}; \
+ static constexpr Int natural_space_dimension{ndim}; \
}
#else
#define AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(itp_type, itp_kind, \
nb_nodes, ndim)
#endif
/* -------------------------------------------------------------------------- */
/// Generic (templated by the enum InterpolationType which specifies the order
/// and the dimension of the interpolation) class handling the elemental
/// interpolation
template <InterpolationType interpolation_type,
InterpolationKind kind =
InterpolationProperty<interpolation_type>::kind>
class InterpolationElement {
public:
using interpolation_property = InterpolationProperty<interpolation_type>;
/// compute the shape values for a given set of points in natural coordinates
- static inline void computeShapes(const Matrix<Real> & natural_coord,
- Matrix<Real> & N);
+ template <class D1, class D2,
+ aka::enable_if_t<aka::are_matrices<D1, D2>::value> * = nullptr>
+ static inline void computeShapes(const Eigen::MatrixBase<D1> & Xs,
+ const Eigen::MatrixBase<D2> & N_);
/// compute the shape values for a given point in natural coordinates
- template <class vector_type>
- static inline void computeShapes(const vector_type & /*unused*/,
- vector_type & /*unused*/) {
+ template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> * = nullptr>
+ static inline void computeShapes(const Eigen::MatrixBase<D1> & /*Xs*/,
+ Eigen::MatrixBase<D2> & /*N_*/) {
AKANTU_TO_IMPLEMENT();
}
/**
* compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of
* shape functions along with variation of natural coordinates on a given set
* of points in natural coordinates
*/
- static inline void computeDNDS(const Matrix<Real> & natural_coord,
- Tensor3<Real> & dnds);
+ template <class D>
+ static inline void computeDNDS(const Eigen::MatrixBase<D> & Xs,
+ Tensor3Base<Real> & dnds);
/**
* compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of
* shape functions along with
* variation of natural coordinates on a given point in natural
* coordinates
*/
- template <class vector_type, class matrix_type>
- static inline void computeDNDS(const vector_type & /*unused*/,
- matrix_type & /*unused*/) {
+ template <class D1, class D2>
+ static inline void computeDNDS(const Eigen::MatrixBase<D1> & /*Xs*/,
+ Eigen::MatrixBase<D2> & /*dNdS*/) {
AKANTU_TO_IMPLEMENT();
}
/**
* compute @f$ @f$
**/
static inline void computeD2NDS2(const Matrix<Real> & natural_coord,
Tensor3<Real> & d2nds2);
/**
* compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the
* second variation of
* shape functions along with
* variation of natural coordinates on a given point in natural
* coordinates
*/
template <class vector_type, class matrix_type>
static inline void computeD2NDS2(const vector_type & /*unused*/,
matrix_type & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/// compute jacobian (or integration variable change factor) for a given point
/// in the case of spatial_dimension != natural_space_dimension
- static inline void computeSpecialJacobian(const Matrix<Real> & /*unused*/,
- Real & /*unused*/) {
+ template <class D>
+ static inline Real computeSpecialJacobian(const Eigen::MatrixBase<D> &) {
AKANTU_TO_IMPLEMENT();
}
/// interpolate a field given (arbitrary) natural coordinates
- static inline void
- interpolateOnNaturalCoordinates(const Vector<Real> & natural_coords,
- const Matrix<Real> & nodal_values,
- Vector<Real> & interpolated);
+ template <class Derived1, class Derived2>
+ static inline decltype(auto) interpolateOnNaturalCoordinates(
+ const Eigen::MatrixBase<Derived1> & natural_coords,
+ const Eigen::MatrixBase<Derived2> & nodal_values) {
+ using interpolation = InterpolationProperty<interpolation_type>;
+ Eigen::Matrix<Real, interpolation::nb_nodes_per_element, 1> shapes;
+ computeShapes(natural_coords, shapes);
+
+ Matrix<Real, Eigen::Dynamic, 1> res;
+ res.noalias() = interpolate(nodal_values, shapes);
+
+ return res;
+ }
/// interpolate a field given the shape functions on the interpolation point
- static inline void interpolate(const Matrix<Real> & nodal_values,
- const Vector<Real> & shapes,
- Vector<Real> & interpolated);
+ template <class Derived1, class Derived2>
+ static inline auto
+ interpolate(const Eigen::MatrixBase<Derived1> & nodal_values,
+ const Eigen::MatrixBase<Derived2> & shapes);
/// interpolate a field given the shape functions on the interpolations points
- static inline void interpolate(const Matrix<Real> & nodal_values,
- const Matrix<Real> & shapes,
- Matrix<Real> & interpolated);
+ template <class Derived1, class Derived2, class Derived3>
+ static inline void
+ interpolate(const Eigen::MatrixBase<Derived1> & nodal_values,
+ const Eigen::MatrixBase<Derived2> & Ns,
+ const Eigen::MatrixBase<Derived3> & interpolated);
/// compute the gradient of a given field on the given natural coordinates
+ template <class D1, class D2, class D3>
static inline void
- gradientOnNaturalCoordinates(const Vector<Real> & natural_coords,
- const Matrix<Real> & f, Matrix<Real> & gradient);
+ gradientOnNaturalCoordinates(const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & f,
+ const Eigen::MatrixBase<D3> & dfds);
public:
- static AKANTU_GET_MACRO_NOT_CONST(
- ShapeSize,
- InterpolationProperty<interpolation_type>::nb_nodes_per_element, UInt);
- static AKANTU_GET_MACRO_NOT_CONST(
- ShapeDerivativesSize,
- (InterpolationProperty<interpolation_type>::nb_nodes_per_element *
- InterpolationProperty<interpolation_type>::natural_space_dimension),
- UInt);
- static AKANTU_GET_MACRO_NOT_CONST(
- NaturalSpaceDimension,
- InterpolationProperty<interpolation_type>::natural_space_dimension, UInt);
- static AKANTU_GET_MACRO_NOT_CONST(
- NbNodesPerInterpolationElement,
- InterpolationProperty<interpolation_type>::nb_nodes_per_element, UInt);
+ static constexpr auto getShapeSize() {
+ return InterpolationProperty<interpolation_type>::nb_nodes_per_element;
+ }
+ static constexpr auto getShapeDerivativesSize() {
+ return (InterpolationProperty<interpolation_type>::nb_nodes_per_element *
+ InterpolationProperty<interpolation_type>::natural_space_dimension);
+ }
+ static constexpr auto getNaturalSpaceDimension() {
+ return InterpolationProperty<interpolation_type>::natural_space_dimension;
+ }
+ static constexpr auto getNbNodesPerInterpolationElement() {
+ return InterpolationProperty<interpolation_type>::nb_nodes_per_element;
+ }
};
/* -------------------------------------------------------------------------- */
/* Integration */
/* -------------------------------------------------------------------------- */
-template <GaussIntegrationType git_class, UInt nb_points>
+template <GaussIntegrationType git_class, Int nb_points>
struct GaussIntegrationTypeData {
/// quadrature points in natural coordinates
static Real quad_positions[];
/// weights for the Gauss integration
static Real quad_weights[];
};
template <ElementType type,
- UInt n = ElementClassProperty<type>::polynomial_degree>
+ Int n = ElementClassProperty<type>::polynomial_degree>
class GaussIntegrationElement {
+ static constexpr InterpolationType itp_type =
+ ElementClassProperty<type>::interpolation_type;
+ using interpolation_property = InterpolationProperty<itp_type>;
+
public:
- static UInt getNbQuadraturePoints();
- static Matrix<Real> getQuadraturePoints();
- static Vector<Real> getWeights();
+ static constexpr Int getNbQuadraturePoints();
+ static constexpr auto getQuadraturePoints();
+ static constexpr auto getWeights();
};
/* -------------------------------------------------------------------------- */
/* ElementClass */
/* -------------------------------------------------------------------------- */
template <ElementType element_type,
ElementKind element_kind =
ElementClassProperty<element_type>::element_kind>
class ElementClass
: public GeometricalElement<
ElementClassProperty<element_type>::geometrical_type>,
public InterpolationElement<
ElementClassProperty<element_type>::interpolation_type> {
protected:
using geometrical_element =
GeometricalElement<ElementClassProperty<element_type>::geometrical_type>;
using interpolation_element = InterpolationElement<
ElementClassProperty<element_type>::interpolation_type>;
using element_property = ElementClassProperty<element_type>;
using interpolation_property =
typename interpolation_element::interpolation_property;
public:
/**
* compute @f$ J = \frac{\partial x_j}{\partial s_i} @f$ the variation of real
* coordinates along with variation of natural coordinates on a given point in
* natural coordinates
*/
- static inline void computeJMat(const Matrix<Real> & dnds,
- const Matrix<Real> & node_coords,
- Matrix<Real> & J);
+ template <class D1, class D2>
+ static inline decltype(auto)
+ computeJMat(const Eigen::MatrixBase<D1> & dnds,
+ const Eigen::MatrixBase<D2> & node_coords);
/**
* compute the Jacobian matrix by computing the variation of real coordinates
* along with variation of natural coordinates on a given set of points in
* natural coordinates
*/
- static inline void computeJMat(const Tensor3<Real> & dnds,
- const Matrix<Real> & node_coords,
- Tensor3<Real> & J);
+ template <class D>
+ static inline void computeJMat(const Tensor3Base<Real> & dnds,
+ const Eigen::MatrixBase<D> & node_coords,
+ Tensor3Base<Real> & J);
/// compute the jacobians of a serie of natural coordinates
- static inline void computeJacobian(const Matrix<Real> & natural_coords,
- const Matrix<Real> & node_coords,
- Vector<Real> & jacobians);
+ template <class D1, class D2, class D3>
+ static inline void
+ computeJacobian(const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & node_coords,
+ Eigen::MatrixBase<D3> & jacobians);
/// compute jacobian (or integration variable change factor) for a set of
/// points
- static inline void computeJacobian(const Tensor3<Real> & J,
- Vector<Real> & jacobians);
+ template <class D>
+ static inline void computeJacobian(const Tensor3Base<Real> & J,
+ Eigen::MatrixBase<D> & jacobians);
/// compute jacobian (or integration variable change factor) for a given point
- static inline void computeJacobian(const Matrix<Real> & J, Real & jacobians);
+ template <class D>
+ static inline Real computeJacobian(const Eigen::MatrixBase<D> & J);
/// compute shape derivatives (input is dxds) for a set of points
- static inline void computeShapeDerivatives(const Tensor3<Real> & J,
- const Tensor3<Real> & dnds,
- Tensor3<Real> & shape_deriv);
+ static inline void computeShapeDerivatives(const Tensor3Base<Real> & J,
+ const Tensor3Base<Real> & dnds,
+ Tensor3Base<Real> & shape_deriv);
/// compute shape derivatives (input is dxds) for a given point
- static inline void computeShapeDerivatives(const Matrix<Real> & J,
- const Matrix<Real> & dnds,
- Matrix<Real> & shape_deriv);
+ template <class D1, class D2, class D3>
+ static inline void
+ computeShapeDerivatives(const Eigen::MatrixBase<D1> & J,
+ const Eigen::MatrixBase<D2> & dnds,
+ Eigen::MatrixBase<D3> & shape_deriv);
/// compute the normal of a surface defined by the function f
+ template <class D1, class D2, class D3>
static inline void
- computeNormalsOnNaturalCoordinates(const Matrix<Real> & coord,
- Matrix<Real> & f, Matrix<Real> & normals);
+ computeNormalsOnNaturalCoordinates(const Eigen::MatrixBase<D1> & coord,
+ const Eigen::MatrixBase<D2> & f,
+ Eigen::MatrixBase<D3> & normals);
/// get natural coordinates from real coordinates
- static inline void inverseMap(const Vector<Real> & real_coords,
- const Matrix<Real> & node_coords,
- Vector<Real> & natural_coords,
- UInt max_iterations = 100,
+ template <class D1, class D2, class D3,
+ aka::enable_if_vectors_t<D1, D3> * = nullptr>
+ static inline void inverseMap(const Eigen::MatrixBase<D1> & real_coords,
+ const Eigen::MatrixBase<D2> & node_coords,
+ const Eigen::MatrixBase<D3> & natural_coords,
+ Int max_iterations = 100,
Real tolerance = 1e-10);
/// get natural coordinates from real coordinates
- static inline void inverseMap(const Matrix<Real> & real_coords,
- const Matrix<Real> & node_coords,
- Matrix<Real> & natural_coords,
- UInt max_iterations = 100,
+ template <class D1, class D2, class D3,
+ aka::enable_if_matrices_t<D1, D3> * = nullptr>
+ static inline void inverseMap(const Eigen::MatrixBase<D1> & real_coords,
+ const Eigen::MatrixBase<D2> & node_coords,
+ const Eigen::MatrixBase<D3> & natural_coords_,
+ Int max_iterations = 100,
Real tolerance = 1e-10);
public:
- static AKANTU_GET_MACRO_NOT_CONST(Kind, element_kind, ElementKind);
- static constexpr AKANTU_GET_MACRO_NOT_CONST(
- SpatialDimension, ElementClassProperty<element_type>::spatial_dimension,
- UInt);
+ static constexpr auto getKind() { return element_kind; }
+ static constexpr auto getSpatialDimension() {
+ return ElementClassProperty<element_type>::spatial_dimension;
+ }
using element_class_extra_geom_property =
ElementClassExtraGeometryProperties<element_type>;
- static constexpr auto getP1ElementType() {
+ static constexpr decltype(auto) getP1ElementType() {
return element_class_extra_geom_property::p1_type;
}
- static constexpr auto getFacetType(UInt t = 0) {
+ static constexpr decltype(auto) getFacetType(UInt t = 0) {
return element_class_extra_geom_property::facet_type[t];
}
- static constexpr auto getFacetTypes();
+ static constexpr decltype(auto) getFacetTypes();
};
/* -------------------------------------------------------------------------- */
} // namespace akantu
/* -------------------------------------------------------------------------- */
-#include "geometrical_element_property.hh"
#include "interpolation_element_tmpl.hh"
/* -------------------------------------------------------------------------- */
+#include "geometrical_element_property.hh"
+/* -------------------------------------------------------------------------- */
#include "element_class_tmpl.hh"
/* -------------------------------------------------------------------------- */
#include "element_class_hexahedron_8_inline_impl.hh"
#include "element_class_pentahedron_6_inline_impl.hh"
/* keep order */
#include "element_class_hexahedron_20_inline_impl.hh"
#include "element_class_pentahedron_15_inline_impl.hh"
#include "element_class_point_1_inline_impl.hh"
#include "element_class_quadrangle_4_inline_impl.hh"
#include "element_class_quadrangle_8_inline_impl.hh"
#include "element_class_segment_2_inline_impl.hh"
#include "element_class_segment_3_inline_impl.hh"
#include "element_class_tetrahedron_10_inline_impl.hh"
#include "element_class_tetrahedron_4_inline_impl.hh"
#include "element_class_triangle_3_inline_impl.hh"
#include "element_class_triangle_6_inline_impl.hh"
-
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_STRUCTURAL_MECHANICS)
#include "element_class_structural.hh"
#endif
#if defined(AKANTU_COHESIVE_ELEMENT)
#include "cohesive_element.hh"
#endif
#if defined(AKANTU_IGFEM)
#include "element_class_igfem.hh"
#endif
#endif /* AKANTU_ELEMENT_CLASS_HH_ */
diff --git a/src/fe_engine/element_class_helper.hh b/src/fe_engine/element_class_helper.hh
index ed04ebaf7..6d87b8537 100644
--- a/src/fe_engine/element_class_helper.hh
+++ b/src/fe_engine/element_class_helper.hh
@@ -1,75 +1,79 @@
#ifndef ELEMENT_CLASS_HELPER_HH
#define ELEMENT_CLASS_HELPER_HH
#include "element_class.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <ElementKind kind> class ElementClassHelper {};
/* -------------------------------------------------------------------------- */
template <> class ElementClassHelper<_ek_regular> {
public:
static inline Vector<Real> getN(const Vector<Real> & natural_coords,
ElementType type) {
-#define GET_SHAPE_NATURAL(type) \
- auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement(); \
- Vector<Real> shapes(nb_nodes_per_element); \
- ElementClass<type>::computeShapes(natural_coords, shapes); \
- return shapes
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_SHAPE_NATURAL);
-#undef GET_SHAPE_NATURAL
-
- return Vector<Real>(0);
+ return tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ constexpr auto nb_nodes_per_element =
+ ElementClass<type>::getNbNodesPerElement();
+ Vector<Real> shapes(nb_nodes_per_element);
+ ElementClass<type>::computeShapes(natural_coords, shapes);
+ return shapes;
+ },
+ type);
}
/* ------------------------------------------------------------------------ */
static inline Matrix<Real> getDNDS(const Vector<Real> & natural_coords,
ElementType type) {
-#define GET_DNDS_NATURAL(type) \
- auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement(); \
- Matrix<Real> dnds(natural_coords.size(), nb_nodes_per_element); \
- ElementClass<type>::computeDNDS(natural_coords, dnds); \
- return dnds
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_DNDS_NATURAL);
-#undef GET_DNDS_NATURAL
-
- return Matrix<Real>(0, 0);
+ return tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ constexpr auto nb_nodes_per_element =
+ ElementClass<type>::getNbNodesPerElement();
+ Matrix<Real> dnds(natural_coords.size(), nb_nodes_per_element);
+ ElementClass<type>::computeDNDS(natural_coords, dnds);
+ return dnds;
+ },
+ type);
}
/* ------------------------------------------------------------------------ */
static inline Matrix<Real> getD2NDS2(const Vector<Real> & natural_coords,
ElementType type) {
-#define GET_D2ND2S_NATURAL(type) \
- auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement(); \
- auto dim = natural_coords.size(); \
- Matrix<Real> d2nds2(dim * dim, nb_nodes_per_element); \
- ElementClass<type>::computeD2NDS2(natural_coords, d2nds2); \
- return d2nds2
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_D2ND2S_NATURAL);
-#undef GET_D2NDS2_NATURAL
-
- return Matrix<Real>(0, 0);
+ return tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ constexpr auto nb_nodes_per_element =
+ ElementClass<type>::getNbNodesPerElement();
+ auto dim = natural_coords.size();
+ Matrix<Real> d2nds2(dim * dim, nb_nodes_per_element);
+ ElementClass<type>::computeD2NDS2(natural_coords, d2nds2);
+ return d2nds2;
+ },
+ type);
}
/* ------------------------------------------------------------------------ */
static inline Matrix<Real> getJMat(const Vector<Real> & natural_coords,
const Matrix<Real> & positions,
ElementType type) {
-#define GET_JMAT_NATURAL(type) \
- auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement(); \
- Matrix<Real> dnds(natural_coords.size(), nb_nodes_per_element); \
- Matrix<Real> jmat(dnds.rows(), positions.rows()); \
- ElementClass<type>::computeDNDS(natural_coords, dnds); \
- ElementClass<type>::computeJMat(dnds, positions, jmat); \
- return jmat
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_JMAT_NATURAL);
-#undef GET_JMAT_NATURAL
-
- return Matrix<Real>(0, 0);
+ return tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ constexpr auto nb_nodes_per_element =
+ ElementClass<type>::getNbNodesPerElement();
+ Matrix<Real> dnds(natural_coords.size(), nb_nodes_per_element);
+ Matrix<Real> jmat(dnds.rows(), positions.rows());
+ ElementClass<type>::computeDNDS(natural_coords, dnds);
+ jmat = ElementClass<type>::computeJMat(dnds, positions);
+ return jmat;
+ },
+ type);
}
};
} // namespace akantu
#endif // ELEMENT_CLASS_HELPER_H
diff --git a/src/fe_engine/element_class_structural.hh b/src/fe_engine/element_class_structural.hh
index c9d6c569c..5dbb0597d 100644
--- a/src/fe_engine/element_class_structural.hh
+++ b/src/fe_engine/element_class_structural.hh
@@ -1,276 +1,316 @@
/**
* @file element_class_structural.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Spielmann <damien.spielmann@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Mon Feb 01 2021
*
* @brief Specialization of the element classes for structural elements
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "aka_iterators.hh"
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_CLASS_STRUCTURAL_HH_
#define AKANTU_ELEMENT_CLASS_STRUCTURAL_HH_
namespace akantu {
/// Macro to generate the InterpolationProperty structures for different
/// interpolation types
#define AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY( \
itp_type, itp_geom_type, ndof, nb_stress, nb_dnds_cols) \
template <> struct InterpolationProperty<itp_type> { \
- static const InterpolationKind kind{_itk_structural}; \
- static const UInt nb_nodes_per_element{ \
+ static constexpr InterpolationKind kind{_itk_structural}; \
+ static constexpr Int nb_nodes_per_element{ \
InterpolationProperty<itp_geom_type>::nb_nodes_per_element}; \
- static const InterpolationType itp_geometry_type{itp_geom_type}; \
- static const UInt natural_space_dimension{ \
+ static constexpr InterpolationType itp_geometry_type{itp_geom_type}; \
+ static constexpr Int natural_space_dimension{ \
InterpolationProperty<itp_geom_type>::natural_space_dimension}; \
- static const UInt nb_degree_of_freedom{ndof}; \
- static const UInt nb_stress_components{nb_stress}; \
- static const UInt dnds_columns{nb_dnds_cols}; \
+ static constexpr Int nb_degree_of_freedom{ndof}; \
+ static constexpr Int nb_stress_components{nb_stress}; \
+ static constexpr Int dnds_columns{nb_dnds_cols}; \
+ } // namespace akantu
+
+/// Macro to generate the element class structures for different structural
+/// element types
+/* -------------------------------------------------------------------------- */
+#define AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY( \
+ elem_type, geom_type, interp_type, parent_el_type, sp, gauss_int_type, \
+ min_int_order) \
+ template <> struct ElementClassProperty<elem_type> { \
+ static constexpr GeometricalType geometrical_type{geom_type}; \
+ static constexpr InterpolationType interpolation_type{interp_type}; \
+ static constexpr ElementType parent_element_type{parent_el_type}; \
+ static constexpr ElementKind element_kind{_ek_structural}; \
+ static constexpr Int spatial_dimension{sp}; \
+ static constexpr GaussIntegrationType gauss_integration_type{ \
+ gauss_int_type}; \
+ static constexpr Int polynomial_degree{min_int_order}; \
}
+/* -------------------------------------------------------------------------- */
+AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_bernoulli_beam_2,
+ _itp_lagrange_segment_2, 3,
+ 2, 6);
+
+AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_bernoulli_beam_3,
+ _itp_lagrange_segment_2, 6,
+ 4, 6);
+
+AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(_bernoulli_beam_2,
+ _gt_segment_2,
+ _itp_bernoulli_beam_2,
+ _segment_2, 2, _git_segment, 3);
+
+AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(_bernoulli_beam_3,
+ _gt_segment_2,
+ _itp_bernoulli_beam_3,
+ _segment_2, 3, _git_segment, 3);
+/* -------------------------------------------------------------------------- */
+AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(
+ _itp_discrete_kirchhoff_triangle_18, _itp_lagrange_triangle_3, 6, 6, 21);
+
+AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(
+ _discrete_kirchhoff_triangle_18, _gt_triangle_3,
+ _itp_discrete_kirchhoff_triangle_18, _triangle_3, 3, _git_triangle, 2);
+/* -------------------------------------------------------------------------- */
+
/* -------------------------------------------------------------------------- */
template <InterpolationType interpolation_type>
class InterpolationElement<interpolation_type, _itk_structural> {
public:
using interpolation_property = InterpolationProperty<interpolation_type>;
+ /// compute the shape values for a given point in natural coordinates
+ template <class D1, class D2, class D3>
+ static inline void computeShapes(const Eigen::MatrixBase<D1> & natural_coord,
+ const Eigen::MatrixBase<D2> & real_coord,
+ Eigen::MatrixBase<D3> & N);
+
/// compute the shape values for a given set of points in natural coordinates
- static inline void computeShapes(const Matrix<Real> & natural_coord,
- const Matrix<Real> & real_coord,
- const Matrix<Real> & T, Tensor3<Real> & Ns) {
- for (UInt i = 0; i < natural_coord.cols(); ++i) {
- Matrix<Real> N_T = Ns(i);
- Matrix<Real> N(N_T.rows(), N_T.cols());
- computeShapes(natural_coord(i), real_coord, N);
- N_T.mul<false, false>(N, T);
+ template <class D1, class D2, class D3>
+ static inline void computeShapes(const Eigen::MatrixBase<D1> & Xs,
+ const Eigen::MatrixBase<D2> & x,
+ const Eigen::MatrixBase<D3> & T,
+ TensorBase<Real, 3> & Ns) {
+
+ Matrix<Real> N(Ns.size(0), Ns.size(1));
+ for (auto && data : zip(Xs, Ns)) {
+ auto && X = std::get<0>(data);
+ auto && N_T = std::get<1>(data);
+
+ computeShapes(X, x, N);
+
+ N_T = N * T;
}
}
- /// compute the shape values for a given point in natural coordinates
- static inline void computeShapes(const Vector<Real> & natural_coord,
- const Matrix<Real> & real_coord,
- Matrix<Real> & N);
-
- static inline void computeShapesMass(const Matrix<Real> & natural_coords,
- const Matrix<Real> & xs,
- const Matrix<Real> & T,
- Tensor3<Real> & Ns) {
- for (UInt i = 0; i < natural_coords.cols(); ++i) {
- Matrix<Real> N_T = Ns(i);
- Vector<Real> X = natural_coords(i);
+ template <class D1, class D2, class D3>
+ static inline void computeShapesMass(const Eigen::MatrixBase<D1> & Xs,
+ const Eigen::MatrixBase<D2> & x,
+ const Eigen::MatrixBase<D3> & T,
+ TensorBase<Real, 3> & Ns) {
+ for (int i = 0; i < Xs.cols(); ++i) {
+ auto N_T = Ns(i);
+
Matrix<Real> N(interpolation_property::nb_degree_of_freedom, N_T.cols());
+ computeShapes(Xs(i), x, N);
- computeShapes(X, xs, N);
- N_T.mul<false, false>(N.block(0, 0, N_T.rows(), N_T.cols()), T);
+ N_T = N.block(0, 0, N_T.rows(), N_T.cols()) * T;
}
}
/// compute shape derivatives (input is dxds) for a set of points
- static inline void computeShapeDerivatives(const Tensor3<Real> & Js,
- const Tensor3<Real> & DNDSs,
- const Matrix<Real> & R,
- Tensor3<Real> & Bs) {
- for (UInt i = 0; i < Js.size(2); ++i) {
- Matrix<Real> J = Js(i);
- Matrix<Real> DNDS = DNDSs(i);
- Matrix<Real> DNDX(DNDS.rows(), DNDS.cols());
- auto inv_J = J.inverse();
- DNDX.mul<false, false>(inv_J, DNDS);
- Matrix<Real> B_R = Bs(i);
+ template <class D>
+ static inline void computeShapeDerivatives(const TensorBase<Real, 3> & Js,
+ const TensorBase<Real, 3> & DNDSs,
+ const Eigen::MatrixBase<D> & R,
+ TensorBase<Real, 3> & Bs) {
+ for (Int i = 0; i < Js.size(2); ++i) {
+ auto && DNDX = Js(i).inverse() * DNDSs(i);
+ auto && B_R = Bs(i);
Matrix<Real> B(B_R.rows(), B_R.cols());
arrangeInVoigt(DNDX, B);
- B_R.mul<false, false>(B, R);
+ B_R = B * R;
}
}
/**
* compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of
* shape functions along with variation of natural coordinates on a given set
* of points in natural coordinates
*/
- static inline void computeDNDS(const Matrix<Real> & natural_coord,
- const Matrix<Real> & real_coord,
- Tensor3<Real> & dnds) {
- for (UInt i = 0; i < natural_coord.cols(); ++i) {
- Matrix<Real> dnds_t = dnds(i);
- computeDNDS(natural_coord(i), real_coord, dnds_t);
- }
+ template <typename D1, typename D2>
+ static inline void computeDNDS(const Eigen::MatrixBase<D1> & Xs,
+ const Eigen::MatrixBase<D2> & xs,
+ TensorBase<Real, 3> & dnds) {
+ for (auto && data : zip(Xs, dnds))
+ computeDNDS(std::get<0>(data), xs, std::get<1>(data));
}
/**
* compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of
* shape functions along with
* variation of natural coordinates on a given point in natural
* coordinates
*/
- static inline void computeDNDS(const Vector<Real> & natural_coord,
- const Matrix<Real> & real_coord,
- Matrix<Real> & dnds);
+ template <typename D1, typename D2, typename D3>
+ static inline void computeDNDS(const Eigen::MatrixBase<D1> & Xs,
+ const Eigen::MatrixBase<D2> & xs,
+ Eigen::MatrixBase<D3> & dnds);
/**
* arrange B in Voigt notation from DNDS
*/
- static inline void arrangeInVoigt(const Matrix<Real> & dnds,
- Matrix<Real> & B) {
+ template <class D1, class D2>
+ static inline void arrangeInVoigt(const Eigen::MatrixBase<D1> & dnds,
+ Eigen::MatrixBase<D2> & B) {
// Default implementation assumes dnds is already in Voigt notation
- B.deepCopy(dnds);
+ B = dnds;
}
public:
static inline constexpr auto getNbNodesPerInterpolationElement() {
return interpolation_property::nb_nodes_per_element;
}
static inline constexpr auto getShapeSize() {
return interpolation_property::nb_nodes_per_element *
interpolation_property::nb_degree_of_freedom *
interpolation_property::nb_degree_of_freedom;
}
static inline constexpr auto getShapeIndependantSize() {
return interpolation_property::nb_nodes_per_element *
interpolation_property::nb_degree_of_freedom *
interpolation_property::nb_stress_components;
}
static inline constexpr auto getShapeDerivativesSize() {
return interpolation_property::nb_nodes_per_element *
interpolation_property::nb_degree_of_freedom *
interpolation_property::nb_stress_components;
}
static inline constexpr auto getNaturalSpaceDimension() {
return interpolation_property::natural_space_dimension;
}
static inline constexpr auto getNbDegreeOfFreedom() {
return interpolation_property::nb_degree_of_freedom;
}
static inline constexpr auto getNbStressComponents() {
return interpolation_property::nb_stress_components;
}
};
-/// Macro to generate the element class structures for different structural
-/// element types
-/* -------------------------------------------------------------------------- */
-#define AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY( \
- elem_type, geom_type, interp_type, parent_el_type, elem_kind, sp, \
- gauss_int_type, min_int_order) \
- template <> struct ElementClassProperty<elem_type> { \
- static const GeometricalType geometrical_type{geom_type}; \
- static const InterpolationType interpolation_type{interp_type}; \
- static const ElementType parent_element_type{parent_el_type}; \
- static const ElementKind element_kind{elem_kind}; \
- static const UInt spatial_dimension{sp}; \
- static const GaussIntegrationType gauss_integration_type{gauss_int_type}; \
- static const UInt polynomial_degree{min_int_order}; \
- }
-
/* -------------------------------------------------------------------------- */
/* ElementClass for structural elements */
/* -------------------------------------------------------------------------- */
template <ElementType element_type>
class ElementClass<element_type, _ek_structural>
: public GeometricalElement<
ElementClassProperty<element_type>::geometrical_type>,
public InterpolationElement<
ElementClassProperty<element_type>::interpolation_type> {
protected:
using geometrical_element =
GeometricalElement<ElementClassProperty<element_type>::geometrical_type>;
using interpolation_element = InterpolationElement<
ElementClassProperty<element_type>::interpolation_type>;
using parent_element =
ElementClass<ElementClassProperty<element_type>::parent_element_type>;
public:
+ template <class D1, class D2, class D3>
static inline void
- computeRotationMatrix(Matrix<Real> & /*R*/, const Matrix<Real> & /*X*/,
- const Vector<Real> & /*extra_normal*/) {
+ computeRotationMatrix(Eigen::MatrixBase<D1> & /*R*/,
+ const Eigen::MatrixBase<D2> & /*X*/,
+ const Eigen::MatrixBase<D3> & /*extra_normal*/) {
AKANTU_TO_IMPLEMENT();
}
/// compute jacobian (or integration variable change factor) for a given point
- static inline void computeJMat(const Vector<Real> & natural_coords,
- const Matrix<Real> & Xs, Matrix<Real> & J) {
+ template <typename D1, typename D2, typename D3>
+ static inline void computeJMat(const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & Xs,
+ Eigen::MatrixBase<D3> & J) {
Matrix<Real> dnds(Xs.rows(), Xs.cols());
parent_element::computeDNDS(natural_coords, dnds);
- J.mul<false, true>(dnds, Xs);
+ J = dnds * Xs.transpose();
}
- static inline void computeJMat(const Matrix<Real> & natural_coords,
- const Matrix<Real> & Xs, Tensor3<Real> & Js) {
- for (UInt i = 0; i < natural_coords.cols(); ++i) {
- // because non-const l-value reference does not bind to r-value
- Matrix<Real> J = Js(i);
- computeJMat(Vector<Real>(natural_coords(i)), Xs, J);
+ template <typename D1, typename D2>
+ static inline void computeJMat(const Eigen::MatrixBase<D1> & Xs,
+ const Eigen::MatrixBase<D2> & xs,
+ Tensor3<Real> & Js) {
+ for (auto && data : zip(Xs, Js)) {
+ computeJMat(std::get<0>(data), xs, std::get<1>(data));
}
}
- static inline void computeJacobian(const Matrix<Real> & natural_coords,
- const Matrix<Real> & node_coords,
- Vector<Real> & jacobians) {
+ template <typename D1, typename D2, typename D3,
+ std::enable_if_t<aka::is_vector_v<D3>> * = nullptr>
+ static inline void computeJacobian(const Eigen::MatrixBase<D1> & Xs,
+ const Eigen::MatrixBase<D2> & xs,
+ Eigen::MatrixBase<D3> & jacobians) {
using itp = typename interpolation_element::interpolation_property;
Tensor3<Real> Js(itp::natural_space_dimension, itp::natural_space_dimension,
- natural_coords.cols());
- computeJMat(natural_coords, node_coords, Js);
- for (UInt i = 0; i < natural_coords.cols(); ++i) {
- Matrix<Real> J = Js(i);
- jacobians(i) = J.det();
+ Xs.cols());
+ computeJMat(Xs, xs, Js);
+ for (auto && data : zip(jacobians, Js)) {
+ std::get<0>(data) = std::get<1>(data).determinant();
}
}
- static inline void computeRotation(const Matrix<Real> & node_coords,
- Matrix<Real> & rotation);
+ template <typename D1, typename D2>
+ static inline void computeRotation(const Eigen::MatrixBase<D1> & xs,
+ Eigen::MatrixBase<D2> & R);
public:
- static AKANTU_GET_MACRO_NOT_CONST(Kind, _ek_structural, ElementKind);
- static AKANTU_GET_MACRO_NOT_CONST(P1ElementType, _not_defined, ElementType);
- static AKANTU_GET_MACRO_NOT_CONST(FacetType, _not_defined, ElementType);
- static constexpr auto getFacetType(__attribute__((unused)) UInt t = 0) {
+ static constexpr AKANTU_GET_MACRO_AUTO_NOT_CONST(Kind, _ek_structural);
+ static constexpr AKANTU_GET_MACRO_AUTO_NOT_CONST(P1ElementType, _not_defined);
+ static constexpr AKANTU_GET_MACRO_AUTO_NOT_CONST(FacetType, _not_defined);
+ static constexpr auto getFacetType(__attribute__((unused)) Int t = 0) {
return _not_defined;
}
- static constexpr AKANTU_GET_MACRO_NOT_CONST(
- SpatialDimension, ElementClassProperty<element_type>::spatial_dimension,
- UInt);
+ static constexpr AKANTU_GET_MACRO_AUTO_NOT_CONST(
+ SpatialDimension, ElementClassProperty<element_type>::spatial_dimension);
static constexpr auto getFacetTypes() {
return ElementClass<_not_defined>::getFacetTypes();
}
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
#include "element_class_hermite_inline_impl.hh"
/* keep order */
#include "element_class_bernoulli_beam_inline_impl.hh"
#include "element_class_kirchhoff_shell_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_ELEMENT_CLASS_STRUCTURAL_HH_ */
diff --git a/src/fe_engine/element_class_tmpl.hh b/src/fe_engine/element_class_tmpl.hh
index a66857002..5fb2c36d4 100644
--- a/src/fe_engine/element_class_tmpl.hh
+++ b/src/fe_engine/element_class_tmpl.hh
@@ -1,541 +1,589 @@
/**
* @file element_class_tmpl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Thomas Menouillard <tmenouillard@stucky.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Fri Dec 11 2020
*
* @brief Implementation of the inline templated function of the element class
* descriptions
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "element_class.hh"
+//#include "element_class.hh"
+#include "aka_iterators.hh"
#include "gauss_integration_tmpl.hh"
/* -------------------------------------------------------------------------- */
#include <type_traits>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_CLASS_TMPL_HH_
#define AKANTU_ELEMENT_CLASS_TMPL_HH_
namespace akantu {
template <ElementType element_type, ElementKind element_kind>
-inline constexpr auto
+inline constexpr decltype(auto)
ElementClass<element_type, element_kind>::getFacetTypes() {
- return VectorProxy<const ElementType>(
- element_class_extra_geom_property::facet_type.data(),
- geometrical_element::getNbFacetTypes());
+ return Eigen::Map<const Eigen::Matrix<
+ ElementType, geometrical_element::getNbFacetTypes(), 1>>(
+ element_class_extra_geom_property::facet_type.data());
}
/* -------------------------------------------------------------------------- */
/* GeometricalElement */
/* -------------------------------------------------------------------------- */
template <GeometricalType geometrical_type, GeometricalShapeType shape>
-inline constexpr auto
+template <Idx t, std::size_t size, std::enable_if_t<not(t < size)> *>
+inline constexpr decltype(auto)
GeometricalElement<geometrical_type,
- shape>::getFacetLocalConnectivityPerElement(UInt t) {
- int pos = 0;
- for (UInt i = 0; i < t; ++i) {
+ shape>::getFacetLocalConnectivityPerElement() {
+ throw std::range_error("Not a valid facet id for this element type");
+}
+
+template <GeometricalType geometrical_type, GeometricalShapeType shape>
+template <Idx t, std::size_t size, std::enable_if_t<(t < size)> *>
+inline constexpr decltype(auto)
+GeometricalElement<geometrical_type,
+ shape>::getFacetLocalConnectivityPerElement() {
+ Int pos = 0;
+ for (Int i = 0; i < t; ++i) {
+ pos += geometrical_property::nb_facets[i] *
+ geometrical_property::nb_nodes_per_facet[i];
+ }
+
+ return Eigen::Map<
+ const Eigen::Matrix<Idx, geometrical_property::nb_facets[t],
+ geometrical_property::nb_nodes_per_facet[t]>>(
+ geometrical_property::facet_connectivity_vect.data() + pos);
+}
+
+/* -------------------------------------------------------------------------- */
+template <GeometricalType geometrical_type, GeometricalShapeType shape>
+inline constexpr decltype(auto)
+GeometricalElement<geometrical_type,
+ shape>::getFacetLocalConnectivityPerElement(Idx t) {
+
+ Int pos = 0;
+ for (Int i = 0; i < t; ++i) {
pos += geometrical_property::nb_facets[i] *
geometrical_property::nb_nodes_per_facet[i];
}
- return MatrixProxy<const UInt>(
+ return Eigen::Map<const Eigen::Matrix<Idx, Eigen::Dynamic, Eigen::Dynamic>>(
geometrical_property::facet_connectivity_vect.data() + pos,
geometrical_property::nb_facets[t],
geometrical_property::nb_nodes_per_facet[t]);
}
/* -------------------------------------------------------------------------- */
template <GeometricalType geometrical_type, GeometricalShapeType shape>
-inline UInt
+inline constexpr Int
GeometricalElement<geometrical_type, shape>::getNbFacetsPerElement() {
- UInt total_nb_facets = 0;
- for (UInt n = 0; n < geometrical_property::nb_facet_types; ++n) {
+ Int total_nb_facets = 0;
+ for (Int n = 0; n < geometrical_property::nb_facet_types; ++n) {
total_nb_facets += geometrical_property::nb_facets[n];
}
return total_nb_facets;
}
/* -------------------------------------------------------------------------- */
template <GeometricalType geometrical_type, GeometricalShapeType shape>
-inline UInt
-GeometricalElement<geometrical_type, shape>::getNbFacetsPerElement(UInt t) {
+inline constexpr Int
+GeometricalElement<geometrical_type, shape>::getNbFacetsPerElement(Idx t) {
return geometrical_property::nb_facets[t];
}
/* -------------------------------------------------------------------------- */
template <GeometricalType geometrical_type, GeometricalShapeType shape>
-template <class vector_type>
+template <class D>
inline bool GeometricalElement<geometrical_type, shape>::contains(
- const vector_type & coords) {
+ const Eigen::MatrixBase<D> & coords) {
return GeometricalShapeContains<shape>::contains(coords);
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
-inline bool
-GeometricalShapeContains<_gst_point>::contains(const vector_type & coords) {
+template <class D>
+inline bool GeometricalShapeContains<_gst_point>::contains(
+ const Eigen::MatrixBase<D> & coords) {
return (coords(0) < std::numeric_limits<Real>::epsilon());
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
-inline bool
-GeometricalShapeContains<_gst_square>::contains(const vector_type & coords) {
+template <class D>
+inline bool GeometricalShapeContains<_gst_square>::contains(
+ const Eigen::MatrixBase<D> & coords) {
bool in = true;
- for (UInt i = 0; i < coords.size() && in; ++i) {
+ for (Int i = 0; i < coords.size() && in; ++i) {
in &= ((coords(i) >= -(1. + std::numeric_limits<Real>::epsilon())) &&
(coords(i) <= (1. + std::numeric_limits<Real>::epsilon())));
}
return in;
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
-inline bool
-GeometricalShapeContains<_gst_triangle>::contains(const vector_type & coords) {
+template <class D>
+inline bool GeometricalShapeContains<_gst_triangle>::contains(
+ const Eigen::MatrixBase<D> & coords) {
bool in = true;
Real sum = 0;
- for (UInt i = 0; (i < coords.size()) && in; ++i) {
+ for (Int i = 0; (i < coords.size()) && in; ++i) {
in &= ((coords(i) >= -(Math::getTolerance())) &&
(coords(i) <= (1. + Math::getTolerance())));
sum += coords(i);
}
if (in) {
return (in && (sum <= (1. + Math::getTolerance())));
}
return in;
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
-inline bool
-GeometricalShapeContains<_gst_prism>::contains(const vector_type & coords) {
+template <class D>
+inline bool GeometricalShapeContains<_gst_prism>::contains(
+ const Eigen::MatrixBase<D> & coords) {
bool in = ((coords(0) >= -1.) && (coords(0) <= 1.)); // x in segment [-1, 1]
// y and z in triangle
in &= ((coords(1) >= 0) && (coords(1) <= 1.));
in &= ((coords(2) >= 0) && (coords(2) <= 1.));
Real sum = coords(1) + coords(2);
return (in && (sum <= 1));
}
/* -------------------------------------------------------------------------- */
/* InterpolationElement */
/* -------------------------------------------------------------------------- */
template <InterpolationType interpolation_type, InterpolationKind kind>
+template <typename D1, typename D2,
+ aka::enable_if_t<aka::are_matrices<D1, D2>::value> *>
inline void InterpolationElement<interpolation_type, kind>::computeShapes(
- const Matrix<Real> & natural_coord, Matrix<Real> & N) {
- UInt nb_points = natural_coord.cols();
- for (UInt p = 0; p < nb_points; ++p) {
- Vector<Real> Np(N(p));
- Vector<Real> ncoord_p(natural_coord(p));
- computeShapes(ncoord_p, Np);
+ const Eigen::MatrixBase<D1> & Xs, const Eigen::MatrixBase<D2> & N_) {
+
+ Eigen::MatrixBase<D2> & N = const_cast<Eigen::MatrixBase<D2> &>(
+ N_); // as advised by the Eigen developers
+
+ for (auto && data : zip(Xs, N)) {
+ computeShapes(std::get<0>(data), std::get<1>(data));
}
}
/* -------------------------------------------------------------------------- */
template <InterpolationType interpolation_type, InterpolationKind kind>
+template <class D>
inline void InterpolationElement<interpolation_type, kind>::computeDNDS(
- const Matrix<Real> & natural_coord, Tensor3<Real> & dnds) {
- UInt nb_points = natural_coord.cols();
- for (UInt p = 0; p < nb_points; ++p) {
- Matrix<Real> dnds_p(dnds(p));
- Vector<Real> ncoord_p(natural_coord(p));
- computeDNDS(ncoord_p, dnds_p);
+ const Eigen::MatrixBase<D> & Xs, Tensor3Base<Real> & dNdS) {
+ for (auto && data : zip(Xs, dNdS)) {
+ computeDNDS(std::get<0>(data), std::get<1>(data));
}
}
/* -------------------------------------------------------------------------- */
/**
* interpolate on a point a field for which values are given on the
* node of the element using the shape functions at this interpolation point
*
* @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j}
*@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$
*nb_degree_of_freedom
* @param shapes value of shape functions at the interpolation point
- * @param interpolated interpolated value of f @f$ f_j(\xi) = \sum_i f_{n_i j}
- *N_i @f$
+ * @param interpolated interpolated value of f @f$ f_j(\xi) = \sum_i f_{n_i
+ j} *N_i @f$
*/
template <InterpolationType interpolation_type, InterpolationKind kind>
-inline void InterpolationElement<interpolation_type, kind>::interpolate(
- const Matrix<Real> & nodal_values, const Vector<Real> & shapes,
- Vector<Real> & interpolated) {
- Matrix<Real> interpm(interpolated.storage(), nodal_values.rows(), 1);
- Matrix<Real> shapesm(
- shapes.storage(),
- InterpolationProperty<interpolation_type>::nb_nodes_per_element, 1);
- interpm.mul<false, false>(nodal_values, shapesm);
+template <typename Derived1, typename Derived2>
+inline auto InterpolationElement<interpolation_type, kind>::interpolate(
+ const Eigen::MatrixBase<Derived1> & nodal_values,
+ const Eigen::MatrixBase<Derived2> & shapes) {
+ return nodal_values * shapes;
}
/* -------------------------------------------------------------------------- */
/**
* interpolate on several points a field for which values are given on the
* node of the element using the shape functions at the interpolation point
*
* @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j}
*@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$
*nb_degree_of_freedom
* @param shapes value of shape functions at the interpolation point
* @param interpolated interpolated values of f @f$ f_j(\xi) = \sum_i f_{n_i j}
*N_i @f$
*/
template <InterpolationType interpolation_type, InterpolationKind kind>
+template <typename Derived1, typename Derived2, typename Derived3>
inline void InterpolationElement<interpolation_type, kind>::interpolate(
- const Matrix<Real> & nodal_values, const Matrix<Real> & shapes,
- Matrix<Real> & interpolated) {
- UInt nb_points = shapes.cols();
- for (UInt p = 0; p < nb_points; ++p) {
- Vector<Real> Np(shapes(p));
- Vector<Real> interpolated_p(interpolated(p));
- interpolate(nodal_values, Np, interpolated_p);
+ const Eigen::MatrixBase<Derived1> & nodal_values,
+ const Eigen::MatrixBase<Derived2> & Ns,
+ const Eigen::MatrixBase<Derived3> & interpolated_) {
+
+ auto && interpolated = const_cast<Eigen::MatrixBase<Derived3> &>(
+ interpolated_); // as advised by the Eigen developers
+
+ auto nb_points = Ns.cols();
+ for (auto p = 0; p < nb_points; ++p) {
+ interpolated.col(p).noalias() = interpolate(nodal_values, Ns.col(p));
}
}
/* -------------------------------------------------------------------------- */
/**
* interpolate the field on a point given in natural coordinates the field which
* values are given on the node of the element
*
* @param natural_coords natural coordinates of point where to interpolate \xi
* @param nodal_values values of the function per node @f$ f_{ij} = f_{n_i j}
*@f$ so it should be a matrix of size nb_nodes_per_element @f$\times@f$
*nb_degree_of_freedom
* @param interpolated interpolated value of f @f$ f_j(\xi) = \sum_i f_{n_i j}
*N_i @f$
*/
-template <InterpolationType interpolation_type, InterpolationKind kind>
-inline void
-InterpolationElement<interpolation_type, kind>::interpolateOnNaturalCoordinates(
- const Vector<Real> & natural_coords, const Matrix<Real> & nodal_values,
- Vector<Real> & interpolated) {
- Vector<Real> shapes(
- InterpolationProperty<interpolation_type>::nb_nodes_per_element);
- computeShapes(natural_coords, shapes);
-
- interpolate(nodal_values, shapes, interpolated);
-}
+// template <InterpolationType interpolation_type, InterpolationKind kind>
+// inline decltype(auto)
+// InterpolationElement<interpolation_type,
+// kind>::interpolateOnNaturalCoordinates(
+// const Ref<const VectorXr> & natural_coords,
+// const Ref<const MatrixXr> & nodal_values, Ref<VectorXr> interpolated) {
+// using interpolation = InterpolationProperty<interpolation_type>;
+// Eigen::Matrix<Real, interpolation::nb_nodes_per_element, 1> shapes;
+// computeShapes(natural_coords, shapes);
+
+// return interpolate(nodal_values, shapes);
+// }
/* -------------------------------------------------------------------------- */
/// @f$ gradient_{ij} = \frac{\partial f_j}{\partial s_i} = \sum_k
/// \frac{\partial N_k}{\partial s_i}f_{j n_k} @f$
template <InterpolationType interpolation_type, InterpolationKind kind>
+template <typename D1, typename D2, typename D3>
inline void
InterpolationElement<interpolation_type, kind>::gradientOnNaturalCoordinates(
- const Vector<Real> & natural_coords, const Matrix<Real> & f,
- Matrix<Real> & gradient) {
- Matrix<Real> dnds(
- InterpolationProperty<interpolation_type>::natural_space_dimension,
- InterpolationProperty<interpolation_type>::nb_nodes_per_element);
+ const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & f, const Eigen::MatrixBase<D3> & dfds_) {
+
+ constexpr auto nsp =
+ InterpolationProperty<interpolation_type>::natural_space_dimension;
+ constexpr auto nnodes =
+ InterpolationProperty<interpolation_type>::nb_nodes_per_element;
+ Eigen::Matrix<Real, D3::ColsAtCompileTime, D2::ColsAtCompileTime> dnds(
+ nsp, nnodes);
+ auto & dfds = const_cast<Eigen::MatrixBase<D3> &>(dfds_);
computeDNDS(natural_coords, dnds);
- gradient.mul<false, true>(f, dnds);
+ dfds.noalias() = f * dnds.transpose();
}
/* -------------------------------------------------------------------------- */
/* ElementClass */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
-inline void
-ElementClass<type, kind>::computeJMat(const Tensor3<Real> & dnds,
- const Matrix<Real> & node_coords,
- Tensor3<Real> & J) {
- UInt nb_points = dnds.size(2);
- for (UInt p = 0; p < nb_points; ++p) {
- Matrix<Real> J_p(J(p));
- Matrix<Real> dnds_p(dnds(p));
- computeJMat(dnds_p, node_coords, J_p);
- }
+template <class D1, class D2>
+inline decltype(auto) ElementClass<type, kind>::computeJMat(
+ const Eigen::MatrixBase<D1> & dnds,
+ const Eigen::MatrixBase<D2> & node_coords) {
+ /// @f$ J = dxds = dnds * x @f$
+ return dnds * node_coords.transpose();
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
+template <class D>
inline void
-ElementClass<type, kind>::computeJMat(const Matrix<Real> & dnds,
- const Matrix<Real> & node_coords,
- Matrix<Real> & J) {
- /// @f$ J = dxds = dnds * x @f$
- J.mul<false, true>(dnds, node_coords);
+ElementClass<type, kind>::computeJMat(const Tensor3Base<Real> & dnds,
+ const Eigen::MatrixBase<D> & node_coords,
+ Tensor3Base<Real> & J) {
+ for (auto && data : zip(J, dnds)) {
+ std::get<0>(data) = computeJMat(std::get<1>(data), node_coords);
+ }
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
-inline void
-ElementClass<type, kind>::computeJacobian(const Matrix<Real> & natural_coords,
- const Matrix<Real> & node_coords,
- Vector<Real> & jacobians) {
- UInt nb_points = natural_coords.cols();
- Matrix<Real> dnds(interpolation_property::natural_space_dimension,
- interpolation_property::nb_nodes_per_element);
+template <class D1, class D2, class D3>
+inline void ElementClass<type, kind>::computeJacobian(
+ const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & node_coords,
+ Eigen::MatrixBase<D3> & jacobians) {
+ auto nb_points = natural_coords.cols();
+ Matrix<Real, interpolation_property::natural_space_dimension,
+ interpolation_property::nb_nodes_per_element>
+ dnds;
Matrix<Real> J(natural_coords.rows(), node_coords.rows());
- for (UInt p = 0; p < nb_points; ++p) {
- Vector<Real> ncoord_p(natural_coords(p));
- interpolation_element::computeDNDS(ncoord_p, dnds);
- computeJMat(dnds, node_coords, J);
- computeJacobian(J, jacobians(p));
+ for (Int p = 0; p < nb_points; ++p) {
+ interpolation_element::computeDNDS(natural_coords.col(p), dnds);
+ J = computeJMat(dnds, node_coords);
+ jacobians(p) = computeJacobian(J);
}
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
+template <class D>
inline void
-ElementClass<type, kind>::computeJacobian(const Tensor3<Real> & J,
- Vector<Real> & jacobians) {
- UInt nb_points = J.size(2);
- for (UInt p = 0; p < nb_points; ++p) {
- computeJacobian(J(p), jacobians(p));
+ElementClass<type, kind>::computeJacobian(const Tensor3Base<Real> & J,
+ Eigen::MatrixBase<D> & jacobians) {
+ auto nb_points = J.size(2);
+ for (Int p = 0; p < nb_points; ++p) {
+ computeJacobian(J(p), jacobians.col(p));
}
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
-inline void ElementClass<type, kind>::computeJacobian(const Matrix<Real> & J,
- Real & jacobians) {
+template <class D>
+inline Real
+ElementClass<type, kind>::computeJacobian(const Eigen::MatrixBase<D> & J) {
if (J.rows() == J.cols()) {
- jacobians = Math::det<element_property::spatial_dimension>(J.storage());
+ return J.determinant();
} else {
- interpolation_element::computeSpecialJacobian(J, jacobians);
+ switch (interpolation_property::natural_space_dimension) {
+ case 1: {
+ return J.norm();
+ }
+ case 2: {
+ auto Jstatic =
+ Eigen::Map<const Eigen::Matrix<Real, 2, 3>>(J.derived().data());
+ return (Jstatic.row(0)).cross(Jstatic.row(1)).norm();
+ }
+ default: {
+ return 0;
+ }
+ }
}
+ return 0; // avoids a warning
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
-inline void
-ElementClass<type, kind>::computeShapeDerivatives(const Tensor3<Real> & J,
- const Tensor3<Real> & dnds,
- Tensor3<Real> & shape_deriv) {
- UInt nb_points = J.size(2);
- for (UInt p = 0; p < nb_points; ++p) {
- Matrix<Real> shape_deriv_p(shape_deriv(p));
- computeShapeDerivatives(J(p), dnds(p), shape_deriv_p);
- }
+template <class D1, class D2, class D3>
+inline void ElementClass<type, kind>::computeShapeDerivatives(
+ const Eigen::MatrixBase<D1> & J, const Eigen::MatrixBase<D2> & dnds,
+ Eigen::MatrixBase<D3> & shape_deriv) {
+ shape_deriv = J.inverse() * dnds;
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
-inline void
-ElementClass<type, kind>::computeShapeDerivatives(const Matrix<Real> & J,
- const Matrix<Real> & dnds,
- Matrix<Real> & shape_deriv) {
- Matrix<Real> inv_J(J.rows(), J.cols());
- Math::inv<element_property::spatial_dimension>(J.storage(), inv_J.storage());
-
- shape_deriv.mul<false, false>(inv_J, dnds);
+inline void ElementClass<type, kind>::computeShapeDerivatives(
+ const Tensor3Base<Real> & J, const Tensor3Base<Real> & dnds,
+ Tensor3Base<Real> & shape_deriv) {
+ auto nb_points = J.size(2);
+ for (Int p = 0; p < nb_points; ++p) {
+ auto && J_ = J(p);
+ auto && dnds_ = dnds(p);
+ auto && dndx_ = shape_deriv(p);
+ dndx_ = J_.inverse() * dnds_;
+ // computeShapeDerivatives(J_, dnds_, dndx_);
+ }
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
+template <class D1, class D2, class D3>
inline void ElementClass<type, kind>::computeNormalsOnNaturalCoordinates(
- const Matrix<Real> & coord, Matrix<Real> & f, Matrix<Real> & normals) {
- UInt dimension = normals.rows();
- UInt nb_points = coord.cols();
+ const Eigen::MatrixBase<D1> & coord, const Eigen::MatrixBase<D2> & f,
+ Eigen::MatrixBase<D3> & normals) {
+ auto dimension = normals.rows();
+ auto nb_points = coord.cols();
- AKANTU_DEBUG_ASSERT((dimension - 1) ==
- interpolation_property::natural_space_dimension,
+ constexpr auto ndim = interpolation_property::natural_space_dimension;
+ AKANTU_DEBUG_ASSERT((dimension - 1) == ndim,
"cannot extract a normal because of dimension mismatch "
- << dimension - 1 << " "
- << interpolation_property::natural_space_dimension);
+ << dimension - 1 << " " << ndim);
- Matrix<Real> J(dimension, interpolation_property::natural_space_dimension);
- for (UInt p = 0; p < nb_points; ++p) {
- interpolation_element::gradientOnNaturalCoordinates(coord(p), f, J);
+ Matrix<Real, Eigen::Dynamic, ndim> J(dimension, ndim);
+ for (Int p = 0; p < nb_points; ++p) {
+ interpolation_element::gradientOnNaturalCoordinates(coord.col(p), f, J);
if (dimension == 2) {
- Math::normal2(J.storage(), normals(p).storage());
+ normals.col(p) = Math::normal(J);
}
if (dimension == 3) {
- Math::normal3(J(0).storage(), J(1).storage(), normals(p).storage());
+ normals.col(p) = Math::normal(J.col(0), J.col(1));
}
}
}
/* ------------------------------------------------------------------------- */
/**
* In the non linear cases we need to iterate to find the natural coordinates
*@f$\xi@f$
* provided real coordinates @f$x@f$.
*
* We want to solve: @f$ x- \phi(\xi) = 0@f$ with @f$\phi(\xi) = \sum_I N_I(\xi)
*x_I@f$
* the mapping function which uses the nodal coordinates @f$x_I@f$.
*
* To that end we use the Newton method and the following series:
*
* @f$ \frac{\partial \phi(x_k)}{\partial \xi} \left( \xi_{k+1} - \xi_k \right)
*= x - \phi(x_k)@f$
*
* When we consider elements embedded in a dimension higher than them (2D
*triangle in a 3D space for example)
* @f$ J = \frac{\partial \phi(\xi_k)}{\partial \xi}@f$ is of dimension
*@f$dim_{space} \times dim_{elem}@f$ which
* is not invertible in most cases. Rather we can solve the problem:
*
* @f$ J^T J \left( \xi_{k+1} - \xi_k \right) = J^T \left( x - \phi(\xi_k)
*\right) @f$
*
* So that
*
* @f$ d\xi = \xi_{k+1} - \xi_k = (J^T J)^{-1} J^T \left( x - \phi(\xi_k)
*\right) @f$
*
* So that if the series converges we have:
*
* @f$ 0 = J^T \left( \phi(\xi_\infty) - x \right) @f$
*
* And we see that this is ill-posed only if @f$ J^T x = 0@f$ which means that
*the vector provided
* is normal to any tangent which means it is outside of the element itself.
*
* @param real_coords: the real coordinates the natural coordinates are sought
*for
* @param node_coords: the coordinates of the nodes forming the element
* @param natural_coords: output->the sought natural coordinates
* @param spatial_dimension: spatial dimension of the problem
*
**/
template <ElementType type, ElementKind kind>
+template <class D1, class D2, class D3, aka::enable_if_vectors_t<D1, D3> *>
inline void ElementClass<type, kind>::inverseMap(
- const Vector<Real> & real_coords, const Matrix<Real> & node_coords,
- Vector<Real> & natural_coords, UInt max_iterations, Real tolerance) {
- UInt spatial_dimension = real_coords.size();
- UInt dimension = natural_coords.size();
+ const Eigen::MatrixBase<D1> & real_coords,
+ const Eigen::MatrixBase<D2> & node_coords,
+ const Eigen::MatrixBase<D3> & natural_coords_, Int max_iterations,
+ Real tolerance) {
+ auto & natural_coords = const_cast<Eigen::MatrixBase<D3> &>(
+ natural_coords_); // as advised by the Eigen developers
+
+ auto spatial_dimension = real_coords.size();
+ constexpr auto dimension = getSpatialDimension();
// matrix copy of the real_coords
- Matrix<Real> mreal_coords(real_coords.storage(), spatial_dimension, 1);
+ // MatrixProxy<const Real> mreal_coords(real_coords.data(),
+ // spatial_dimension,
+ // 1);
// initial guess
natural_coords.zero();
// real space coordinates provided by initial guess
- Matrix<Real> physical_guess(spatial_dimension, 1);
+ Vector<Real> physical_guess(spatial_dimension);
// objective function f = real_coords - physical_guess
- Matrix<Real> f(spatial_dimension, 1);
-
- // J Jacobian matrix computed on the natural_guess
- Matrix<Real> J(dimension, spatial_dimension);
-
- // J^t
- Matrix<Real> Jt(spatial_dimension, dimension);
+ Vector<Real> f(spatial_dimension);
// G = J^t * J
Matrix<Real> G(dimension, dimension);
- // Ginv = G^{-1}
- Matrix<Real> Ginv(dimension, dimension);
-
- // J = Ginv * J^t
+ // F = G.inverse() * J^t
Matrix<Real> F(spatial_dimension, dimension);
- // dxi = \xi_{k+1} - \xi in the iterative process
- Matrix<Real> dxi(dimension, 1);
+ // J^t
+ Matrix<Real> Jt(spatial_dimension, dimension);
- Matrix<Real> dxit(1, dimension);
+ // dxi = \xi_{k+1} - \xi in the iterative process
+ Vector<Real> dxi(dimension);
/* --------------------------- */
/* init before iteration loop */
/* --------------------------- */
// do interpolation
auto update_f = [&f, &physical_guess, &natural_coords, &node_coords,
- &mreal_coords, spatial_dimension]() {
- Vector<Real> physical_guess_v(physical_guess.storage(), spatial_dimension);
- interpolation_element::interpolateOnNaturalCoordinates(
- natural_coords, node_coords, physical_guess_v);
+ &real_coords]() {
+ physical_guess = interpolation_element::interpolateOnNaturalCoordinates(
+ natural_coords, node_coords);
- // compute initial objective function value f = real_coords - physical_guess
- f = mreal_coords;
- f -= physical_guess;
+ // compute initial objective function value f = real_coords -
+ // physical_guess
+ f = real_coords - physical_guess;
// compute initial error
- auto error = f.norm<L_2>();
+ auto error = f.norm();
return error;
};
auto inverse_map_error = update_f();
/* --------------------------- */
/* iteration loop */
/* --------------------------- */
- UInt iterations{0};
+ Int iterations{0};
while (tolerance < inverse_map_error and iterations < max_iterations) {
// compute J^t
interpolation_element::gradientOnNaturalCoordinates(natural_coords,
node_coords, Jt);
- J = Jt.transpose();
-
// compute G
- G.mul<false, true>(J, J);
-
- // inverse G
- Ginv.inverse(G);
+ G = Jt.transpose() * Jt;
// compute F
- F.mul<true, false>(J, Ginv);
+ F = Jt * G.inverse();
// compute increment
- dxit.mul<true, false>(f, F);
-
- dxi = dxit.transpose();
+ dxi = F.transpose() * f;
// update our guess
- natural_coords += Vector<Real>(dxi(0));
+ natural_coords += dxi;
inverse_map_error = update_f();
iterations++;
}
if (iterations >= max_iterations) {
AKANTU_EXCEPTION("The solver in inverse map did not converge");
}
}
/* -------------------------------------------------------------------------- */
template <ElementType type, ElementKind kind>
+template <class D1, class D2, class D3, aka::enable_if_matrices_t<D1, D3> *>
inline void ElementClass<type, kind>::inverseMap(
- const Matrix<Real> & real_coords, const Matrix<Real> & node_coords,
- Matrix<Real> & natural_coords, UInt max_iterations, Real tolerance) {
- UInt nb_points = real_coords.cols();
- for (UInt p = 0; p < nb_points; ++p) {
- Vector<Real> X(real_coords(p));
- Vector<Real> ncoord_p(natural_coords(p));
- inverseMap(X, node_coords, ncoord_p, max_iterations, tolerance);
+ const Eigen::MatrixBase<D1> & real_coords,
+ const Eigen::MatrixBase<D2> & node_coords,
+ const Eigen::MatrixBase<D3> & natural_coords_, Int max_iterations,
+ Real tolerance) {
+ auto & natural_coords = const_cast<Eigen::MatrixBase<D2> &>(
+ natural_coords_); // as advised by the Eigen developers
+
+ auto nb_points = real_coords.cols();
+ for (Int p = 0; p < nb_points; ++p) {
+ inverseMap(real_coords(p), node_coords, natural_coords(p), max_iterations,
+ tolerance);
}
}
} // namespace akantu
#endif /* AKANTU_ELEMENT_CLASS_TMPL_HH_ */
diff --git a/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.hh b/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.hh
index 7adc2af0d..23b0352e2 100644
--- a/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.hh
@@ -1,238 +1,226 @@
/**
* @file element_class_bernoulli_beam_inline_impl.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jul 15 2011
* @date last modification: Fri Feb 05 2021
*
* @brief Specialization of the element_class class for the type
* _bernoulli_beam_2
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
--x-----q1----|----q2-----x---> x
-1 0 1
@endverbatim
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_static_if.hh"
-#include "element_class_structural.hh"
-//#include "aka_element_classes_info.hh"
+//#include "element_class_structural.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_CLASS_BERNOULLI_BEAM_INLINE_IMPL_HH_
#define AKANTU_ELEMENT_CLASS_BERNOULLI_BEAM_INLINE_IMPL_HH_
namespace akantu {
-/* -------------------------------------------------------------------------- */
-AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_bernoulli_beam_2,
- _itp_lagrange_segment_2, 3,
- 2, 6);
-
-AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_bernoulli_beam_3,
- _itp_lagrange_segment_2, 6,
- 4, 6);
-
-AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(_bernoulli_beam_2,
- _gt_segment_2,
- _itp_bernoulli_beam_2,
- _segment_2, _ek_structural, 2,
- _git_segment, 3);
-
-AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(_bernoulli_beam_3,
- _gt_segment_2,
- _itp_bernoulli_beam_3,
- _segment_2, _ek_structural, 3,
- _git_segment, 3);
/* -------------------------------------------------------------------------- */
template <>
+template <typename D1, typename D2, typename D3>
inline void
InterpolationElement<_itp_bernoulli_beam_2, _itk_structural>::computeShapes(
- const Vector<Real> & natural_coords, const Matrix<Real> & real_coord,
- Matrix<Real> & N) {
- Vector<Real> L(2);
+ const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & real_coord, Eigen::MatrixBase<D3> & N) {
+ Eigen::Matrix<Real, 2, 1> L;
InterpolationElement<_itp_lagrange_segment_2, _itk_lagrangian>::computeShapes(
natural_coords, L);
- Matrix<Real> H(2, 4);
+ Eigen::Matrix<Real, 2, 4> H;
InterpolationElement<_itp_hermite_2, _itk_structural>::computeShapes(
natural_coords, real_coord, H);
// clang-format off
- // u1 v1 t1 u2 v2 t2
- N = {{L(0), 0 , 0 , L(1), 0 , 0 }, // u
- {0 , H(0, 0), H(0, 1), 0 , H(0, 2), H(0, 3)}, // v
- {0 , H(1, 0), H(1, 1), 0 , H(1, 2), H(1, 3)}}; // theta
+ // u1 v1 t1 u2 v2 t2
+ N= Matrix<Real, 3, 6>{{L(0), 0 , 0 , L(1), 0 , 0 }, // u
+ {0 , H(0, 0), H(0, 1), 0 , H(0, 2), H(0, 3)}, // v
+ {0 , H(1, 0), H(1, 1), 0 , H(1, 2), H(1, 3)}}; // theta
// clang-format on
}
template <>
+template <typename D1, typename D2, typename D3>
inline void
InterpolationElement<_itp_bernoulli_beam_3, _itk_structural>::computeShapes(
- const Vector<Real> & natural_coords, const Matrix<Real> & real_coord,
- Matrix<Real> & N) {
- Vector<Real> L(2);
+ const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & real_coord, Eigen::MatrixBase<D3> & N) {
+ Eigen::Matrix<Real, 2, 1> L;
InterpolationElement<_itp_lagrange_segment_2, _itk_lagrangian>::computeShapes(
natural_coords, L);
- Matrix<Real> H(2, 4);
+ Eigen::Matrix<Real, 2, 4> H;
InterpolationElement<_itp_hermite_2, _itk_structural>::computeShapes(
natural_coords, real_coord, H);
// clang-format off
// u1 v1 w1 tx1 ty1 tz1 u2 v2 w2 tx2 ty2 tz2
- N = {{L(0), 0 , 0 , 0 , 0 , 0 , L(1), 0 , 0 , 0 , 0 , 0 }, // u
- {0 , H(0, 0), 0 , 0 , 0 , H(0, 1), 0 , H(0, 2), 0 , 0 , 0 , H(0, 3)}, // v
- {0 , 0 , H(0, 0), 0 , -H(0, 1), 0 , 0 , 0 , H(0, 2), 0 , -H(0, 3), 0 }, // w
- {0 , 0 , 0 , L(0), 0 , 0 , 0 , 0 , 0 , L(1), 0 , 0 }, // thetax
- {0 , 0 , H(1, 0), 0 , -H(1, 1), 0 , 0 , 0 , H(1, 2), 0 , -H(1, 3), 0 }, // thetay
- {0 , H(1, 0), 0 , 0 , 0 , H(1, 1), 0 , H(1, 2), 0 , 0 , 0 , H(1, 3)}}; // thetaz
+ N = Matrix<Real, 6, 12>{{L(0), 0 , 0 , 0 , 0 , 0 , L(1), 0 , 0 , 0 , 0 , 0 }, // u
+ {0 , H(0, 0), 0 , 0 , 0 , H(0, 1), 0 , H(0, 2), 0 , 0 , 0 , H(0, 3)}, // v
+ {0 , 0 , H(0, 0), 0 , -H(0, 1), 0 , 0 , 0 , H(0, 2), 0 , -H(0, 3), 0 }, // w
+ {0 , 0 , 0 , L(0), 0 , 0 , 0 , 0 , 0 , L(1), 0 , 0 }, // thetax
+ {0 , 0 , H(1, 0), 0 , -H(1, 1), 0 , 0 , 0 , H(1, 2), 0 , -H(1, 3), 0 }, // thetay
+ {0 , H(1, 0), 0 , 0 , 0 , H(1, 1), 0 , H(1, 2), 0 , 0 , 0 , H(1, 3)}}; // thetaz
// clang-format on
}
/* -------------------------------------------------------------------------- */
#if 0
template <>
inline void
InterpolationElement<_itp_bernoulli_beam_3, _itk_structural>::computeShapesDisplacements(
const Vector<Real> & natural_coords, const Matrix<Real> & real_coord,
Matrix<Real> & N) {
}
#endif
/* -------------------------------------------------------------------------- */
template <>
+template <class D1, class D2, class D3>
inline void
InterpolationElement<_itp_bernoulli_beam_2, _itk_structural>::computeDNDS(
- const Vector<Real> & natural_coords, const Matrix<Real> & real_coord,
- Matrix<Real> & dnds) {
- Matrix<Real> L(1, 2);
+ const Eigen::MatrixBase<D1> & Xs, const Eigen::MatrixBase<D2> & xs,
+ Eigen::MatrixBase<D3> & dnds) {
+ Eigen::Matrix<Real, 1, 2> L;
InterpolationElement<_itp_lagrange_segment_2, _itk_lagrangian>::computeDNDS(
- natural_coords, L);
- Matrix<Real> H(1, 4);
- InterpolationElement<_itp_hermite_2, _itk_structural>::computeDNDS(
- natural_coords, real_coord, H);
+ Xs, L);
+ Eigen::Matrix<Real, 1, 4> H;
+ InterpolationElement<_itp_hermite_2, _itk_structural>::computeDNDS(Xs, xs, H);
// Storing the derivatives in dnds
- dnds.block(L, 0, 0);
- dnds.block(H, 0, 2);
+ dnds.template block<1, 2>(0, 0) = L;
+ dnds.template block<1, 4>(0, 2) = H;
}
/* -------------------------------------------------------------------------- */
template <>
+template <class D1, class D2>
inline void
InterpolationElement<_itp_bernoulli_beam_2, _itk_structural>::arrangeInVoigt(
- const Matrix<Real> & dnds, Matrix<Real> & B) {
- auto L = dnds.block(0, 0, 1, 2); // Lagrange shape derivatives
- auto H = dnds.block(0, 2, 1, 4); // Hermite shape derivatives
+ const Eigen::MatrixBase<D1> & dnds, Eigen::MatrixBase<D2> & B) {
+ auto L = dnds.template block<1, 2>(0, 0); // Lagrange shape derivatives
+ auto H = dnds.template block<1, 4>(0, 2); // Hermite shape derivatives
// clang-format off
// u1 v1 t1 u2 v2 t2
- B = {{L(0, 0), 0, 0, L(0, 1), 0, 0 },
- {0, -H(0, 0), -H(0, 1), 0, -H(0, 2), -H(0, 3)}};
+ B = Matrix<Real, 2, 6>{{L(0, 0), 0, 0, L(0, 1), 0, 0 },
+ {0, -H(0, 0), -H(0, 1), 0, -H(0, 2), -H(0, 3)}};
// clang-format on
}
/* -------------------------------------------------------------------------- */
template <>
+template <class D1, class D2, class D3>
inline void
InterpolationElement<_itp_bernoulli_beam_3, _itk_structural>::computeDNDS(
- const Vector<Real> & natural_coords, const Matrix<Real> & real_coord,
- Matrix<Real> & dnds) {
+ const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & real_coord, Eigen::MatrixBase<D3> & dnds) {
InterpolationElement<_itp_bernoulli_beam_2, _itk_structural>::computeDNDS(
natural_coords, real_coord, dnds);
}
/* -------------------------------------------------------------------------- */
template <>
+template <class D1, class D2>
inline void
InterpolationElement<_itp_bernoulli_beam_3, _itk_structural>::arrangeInVoigt(
- const Matrix<Real> & dnds, Matrix<Real> & B) {
- auto L = dnds.block(0, 0, 1, 2); // Lagrange shape derivatives
- auto H = dnds.block(0, 2, 1, 4); // Hermite shape derivatives
+ const Eigen::MatrixBase<D1> & dnds, Eigen::MatrixBase<D2> & B) {
+ auto L = dnds.template block<1, 2>(0, 0); // Lagrange shape derivatives
+ auto H = dnds.template block<1, 4>(0, 2); // Hermite shape derivatives
// clang-format off
// u1 v1 w1 x1 y1 z1 u2 v2 w2 x2 y2 z2
- B = {{L(0, 0), 0 , 0 , 0 , 0 , 0 , L(0, 1), 0 , 0 , 0 , 0 , 0 }, // eps
- {0 , -H(0, 0), 0 , 0 , 0 , -H(0, 1), 0 , -H(0, 2), 0 , 0 , 0 ,-H(0, 3)}, // chi strong axis
- {0 , 0 , -H(0, 0), 0 , H(0, 1) , 0 , 0 , 0 , -H(0, 2) , 0 , H(0, 3) , 0 }, // chi weak axis
- {0 , 0 , 0 , L(0, 0), 0 , 0 , 0 , 0 , 0 , L(0, 1), 0 , 0 }}; // chi torsion
+ B = Matrix<Real, 4, 12>{{L(0, 0), 0 , 0 , 0 , 0 , 0 , L(0, 1), 0 , 0 , 0 , 0 , 0 }, // eps
+ {0 , -H(0, 0), 0 , 0 , 0 , -H(0, 1), 0 , -H(0, 2), 0 , 0 , 0 ,-H(0, 3)}, // chi strong axis
+ {0 , 0 , -H(0, 0), 0 , H(0, 1) , 0 , 0 , 0 , -H(0, 2) , 0 , H(0, 3) , 0 }, // chi weak axis
+ {0 , 0 , 0 , L(0, 0), 0 , 0 , 0 , 0 , 0 , L(0, 1), 0 , 0 }}; // chi torsion
// clang-format on
}
/* -------------------------------------------------------------------------- */
template <>
+template <class D1, class D2, class D3>
inline void ElementClass<_bernoulli_beam_2>::computeRotationMatrix(
- Matrix<Real> & R, const Matrix<Real> & X, const Vector<Real> & /*n*/) {
- Vector<Real> x2 = X(1); // X2
- Vector<Real> x1 = X(0); // X1
+ Eigen::MatrixBase<D1> & R, const Eigen::MatrixBase<D2> & X,
+ const Eigen::MatrixBase<D3> &) {
+ auto && x2 = X(1); // X2
+ auto && x1 = X(0); // X1
- auto cs = (x2 - x1);
- cs.normalize();
+ auto cs = (x2 - x1) / (x2 - x1).norm();
auto c = cs(0);
auto s = cs(1);
// clang-format off
/// Definition of the rotation matrix
- R = {{ c, s, 0.},
- {-s, c, 0.},
- { 0., 0., 1.}};
+ R= Matrix<Real, 3, 3>{{ c, s, 0.},
+ {-s, c, 0.},
+ {0., 0., 1.}};
// clang-format on
}
/* -------------------------------------------------------------------------- */
template <>
+template <class D1, class D2, class D3>
inline void ElementClass<_bernoulli_beam_3>::computeRotationMatrix(
- Matrix<Real> & R, const Matrix<Real> & X, const Vector<Real> & n) {
- Vector<Real> x2 = X(1); // X2
- Vector<Real> x1 = X(0); // X1
+ Eigen::MatrixBase<D1> & R, const Eigen::MatrixBase<D2> & X,
+ const Eigen::MatrixBase<D3> & n) {
auto dim = X.rows();
- auto x = (x2 - x1);
+ Eigen::Matrix<Real, 1, 3> x = (X(1) - X(0));
+ Eigen::Matrix<Real, 1, 3> nv = n;
+
x.normalize();
- auto x_n = x.crossProduct(n);
+ auto x_n = x.cross(nv);
- Matrix<Real> Pe = {{1., 0., 0.}, {0., -1., 0.}, {0., 0., 1.}};
+ Matrix<Real> Pe(dim, dim);
+ Pe << 1., 0., 0., 0., -1., 0., 0., 0., 1.;
Matrix<Real> Pg(dim, dim);
Pg(0) = x;
Pg(1) = x_n;
Pg(2) = n;
Pe *= Pg.inverse();
R.zero();
/// Definition of the rotation matrix
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
+ for (Int i = 0; i < dim; ++i) {
+ for (Int j = 0; j < dim; ++j) {
R(i + dim, j + dim) = R(i, j) = Pe(i, j);
}
}
}
} // namespace akantu
+
#endif /* AKANTU_ELEMENT_CLASS_BERNOULLI_BEAM_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/element_classes/element_class_hermite_inline_impl.hh b/src/fe_engine/element_classes/element_class_hermite_inline_impl.hh
index cd4dfd565..c9c8fde43 100644
--- a/src/fe_engine/element_classes/element_class_hermite_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_hermite_inline_impl.hh
@@ -1,182 +1,182 @@
/**
* @file element_class_hermite_inline_impl.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Nov 10 2017
* @date last modification: Tue Feb 09 2021
*
* @brief Specialization of the element_class class for the type
* _hermite
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
--x-----q1----|----q2-----x---> x
-1 0 1
@endverbatim
*
* @f[
* \begin{array}{ll}
* M_1(\xi) &= 1/4(\xi^{3}/-3\xi+2)\\
* M_2(\xi) &= -1/4(\xi^{3}-3\xi-2)
* \end{array}
*
* \begin{array}{ll}
* L_1(\xi) &= 1/4(\xi^{3}-\xi^{2}-\xi+1)\\
* L_2(\xi) &= 1/4(\xi^{3}+\xi^{2}-\xi-1)
* \end{array}
*
* \begin{array}{ll}
* M'_1(\xi) &= 3/4(\xi^{2}-1)\\
* M'_2(\xi) &= -3/4(\xi^{2}-1)
* \end{array}
*
* \begin{array}{ll}
* L'_1(\xi) &= 1/4(3\xi^{2}-2\xi-1)\\
* L'_2(\xi) &= 1/4(3\xi^{2}+2\xi-1)
* \end{array}
*@f]
*
*
*@f[
* \begin{array}{ll}
* N'_1(\xi) &= -1/2\\
* N'_2(\xi) &= 1/2
* \end{array}]
*
* \begin{array}{ll}
* -M''_1(\xi) &= -3\xi/2\\
* -M''_2(\xi) &= 3\xi/2\\
* \end{array}
*
* \begin{array}{ll}
* -L''_1(\xi) &= -1/2a(3\xi/a-1)\\
* -L''_2(\xi) &= -1/2a(3\xi/a+1)
* \end{array}
*@f]
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_static_if.hh"
-#include "element_class_structural.hh"
+//#include "element_class_structural.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_CLASS_HERMITE_INLINE_IMPL_HH_
#define AKANTU_ELEMENT_CLASS_HERMITE_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_hermite_2,
_itp_lagrange_segment_2, 2,
1, 4);
/* -------------------------------------------------------------------------- */
-
-namespace {
- namespace details {
- inline Real computeLength(const Matrix<Real> & real_coord) {
- Vector<Real> x1 = real_coord(0);
- Vector<Real> x2 = real_coord(1);
- return x1.distance(x2);
- }
-
- inline void computeShapes(const Vector<Real> & natural_coords, Real a,
- Matrix<Real> & N) {
- /// natural coordinate
- Real xi = natural_coords(0);
- auto xi2 = xi * xi;
- auto xi3 = xi * xi * xi;
- // Cubic Hermite splines interpolating displacement
- auto M1 = 1. / 4. * (2. - 3. * xi + xi3);
- auto M2 = 1. / 4. * (2. + 3. * xi - xi3);
- auto L1 = a / 4. * (1 - xi - xi2 + xi3);
- auto L2 = a / 4. * (-1 - xi + xi2 + xi3);
- ;
+namespace details {
+ template <class D1>
+ inline Real computeLength(const Eigen::MatrixBase<D1> & real_coord) {
+ auto && x1 = real_coord(0);
+ auto && x2 = real_coord(1);
+ return x1.distance(x2);
+ }
+
+ template <class D1, class D2>
+ inline void computeShapes(const Eigen::MatrixBase<D1> & natural_coords, Real a,
+ Eigen::MatrixBase<D2> & N) {
+ /// natural coordinate
+ Real xi = natural_coords(0);
+ auto xi2 = xi * xi;
+ auto xi3 = xi * xi * xi;
+ // Cubic Hermite splines interpolating displacement
+ auto M1 = 1. / 4. * (2. - 3. * xi + xi3);
+ auto M2 = 1. / 4. * (2. + 3. * xi - xi3);
+ auto L1 = a / 4. * (1 - xi - xi2 + xi3);
+ auto L2 = a / 4. * (-1 - xi + xi2 + xi3);
#if 1 // Version where we also interpolate the rotations
// Derivatives (with respect to x) of previous functions interpolating
// rotations
- auto M1_ = 3. / (4. * a) * (xi2 - 1);
- auto M2_ = 3. / (4. * a) * (1 - xi2);
- auto L1_ = 1 / 4. * (3 * xi2 - 2 * xi - 1);
- auto L2_ = 1 / 4. * (3 * xi2 + 2 * xi - 1);
+ auto M1_ = 3. / (4. * a) * (xi2 - 1);
+ auto M2_ = 3. / (4. * a) * (1 - xi2);
+ auto L1_ = 1 / 4. * (3 * xi2 - 2 * xi - 1);
+ auto L2_ = 1 / 4. * (3 * xi2 + 2 * xi - 1);
- // clang-format off
+ // clang-format off
// v1 t1 v2 t2
- N = {{M1 , L1 , M2 , L2}, // displacement interpolation
- {M1_, L1_, M2_, L2_}}; // rotation interpolation
- // clang-format on
+ N << M1 , L1 , M2 , L2, // displacement interpolation
+ M1_, L1_, M2_, L2_; // rotation interpolation
+ // clang-format on
#else // Version where we only interpolate displacements
// clang-format off
// v1 t1 v2 t2
N = {{M1, L1, M2, L2}};
// clang-format on
#endif
- }
-
- /* ---------------------------------------------------------------------- */
-
- inline void computeDNDS(const Vector<Real> & natural_coords, Real a,
- Matrix<Real> & B) {
- // natural coordinate
- Real xi = natural_coords(0);
- // Derivatives with respect to xi for rotations
- auto M1 = 3. / 2. * xi;
- auto M2 = 3. / 2. * (-xi);
- auto L1 = 1. * a / 2. * (3 * xi - 1);
- auto L2 = 1. * a / 2. * (3 * xi + 1);
-
- // v1 t1 v2 t2
- B = {{M1, L1, M2, L2}}; // computing curvature : {chi} = [B]{d}
- B /= a; // to account for first order deriv w/r to x
- }
- } // namespace details
-} // namespace
+ }
+
+ /* ---------------------------------------------------------------------- */
+ template <class D1, class D2>
+ inline void computeDNDS(const Eigen::MatrixBase<D1> & natural_coords, Real a,
+ Eigen::MatrixBase<D2> & B) {
+ // natural coordinate
+ Real xi = natural_coords(0);
+ // Derivatives with respect to xi for rotations
+ auto M1 = 3. / 2. * xi;
+ auto M2 = 3. / 2. * (-xi);
+ auto L1 = 1. * a / 2. * (3 * xi - 1);
+ auto L2 = 1. * a / 2. * (3 * xi + 1);
+
+ // v1 t1 v2 t2
+ B << M1, L1, M2, L2; // computing curvature : {chi} = [B]{d}
+ B /= a; // to account for first order deriv w/r to x
+ }
+} // namespace details
/* -------------------------------------------------------------------------- */
template <>
+template <typename D1, typename D2, typename D3>
inline void
InterpolationElement<_itp_hermite_2, _itk_structural>::computeShapes(
- const Vector<Real> & natural_coords, const Matrix<Real> & real_coord,
- Matrix<Real> & N) {
+ const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & real_coord, Eigen::MatrixBase<D3> & N) {
auto L = details::computeLength(real_coord);
details::computeShapes(natural_coords, L / 2, N);
}
/* -------------------------------------------------------------------------- */
template <>
+template <typename D1, typename D2, typename D3>
inline void InterpolationElement<_itp_hermite_2, _itk_structural>::computeDNDS(
- const Vector<Real> & natural_coords, const Matrix<Real> & real_coord,
- Matrix<Real> & B) {
- auto L = details::computeLength(real_coord);
- details::computeDNDS(natural_coords, L / 2, B);
+ const Eigen::MatrixBase<D1> & Xs, const Eigen::MatrixBase<D2> & xs,
+ Eigen::MatrixBase<D3> & B) {
+ auto L = details::computeLength(xs);
+ details::computeDNDS(Xs, L / 2, B);
}
} // namespace akantu
#endif /* AKANTU_ELEMENT_CLASS_HERMITE_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh b/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh
index 8e364fced..c5c9a558a 100644
--- a/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh
@@ -1,231 +1,232 @@
/**
* @file element_class_hexahedron_20_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Sacha Laffely <sacha.laffely@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Scantamburlo <damien.scantamburlo@epfl.ch>
*
* @date creation: Tue Mar 31 2015
* @date last modification: Fri Feb 07 2020
*
* @brief Specialization of the element_class class for the type _hexahedron_20
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\y
\z /
| /
7-----|18--------6
/| | / /|
/ | | / / |
19 | | / 17 |
/ 15 | / / 14
/ | | / / |
4-------16---/---5 |
| | +----|------------\x
| 3-------10-|-----2
| / | /
12 / 13 /
| 11 | 9
| / | /
|/ |/
0--------8-------1
x y z
* N0 -1 -1 -1
* N1 1 -1 -1
* N2 1 1 -1
* N3 -1 1 -1
* N4 -1 -1 1
* N5 1 -1 1
* N6 1 1 1
* N7 -1 1 1
* N8 0 -1 -1
* N9 1 0 -1
* N10 0 1 -1
* N11 -1 0 -1
* N12 -1 -1 0
* N13 1 -1 0
* N14 1 1 0
* N15 -1 1 0
* N16 0 -1 1
* N17 1 0 1
* N18 0 1 1
* N19 -1 0 1
* \endverbatim
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_hexahedron_20, _gt_hexahedron_20,
_itp_serendip_hexahedron_20, _ek_regular,
3, _git_segment, 3);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_serendip_hexahedron_20>::computeShapes(
- const vector_type & c, vector_type & N) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &N) {
// Shape function , Natural coordinates
N(0) =
0.125 * (1 - c(0)) * (1 - c(1)) * (1 - c(2)) * (-2 - c(0) - c(1) - c(2));
N(1) =
0.125 * (1 + c(0)) * (1 - c(1)) * (1 - c(2)) * (-2 + c(0) - c(1) - c(2));
N(2) =
0.125 * (1 + c(0)) * (1 + c(1)) * (1 - c(2)) * (-2 + c(0) + c(1) - c(2));
N(3) =
0.125 * (1 - c(0)) * (1 + c(1)) * (1 - c(2)) * (-2 - c(0) + c(1) - c(2));
N(4) =
0.125 * (1 - c(0)) * (1 - c(1)) * (1 + c(2)) * (-2 - c(0) - c(1) + c(2));
N(5) =
0.125 * (1 + c(0)) * (1 - c(1)) * (1 + c(2)) * (-2 + c(0) - c(1) + c(2));
N(6) =
0.125 * (1 + c(0)) * (1 + c(1)) * (1 + c(2)) * (-2 + c(0) + c(1) + c(2));
N(7) =
0.125 * (1 - c(0)) * (1 + c(1)) * (1 + c(2)) * (-2 - c(0) + c(1) + c(2));
N(8) = 0.25 * (1 - c(0) * c(0)) * (1 - c(1)) * (1 - c(2));
N(9) = 0.25 * (1 - c(1) * c(1)) * (1 + c(0)) * (1 - c(2));
N(10) = 0.25 * (1 - c(0) * c(0)) * (1 + c(1)) * (1 - c(2));
N(11) = 0.25 * (1 - c(1) * c(1)) * (1 - c(0)) * (1 - c(2));
N(12) = 0.25 * (1 - c(2) * c(2)) * (1 - c(0)) * (1 - c(1));
N(13) = 0.25 * (1 - c(2) * c(2)) * (1 + c(0)) * (1 - c(1));
N(14) = 0.25 * (1 - c(2) * c(2)) * (1 + c(0)) * (1 + c(1));
N(15) = 0.25 * (1 - c(2) * c(2)) * (1 - c(0)) * (1 + c(1));
N(16) = 0.25 * (1 - c(0) * c(0)) * (1 - c(1)) * (1 + c(2));
N(17) = 0.25 * (1 - c(1) * c(1)) * (1 + c(0)) * (1 + c(2));
N(18) = 0.25 * (1 - c(0) * c(0)) * (1 + c(1)) * (1 + c(2));
N(19) = 0.25 * (1 - c(1) * c(1)) * (1 - c(0)) * (1 + c(2));
}
-/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_serendip_hexahedron_20>::computeDNDS(
- const vector_type & c, matrix_type & dnds) {
- // derivatives
- // ddx
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &dnds) {
+ // derivatives ddx
dnds(0, 0) =
0.25 * (c(0) + 0.5 * (c(1) + c(2) + 1)) * (c(1) - 1) * (c(2) - 1);
dnds(0, 1) =
0.25 * (c(0) - 0.5 * (c(1) + c(2) + 1)) * (c(1) - 1) * (c(2) - 1);
dnds(0, 2) =
-0.25 * (c(0) + 0.5 * (c(1) - c(2) - 1)) * (c(1) + 1) * (c(2) - 1);
dnds(0, 3) =
-0.25 * (c(0) - 0.5 * (c(1) - c(2) - 1)) * (c(1) + 1) * (c(2) - 1);
dnds(0, 4) =
-0.25 * (c(0) + 0.5 * (c(1) - c(2) + 1)) * (c(1) - 1) * (c(2) + 1);
dnds(0, 5) =
-0.25 * (c(0) - 0.5 * (c(1) - c(2) + 1)) * (c(1) - 1) * (c(2) + 1);
dnds(0, 6) =
0.25 * (c(0) + 0.5 * (c(1) + c(2) - 1)) * (c(1) + 1) * (c(2) + 1);
dnds(0, 7) =
0.25 * (c(0) - 0.5 * (c(1) + c(2) - 1)) * (c(1) + 1) * (c(2) + 1);
dnds(0, 8) = -0.5 * c(0) * (c(1) - 1) * (c(2) - 1);
dnds(0, 9) = 0.25 * (c(1) * c(1) - 1) * (c(2) - 1);
dnds(0, 10) = 0.5 * c(0) * (c(1) + 1) * (c(2) - 1);
dnds(0, 11) = -0.25 * (c(1) * c(1) - 1) * (c(2) - 1);
dnds(0, 12) = -0.25 * (c(2) * c(2) - 1) * (c(1) - 1);
dnds(0, 13) = 0.25 * (c(1) - 1) * (c(2) * c(2) - 1);
dnds(0, 14) = -0.25 * (c(1) + 1) * (c(2) * c(2) - 1);
dnds(0, 15) = 0.25 * (c(1) + 1) * (c(2) * c(2) - 1);
dnds(0, 16) = 0.5 * c(0) * (c(1) - 1) * (c(2) + 1);
dnds(0, 17) = -0.25 * (c(2) + 1) * (c(1) * c(1) - 1);
dnds(0, 18) = -0.5 * c(0) * (c(1) + 1) * (c(2) + 1);
dnds(0, 19) = 0.25 * (c(2) + 1) * (c(1) * c(1) - 1);
// ddy
dnds(1, 0) =
0.25 * (c(1) + 0.5 * (c(0) + c(2) + 1)) * (c(0) - 1) * (c(2) - 1);
dnds(1, 1) =
-0.25 * (c(1) - 0.5 * (c(0) - c(2) - 1)) * (c(0) + 1) * (c(2) - 1);
dnds(1, 2) =
-0.25 * (c(1) + 0.5 * (c(0) - c(2) - 1)) * (c(0) + 1) * (c(2) - 1);
dnds(1, 3) =
0.25 * (c(1) - 0.5 * (c(0) + c(2) + 1)) * (c(0) - 1) * (c(2) - 1);
dnds(1, 4) =
-0.25 * (c(1) + 0.5 * (c(0) - c(2) + 1)) * (c(0) - 1) * (c(2) + 1);
dnds(1, 5) =
0.25 * (c(1) - 0.5 * (c(0) + c(2) - 1)) * (c(0) + 1) * (c(2) + 1);
dnds(1, 6) =
0.25 * (c(1) + 0.5 * (c(0) + c(2) - 1)) * (c(0) + 1) * (c(2) + 1);
dnds(1, 7) =
-0.25 * (c(1) - 0.5 * (c(0) - c(2) + 1)) * (c(0) - 1) * (c(2) + 1);
dnds(1, 8) = -0.25 * (c(0) * c(0) - 1) * (c(2) - 1);
dnds(1, 9) = 0.5 * c(1) * (c(0) + 1) * (c(2) - 1);
dnds(1, 10) = 0.25 * (c(0) * c(0) - 1) * (c(2) - 1);
dnds(1, 11) = -0.5 * c(1) * (c(0) - 1) * (c(2) - 1);
dnds(1, 12) = -0.25 * (c(2) * c(2) - 1) * (c(0) - 1);
dnds(1, 13) = 0.25 * (c(0) + 1) * (c(2) * c(2) - 1);
dnds(1, 14) = -0.25 * (c(0) + 1) * (c(2) * c(2) - 1);
dnds(1, 15) = 0.25 * (c(0) - 1) * (c(2) * c(2) - 1);
dnds(1, 16) = 0.25 * (c(2) + 1) * (c(0) * c(0) - 1);
dnds(1, 17) = -0.5 * c(1) * (c(0) + 1) * (c(2) + 1);
dnds(1, 18) = -0.25 * (c(2) + 1) * (c(0) * c(0) - 1);
dnds(1, 19) = 0.5 * c(1) * (c(0) - 1) * (c(2) + 1);
// ddz
dnds(2, 0) =
0.25 * (c(2) + 0.5 * (c(0) + c(1) + 1)) * (c(0) - 1) * (c(1) - 1);
dnds(2, 1) =
-0.25 * (c(2) - 0.5 * (c(0) - c(1) - 1)) * (c(0) + 1) * (c(1) - 1);
dnds(2, 2) =
0.25 * (c(2) - 0.5 * (c(0) + c(1) - 1)) * (c(0) + 1) * (c(1) + 1);
dnds(2, 3) =
-0.25 * (c(2) + 0.5 * (c(0) - c(1) + 1)) * (c(0) - 1) * (c(1) + 1);
dnds(2, 4) =
0.25 * (c(2) - 0.5 * (c(0) + c(1) + 1)) * (c(0) - 1) * (c(1) - 1);
dnds(2, 5) =
-0.25 * (c(2) + 0.5 * (c(0) - c(1) - 1)) * (c(0) + 1) * (c(1) - 1);
dnds(2, 6) =
0.25 * (c(2) + 0.5 * (c(0) + c(1) - 1)) * (c(0) + 1) * (c(1) + 1);
dnds(2, 7) =
-0.25 * (c(2) - 0.5 * (c(0) - c(1) + 1)) * (c(0) - 1) * (c(1) + 1);
dnds(2, 8) = -0.25 * (c(0) * c(0) - 1) * (c(1) - 1);
dnds(2, 9) = 0.25 * (c(1) * c(1) - 1) * (c(0) + 1);
dnds(2, 10) = 0.25 * (c(0) * c(0) - 1) * (c(1) + 1);
dnds(2, 11) = -0.25 * (c(1) * c(1) - 1) * (c(0) - 1);
dnds(2, 12) = -0.5 * c(2) * (c(1) - 1) * (c(0) - 1);
dnds(2, 13) = 0.5 * c(2) * (c(0) + 1) * (c(1) - 1);
dnds(2, 14) = -0.5 * c(2) * (c(0) + 1) * (c(1) + 1);
dnds(2, 15) = 0.5 * c(2) * (c(0) - 1) * (c(1) + 1);
dnds(2, 16) = 0.25 * (c(1) - 1) * (c(0) * c(0) - 1);
dnds(2, 17) = -0.25 * (c(0) + 1) * (c(1) * c(1) - 1);
dnds(2, 18) = -0.25 * (c(1) + 1) * (c(0) * c(0) - 1);
dnds(2, 19) = 0.25 * (c(0) - 1) * (c(1) * c(1) - 1);
}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_hexahedron_20>::getInradius(const Matrix<Real> & coord) {
+template <class D>
+inline Real GeometricalElement<_gt_hexahedron_20>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
return GeometricalElement<_gt_hexahedron_8>::getInradius(coord) * 0.5;
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh b/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh
index 67bb4b099..27cc5560c 100644
--- a/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh
@@ -1,253 +1,226 @@
/**
* @file element_class_hexahedron_8_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Peter Spijker <peter.spijker@epfl.ch>
*
* @date creation: Mon Mar 14 2011
* @date last modification: Fri Feb 07 2020
*
* @brief Specialization of the element_class class for the type _hexahedron_8
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\zeta
^
(-1,1,1) | (1,1,1)
7---|------6
/| | /|
/ | | / |
(-1,-1,1) 4----------5 | (1,-1,1)
| | | | |
| | | | |
| | +---|-------> \xi
| | / | |
(-1,1,-1) | 3-/-----|--2 (1,1,-1)
| / / | /
|/ / |/
0-/--------1
(-1,-1,-1) / (1,-1,-1)
/
\eta
@endverbatim
*
* \f[
* \begin{array}{llll}
* N1 = (1 - \xi) (1 - \eta) (1 - \zeta) / 8
* & \frac{\partial N1}{\partial \xi} = - (1 - \eta) (1 - \zeta) / 8
* & \frac{\partial N1}{\partial \eta} = - (1 - \xi) (1 - \zeta) / 8
* & \frac{\partial N1}{\partial \zeta} = - (1 - \xi) (1 - \eta) / 8 \\
* N2 = (1 + \xi) (1 - \eta) (1 - \zeta) / 8
* & \frac{\partial N2}{\partial \xi} = (1 - \eta) (1 - \zeta) / 8
* & \frac{\partial N2}{\partial \eta} = - (1 + \xi) (1 - \zeta) / 8
* & \frac{\partial N2}{\partial \zeta} = - (1 + \xi) (1 - \eta) / 8 \\
* N3 = (1 + \xi) (1 + \eta) (1 - \zeta) / 8
* & \frac{\partial N3}{\partial \xi} = (1 + \eta) (1 - \zeta) / 8
* & \frac{\partial N3}{\partial \eta} = (1 + \xi) (1 - \zeta) / 8
* & \frac{\partial N3}{\partial \zeta} = - (1 + \xi) (1 + \eta) / 8 \\
* N4 = (1 - \xi) (1 + \eta) (1 - \zeta) / 8
* & \frac{\partial N4}{\partial \xi} = - (1 + \eta) (1 - \zeta) / 8
* & \frac{\partial N4}{\partial \eta} = (1 - \xi) (1 - \zeta) / 8
* & \frac{\partial N4}{\partial \zeta} = - (1 - \xi) (1 + \eta) / 8 \\
* N5 = (1 - \xi) (1 - \eta) (1 + \zeta) / 8
* & \frac{\partial N5}{\partial \xi} = - (1 - \eta) (1 + \zeta) / 8
* & \frac{\partial N5}{\partial \eta} = - (1 - \xi) (1 + \zeta) / 8
* & \frac{\partial N5}{\partial \zeta} = (1 - \xi) (1 - \eta) / 8 \\
* N6 = (1 + \xi) (1 - \eta) (1 + \zeta) / 8
* & \frac{\partial N6}{\partial \xi} = (1 - \eta) (1 + \zeta) / 8
* & \frac{\partial N6}{\partial \eta} = - (1 + \xi) (1 + \zeta) / 8
* & \frac{\partial N6}{\partial \zeta} = (1 + \xi) (1 - \eta) / 8 \\
* N7 = (1 + \xi) (1 + \eta) (1 + \zeta) / 8
* & \frac{\partial N7}{\partial \xi} = (1 + \eta) (1 + \zeta) / 8
* & \frac{\partial N7}{\partial \eta} = (1 + \xi) (1 + \zeta) / 8
* & \frac{\partial N7}{\partial \zeta} = (1 + \xi) (1 + \eta) / 8 \\
* N8 = (1 - \xi) (1 + \eta) (1 + \zeta) / 8
* & \frac{\partial N8}{\partial \xi} = - (1 + \eta) (1 + \zeta) / 8
* & \frac{\partial N8}{\partial \eta} = (1 - \xi) (1 + \zeta) / 8
* & \frac{\partial N8}{\partial \zeta} = (1 - \xi) (1 + \eta) / 8 \\
* \end{array}
* \f]
*
* @f{eqnarray*}{
* \xi_{q0} &=& -1/\sqrt{3} \qquad \eta_{q0} = -1/\sqrt{3} \qquad \zeta_{q0} =
-1/\sqrt{3} \\
* \xi_{q1} &=& 1/\sqrt{3} \qquad \eta_{q1} = -1/\sqrt{3} \qquad \zeta_{q1} =
-1/\sqrt{3} \\
* \xi_{q2} &=& 1/\sqrt{3} \qquad \eta_{q2} = 1/\sqrt{3} \qquad \zeta_{q2} =
-1/\sqrt{3} \\
* \xi_{q3} &=& -1/\sqrt{3} \qquad \eta_{q3} = 1/\sqrt{3} \qquad \zeta_{q3} =
-1/\sqrt{3} \\
* \xi_{q4} &=& -1/\sqrt{3} \qquad \eta_{q4} = -1/\sqrt{3} \qquad \zeta_{q4} =
1/\sqrt{3} \\
* \xi_{q5} &=& 1/\sqrt{3} \qquad \eta_{q5} = -1/\sqrt{3} \qquad \zeta_{q5} =
1/\sqrt{3} \\
* \xi_{q6} &=& 1/\sqrt{3} \qquad \eta_{q6} = 1/\sqrt{3} \qquad \zeta_{q6} =
1/\sqrt{3} \\
* \xi_{q7} &=& -1/\sqrt{3} \qquad \eta_{q7} = 1/\sqrt{3} \qquad \zeta_{q7} =
1/\sqrt{3} \\
* @f}
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_hexahedron_8, _gt_hexahedron_8,
_itp_lagrange_hexahedron_8, _ek_regular, 3,
_git_segment, 2);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_hexahedron_8>::computeShapes(
- const vector_type & c, vector_type & N) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &N) {
/// Natural coordinates
N(0) = .125 * (1 - c(0)) * (1 - c(1)) * (1 - c(2)); /// N1(q_0)
N(1) = .125 * (1 + c(0)) * (1 - c(1)) * (1 - c(2)); /// N2(q_0)
N(2) = .125 * (1 + c(0)) * (1 + c(1)) * (1 - c(2)); /// N3(q_0)
N(3) = .125 * (1 - c(0)) * (1 + c(1)) * (1 - c(2)); /// N4(q_0)
N(4) = .125 * (1 - c(0)) * (1 - c(1)) * (1 + c(2)); /// N5(q_0)
N(5) = .125 * (1 + c(0)) * (1 - c(1)) * (1 + c(2)); /// N6(q_0)
N(6) = .125 * (1 + c(0)) * (1 + c(1)) * (1 + c(2)); /// N7(q_0)
N(7) = .125 * (1 - c(0)) * (1 + c(1)) * (1 + c(2)); /// N8(q_0)
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_hexahedron_8>::computeDNDS(
- const vector_type & c, matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &dnds) {
/**
* @f[
* dnds = \left(
* \begin{array}{cccccccc}
* \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial
* \xi}
* & \frac{\partial N3}{\partial \xi} & \frac{\partial
* N4}{\partial \xi}
* & \frac{\partial N5}{\partial \xi} & \frac{\partial
* N6}{\partial \xi}
* & \frac{\partial N7}{\partial \xi} & \frac{\partial
* N8}{\partial \xi}\\
* \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial
* \eta}
* & \frac{\partial N3}{\partial \eta} & \frac{\partial
* N4}{\partial \eta}
* & \frac{\partial N5}{\partial \eta} & \frac{\partial
* N6}{\partial \eta}
* & \frac{\partial N7}{\partial \eta} & \frac{\partial
* N8}{\partial \eta}\\
* \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial
* \zeta}
* & \frac{\partial N3}{\partial \zeta} & \frac{\partial
* N4}{\partial \zeta}
* & \frac{\partial N5}{\partial \zeta} & \frac{\partial
* N6}{\partial \zeta}
* & \frac{\partial N7}{\partial \zeta} & \frac{\partial
* N8}{\partial \zeta}
* \end{array}
* \right)
* @f]
*/
dnds(0, 0) = -.125 * (1 - c(1)) * (1 - c(2));
dnds(0, 1) = .125 * (1 - c(1)) * (1 - c(2));
dnds(0, 2) = .125 * (1 + c(1)) * (1 - c(2));
dnds(0, 3) = -.125 * (1 + c(1)) * (1 - c(2));
dnds(0, 4) = -.125 * (1 - c(1)) * (1 + c(2));
- ;
dnds(0, 5) = .125 * (1 - c(1)) * (1 + c(2));
- ;
dnds(0, 6) = .125 * (1 + c(1)) * (1 + c(2));
- ;
dnds(0, 7) = -.125 * (1 + c(1)) * (1 + c(2));
- ;
dnds(1, 0) = -.125 * (1 - c(0)) * (1 - c(2));
- ;
dnds(1, 1) = -.125 * (1 + c(0)) * (1 - c(2));
- ;
dnds(1, 2) = .125 * (1 + c(0)) * (1 - c(2));
- ;
dnds(1, 3) = .125 * (1 - c(0)) * (1 - c(2));
- ;
dnds(1, 4) = -.125 * (1 - c(0)) * (1 + c(2));
- ;
dnds(1, 5) = -.125 * (1 + c(0)) * (1 + c(2));
- ;
dnds(1, 6) = .125 * (1 + c(0)) * (1 + c(2));
- ;
dnds(1, 7) = .125 * (1 - c(0)) * (1 + c(2));
- ;
dnds(2, 0) = -.125 * (1 - c(0)) * (1 - c(1));
- ;
dnds(2, 1) = -.125 * (1 + c(0)) * (1 - c(1));
- ;
dnds(2, 2) = -.125 * (1 + c(0)) * (1 + c(1));
- ;
dnds(2, 3) = -.125 * (1 - c(0)) * (1 + c(1));
- ;
dnds(2, 4) = .125 * (1 - c(0)) * (1 - c(1));
- ;
dnds(2, 5) = .125 * (1 + c(0)) * (1 - c(1));
- ;
dnds(2, 6) = .125 * (1 + c(0)) * (1 + c(1));
- ;
dnds(2, 7) = .125 * (1 - c(0)) * (1 + c(1));
- ;
}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_hexahedron_8>::getInradius(const Matrix<Real> & coord) {
- Vector<Real> u0 = coord(0);
- Vector<Real> u1 = coord(1);
- Vector<Real> u2 = coord(2);
- Vector<Real> u3 = coord(3);
- Vector<Real> u4 = coord(4);
- Vector<Real> u5 = coord(5);
- Vector<Real> u6 = coord(6);
- Vector<Real> u7 = coord(7);
+template <class D>
+inline Real GeometricalElement<_gt_hexahedron_8>::getInradius(
+ const Eigen::MatrixBase<D> &X) {
+ auto &&a = (X(0) - X(1)).norm();
+ auto &&b = (X(1) - X(2)).norm();
+ auto &&c = (X(2) - X(3)).norm();
+ auto &&d = (X(3) - X(0)).norm();
+ auto &&e = (X(0) - X(4)).norm();
+ auto &&f = (X(1) - X(5)).norm();
+ auto &&g = (X(2) - X(6)).norm();
+ auto &&h = (X(3) - X(7)).norm();
+ auto &&i = (X(4) - X(5)).norm();
+ auto &&j = (X(5) - X(6)).norm();
+ auto &&k = (X(6) - X(7)).norm();
+ auto &&l = (X(7) - X(4)).norm();
- Real a = u0.distance(u1);
- Real b = u1.distance(u2);
- Real c = u2.distance(u3);
- Real d = u3.distance(u0);
- Real e = u0.distance(u4);
- Real f = u1.distance(u5);
- Real g = u2.distance(u6);
- Real h = u3.distance(u7);
- Real i = u4.distance(u5);
- Real j = u5.distance(u6);
- Real k = u6.distance(u7);
- Real l = u7.distance(u4);
-
- Real p = std::min({a, b, c, d, e, f, g, h, i, j, k, l});
+ auto p = std::min({a, b, c, d, e, f, g, h, i, j, k, l});
return p;
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.hh b/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.hh
index 804dce975..21b995920 100644
--- a/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.hh
@@ -1,226 +1,219 @@
/**
* @file element_class_kirchhoff_shell_inline_impl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Spielmann <damien.spielmann@epfl.ch>
*
* @date creation: Fri Jul 04 2014
* @date last modification: Tue Sep 29 2020
*
* @brief Element class Kirchhoff Shell
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "element_class_structural.hh"
+//#include "element_class_structural.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_CLASS_KIRCHHOFF_SHELL_INLINE_IMPL_HH_
#define AKANTU_ELEMENT_CLASS_KIRCHHOFF_SHELL_INLINE_IMPL_HH_
namespace akantu {
-/* -------------------------------------------------------------------------- */
-AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(
- _itp_discrete_kirchhoff_triangle_18, _itp_lagrange_triangle_3, 6, 6, 21);
-AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(
- _discrete_kirchhoff_triangle_18, _gt_triangle_3,
- _itp_discrete_kirchhoff_triangle_18, _triangle_3, _ek_structural, 3,
- _git_triangle, 2);
-
/* -------------------------------------------------------------------------- */
namespace detail {
- inline void computeBasisChangeMatrix(Matrix<Real> & P,
- const Matrix<Real> & X) {
- Vector<Real> X1 = X(0);
- Vector<Real> X2 = X(1);
- Vector<Real> X3 = X(2);
+ template <class D>
+ inline Eigen::Matrix<Real, 3, 3>
+ computeBasisChangeMatrix(const Eigen::MatrixBase<D> & X) {
+ auto && X1 = X(0);
+ auto && X2 = X(1);
+ auto && X3 = X(2);
- Vector<Real> a1 = X2 - X1;
- Vector<Real> a2 = X3 - X1;
+ Eigen::Matrix<Real, 1, 3> a1 = X2 - X1;
+ Eigen::Matrix<Real, 1, 3> a2 = X3 - X1;
a1.normalize();
- Vector<Real> e3 = a1.crossProduct(a2);
- e3.normalize();
- Vector<Real> e2 = e3.crossProduct(a1);
+ auto && e3 = a1.cross(a2).normalized();
+ auto && e2 = e3.cross(a1);
+ Eigen::Matrix<Real, 3, 3> P;
P(0) = a1;
P(1) = e2;
P(2) = e3;
- P = P.transpose();
+
+ return P.transpose();
}
} // namespace detail
/* -------------------------------------------------------------------------- */
template <>
+template <class D1, class D2, class D3>
inline void
ElementClass<_discrete_kirchhoff_triangle_18>::computeRotationMatrix(
- Matrix<Real> & R, const Matrix<Real> & X, const Vector<Real> & /*n*/) {
+ Eigen::MatrixBase<D1> & R, const Eigen::MatrixBase<D2> & X,
+ const Eigen::MatrixBase<D3> &) {
auto dim = X.rows();
- Matrix<Real> P(dim, dim);
- detail::computeBasisChangeMatrix(P, X);
+
+ auto && P = detail::computeBasisChangeMatrix(X);
R.zero();
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
+ for (Int i = 0; i < dim; ++i) {
+ for (Int j = 0; j < dim; ++j) {
R(i + dim, j + dim) = R(i, j) = P(i, j);
}
}
}
/* -------------------------------------------------------------------------- */
template <>
+template <typename D1, typename D2, typename D3>
inline void
InterpolationElement<_itp_discrete_kirchhoff_triangle_18>::computeShapes(
- const Vector<Real> & /*natural_coords*/,
- const Matrix<Real> & /*real_coord*/, Matrix<Real> & /*N*/) {}
+ const Eigen::MatrixBase<D1> & /*natural_coords*/,
+ const Eigen::MatrixBase<D2> & /*real_coord*/,
+ Eigen::MatrixBase<D3> & /*N*/) {}
/* -------------------------------------------------------------------------- */
template <>
+template <typename D1, typename D2, typename D3>
inline void
InterpolationElement<_itp_discrete_kirchhoff_triangle_18>::computeDNDS(
- const Vector<Real> & natural_coords, const Matrix<Real> & real_coordinates,
- Matrix<Real> & B) {
+ const Eigen::MatrixBase<D1> & natural_coords,
+ const Eigen::MatrixBase<D2> & real_coordinates, Eigen::MatrixBase<D3> & B) {
+
+ auto && P = detail::computeBasisChangeMatrix(real_coordinates);
- auto dim = real_coordinates.cols();
- Matrix<Real> P(dim, dim);
- detail::computeBasisChangeMatrix(P, real_coordinates);
- auto X = P * real_coordinates;
- Vector<Real> X1 = X(0);
- Vector<Real> X2 = X(1);
- Vector<Real> X3 = X(2);
+ auto && X = P * real_coordinates;
+ auto && X1 = X(0);
+ auto && X2 = X(1);
+ auto && X3 = X(2);
std::array<Vector<Real>, 3> A = {X2 - X1, X3 - X2, X1 - X3};
std::array<Real, 3> L;
std::array<Real, 3> C;
std::array<Real, 3> S;
// Setting all last coordinates to 0
std::for_each(A.begin(), A.end(), [](auto & a) { a(2) = 0; });
// Computing lengths
std::transform(A.begin(), A.end(), L.begin(),
- [](auto & a) { return a.template norm<L_2>(); });
+ [](auto & a) { return a.norm(); });
// Computing cosines
std::transform(A.begin(), A.end(), L.begin(), C.begin(),
[](auto & a, auto & l) { return a(0) / l; });
// Computing sines
std::transform(A.begin(), A.end(), L.begin(), S.begin(),
[](auto & a, auto & l) { return a(1) / l; });
// Natural coordinates
Real xi = natural_coords(0);
Real eta = natural_coords(1);
// Derivative of quadratic interpolation functions
- Matrix<Real> dP = {{4 * (1 - 2 * xi - eta), 4 * eta, -4 * eta},
- {-4 * xi, 4 * xi, 4 * (1 - xi - 2 * eta)}};
+ Eigen::Matrix<Real, 2, 3> dP{{4 * (1 - 2 * xi - eta), 4 * eta, -4 * eta},
+ {-4 * xi, 4 * xi, 4 * (1 - xi - 2 * eta)}};
- Matrix<Real> dNx1 = {
+ Eigen::Matrix<Real, 2, 3> dNx1{
{3. / 2 * (dP(0, 0) * C[0] / L[0] - dP(0, 2) * C[2] / L[2]),
3. / 2 * (dP(0, 1) * C[1] / L[1] - dP(0, 0) * C[0] / L[0]),
3. / 2 * (dP(0, 2) * C[2] / L[2] - dP(0, 1) * C[1] / L[1])},
{3. / 2 * (dP(1, 0) * C[0] / L[0] - dP(1, 2) * C[2] / L[2]),
3. / 2 * (dP(1, 1) * C[1] / L[1] - dP(1, 0) * C[0] / L[0]),
3. / 2 * (dP(1, 2) * C[2] / L[2] - dP(1, 1) * C[1] / L[1])}};
- Matrix<Real> dNx2 = {
- // clang-format off
+ Eigen::Matrix<Real, 2, 3> dNx2{
{-1 - 3. / 4 * (dP(0, 0) * C[0] * C[0] + dP(0, 2) * C[2] * C[2]),
- 1 - 3. / 4 * (dP(0, 1) * C[1] * C[1] + dP(0, 0) * C[0] * C[0]),
- - 3. / 4 * (dP(0, 2) * C[2] * C[2] + dP(0, 1) * C[1] * C[1])},
+ 1 - 3. / 4 * (dP(0, 1) * C[1] * C[1] + dP(0, 0) * C[0] * C[0]),
+ -3. / 4 * (dP(0, 2) * C[2] * C[2] + dP(0, 1) * C[1] * C[1])},
{-1 - 3. / 4 * (dP(1, 0) * C[0] * C[0] + dP(1, 2) * C[2] * C[2]),
- - 3. / 4 * (dP(1, 1) * C[1] * C[1] + dP(1, 0) * C[0] * C[0]),
- 1 - 3. / 4 * (dP(1, 2) * C[2] * C[2] + dP(1, 1) * C[1] * C[1])}};
- // clang-format on
- Matrix<Real> dNx3 = {
+ -3. / 4 * (dP(1, 1) * C[1] * C[1] + dP(1, 0) * C[0] * C[0]),
+ 1 - 3. / 4 * (dP(1, 2) * C[2] * C[2] + dP(1, 1) * C[1] * C[1])}};
+
+ Eigen::Matrix<Real, 2, 3> dNx3{
{-3. / 4 * (dP(0, 0) * C[0] * S[0] + dP(0, 2) * C[2] * S[2]),
-3. / 4 * (dP(0, 1) * C[1] * S[1] + dP(0, 0) * C[0] * S[0]),
-3. / 4 * (dP(0, 2) * C[2] * S[2] + dP(0, 1) * C[1] * S[1])},
{-3. / 4 * (dP(1, 0) * C[0] * S[0] + dP(1, 2) * C[2] * S[2]),
-3. / 4 * (dP(1, 1) * C[1] * S[1] + dP(1, 0) * C[0] * S[0]),
-3. / 4 * (dP(1, 2) * C[2] * S[2] + dP(1, 1) * C[1] * S[1])}};
- Matrix<Real> dNy1 = {
+ Eigen::Matrix<Real, 2, 3> dNy1{
{3. / 2 * (dP(0, 0) * S[0] / L[0] - dP(0, 2) * S[2] / L[2]),
3. / 2 * (dP(0, 1) * S[1] / L[1] - dP(0, 0) * S[0] / L[0]),
3. / 2 * (dP(0, 2) * S[2] / L[2] - dP(0, 1) * S[1] / L[1])},
{3. / 2 * (dP(1, 0) * S[0] / L[0] - dP(1, 2) * S[2] / L[2]),
3. / 2 * (dP(1, 1) * S[1] / L[1] - dP(1, 0) * S[0] / L[0]),
3. / 2 * (dP(1, 2) * S[2] / L[2] - dP(1, 1) * S[1] / L[1])}};
- const Matrix<Real> & dNy2 = dNx3;
- Matrix<Real> dNy3 = {
- // clang-format off
+ auto dNy2 = dNx3;
+
+ Eigen::Matrix<Real, 2, 3> dNy3{
{-1 - 3. / 4 * (dP(0, 0) * S[0] * S[0] + dP(0, 2) * S[2] * S[2]),
- 1 - 3. / 4 * (dP(0, 1) * S[1] * S[1] + dP(0, 0) * S[0] * S[0]),
- - 3. / 4 * (dP(0, 2) * S[2] * S[2] + dP(0, 1) * S[1] * S[1])},
+ 1 - 3. / 4 * (dP(0, 1) * S[1] * S[1] + dP(0, 0) * S[0] * S[0]),
+ -3. / 4 * (dP(0, 2) * S[2] * S[2] + dP(0, 1) * S[1] * S[1])},
{-1 - 3. / 4 * (dP(1, 0) * S[0] * S[0] + dP(1, 2) * S[2] * S[2]),
- - 3. / 4 * (dP(1, 1) * S[1] * S[1] + dP(1, 0) * S[0] * S[0]),
- 1 - 3. / 4 * (dP(1, 2) * S[2] * S[2] + dP(1, 1) * S[1] * S[1])}};
- // clang-format on
+ -3. / 4 * (dP(1, 1) * S[1] * S[1] + dP(1, 0) * S[0] * S[0]),
+ 1 - 3. / 4 * (dP(1, 2) * S[2] * S[2] + dP(1, 1) * S[1] * S[1])}};
// Derivative of linear (membrane mode) functions
- Matrix<Real> dNm(2, 3);
+ Eigen::Matrix<Real, 2, 3> dNm;
InterpolationElement<_itp_lagrange_triangle_3, _itk_lagrangian>::computeDNDS(
natural_coords, dNm);
UInt i = 0;
- for (const Matrix<Real> & mat : {dNm, dNx1, dNx2, dNx3, dNy1, dNy2, dNy3}) {
- B.block(mat, 0, i);
+ for (auto && mat : {dNm, dNx1, dNx2, dNx3, dNy1, dNy2, dNy3}) {
+ B.template block<2, 3>(0, i) = mat;
i += mat.cols();
}
}
+
/* -------------------------------------------------------------------------- */
template <>
+template <typename D1, typename D2>
inline void
-InterpolationElement<_itp_discrete_kirchhoff_triangle_18,
- _itk_structural>::arrangeInVoigt(const Matrix<Real> & dnds,
- Matrix<Real> & B) {
- Matrix<Real> dNm(2, 3);
- Matrix<Real> dNx1(2, 3);
- Matrix<Real> dNx2(2, 3);
- Matrix<Real> dNx3(2, 3);
- Matrix<Real> dNy1(2, 3);
- Matrix<Real> dNy2(2, 3);
- Matrix<Real> dNy3(2, 3);
- UInt i = 0;
+InterpolationElement<_itp_discrete_kirchhoff_triangle_18, _itk_structural>::
+ arrangeInVoigt(const Eigen::MatrixBase<D1> & dnds,
+ Eigen::MatrixBase<D2> & B) {
+ Eigen::Matrix<Real, 2, 3> dNm, dNx1, dNx2, dNx3, dNy1, dNy2, dNy3;
- for (Matrix<Real> * mat : {&dNm, &dNx1, &dNx2, &dNx3, &dNy1, &dNy2, &dNy3}) {
- *mat = dnds.block(0, i, 2, 3);
+ UInt i = 0;
+ for (auto && mat : {&dNm, &dNx1, &dNx2, &dNx3, &dNy1, &dNy2, &dNy3}) {
+ *mat = dnds.template block<2, 3>(0, i);
i += mat->cols();
}
- for (UInt i = 0; i < 3; ++i) {
- // clang-format off
- Matrix<Real> Bm = {{dNm(0, i), 0, 0, 0, 0, 0},
- {0, dNm(1, i), 0, 0, 0, 0},
- {dNm(1, i), dNm(0, i), 0, 0, 0, 0}};
- Matrix<Real> Bf = {{0, 0, dNx1(0, i), -dNx3(0, i), dNx2(0, i), 0},
- {0, 0, dNy1(1, i), -dNy3(1, i), dNy2(1, i), 0},
- {0, 0, dNx1(1, i) + dNy1(0, i), -dNx3(1, i) - dNy3(0, i), dNx2(1, i) + dNy2(0, i), 0}};
- // clang-format on
- B.block(Bm, 0, i * 6);
- B.block(Bf, 3, i * 6);
+ for (Int i = 0; i < 3; ++i) {
+ Eigen::Matrix<Real, 3, 6> Bm{{dNm(0, i), 0, 0, 0, 0, 0},
+ {0, dNm(1, i), 0, 0, 0, 0},
+ {dNm(1, i), dNm(0, i), 0, 0, 0, 0}};
+ Eigen::Matrix<Real, 3, 6> Bf{{0, 0, dNx1(0, i), -dNx3(0, i), dNx2(0, i), 0},
+ {0, 0, dNy1(1, i), -dNy3(1, i), dNy2(1, i), 0},
+ {0, 0, dNx1(1, i) + dNy1(0, i),
+ -dNx3(1, i) - dNy3(0, i),
+ dNx2(1, i) + dNy2(0, i), 0}};
+
+ B.template block<3, 6>(0, i * 6) = Bm;
+ B.template block<3, 6>(3, i * 6) = Bf;
}
}
} // namespace akantu
#endif /* AKANTU_ELEMENT_CLASS_KIRCHHOFF_SHELL_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh b/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh
index 01362e6eb..203c62629 100644
--- a/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh
@@ -1,184 +1,186 @@
/**
* @file element_class_pentahedron_15_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Sacha Laffely <sacha.laffely@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Scantamburlo <damien.scantamburlo@epfl.ch>
*
* @date creation: Tue Mar 31 2015
* @date last modification: Fri Feb 07 2020
*
* @brief Specialization of the element_class class for the type
* _pentahedron_15
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* \verbatim
z
^
|
|
| 1
| /|\
|/ | \
10 7 6
/ | \
/ | \
4 2--8--0
| \ / /
| \11 /
13 12 9---------->y
| / \ /
|/ \ /
5--14--3
/
/
/
v
x
\endverbatim
x y z
* N0 -1 1 0
* N1 -1 0 1
* N2 -1 0 0
* N3 1 1 0
* N4 1 0 1
* N5 1 0 0
* N6 -1 0.5 0.5
* N7 -1 0 0.5
* N8 -1 0.5 0
* N9 0 1 0
* N10 0 0 1
* N11 0 0 0
* N12 1 0.5 0.5
* N13 1 0 0.5
* N14 1 0.5 0
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_pentahedron_15, _gt_pentahedron_15,
_itp_lagrange_pentahedron_15, _ek_regular,
3, _git_pentahedron, 2);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_pentahedron_15>::computeShapes(
- const vector_type & c, vector_type & N) {
- auto & x = c(0);
- auto & y = c(1);
- auto & z = c(2);
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &N) {
+ auto &&x = c(0);
+ auto &&y = c(1);
+ auto &&z = c(2);
// Shape Functions, Natural coordinates
N(0) = 0.5 * y * (1 - x) * (2 * y - 2 - x);
N(1) = 0.5 * z * (1 - x) * (2 * z - 2 - x);
N(2) = 0.5 * (x - 1) * (1 - y - z) * (x + 2 * y + 2 * z);
N(3) = 0.5 * y * (1 + x) * (2 * y - 2 + x);
N(4) = 0.5 * z * (1 + x) * (2 * z - 2 + x);
N(5) = 0.5 * (-x - 1) * (1 - y - z) * (-x + 2 * y + 2 * z);
N(6) = 2.0 * y * z * (1 - x);
N(7) = 2.0 * z * (1 - y - z) * (1 - x);
N(8) = 2.0 * y * (1 - x) * (1 - y - z);
N(9) = y * (1 - x * x);
N(10) = z * (1 - x * x);
N(11) = (1 - y - z) * (1 - x * x);
N(12) = 2.0 * y * z * (1 + x);
N(13) = 2.0 * z * (1 - y - z) * (1 + x);
N(14) = 2.0 * y * (1 - y - z) * (1 + x);
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_pentahedron_15>::computeDNDS(
- const vector_type & c, matrix_type & dnds) {
- auto & x = c(0);
- auto & y = c(1);
- auto & z = c(2);
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &dnds) {
+ auto &&x = c(0);
+ auto &&y = c(1);
+ auto &&z = c(2);
// ddx
dnds(0, 0) = 0.5 * y * (2 * x - 2 * y + 1);
dnds(0, 1) = 0.5 * z * (2 * x - 2 * z + 1);
dnds(0, 2) = -0.5 * (2 * x + 2 * y + 2 * z - 1) * (y + z - 1);
dnds(0, 3) = 0.5 * y * (2 * x + 2 * y - 1);
dnds(0, 4) = 0.5 * z * (2 * x + 2 * z - 1);
dnds(0, 5) = -0.5 * (y + z - 1) * (2 * x - 2 * y - 2 * z + 1);
dnds(0, 6) = -2.0 * y * z;
dnds(0, 7) = 2.0 * z * (y + z - 1);
dnds(0, 8) = 2.0 * y * (y + z - 1);
dnds(0, 9) = -2.0 * x * y;
dnds(0, 10) = -2.0 * x * z;
dnds(0, 11) = 2.0 * x * (y + z - 1);
dnds(0, 12) = 2.0 * y * z;
dnds(0, 13) = -2.0 * z * (y + z - 1);
dnds(0, 14) = -2.0 * y * (y + z - 1);
// ddy
dnds(1, 0) = -0.5 * (x - 1) * (4 * y - x - 2);
dnds(1, 1) = 0.0;
dnds(1, 2) = -0.5 * (x - 1) * (4 * y + x + 2 * (2 * z - 1));
dnds(1, 3) = 0.5 * (x + 1) * (4 * y + x - 2);
dnds(1, 4) = 0.0;
dnds(1, 5) = 0.5 * (x + 1) * (4 * y - x + 2 * (2 * z - 1));
dnds(1, 6) = -2.0 * (x - 1) * z;
dnds(1, 7) = 2.0 * z * (x - 1);
dnds(1, 8) = 2.0 * (2 * y + z - 1) * (x - 1);
dnds(1, 9) = -(x * x - 1);
dnds(1, 10) = 0.0;
dnds(1, 11) = (x * x - 1);
dnds(1, 12) = 2.0 * z * (x + 1);
dnds(1, 13) = -2.0 * z * (x + 1);
dnds(1, 14) = -2.0 * (2 * y + z - 1) * (x + 1);
// ddz
dnds(2, 0) = 0.0;
dnds(2, 1) = -0.5 * (x - 1) * (4 * z - x - 2);
dnds(2, 2) = -0.5 * (x - 1) * (4 * z + x + 2 * (2 * y - 1));
dnds(2, 3) = 0.0;
dnds(2, 4) = 0.5 * (x + 1) * (4 * z + x - 2);
dnds(2, 5) = 0.5 * (x + 1) * (4 * z - x + 2 * (2 * y - 1));
dnds(2, 6) = -2.0 * (x - 1) * y;
dnds(2, 7) = 2.0 * (x - 1) * (2 * z + y - 1);
dnds(2, 8) = 2.0 * y * (x - 1);
dnds(2, 9) = 0.0;
dnds(2, 10) = -(x * x - 1);
dnds(2, 11) = (x * x - 1);
dnds(2, 12) = 2.0 * (x + 1) * y;
dnds(2, 13) = -2.0 * (x + 1) * (2 * z + y - 1);
dnds(2, 14) = -2.0 * (x + 1) * y;
}
/* -------------------------------------------------------------------------- */
template <>
+template <class D>
inline Real GeometricalElement<_gt_pentahedron_15>::getInradius(
- const Matrix<Real> & coord) {
+ const Eigen::MatrixBase<D> &coord) {
return GeometricalElement<_gt_pentahedron_6>::getInradius(coord) * 0.5;
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh b/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh
index 290904cb0..04365f439 100644
--- a/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh
@@ -1,168 +1,142 @@
/**
* @file element_class_pentahedron_6_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <mchambart@stucky.ch>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Thomas Menouillard <tmenouillard@stucky.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Mar 14 2011
* @date last modification: Tue Sep 29 2020
*
* @brief Specialization of the element_class class for the type _pentahedron_6
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
/z
|
|
| 1
| /|\
|/ | \
/ | \
/ | \
/ | \
4 2-----0
| \ / /
| \/ /
| \ /----------/y
| / \ /
|/ \ /
5---.--3
/
/
/
\x
x y z
* N0 -1 1 0
* N1 -1 0 1
-* N2 -1 0 0
+* N2 -1 0 0
* N3 1 1 0
* N4 1 0 1
* N5 1 0 0
\endverbatim
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_pentahedron_6, _gt_pentahedron_6,
_itp_lagrange_pentahedron_6, _ek_regular,
3, _git_pentahedron, 1);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_pentahedron_6>::computeShapes(
- const vector_type & c, vector_type & N) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &N) {
/// Natural coordinates
N(0) = 0.5 * c(1) * (1 - c(0)); // N1(q)
N(1) = 0.5 * c(2) * (1 - c(0)); // N2(q)
N(2) = 0.5 * (1 - c(1) - c(2)) * (1 - c(0)); // N3(q)
N(3) = 0.5 * c(1) * (1 + c(0)); // N4(q)
N(4) = 0.5 * c(2) * (1 + c(0)); // N5(q)
N(5) = 0.5 * (1 - c(1) - c(2)) * (1 + c(0)); // N6(q)
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_pentahedron_6>::computeDNDS(
- const vector_type & c, matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &dnds) {
dnds(0, 0) = -0.5 * c(1);
dnds(0, 1) = -0.5 * c(2);
dnds(0, 2) = -0.5 * (1 - c(1) - c(2));
dnds(0, 3) = 0.5 * c(1);
dnds(0, 4) = 0.5 * c(2);
dnds(0, 5) = 0.5 * (1 - c(1) - c(2));
dnds(1, 0) = 0.5 * (1 - c(0));
dnds(1, 1) = 0.0;
dnds(1, 2) = -0.5 * (1 - c(0));
dnds(1, 3) = 0.5 * (1 + c(0));
dnds(1, 4) = 0.0;
dnds(1, 5) = -0.5 * (1 + c(0));
dnds(2, 0) = 0.0;
dnds(2, 1) = 0.5 * (1 - c(0));
dnds(2, 2) = -0.5 * (1 - c(0));
dnds(2, 3) = 0.0;
dnds(2, 4) = 0.5 * (1 + c(0));
dnds(2, 5) = -0.5 * (1 + c(0));
}
-/* -------------------------------------------------------------------------- */
-// I have to duplicate this code since the Real * coords do not know their size
-// in the Math module.
-// If later we use eigen or Vector to implement this function
-// there should be only one function in akantu::Math
-// -> this is temporary for the release deadline which was so extended
-
-inline Real triangle_inradius(const Real * coord1, const Real * coord2,
- const Real * coord3) {
- /**
- * @f{eqnarray*}{
- * r &=& A / s \\
- * A &=& 1/4 * \sqrt{(a + b + c) * (a - b + c) * (a + b - c) (-a + b + c)} \\
- * s &=& \frac{a + b + c}{2}
- * @f}
- */
-
- auto a = Math::distance_3d(coord1, coord2);
- auto b = Math::distance_3d(coord2, coord3);
- auto c = Math::distance_3d(coord1, coord3);
-
- auto s = (a + b + c) * 0.5;
-
- return std::sqrt((s - a) * (s - b) * (s - c) / s);
-}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_pentahedron_6>::getInradius(const Matrix<Real> & coord) {
- Vector<Real> u0 = coord(0);
- Vector<Real> u1 = coord(1);
- Vector<Real> u2 = coord(2);
- Vector<Real> u3 = coord(3);
- Vector<Real> u4 = coord(4);
- Vector<Real> u5 = coord(5);
-
- auto inradius_triangle_1 =
- triangle_inradius(u0.storage(), u1.storage(), u2.storage());
+template <class D>
+inline Real GeometricalElement<_gt_pentahedron_6>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ auto &&u0 = coord.col(0);
+ auto &&u1 = coord.col(1);
+ auto &&u2 = coord.col(2);
+ auto &&u3 = coord.col(3);
+ auto &&u4 = coord.col(4);
+ auto &&u5 = coord.col(5);
- auto inradius_triangle_2 =
- triangle_inradius(u3.storage(), u4.storage(), u5.storage());
+ auto inradius_triangle_1 = Math::triangle_inradius(u0, u1, u2);
+ auto inradius_triangle_2 = Math::triangle_inradius(u3, u4, u5);
- auto d1 = u3.distance(u0) * 0.5;
- auto d2 = u5.distance(u2) * 0.5;
- auto d3 = u4.distance(u1) * 0.5;
+ auto d1 = (u3 - u0).norm() * 0.5;
+ auto d2 = (u5 - u2).norm() * 0.5;
+ auto d3 = (u4 - u1).norm() * 0.5;
auto p =
2. * std::min({inradius_triangle_1, inradius_triangle_2, d1, d2, d3});
return p;
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh b/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh
index 0bd4f81a1..1193333f2 100644
--- a/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_point_1_inline_impl.hh
@@ -1,86 +1,96 @@
/**
* @file element_class_point_1_inline_impl.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Feb 28 2020
*
* @brief Specialization of the element_class class for the type _point_1
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
x
(0)
@endverbatim
*
* @f{eqnarray*}{
* N1 &=& 1
* @f}
*
* @f{eqnarray*}{
* q_0 &=& 0
* @f}
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_point_1, _gt_point, _itp_lagrange_point_1,
_ek_regular, 0, _git_point, 1);
-/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2, class D3>
+inline void
+ElementClass<_point_1, _ek_regular>::computeNormalsOnNaturalCoordinates(
+ const Eigen::MatrixBase<D1> & /*coord*/,
+ const Eigen::MatrixBase<D2> & /*f*/, Eigen::MatrixBase<D3> & /*normals*/) {}
+
+/* --------------r------------------------------------------------------------
+ */
+template <>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_point_1>::computeShapes(
- __attribute__((unused)) const vector_type & natural_coords,
- vector_type & N) {
+ const Eigen::MatrixBase<D1> & /*natural_coords*/,
+ Eigen::MatrixBase<D2> & N) {
N(0) = 1; /// N1(q_0)
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_point_1>::computeDNDS(
- __attribute__((unused)) const vector_type & natural_coords,
- __attribute__((unused)) matrix_type & dnds) {}
+ const Eigen::MatrixBase<D1> & /*natural_coords*/,
+ Eigen::MatrixBase<D2> & /*dnds*/) {}
/* -------------------------------------------------------------------------- */
template <>
-inline void InterpolationElement<_itp_lagrange_point_1>::computeSpecialJacobian(
- __attribute__((unused)) const Matrix<Real> & J, Real & jac) {
- jac = 0.;
+template <class D>
+inline Real InterpolationElement<_itp_lagrange_point_1>::computeSpecialJacobian(
+ const Eigen::MatrixBase<D> & /*J*/) {
+ return 0.;
}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_point>::getInradius(__attribute__((unused))
- const Matrix<Real> & coord) {
+template <class D>
+inline Real GeometricalElement<_gt_point>::getInradius(
+ const Eigen::MatrixBase<D> & /*coord*/) {
return 0.;
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh b/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh
index e1a537410..011cea5c8 100644
--- a/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh
@@ -1,179 +1,170 @@
/**
* @file element_class_quadrangle_4_inline_impl.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Fri Dec 11 2020
*
* @brief Specialization of the element_class class for the type _quadrangle_4
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\eta
^
(-1,1) | (1,1)
x---------x
| | |
| | |
--|---------|-----> \xi
| | |
| | |
x---------x
(-1,-1) | (1,-1)
@endverbatim
*
* @f[
* \begin{array}{lll}
* N1 = (1 - \xi) (1 - \eta) / 4
* & \frac{\partial N1}{\partial \xi} = - (1 - \eta) / 4
* & \frac{\partial N1}{\partial \eta} = - (1 - \xi) / 4 \\
* N2 = (1 + \xi) (1 - \eta) / 4 \\
* & \frac{\partial N2}{\partial \xi} = (1 - \eta) / 4
* & \frac{\partial N2}{\partial \eta} = - (1 + \xi) / 4 \\
* N3 = (1 + \xi) (1 + \eta) / 4 \\
* & \frac{\partial N3}{\partial \xi} = (1 + \eta) / 4
* & \frac{\partial N3}{\partial \eta} = (1 + \xi) / 4 \\
* N4 = (1 - \xi) (1 + \eta) / 4
* & \frac{\partial N4}{\partial \xi} = - (1 + \eta) / 4
* & \frac{\partial N4}{\partial \eta} = (1 - \xi) / 4 \\
* \end{array}
* @f]
*
* @f{eqnarray*}{
* \xi_{q0} &=& 0 \qquad \eta_{q0} = 0
* @f}
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_quadrangle_4, _gt_quadrangle_4,
_itp_lagrange_quadrangle_4, _ek_regular, 2,
_git_segment, 2);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeShapes(
- const vector_type & c, vector_type & N) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &N) {
N(0) = 1. / 4. * (1. - c(0)) * (1. - c(1)); /// N1(q_0)
N(1) = 1. / 4. * (1. + c(0)) * (1. - c(1)); /// N2(q_0)
N(2) = 1. / 4. * (1. + c(0)) * (1. + c(1)); /// N3(q_0)
N(3) = 1. / 4. * (1. - c(0)) * (1. + c(1)); /// N4(q_0)
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeDNDS(
- const vector_type & c, matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &dnds) {
/**
* @f[
* dnds = \left(
* \begin{array}{cccc}
* \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial
* \xi}
* & \frac{\partial N3}{\partial \xi} & \frac{\partial
* N4}{\partial \xi}\\
* \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial
* \eta}
* & \frac{\partial N3}{\partial \eta} & \frac{\partial
* N4}{\partial \eta}
* \end{array}
* \right)
* @f]
*/
dnds(0, 0) = -1. / 4. * (1. - c(1));
dnds(0, 1) = 1. / 4. * (1. - c(1));
dnds(0, 2) = 1. / 4. * (1. + c(1));
dnds(0, 3) = -1. / 4. * (1. + c(1));
dnds(1, 0) = -1. / 4. * (1. - c(0));
dnds(1, 1) = -1. / 4. * (1. + c(0));
dnds(1, 2) = 1. / 4. * (1. + c(0));
dnds(1, 3) = 1. / 4. * (1. - c(0));
}
/* -------------------------------------------------------------------------- */
template <>
template <class vector_type, class matrix_type>
inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeD2NDS2(
- const vector_type & /*c*/, matrix_type & d2nds2) {
+ const vector_type & /*c*/, matrix_type &d2nds2) {
d2nds2.zero();
d2nds2(1, 0) = 1. / 4.;
d2nds2(1, 1) = -1. / 4.;
d2nds2(1, 2) = 1. / 4.;
d2nds2(1, 3) = -1. / 4.;
d2nds2(2, 0) = 1. / 4.;
d2nds2(2, 1) = -1. / 4.;
d2nds2(2, 2) = 1. / 4.;
d2nds2(2, 3) = -1. / 4.;
}
/* -------------------------------------------------------------------------- */
template <>
-inline void
-InterpolationElement<_itp_lagrange_quadrangle_4>::computeSpecialJacobian(
- const Matrix<Real> & J, Real & jac) {
- Vector<Real> vprod(J.cols());
- Matrix<Real> Jt(J.transpose(), true);
- vprod.crossProduct(Jt(0), Jt(1));
- jac = vprod.norm();
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline Real
-GeometricalElement<_gt_quadrangle_4>::getInradius(const Matrix<Real> & coord) {
- Vector<Real> u0 = coord(0);
- Vector<Real> u1 = coord(1);
- Vector<Real> u2 = coord(2);
- Vector<Real> u3 = coord(3);
- Real a = u0.distance(u1);
- Real b = u1.distance(u2);
- Real c = u2.distance(u3);
- Real d = u3.distance(u0);
+template <class D>
+inline Real GeometricalElement<_gt_quadrangle_4>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ auto &&u0 = coord.col(0);
+ auto &&u1 = coord.col(1);
+ auto &&u2 = coord.col(2);
+ auto &&u3 = coord.col(3);
+ Real a = (u0 - u1).norm();
+ Real b = (u1 - u2).norm();
+ Real c = (u2 - u3).norm();
+ Real d = (u3 - u0).norm();
// Real septimetre = (a + b + c + d) / 2.;
// Real p = Math::distance_2d(coord + 0, coord + 4);
// Real q = Math::distance_2d(coord + 2, coord + 6);
// Real area = sqrt(4*(p*p * q*q) - (a*a + b*b + c*c + d*d)*(a*a + c*c - b*b -
// d*d)) / 4.;
// Real h = sqrt(area); // to get a length
// Real h = area / septimetre; // formula of inradius for circumscritable
// quadrelateral
Real h = std::min({a, b, c, d});
return h;
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh b/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh
index 6944b42b1..52d16d869 100644
--- a/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh
@@ -1,189 +1,181 @@
/**
* @file element_class_quadrangle_8_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed May 18 2011
* @date last modification: Tue Sep 29 2020
*
* @brief Specialization of the ElementClass for the _quadrangle_8
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\eta
^
|
(-1,1) (0,1) (1,1)
x-------x-------x
| | |
| | |
| | |
(-1,0)| | |(1,0)
----x---------------X-----> \xi
| | |
| | |
| | |
| | |
x-------x-------x
(-1,-1) (0,-1) (1,-1)
|
@endverbatim
*
* @f[
* \begin{array}{lll}
* N1 = (1 - \xi) (1 - \eta)(- 1 - \xi - \eta) / 4
* & \frac{\partial N1}{\partial \xi} = (1 - \eta)(2 \xi + \eta) / 4
* & \frac{\partial N1}{\partial \eta} = (1 - \xi)(\xi + 2 \eta) / 4 \\
* N2 = (1 + \xi) (1 - \eta)(- 1 + \xi - \eta) / 4 \\
* & \frac{\partial N2}{\partial \xi} = (1 - \eta)(2 \xi - \eta) / 4
* & \frac{\partial N2}{\partial \eta} = - (1 + \xi)(\xi - 2 \eta) / 4 \\
* N3 = (1 + \xi) (1 + \eta)(- 1 + \xi + \eta) / 4 \\
* & \frac{\partial N3}{\partial \xi} = (1 + \eta)(2 \xi + \eta) / 4
* & \frac{\partial N3}{\partial \eta} = (1 + \xi)(\xi + 2 \eta) / 4 \\
* N4 = (1 - \xi) (1 + \eta)(- 1 - \xi + \eta) / 4
* & \frac{\partial N4}{\partial \xi} = (1 + \eta)(2 \xi - \eta) / 4
* & \frac{\partial N4}{\partial \eta} = - (1 - \xi)(\xi - 2 \eta) / 4 \\
* N5 = (1 - \xi^2) (1 - \eta) / 2
* & \frac{\partial N1}{\partial \xi} = - \xi (1 - \eta)
* & \frac{\partial N1}{\partial \eta} = - (1 - \xi^2) / 2 \\
* N6 = (1 + \xi) (1 - \eta^2) / 2 \\
* & \frac{\partial N2}{\partial \xi} = (1 - \eta^2) / 2
* & \frac{\partial N2}{\partial \eta} = - \eta (1 + \xi) \\
* N7 = (1 - \xi^2) (1 + \eta) / 2 \\
* & \frac{\partial N3}{\partial \xi} = - \xi (1 + \eta)
* & \frac{\partial N3}{\partial \eta} = (1 - \xi^2) / 2 \\
* N8 = (1 - \xi) (1 - \eta^2) / 2
* & \frac{\partial N4}{\partial \xi} = - (1 - \eta^2) / 2
* & \frac{\partial N4}{\partial \eta} = - \eta (1 - \xi) \\
* \end{array}
* @f]
*
* @f{eqnarray*}{
* \xi_{q0} &=& 0 \qquad \eta_{q0} = 0
* @f}
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_quadrangle_8, _gt_quadrangle_8,
_itp_serendip_quadrangle_8, _ek_regular, 2,
_git_segment, 3);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_serendip_quadrangle_8>::computeShapes(
- const vector_type & c, vector_type & N) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &N) {
/// Natural coordinates
const Real xi = c(0);
const Real eta = c(1);
N(0) = .25 * (1 - xi) * (1 - eta) * (-1 - xi - eta);
N(1) = .25 * (1 + xi) * (1 - eta) * (-1 + xi - eta);
N(2) = .25 * (1 + xi) * (1 + eta) * (-1 + xi + eta);
N(3) = .25 * (1 - xi) * (1 + eta) * (-1 - xi + eta);
N(4) = .5 * (1 - xi * xi) * (1 - eta);
N(5) = .5 * (1 + xi) * (1 - eta * eta);
N(6) = .5 * (1 - xi * xi) * (1 + eta);
N(7) = .5 * (1 - xi) * (1 - eta * eta);
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_serendip_quadrangle_8>::computeDNDS(
- const vector_type & c, matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &dnds) {
const Real xi = c(0);
const Real eta = c(1);
/// dN/dxi
dnds(0, 0) = .25 * (1 - eta) * (2 * xi + eta);
dnds(0, 1) = .25 * (1 - eta) * (2 * xi - eta);
dnds(0, 2) = .25 * (1 + eta) * (2 * xi + eta);
dnds(0, 3) = .25 * (1 + eta) * (2 * xi - eta);
dnds(0, 4) = -xi * (1 - eta);
dnds(0, 5) = .5 * (1 - eta * eta);
dnds(0, 6) = -xi * (1 + eta);
dnds(0, 7) = -.5 * (1 - eta * eta);
/// dN/deta
dnds(1, 0) = .25 * (1 - xi) * (2 * eta + xi);
dnds(1, 1) = .25 * (1 + xi) * (2 * eta - xi);
dnds(1, 2) = .25 * (1 + xi) * (2 * eta + xi);
dnds(1, 3) = .25 * (1 - xi) * (2 * eta - xi);
dnds(1, 4) = -.5 * (1 - xi * xi);
dnds(1, 5) = -eta * (1 + xi);
dnds(1, 6) = .5 * (1 - xi * xi);
dnds(1, 7) = -eta * (1 - xi);
}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_quadrangle_8>::getInradius(const Matrix<Real> & coord) {
- Vector<Real> u0 = coord(0);
- Vector<Real> u1 = coord(1);
- Vector<Real> u2 = coord(2);
- Vector<Real> u3 = coord(3);
- Vector<Real> u4 = coord(4);
- Vector<Real> u5 = coord(5);
- Vector<Real> u6 = coord(6);
- Vector<Real> u7 = coord(7);
-
- auto a = u0.distance(u4);
- auto b = u4.distance(u1);
- auto h = std::min(a, b);
-
- a = u1.distance(u5);
- b = u5.distance(u2);
+template <class D>
+inline Real GeometricalElement<_gt_quadrangle_8>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ auto &&u0 = coord.col(0);
+ auto &&u1 = coord.col(1);
+ auto &&u2 = coord.col(2);
+ auto &&u3 = coord.col(3);
+ auto &&u4 = coord.col(4);
+ auto &&u5 = coord.col(5);
+ auto &&u6 = coord.col(6);
+ auto &&u7 = coord.col(7);
+
+ Real a = (u0 - u4).norm();
+ Real b = (u4 - u1).norm();
+ Real h = std::min(a, b);
+
+ a = (u1 - u5).norm();
+ b = (u5 - u2).norm();
h = std::min(h, std::min(a, b));
- a = u2.distance(u6);
- b = u6.distance(u3);
+ a = (u2 - u6).norm();
+ b = (u6 - u3).norm();
h = std::min(h, std::min(a, b));
- a = u3.distance(u7);
- b = u7.distance(u0);
+ a = (u3 - u7).norm();
+ b = (u7 - u0).norm();
h = std::min(h, std::min(a, b));
return h;
}
-/* -------------------------------------------------------------------------- */
-template <>
-inline void
-InterpolationElement<_itp_serendip_quadrangle_8>::computeSpecialJacobian(
- const Matrix<Real> & J, Real & jac) {
- Vector<Real> vprod(J.cols());
- Matrix<Real> Jt(J.transpose(), true);
- vprod.crossProduct(Jt(0), Jt(1));
- jac = vprod.norm();
-}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh b/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh
index 9ebd87b41..a1e40bb13 100644
--- a/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_segment_2_inline_impl.hh
@@ -1,122 +1,115 @@
/**
* @file element_class_segment_2_inline_impl.hh
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jul 16 2010
* @date last modification: Fri Dec 11 2020
*
* @brief Specialization of the element_class class for the type _segment_2
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
q
--x--------|--------x---> x
-1 0 1
@endverbatim
*
* @f{eqnarray*}{
* w_1(x) &=& 1/2(1 - x) \\
* w_2(x) &=& 1/2(1 + x)
* @f}
*
* @f{eqnarray*}{
* x_{q} &=& 0
* @f}
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_segment_2, _gt_segment_2,
_itp_lagrange_segment_2, _ek_regular, 1,
_git_segment, 1);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_segment_2>::computeShapes(
- const vector_type & natural_coords, vector_type & N) {
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &N) {
/// natural coordinate
Real c = natural_coords(0);
/// shape functions
N(0) = 0.5 * (1 - c);
N(1) = 0.5 * (1 + c);
}
-/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_segment_2>::computeDNDS(
- __attribute__((unused)) const vector_type & natural_coords,
- matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> & /*natural_coords*/,
+ Eigen::MatrixBase<D2> &dnds) {
/// dN1/de
dnds(0, 0) = -.5;
/// dN2/de
dnds(0, 1) = .5;
}
/* -------------------------------------------------------------------------- */
template <>
template <class vector_type, class matrix_type>
inline void InterpolationElement<_itp_lagrange_segment_2>::computeD2NDS2(
- const vector_type & /*natural_coords*/, matrix_type & d2nds2) {
+ const vector_type & /*natural_coords*/, matrix_type &d2nds2) {
d2nds2.zero();
}
/* -------------------------------------------------------------------------- */
template <>
-inline void
-InterpolationElement<_itp_lagrange_segment_2>::computeSpecialJacobian(
- const Matrix<Real> & dxds, Real & jac) {
- jac = dxds.norm<L_2>();
+template <class D>
+inline Real GeometricalElement<_gt_segment_2>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ return (coord.col(1) - coord.col(0)).norm();
}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_segment_2>::getInradius(const Matrix<Real> & coord) {
- Vector<Real> a(coord(0));
- Vector<Real> b(coord(1));
- return a.distance(b);
+template <class D1, class D2>
+inline void
+GeometricalElement<_gt_segment_2>::getNormal(const Eigen::MatrixBase<D1> &coord,
+ Eigen::MatrixBase<D2> &normal) {
+ assert(normal.size() == 2 && "The normal is only uniquely defined in 2D");
+ Math::normal(coord.col(0) - coord.col(1), normal);
}
-// /* --------------------------------------------------------------------------
-// */
-// template<> inline bool ElementClass<_segment_2>::contains(const Vector<Real>
-// & natural_coords) {
-// if (natural_coords(0) < -1.) return false;
-// if (natural_coords(0) > 1.) return false;
-// return true;
-// }
-
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh b/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh
index 19d3f1b19..433acb36f 100644
--- a/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_segment_3_inline_impl.hh
@@ -1,111 +1,116 @@
/**
* @file element_class_segment_3_inline_impl.hh
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jul 16 2010
* @date last modification: Wed Dec 09 2020
*
* @brief Specialization of the element_class class for the type _segment_3
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
-1 0 1
-----x---------x---------x-----> x
1 3 2
@endverbatim
*
*
* @f[
* \begin{array}{lll}
* x_{1} = -1 & x_{2} = 1 & x_{3} = 0
* \end{array}
* @f]
*
* @f[
* \begin{array}{ll}
* w_1(x) = \frac{x}{2}(x - 1) & w'_1(x) = x - \frac{1}{2}\\
* w_2(x) = \frac{x}{2}(x + 1) & w'_2(x) = x + \frac{1}{2}\\
* w_3(x) = 1-x^2 & w'_3(x) = -2x
* \end{array}
* @f]
*
* @f[
* \begin{array}{ll}
* x_{q1} = -1/\sqrt{3} & x_{q2} = 1/\sqrt{3}
* \end{array}
* @f]
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_segment_3, _gt_segment_3,
_itp_lagrange_segment_3, _ek_regular, 1,
_git_segment, 2);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_segment_3>::computeShapes(
- const vector_type & natural_coords, vector_type & N) {
-
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &N) {
Real c = natural_coords(0);
N(0) = (c - 1) * c / 2;
N(1) = (c + 1) * c / 2;
N(2) = 1 - c * c;
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_segment_3>::computeDNDS(
- const vector_type & natural_coords, matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &dnds) {
Real c = natural_coords(0);
dnds(0, 0) = c - .5;
dnds(0, 1) = c + .5;
dnds(0, 2) = -2 * c;
}
/* -------------------------------------------------------------------------- */
template <>
-inline void
-InterpolationElement<_itp_lagrange_segment_3>::computeSpecialJacobian(
- const Matrix<Real> & dxds, Real & jac) {
- jac = Math::norm2(dxds.storage());
+template <class D>
+inline Real GeometricalElement<_gt_segment_3>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ auto dist1 = (coord(1) - coord(0)).norm();
+ auto dist2 = (coord(2) - coord(1)).norm();
+ return std::min(dist1, dist2);
}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_segment_3>::getInradius(const Matrix<Real> & coord) {
- Real dist1 = std::abs(coord(0, 0) - coord(0, 1));
- Real dist2 = std::abs(coord(0, 1) - coord(0, 2));
- return std::min(dist1, dist2);
+template <class D1, class D2>
+inline void
+GeometricalElement<_gt_segment_3>::getNormal(const Eigen::MatrixBase<D1> &coord,
+ Eigen::MatrixBase<D2> &normal) {
+ Eigen::Matrix<Real, 1, 1> natural_coords{{.5}};
+ ElementClass<_segment_3>::computeNormalsOnNaturalCoordinates(natural_coords,
+ coord, normal);
}
+
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh b/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh
index 98b7eec10..f6541b66f 100644
--- a/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh
@@ -1,284 +1,287 @@
/**
* @file element_class_tetrahedron_10_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Peter Spijker <peter.spijker@epfl.ch>
*
* @date creation: Fri Jul 16 2010
* @date last modification: Fri Feb 07 2020
*
* @brief Specialization of the element_class class for the type
* _tetrahedron_10
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\zeta
^
|
(0,0,1)
x
|` .
| ` .
| ` .
| ` . (0,0.5,0.5)
| ` x.
| q4 o ` . \eta
| ` . -,
(0,0,0.5) x ` x (0.5,0,0.5) -
| ` x-(0,1,0)
| q3 o` - '
| (0,0.5,0) - ` '
| x- ` x (0.5,0.5,0)
| q1 o - o q2` '
| - ` '
| - ` '
x---------------x--------------` x-----> \xi
(0,0,0) (0.5,0,0) (1,0,0)
@endverbatim
*
*
* @f[
* \begin{array}{lll}
* \xi_{0} = 0 & \eta_{0} = 0 & \zeta_{0} = 0 \\
* \xi_{1} = 1 & \eta_{1} = 0 & \zeta_{1} = 0 \\
* \xi_{2} = 0 & \eta_{2} = 1 & \zeta_{2} = 0 \\
* \xi_{3} = 0 & \eta_{3} = 0 & \zeta_{3} = 1 \\
* \xi_{4} = 1/2 & \eta_{4} = 0 & \zeta_{4} = 0 \\
* \xi_{5} = 1/2 & \eta_{5} = 1/2 & \zeta_{5} = 0 \\
* \xi_{6} = 0 & \eta_{6} = 1/2 & \zeta_{6} = 0 \\
* \xi_{7} = 0 & \eta_{7} = 0 & \zeta_{7} = 1/2 \\
* \xi_{8} = 1/2 & \eta_{8} = 0 & \zeta_{8} = 1/2 \\
* \xi_{9} = 0 & \eta_{9} = 1/2 & \zeta_{9} = 1/2
* \end{array}
* @f]
*
* @f[
* \begin{array}{llll}
* N1 = (1 - \xi - \eta - \zeta) (1 - 2 \xi - 2 \eta - 2 \zeta)
* & \frac{\partial N1}{\partial \xi} = 4 \xi + 4 \eta + 4 \zeta -
3
* & \frac{\partial N1}{\partial \eta} = 4 \xi + 4 \eta + 4 \zeta -
3
* & \frac{\partial N1}{\partial \zeta} = 4 \xi + 4 \eta + 4 \zeta -
3 \\
* N2 = \xi (2 \xi - 1)
* & \frac{\partial N2}{\partial \xi} = 4 \xi - 1
* & \frac{\partial N2}{\partial \eta} = 0
* & \frac{\partial N2}{\partial \zeta} = 0 \\
* N3 = \eta (2 \eta - 1)
* & \frac{\partial N3}{\partial \xi} = 0
* & \frac{\partial N3}{\partial \eta} = 4 \eta - 1
* & \frac{\partial N3}{\partial \zeta} = 0 \\
* N4 = \zeta (2 \zeta - 1)
* & \frac{\partial N4}{\partial \xi} = 0
* & \frac{\partial N4}{\partial \eta} = 0
* & \frac{\partial N4}{\partial \zeta} = 4 \zeta - 1 \\
* N5 = 4 \xi (1 - \xi - \eta - \zeta)
* & \frac{\partial N5}{\partial \xi} = 4 - 8 \xi - 4 \eta - 4
\zeta
* & \frac{\partial N5}{\partial \eta} = -4 \xi
* & \frac{\partial N5}{\partial \zeta} = -4 \xi \\
* N6 = 4 \xi \eta
* & \frac{\partial N6}{\partial \xi} = 4 \eta
* & \frac{\partial N6}{\partial \eta} = 4 \xi
* & \frac{\partial N6}{\partial \zeta} = 0 \\
* N7 = 4 \eta (1 - \xi - \eta - \zeta)
* & \frac{\partial N7}{\partial \xi} = -4 \eta
* & \frac{\partial N7}{\partial \eta} = 4 - 4 \xi - 8 \eta - 4
\zeta
* & \frac{\partial N7}{\partial \zeta} = -4 \eta \\
* N8 = 4 \zeta (1 - \xi - \eta - \zeta)
* & \frac{\partial N8}{\partial \xi} = -4 \zeta
* & \frac{\partial N8}{\partial \eta} = -4 \zeta
* & \frac{\partial N8}{\partial \zeta} = 4 - 4 \xi - 4 \eta - 8
\zeta \\
* N9 = 4 \zeta \xi
* & \frac{\partial N9}{\partial \xi} = 4 \zeta
* & \frac{\partial N9}{\partial \eta} = 0
* & \frac{\partial N9}{\partial \zeta} = 4 \xi \\
* N10 = 4 \eta \zeta
* & \frac{\partial N10}{\partial \xi} = 0
* & \frac{\partial N10}{\partial \eta} = 4 \zeta
* & \frac{\partial N10}{\partial \zeta} = 4 \eta \\
* \end{array}
* @f]
*
* @f[
* a = \frac{5 - \sqrt{5}}{20}\\
* b = \frac{5 + 3 \sqrt{5}}{20}
* \begin{array}{lll}
* \xi_{q_0} = a & \eta_{q_0} = a & \zeta_{q_0} = a \\
* \xi_{q_1} = b & \eta_{q_1} = a & \zeta_{q_1} = a \\
* \xi_{q_2} = a & \eta_{q_2} = b & \zeta_{q_2} = a \\
* \xi_{q_3} = a & \eta_{q_3} = a & \zeta_{q_3} = b
* \end{array}
* @f]
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_tetrahedron_10, _gt_tetrahedron_10,
_itp_lagrange_tetrahedron_10, _ek_regular,
3, _git_tetrahedron, 2);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_tetrahedron_10>::computeShapes(
- const vector_type & natural_coords, vector_type & N) {
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &N) {
/// Natural coordinates
Real xi = natural_coords(0);
Real eta = natural_coords(1);
Real zeta = natural_coords(2);
Real sum = xi + eta + zeta;
Real c0 = 1 - sum;
Real c1 = 1 - 2 * sum;
Real c2 = 2 * xi - 1;
Real c3 = 2 * eta - 1;
Real c4 = 2 * zeta - 1;
/// Shape functions
N(0) = c0 * c1;
N(1) = xi * c2;
N(2) = eta * c3;
N(3) = zeta * c4;
N(4) = 4 * xi * c0;
N(5) = 4 * xi * eta;
N(6) = 4 * eta * c0;
N(7) = 4 * zeta * c0;
N(8) = 4 * xi * zeta;
N(9) = 4 * eta * zeta;
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_tetrahedron_10>::computeDNDS(
- const vector_type & natural_coords, matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &dnds) {
/**
* \f[
* dnds = \left(
* \begin{array}{cccccccccc}
* \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial
* \xi}
* & \frac{\partial N3}{\partial \xi} & \frac{\partial N4}{\partial
* \xi}
* & \frac{\partial N5}{\partial \xi} & \frac{\partial N6}{\partial
* \xi}
* & \frac{\partial N7}{\partial \xi} & \frac{\partial N8}{\partial
* \xi}
* & \frac{\partial N9}{\partial \xi} & \frac{\partial
* N10}{\partial \xi} \\
* \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial
* \eta}
* & \frac{\partial N3}{\partial \eta} & \frac{\partial N4}{\partial
* \eta}
* & \frac{\partial N5}{\partial \eta} & \frac{\partial N6}{\partial
* \eta}
* & \frac{\partial N7}{\partial \eta} & \frac{\partial N8}{\partial
* \eta}
* & \frac{\partial N9}{\partial \eta} & \frac{\partial
* N10}{\partial \eta} \\
* \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial
* \zeta}
* & \frac{\partial N3}{\partial \zeta} & \frac{\partial N4}{\partial
* \zeta}
* & \frac{\partial N5}{\partial \zeta} & \frac{\partial N6}{\partial
* \zeta}
* & \frac{\partial N7}{\partial \zeta} & \frac{\partial N8}{\partial
* \zeta}
* & \frac{\partial N9}{\partial \zeta} & \frac{\partial
* N10}{\partial \zeta}
* \end{array}
* \right)
* \f]
*/
/// Natural coordinates
Real xi = natural_coords(0);
Real eta = natural_coords(1);
Real zeta = natural_coords(2);
Real sum = xi + eta + zeta;
/// \frac{\partial N_i}{\partial \xi}
dnds(0, 0) = 4 * sum - 3;
dnds(0, 1) = 4 * xi - 1;
dnds(0, 2) = 0;
dnds(0, 3) = 0;
dnds(0, 4) = 4 * (1 - sum - xi);
dnds(0, 5) = 4 * eta;
dnds(0, 6) = -4 * eta;
dnds(0, 7) = -4 * zeta;
dnds(0, 8) = 4 * zeta;
dnds(0, 9) = 0;
/// \frac{\partial N_i}{\partial \eta}
dnds(1, 0) = 4 * sum - 3;
dnds(1, 1) = 0;
dnds(1, 2) = 4 * eta - 1;
dnds(1, 3) = 0;
dnds(1, 4) = -4 * xi;
dnds(1, 5) = 4 * xi;
dnds(1, 6) = 4 * (1 - sum - eta);
dnds(1, 7) = -4 * zeta;
dnds(1, 8) = 0;
dnds(1, 9) = 4 * zeta;
/// \frac{\partial N_i}{\partial \zeta}
dnds(2, 0) = 4 * sum - 3;
dnds(2, 1) = 0;
dnds(2, 2) = 0;
dnds(2, 3) = 4 * zeta - 1;
dnds(2, 4) = -4 * xi;
dnds(2, 5) = 0;
dnds(2, 6) = -4 * eta;
dnds(2, 7) = 4 * (1 - sum - zeta);
dnds(2, 8) = 4 * xi;
dnds(2, 9) = 4 * eta;
}
/* -------------------------------------------------------------------------- */
template <>
+template <class D>
inline Real GeometricalElement<_gt_tetrahedron_10>::getInradius(
- const Matrix<Real> & coord) {
+ const Eigen::MatrixBase<D> &coord) {
// Only take the four corner tetrahedra
- UInt tetrahedra[4][4] = {
+
+ Matrix<Idx, 4, 4> tetrahedra{
{0, 4, 6, 7}, {4, 1, 5, 8}, {6, 5, 2, 9}, {7, 8, 9, 3}};
- Real inradius = std::numeric_limits<Real>::max();
- for (UInt t = 0; t < 4; t++) {
- Real ir = Math::tetrahedron_inradius(
- coord(tetrahedra[t][0]).storage(), coord(tetrahedra[t][1]).storage(),
- coord(tetrahedra[t][2]).storage(), coord(tetrahedra[t][3]).storage());
+ auto inradius = std::numeric_limits<Real>::max();
+ for (Int t = 0; t < 4; t++) {
+ auto ir = Math::tetrahedron_inradius(
+ coord.col(tetrahedra(t, 0)), coord.col(tetrahedra(t, 1)),
+ coord.col(tetrahedra(t, 2)), coord.col(tetrahedra(t, 3)));
inradius = std::min(ir, inradius);
}
return 2. * inradius;
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh b/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh
index 8d3e732a7..d14b9cd2c 100644
--- a/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh
@@ -1,143 +1,144 @@
/**
* @file element_class_tetrahedron_4_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jul 16 2010
* @date last modification: Wed Jun 17 2020
*
* @brief Specialization of the element_class class for the type _tetrahedron_4
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\eta
^
|
x (0,0,1,0)
|`
| ` ° \zeta
| ` ° -
| ` x (0,0,0,1)
| q.` - '
| -` '
| - ` '
| - ` '
x------------------x-----> \xi
(1,0,0,0) (0,1,0,0)
@endverbatim
*
* @f{eqnarray*}{
* N1 &=& 1 - \xi - \eta - \zeta \\
* N2 &=& \xi \\
* N3 &=& \eta \\
* N4 &=& \zeta
* @f}
*
* @f[
* \xi_{q0} = 1/4 \qquad \eta_{q0} = 1/4 \qquad \zeta_{q0} = 1/4
* @f]
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_tetrahedron_4, _gt_tetrahedron_4,
_itp_lagrange_tetrahedron_4, _ek_regular,
3, _git_tetrahedron, 1);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_tetrahedron_4>::computeShapes(
- const vector_type & natural_coords, vector_type & N) {
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &N) {
Real c0 = 1 - natural_coords(0) - natural_coords(1) -
natural_coords(2); /// @f$ c0 = 1 - \xi - \eta - \zeta @f$
Real c1 = natural_coords(1); /// @f$ c1 = \xi @f$
Real c2 = natural_coords(2); /// @f$ c2 = \eta @f$
Real c3 = natural_coords(0); /// @f$ c3 = \zeta @f$
N(0) = c0;
N(1) = c1;
N(2) = c2;
N(3) = c3;
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_tetrahedron_4>::computeDNDS(
- __attribute__((unused)) const vector_type & natural_coords,
- matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> & /*natural_coords*/,
+ Eigen::MatrixBase<D2> &dnds) {
/**
* @f[
* dnds = \left(
* \begin{array}{cccccc}
* \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial
* \xi}
* & \frac{\partial N3}{\partial \xi} & \frac{\partial N4}{\partial
* \xi} \\
* \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial
* \eta}
* & \frac{\partial N3}{\partial \eta} & \frac{\partial N4}{\partial
* \eta} \\
* \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial
* \zeta}
* & \frac{\partial N3}{\partial \zeta} & \frac{\partial N4}{\partial
* \zeta}
* \end{array}
* \right)
* @f]
*/
dnds(0, 0) = -1.;
dnds(1, 0) = -1.;
dnds(2, 0) = -1.;
dnds(0, 1) = 0.;
dnds(1, 1) = 1.;
dnds(2, 1) = 0.;
dnds(0, 2) = 0.;
dnds(1, 2) = 0.;
dnds(2, 2) = 1.;
dnds(0, 3) = 1.;
dnds(1, 3) = 0.;
dnds(2, 3) = 0.;
}
/* -------------------------------------------------------------------------- */
template <>
-inline Real
-GeometricalElement<_gt_tetrahedron_4>::getInradius(const Matrix<Real> & coord) {
- return 2. * Math::tetrahedron_inradius(coord(0).storage(), coord(1).storage(),
- coord(2).storage(),
- coord(3).storage());
+template <class D>
+inline Real GeometricalElement<_gt_tetrahedron_4>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ return 2. * Math::tetrahedron_inradius(coord.col(0), coord.col(1),
+ coord.col(2), coord.col(3));
}
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh b/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh
index 450a57810..b104fd548 100644
--- a/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_triangle_3_inline_impl.hh
@@ -1,148 +1,126 @@
/**
* @file element_class_triangle_3_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jul 16 2010
* @date last modification: Fri Dec 11 2020
*
* @brief Specialization of the element_class class for the type _triangle_3
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\eta
^
|
x (0,0,1)
|`
| `
| q `
| ° `
x--------x-----> \xi
(1,0,0) (0,1,0)
@endverbatim
*
* @f{eqnarray*}{
* N1 &=& 1 - \xi - \eta \\
* N2 &=& \xi \\
* N3 &=& \eta
* @f}
*
* @f{eqnarray*}{
* \xi_{q0} &=& 1/3 \qquad \eta_{q0} = 1/3
* @f}
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_triangle_3, _gt_triangle_3,
_itp_lagrange_triangle_3, _ek_regular, 2,
_git_triangle, 1);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_triangle_3>::computeShapes(
- const vector_type & natural_coords, vector_type & N) {
-
- /// Natural coordinates
- Real c0 =
- 1 - natural_coords(0) - natural_coords(1); /// @f$ c0 = 1 - \xi - \eta @f$
- Real c1 = natural_coords(0); /// @f$ c1 = \xi @f$
- Real c2 = natural_coords(1); /// @f$ c2 = \eta @f$
-
- N(0) = c0; /// N1(q_0)
- N(1) = c1; /// N2(q_0)
- N(2) = c2; /// N3(q_0)
+ const Eigen::MatrixBase<D1> &X, Eigen::MatrixBase<D2> &N) {
+ N(0) = 1 - X(0) - X(1); /// @f$ c0 = 1 - \xi - \eta @f$
+ N(1) = X(0); /// @f$ c1 = \xi @f$
+ N(2) = X(1); /// @f$ c2 = \eta @f$
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_triangle_3>::computeDNDS(
- __attribute__((unused)) const vector_type & natural_coords,
- matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> & /*natural_coords*/,
+ Eigen::MatrixBase<D2> &dnds) {
/**
* @f[
* dnds = \left(
* \begin{array}{cccccc}
* \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial
* \xi} & \frac{\partial N3}{\partial \xi} \\
* \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial
* \eta} & \frac{\partial N3}{\partial \eta}
* \end{array}
* \right)
* @f]
*/
dnds(0, 0) = -1.;
dnds(0, 1) = 1.;
dnds(0, 2) = 0.;
dnds(1, 0) = -1.;
dnds(1, 1) = 0.;
dnds(1, 2) = 1.;
}
/* -------------------------------------------------------------------------- */
template <>
template <class vector_type, class matrix_type>
inline void InterpolationElement<_itp_lagrange_triangle_3>::computeD2NDS2(
- const vector_type & /*natural_coords*/, matrix_type & d2nds2) {
+ const vector_type & /*natural_coords*/, matrix_type &d2nds2) {
d2nds2.zero();
}
/* -------------------------------------------------------------------------- */
template <>
-inline void
-InterpolationElement<_itp_lagrange_triangle_3>::computeSpecialJacobian(
- const Matrix<Real> & J, Real & jac) {
- Vector<Real> vprod(J.cols());
- Matrix<Real> Jt(J.transpose(), true);
- vprod.crossProduct(Jt(0), Jt(1));
- jac = vprod.norm();
-}
+template <class D>
+inline Real GeometricalElement<_gt_triangle_3>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ auto &&coord1 = coord.col(0);
+ auto &&coord2 = coord.col(1);
+ auto &&coord3 = coord.col(2);
-/* -------------------------------------------------------------------------- */
-template <>
-inline Real
-GeometricalElement<_gt_triangle_3>::getInradius(const Matrix<Real> & coord) {
- return 2. * Math::triangle_inradius(coord(0), coord(1), coord(2));
+ return 2. * Math::triangle_inradius(coord1, coord2, coord3);
}
-/* -------------------------------------------------------------------------- */
-// template<> inline bool ElementClass<_triangle_3>::contains(const Vector<Real>
-// & natural_coords) {
-// if (natural_coords[0] < 0.) return false;
-// if (natural_coords[0] > 1.) return false;
-// if (natural_coords[1] < 0.) return false;
-// if (natural_coords[1] > 1.) return false;
-// if (natural_coords[0]+natural_coords[1] > 1.) return false;
-// return true;
-// }
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh b/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh
index 961d66a37..091b4545e 100644
--- a/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh
+++ b/src/fe_engine/element_classes/element_class_triangle_6_inline_impl.hh
@@ -1,205 +1,191 @@
/**
* @file element_class_triangle_6_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jul 16 2010
* @date last modification: Fri Feb 28 2020
*
* @brief Specialization of the element_class class for the type _triangle_6
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* @verbatim
\eta
^
|
x 2
| `
| `
| . `
| q2 `
5 x x 4
| `
| `
| .q0 q1. `
| `
x---------x---------x-----> \xi
0 3 1
@endverbatim
*
*
* @f[
* \begin{array}{ll}
* \xi_{0} = 0 & \eta_{0} = 0 \\
* \xi_{1} = 1 & \eta_{1} = 0 \\
* \xi_{2} = 0 & \eta_{2} = 1 \\
* \xi_{3} = 1/2 & \eta_{3} = 0 \\
* \xi_{4} = 1/2 & \eta_{4} = 1/2 \\
* \xi_{5} = 0 & \eta_{5} = 1/2
* \end{array}
* @f]
*
* @f[
* \begin{array}{lll}
* N1 = -(1 - \xi - \eta) (1 - 2 (1 - \xi - \eta))
* & \frac{\partial N1}{\partial \xi} = 1 - 4(1 - \xi - \eta)
* & \frac{\partial N1}{\partial \eta} = 1 - 4(1 - \xi - \eta) \\
* N2 = - \xi (1 - 2 \xi)
* & \frac{\partial N2}{\partial \xi} = - 1 + 4 \xi
* & \frac{\partial N2}{\partial \eta} = 0 \\
* N3 = - \eta (1 - 2 \eta)
* & \frac{\partial N3}{\partial \xi} = 0
* & \frac{\partial N3}{\partial \eta} = - 1 + 4 \eta \\
* N4 = 4 \xi (1 - \xi - \eta)
* & \frac{\partial N4}{\partial \xi} = 4 (1 - 2 \xi - \eta)
* & \frac{\partial N4}{\partial \eta} = - 4 \xi \\
* N5 = 4 \xi \eta
* & \frac{\partial N5}{\partial \xi} = 4 \eta
* & \frac{\partial N5}{\partial \eta} = 4 \xi \\
* N6 = 4 \eta (1 - \xi - \eta)
* & \frac{\partial N6}{\partial \xi} = - 4 \eta
* & \frac{\partial N6}{\partial \eta} = 4 (1 - \xi - 2 \eta)
* \end{array}
* @f]
*
* @f{eqnarray*}{
* \xi_{q0} &=& 1/6 \qquad \eta_{q0} = 1/6 \\
* \xi_{q1} &=& 2/3 \qquad \eta_{q1} = 1/6 \\
* \xi_{q2} &=& 1/6 \qquad \eta_{q2} = 2/3
* @f}
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_triangle_6, _gt_triangle_6,
_itp_lagrange_triangle_6, _ek_regular, 2,
_git_triangle, 2);
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type>
+template <class D1, class D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_triangle_6>::computeShapes(
- const vector_type & natural_coords, vector_type & N) {
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &N) {
/// Natural coordinates
Real c0 =
1 - natural_coords(0) - natural_coords(1); /// @f$ c0 = 1 - \xi - \eta @f$
Real c1 = natural_coords(0); /// @f$ c1 = \xi @f$
Real c2 = natural_coords(1); /// @f$ c2 = \eta @f$
N(0) = c0 * (2 * c0 - 1.);
N(1) = c1 * (2 * c1 - 1.);
N(2) = c2 * (2 * c2 - 1.);
N(3) = 4 * c0 * c1;
N(4) = 4 * c1 * c2;
N(5) = 4 * c2 * c0;
}
/* -------------------------------------------------------------------------- */
template <>
-template <class vector_type, class matrix_type>
+template <class D1, class D2>
inline void InterpolationElement<_itp_lagrange_triangle_6>::computeDNDS(
- const vector_type & natural_coords, matrix_type & dnds) {
+ const Eigen::MatrixBase<D1> &natural_coords, Eigen::MatrixBase<D2> &dnds) {
/**
* @f[
* dnds = \left(
* \begin{array}{cccccc}
* \frac{\partial N1}{\partial \xi}
* & \frac{\partial N2}{\partial \xi}
* & \frac{\partial N3}{\partial \xi}
* & \frac{\partial N4}{\partial \xi}
* & \frac{\partial N5}{\partial \xi}
* & \frac{\partial N6}{\partial \xi} \\
*
* \frac{\partial N1}{\partial \eta}
* & \frac{\partial N2}{\partial \eta}
* & \frac{\partial N3}{\partial \eta}
* & \frac{\partial N4}{\partial \eta}
* & \frac{\partial N5}{\partial \eta}
* & \frac{\partial N6}{\partial \eta}
* \end{array}
* \right)
* @f]
*/
/// Natural coordinates
Real c0 =
1 - natural_coords(0) - natural_coords(1); /// @f$ c0 = 1 - \xi - \eta @f$
Real c1 = natural_coords(0); /// @f$ c1 = \xi @f$
Real c2 = natural_coords(1); /// @f$ c2 = \eta @f$
dnds(0, 0) = 1 - 4 * c0;
dnds(0, 1) = 4 * c1 - 1.;
dnds(0, 2) = 0.;
dnds(0, 3) = 4 * (c0 - c1);
dnds(0, 4) = 4 * c2;
dnds(0, 5) = -4 * c2;
dnds(1, 0) = 1 - 4 * c0;
dnds(1, 1) = 0.;
dnds(1, 2) = 4 * c2 - 1.;
dnds(1, 3) = -4 * c1;
dnds(1, 4) = 4 * c1;
dnds(1, 5) = 4 * (c0 - c2);
}
/* -------------------------------------------------------------------------- */
template <>
-inline void
-InterpolationElement<_itp_lagrange_triangle_6>::computeSpecialJacobian(
- const Matrix<Real> & J, Real & jac) {
- Vector<Real> vprod(J.cols());
- Matrix<Real> Jt(J.transpose(), true);
- vprod.crossProduct(Jt(0), Jt(1));
- jac = vprod.norm();
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline Real
-GeometricalElement<_gt_triangle_6>::getInradius(const Matrix<Real> & coord) {
- UInt triangles[4][3] = {{0, 3, 5}, {3, 1, 4}, {3, 4, 5}, {5, 4, 2}};
+template <class D>
+inline Real GeometricalElement<_gt_triangle_6>::getInradius(
+ const Eigen::MatrixBase<D> &coord) {
+ Int triangles[4][3] = {{0, 3, 5}, {3, 1, 4}, {3, 4, 5}, {5, 4, 2}};
Real inradius = std::numeric_limits<Real>::max();
- for (UInt t = 0; t < 4; t++) {
+ for (Int t = 0; t < 4; t++) {
auto ir = Math::triangle_inradius(
coord(triangles[t][0]), coord(triangles[t][1]), coord(triangles[t][2]));
inradius = std::min(ir, inradius);
}
return 2. * inradius;
}
-/* -------------------------------------------------------------------------- */
-// template<> inline bool ElementClass<_triangle_6>::contains(const Vector<Real>
-// & natural_coords) {
-// return ElementClass<_triangle_3>::contains(natural_coords);
-// }
} // namespace akantu
diff --git a/src/fe_engine/element_type_conversion.hh b/src/fe_engine/element_type_conversion.hh
index 1bd56c58f..59a5b4b8c 100644
--- a/src/fe_engine/element_type_conversion.hh
+++ b/src/fe_engine/element_type_conversion.hh
@@ -1,58 +1,64 @@
/**
* @file element_type_conversion.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief conversion between different types
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_TYPE_CONVERSION_HH_
#define AKANTU_ELEMENT_TYPE_CONVERSION_HH_
namespace akantu {
-template <class InType, class OutType> OutType convertType(InType /*unused*/) {
+template <class InType, class OutType>
+constexpr inline auto convertType(InType /*unused*/) {
return OutType();
}
template <>
-inline InterpolationType
-convertType<ElementType, InterpolationType>(ElementType type) {
- InterpolationType itp_type = _itp_not_defined;
-#define GET_ITP(type) itp_type = ElementClassProperty<type>::interpolation_type;
+constexpr inline auto convertType<ElementType, ElementType>(ElementType type) {
+ return type;
+}
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_ITP);
-#undef GET_ITP
- return itp_type;
+template <>
+constexpr inline auto
+convertType<ElementType, InterpolationType>(ElementType type) {
+ return tuple_dispatch_with_default<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClassProperty<type>::interpolation_type;
+ },
+ type, [&](auto && /*type*/) { return _itp_not_defined; });
}
} // namespace akantu
#endif /* AKANTU_ELEMENT_TYPE_CONVERSION_HH_ */
diff --git a/src/fe_engine/fe_engine.cc b/src/fe_engine/fe_engine.cc
index 060a7f68e..4c32c2872 100644
--- a/src/fe_engine/fe_engine.cc
+++ b/src/fe_engine/fe_engine.cc
@@ -1,90 +1,91 @@
/**
* @file fe_engine.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jul 20 2010
* @date last modification: Fri Feb 28 2020
*
* @brief Implementation of the FEEngine class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
+#include "integrator.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-FEEngine::FEEngine(Mesh & mesh, UInt element_dimension, const ID & id)
+FEEngine::FEEngine(Mesh & mesh, Int element_dimension, const ID & id)
: mesh(mesh), normals_on_integration_points("normals_on_quad_points", id) {
AKANTU_DEBUG_IN();
this->element_dimension = (element_dimension != _all_dimensions)
? element_dimension
: mesh.getSpatialDimension();
- this->mesh.registerEventHandler(*this, _ehp_fe_engine);
+ mesh.registerEventHandler(*this, _ehp_fe_engine);
init();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FEEngine::init() {}
/* -------------------------------------------------------------------------- */
FEEngine::~FEEngine() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
typename FEEngine::ElementTypesIteratorHelper
-FEEngine::elementTypes(UInt dim, GhostType ghost_type, ElementKind kind) const {
+FEEngine::elementTypes(Int dim, GhostType ghost_type, ElementKind kind) const {
return this->getIntegratorInterface().getJacobians().elementTypes(
dim, ghost_type, kind);
}
/* -------------------------------------------------------------------------- */
void FEEngine::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "FEEngine [" << std::endl;
stream << space << " + id : " << id << std::endl;
stream << space << " + element dimension : " << element_dimension
<< std::endl;
stream << space << " + mesh [" << std::endl;
mesh.printself(stream, indent + 2);
stream << space << AKANTU_INDENT << "]" << std::endl;
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/fe_engine/fe_engine.hh b/src/fe_engine/fe_engine.hh
index 111aa45f3..345d379bd 100644
--- a/src/fe_engine/fe_engine.hh
+++ b/src/fe_engine/fe_engine.hh
@@ -1,371 +1,381 @@
/**
* @file fe_engine.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri May 14 2021
*
* @brief FEM class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_type_map.hh"
#include "mesh_events.hh"
/* -------------------------------------------------------------------------- */
#include <functional>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_FE_ENGINE_HH_
#define AKANTU_FE_ENGINE_HH_
namespace akantu {
class Mesh;
class Integrator;
class ShapeFunctions;
class DOFManager;
class Element;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/**
* The generic FEEngine class derived in a FEEngineTemplate class
* containing the
* shape functions and the integration method
*/
class FEEngine : public MeshEventHandler {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- FEEngine(Mesh & mesh, UInt element_dimension = _all_dimensions,
+ FEEngine(Mesh & mesh, Int element_dimension = _all_dimensions,
const ID & id = "fem");
~FEEngine() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// pre-compute all the shape functions, their derivatives and the jacobians
virtual void initShapeFunctions(GhostType ghost_type = _not_ghost) = 0;
/// extract the nodal values and store them per element
template <typename T>
- static void extractNodalToElementField(
- const Mesh & mesh, const Array<T> & nodal_f, Array<T> & elemental_f,
- ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter);
+ static void
+ extractNodalToElementField(const Mesh & mesh, const Array<T> & nodal_f,
+ Array<T> & elemental_f, ElementType type,
+ GhostType ghost_type = _not_ghost,
+ const Array<Int> & filter_elements = empty_filter);
/// filter a field
template <typename T>
static void
- filterElementalData(const Mesh & mesh, const Array<T> & elem_f,
+ filterElementalData(const Mesh & mesh, const Array<T> & quad_f,
Array<T> & filtered_f, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter);
+ const Array<Idx> & filter_elements = empty_filter);
/* ------------------------------------------------------------------------ */
/* Integration method bridges */
/* ------------------------------------------------------------------------ */
/// integrate f for all elements of type "type"
virtual void
- integrate(const Array<Real> & f, Array<Real> & intf,
- UInt nb_degree_of_freedom, ElementType type,
- GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ integrate(const Array<Real> & f, Array<Real> & intf, Int nb_degree_of_freedom,
+ ElementType type, GhostType ghost_type = _not_ghost,
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// integrate a scalar value f on all elements of type "type"
virtual Real
integrate(const Array<Real> & f, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// integrate f for all integration points of type "type" but don't sum over
/// all integration points
virtual void integrateOnIntegrationPoints(
- const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom,
+ const Array<Real> & f, Array<Real> & intf, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// integrate one element scalar value on all elements of type "type"
- virtual Real integrate(const Vector<Real> & f, ElementType type, UInt index,
+ Real integrate(const Ref<const VectorXr> f, const Element & element) const {
+ return integrate(f, element.type, element.element, element.ghost_type);
+ }
+
+private:
+ virtual Real integrate(const Ref<const VectorXr> f, ElementType type,
+ Idx index,
GhostType ghost_type = _not_ghost) const = 0;
/* ------------------------------------------------------------------------ */
/* compatibility with old FEEngine fashion */
/* ------------------------------------------------------------------------ */
+public:
/// get the number of integration points
- virtual UInt
+ virtual Int
getNbIntegrationPoints(ElementType type,
GhostType ghost_type = _not_ghost) const = 0;
/// get the precomputed shapes
const virtual Array<Real> & getShapes(ElementType type,
GhostType ghost_type = _not_ghost,
- UInt id = 0) const = 0;
+ Idx id = 0) const = 0;
/// get the derivatives of shapes
- const virtual Array<Real> &
+ virtual const Array<Real> &
getShapesDerivatives(ElementType type, GhostType ghost_type = _not_ghost,
- UInt id = 0) const = 0;
+ Idx id = 0) const = 0;
/// get integration points
- const virtual Matrix<Real> &
+ virtual const MatrixXr &
getIntegrationPoints(ElementType type,
GhostType ghost_type = _not_ghost) const = 0;
/* ------------------------------------------------------------------------ */
/* Shape method bridges */
/* ------------------------------------------------------------------------ */
/// Compute the gradient nablauq on the integration points of an element type
/// from nodal values u
virtual void gradientOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & nablauq, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// Interpolate a nodal field u at the integration points of an element type
/// -> uq
virtual void interpolateOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & uq, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// Interpolate a nodal field u at the integration points of many element
/// types -> uq
virtual void interpolateOnIntegrationPoints(
const Array<Real> & u, ElementTypeMapArray<Real> & uq,
- const ElementTypeMapArray<UInt> * filter_elements = nullptr) const = 0;
+ const ElementTypeMapArray<Idx> * filter_elements = nullptr) const = 0;
/// pre multiplies a tensor by the shapes derivaties
virtual void
computeBtD(const Array<Real> & Ds, Array<Real> & BtDs, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// left and right multiplies a tensor by the shapes derivaties
virtual void
- computeBtDB(const Array<Real> & Ds, Array<Real> & BtDBs, UInt order_d,
+ computeBtDB(const Array<Real> & Ds, Array<Real> & BtDBs, Int order_d,
ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// left multiples a vector by the shape functions
virtual void
computeNtb(const Array<Real> & bs, Array<Real> & Ntbs, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// left and right multiplies a tensor by the shapes
virtual void
computeNtbN(const Array<Real> & bs, Array<Real> & NtbNs, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// Compute the interpolation point position in the global coordinates for
/// many element types
virtual void computeIntegrationPointsCoordinates(
ElementTypeMapArray<Real> & integration_points_coordinates,
- const ElementTypeMapArray<UInt> * filter_elements = nullptr) const = 0;
+ const ElementTypeMapArray<Idx> * filter_elements = nullptr) const = 0;
/// Compute the interpolation point position in the global coordinates for an
/// element type
virtual void computeIntegrationPointsCoordinates(
Array<Real> & integration_points_coordinates, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Idx> & filter_elements = empty_filter) const = 0;
/// Build pre-computed matrices for interpolation of field form integration
/// points at other given positions (interpolation_points)
virtual void initElementalFieldInterpolationFromIntegrationPoints(
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
ElementTypeMapArray<Real> & integration_points_coordinates_inv_matrices,
- const ElementTypeMapArray<UInt> * element_filter) const = 0;
+ const ElementTypeMapArray<Idx> * element_filter) const = 0;
/// interpolate field at given position (interpolation_points) from given
/// values of this field at integration points (field)
virtual void interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
- ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const = 0;
+ ElementTypeMapArray<Real> & result, const GhostType ghost_type,
+ const ElementTypeMapArray<Idx> * element_filter) const = 0;
/// Interpolate field at given position from given values of this field at
/// integration points (field)
/// using matrices precomputed with
/// initElementalFieldInterplationFromIntegrationPoints
virtual void interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> &
interpolation_points_coordinates_matrices,
const ElementTypeMapArray<Real> &
integration_points_coordinates_inv_matrices,
- ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const = 0;
+ ElementTypeMapArray<Real> & result, const GhostType ghost_type,
+ const ElementTypeMapArray<Idx> * element_filter) const = 0;
/// interpolate on a phyiscal point inside an element
- virtual void interpolate(const Vector<Real> & real_coords,
- const Matrix<Real> & nodal_values,
- Vector<Real> & interpolated,
+ virtual void interpolate(const Ref<const VectorXr> real_coords,
+ const Ref<const MatrixXr> nodal_values,
+ Ref<VectorXr> interpolated,
const Element & element) const = 0;
/// compute the shape on a provided point
- virtual void computeShapes(const Vector<Real> & real_coords, UInt elem,
- ElementType type, Vector<Real> & shapes,
+ virtual void computeShapes(const Ref<const VectorXr> real_coords, Int elem,
+ ElementType type, Ref<VectorXr> shapes,
GhostType ghost_type = _not_ghost) const = 0;
/// compute the shape derivatives on a provided point
virtual void
- computeShapeDerivatives(const Vector<Real> & real_coords, UInt element,
- ElementType type, Matrix<Real> & shape_derivatives,
+ computeShapeDerivatives(const Ref<const VectorXr> real_coords, Int element,
+ ElementType type, Ref<MatrixXr> shape_derivatives,
GhostType ghost_type = _not_ghost) const = 0;
/// assembles the lumped version of @f[ \int N^t rho N @f]
virtual void assembleFieldLumped(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
ElementType type, GhostType ghost_type = _not_ghost) const = 0;
/// assembles the matrix @f[ \int N^t rho N @f]
virtual void assembleFieldMatrix(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
ElementType type, GhostType ghost_type = _not_ghost) const = 0;
/* ------------------------------------------------------------------------ */
/* Other methods */
/* ------------------------------------------------------------------------ */
/// pre-compute normals on integration points
virtual void
computeNormalsOnIntegrationPoints(GhostType ghost_type = _not_ghost) = 0;
/// pre-compute normals on integration points
virtual void
computeNormalsOnIntegrationPoints(const Array<Real> & /*field*/,
GhostType /*ghost_type*/ = _not_ghost) {
AKANTU_TO_IMPLEMENT();
}
/// pre-compute normals on integration points
virtual void computeNormalsOnIntegrationPoints(
const Array<Real> & /*field*/, Array<Real> & /*normal*/,
ElementType /*type*/, GhostType /*ghost_type*/ = _not_ghost) const {
AKANTU_TO_IMPLEMENT();
}
/// function to print the containt of the class
virtual void printself(std::ostream & stream, int indent = 0) const;
private:
/// initialise the class
void init();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
using ElementTypesIteratorHelper =
ElementTypeMapArray<Real, ElementType>::ElementTypesIteratorHelper;
- ElementTypesIteratorHelper elementTypes(UInt dim = _all_dimensions,
+ ElementTypesIteratorHelper elementTypes(Int dim = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_regular) const;
/// get the dimension of the element handeled by this fe_engine object
- AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt);
+ AKANTU_GET_MACRO_AUTO(ElementDimension, element_dimension);
/// get the mesh contained in the fem object
- AKANTU_GET_MACRO(Mesh, mesh, const Mesh &);
+ AKANTU_GET_MACRO_AUTO(Mesh, mesh);
/// get the mesh contained in the fem object
AKANTU_GET_MACRO_NOT_CONST(Mesh, mesh, Mesh &);
/// get the in-radius of an element
- static inline Real getElementInradius(const Matrix<Real> & coord,
- ElementType type);
+ template <class Derived>
+ static inline Real
+ getElementInradius(const Eigen::MatrixBase<Derived> & coord,
+ ElementType type);
inline Real getElementInradius(const Element & element) const;
/// get the normals on integration points
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NormalsOnIntegrationPoints,
normals_on_integration_points, Real);
/// get cohesive element type for a given facet type
- static inline ElementType getCohesiveElementType(ElementType type_facet);
+ static inline constexpr ElementType
+ getCohesiveElementType(ElementType type_facet);
/// get igfem element type for a given regular type
static inline Vector<ElementType> getIGFEMElementTypes(ElementType type);
/// get the interpolation element associated to an element type
- static inline InterpolationType getInterpolationType(ElementType el_type);
+ static inline constexpr auto getInterpolationType(ElementType el_type);
/// get the shape function class (probably useless: see getShapeFunction in
/// fe_engine_template.hh)
virtual const ShapeFunctions & getShapeFunctionsInterface() const = 0;
/// get the integrator class (probably useless: see getIntegrator in
/// fe_engine_template.hh)
virtual const Integrator & getIntegratorInterface() const = 0;
AKANTU_GET_MACRO(ID, id, ID);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ID id;
/// spatial dimension of the problem
- UInt element_dimension;
+ Int element_dimension;
/// the mesh on which all computation are made
Mesh & mesh;
/// normals at integration points
ElementTypeMapArray<Real> normals_on_integration_points;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const FEEngine & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "fe_engine_inline_impl.hh"
#include "fe_engine_template.hh"
#endif /* AKANTU_FE_ENGINE_HH_ */
diff --git a/src/fe_engine/fe_engine_inline_impl.hh b/src/fe_engine/fe_engine_inline_impl.hh
index 8e32a73f6..1c87cdb4a 100644
--- a/src/fe_engine/fe_engine_inline_impl.hh
+++ b/src/fe_engine/fe_engine_inline_impl.hh
@@ -1,208 +1,200 @@
/**
* @file fe_engine_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jul 20 2010
* @date last modification: Fri Dec 11 2020
*
* @brief Implementation of the inline functions of the FEEngine Class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
-#include "fe_engine.hh"
+//#include "fe_engine.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include "element_type_conversion.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_FE_ENGINE_INLINE_IMPL_HH_
-#define AKANTU_FE_ENGINE_INLINE_IMPL_HH_
+// #ifndef __AKANTU_FE_ENGINE_INLINE_IMPL_CC__
+// #define __AKANTU_FE_ENGINE_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline Real FEEngine::getElementInradius(const Matrix<Real> & coord,
- ElementType type) {
- Real inradius = 0;
-
-#define GET_INRADIUS(type) inradius = ElementClass<type>::getInradius(coord);
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_INRADIUS);
-#undef GET_INRADIUS
-
- return inradius;
+template <class Derived>
+inline Real
+FEEngine::getElementInradius(const Eigen::MatrixBase<Derived> & coord,
+ ElementType type) {
+ return tuple_dispatch<AllElementTypes>(
+ [&coord](auto && enum_type) -> Real {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getInradius(coord);
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
inline Real FEEngine::getElementInradius(const Element & element) const {
auto spatial_dimension = mesh.getSpatialDimension();
auto positions = make_view(mesh.getNodes(), spatial_dimension).begin();
auto connectivity = mesh.getConnectivities().get(element);
Matrix<Real> coords(spatial_dimension, connectivity.size());
for (auto && data : zip(connectivity, coords)) {
- Vector<Real>(std::get<1>(data)) =
- Vector<Real>(positions[std::get<0>(data)]);
+ std::get<1>(data) = positions[std::get<0>(data)];
}
return getElementInradius(coords, element.type);
}
/* -------------------------------------------------------------------------- */
-inline InterpolationType FEEngine::getInterpolationType(ElementType type) {
+inline constexpr auto FEEngine::getInterpolationType(ElementType type) {
return convertType<ElementType, InterpolationType>(type);
}
/* -------------------------------------------------------------------------- */
/// @todo rewrite this function in order to get the cohesive element
/// type directly from the facet
#if defined(AKANTU_COHESIVE_ELEMENT)
-inline ElementType FEEngine::getCohesiveElementType(ElementType type) {
- ElementType ctype;
-#define GET_COHESIVE_TYPE(type) \
- ctype = CohesiveFacetProperty<type>::cohesive_type;
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_COHESIVE_TYPE);
-#undef GET_COHESIVE_TYPE
-
- return ctype;
-}
-#else
-inline ElementType FEEngine::getCohesiveElementType(__attribute__((unused))
- ElementType type_facet) {
- return _not_defined;
+inline constexpr ElementType
+FEEngine::getCohesiveElementType(ElementType type) {
+ return tuple_dispatch_with_default<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) -> ElementType {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return CohesiveFacetProperty<type>::cohesive_type;
+ },
+ type, [](auto && /*enum_type*/) { return _not_defined; });
}
#endif
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_IGFEM)
} // akantu
#include "igfem_helper.hh"
namespace akantu {
inline Vector<ElementType> FEEngine::getIGFEMElementTypes(ElementType type) {
-
-#define GET_IGFEM_ELEMENT_TYPES(type) \
- return IGFEMHelper::getIGFEMElementTypes<type>();
-
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_IGFEM_ELEMENT_TYPES);
-
-#undef GET_IGFEM_ELEMENT_TYPES
+ tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return IGFEMHelper::getIGFEMElementTypes<type>();
+ },
+ type);
}
#endif
/* -------------------------------------------------------------------------- */
template <typename T>
void FEEngine::extractNodalToElementField(const Mesh & mesh,
const Array<T> & nodal_f,
Array<T> & elemental_f,
ElementType type,
GhostType ghost_type,
- const Array<UInt> & filter_elements) {
+ const Array<Int> & filter_elements) {
AKANTU_DEBUG_IN();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_degree_of_freedom = nodal_f.getNbComponent();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage();
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_degree_of_freedom = nodal_f.getNbComponent();
+ auto nb_element = mesh.getNbElement(type, ghost_type);
+ auto * conn_val = mesh.getConnectivity(type, ghost_type).data();
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
elemental_f.resize(nb_element);
- T * nodal_f_val = nodal_f.storage();
- T * f_val = elemental_f.storage();
+ T * nodal_f_val = nodal_f.data();
+ T * f_val = elemental_f.data();
- UInt * el_conn;
- for (UInt el = 0; el < nb_element; ++el) {
+ Idx * el_conn;
+ for (Int el = 0; el < nb_element; ++el) {
if (filter_elements != empty_filter) {
el_conn = conn_val + filter_elements(el) * nb_nodes_per_element;
} else {
el_conn = conn_val + el * nb_nodes_per_element;
}
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- UInt node = *(el_conn + n);
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
+ auto node = *(el_conn + n);
std::copy(nodal_f_val + node * nb_degree_of_freedom,
nodal_f_val + (node + 1) * nb_degree_of_freedom, f_val);
f_val += nb_degree_of_freedom;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename T>
void FEEngine::filterElementalData(const Mesh & mesh, const Array<T> & elem_f,
Array<T> & filtered_f, ElementType type,
GhostType ghost_type,
- const Array<UInt> & filter_elements) {
+ const Array<Int> & filter_elements) {
AKANTU_DEBUG_IN();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (nb_element == 0) {
filtered_f.resize(0);
return;
}
- UInt nb_degree_of_freedom = elem_f.getNbComponent();
- UInt nb_data_per_element = elem_f.size() / nb_element;
+ auto nb_degree_of_freedom = elem_f.getNbComponent();
+ auto nb_data_per_element = elem_f.size() / nb_element;
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
filtered_f.resize(nb_element * nb_data_per_element);
- T * elem_f_val = elem_f.storage();
- T * f_val = filtered_f.storage();
+ T * elem_f_val = elem_f.data();
+ T * f_val = filtered_f.data();
UInt el_offset;
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Idx el = 0; el < nb_element; ++el) {
if (filter_elements != empty_filter) {
el_offset = filter_elements(el);
} else {
el_offset = el;
}
std::copy(elem_f_val +
el_offset * nb_data_per_element * nb_degree_of_freedom,
elem_f_val +
(el_offset + 1) * nb_data_per_element * nb_degree_of_freedom,
f_val);
f_val += nb_degree_of_freedom * nb_data_per_element;
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
-#endif /* AKANTU_FE_ENGINE_INLINE_IMPL_HH_ */
+//#endif /* __AKANTU_FE_ENGINE_INLINE_IMPL_CC__ */
diff --git a/src/fe_engine/fe_engine_template.hh b/src/fe_engine/fe_engine_template.hh
index 296ca2117..215002764 100644
--- a/src/fe_engine/fe_engine_template.hh
+++ b/src/fe_engine/fe_engine_template.hh
@@ -1,431 +1,493 @@
/**
* @file fe_engine_template.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri May 14 2021
*
* @brief templated class that calls integration and shape objects
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
-#include "integrator.hh"
-#include "shape_functions.hh"
/* -------------------------------------------------------------------------- */
#include <type_traits>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_FE_ENGINE_TEMPLATE_HH_
#define AKANTU_FE_ENGINE_TEMPLATE_HH_
+namespace akantu {
+class Integrator;
+class ShapeFunctions;
+} // namespace akantu
+
namespace akantu {
class DOFManager;
namespace fe_engine {
namespace details {
template <ElementKind> struct AssembleLumpedTemplateHelper;
template <ElementKind> struct AssembleFieldMatrixHelper;
} // namespace details
} // namespace fe_engine
template <ElementKind, typename> struct AssembleFieldMatrixStructHelper;
struct DefaultIntegrationOrderFunctor {
template <ElementType type> static inline constexpr int getOrder() {
return ElementClassProperty<type>::polynomial_degree;
}
};
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind = _ek_regular,
class IntegrationOrderFunctor = DefaultIntegrationOrderFunctor>
class FEEngineTemplate : public FEEngine {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using Integ = I<kind, IntegrationOrderFunctor>;
using Shape = S<kind>;
- FEEngineTemplate(Mesh & mesh, UInt spatial_dimension = _all_dimensions,
+ FEEngineTemplate(Mesh & mesh, Int spatial_dimension = _all_dimensions,
const ID & id = "fem");
~FEEngineTemplate() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// pre-compute all the shape functions, their derivatives and the jacobians
void initShapeFunctions(GhostType ghost_type = _not_ghost) override;
void initShapeFunctions(const Array<Real> & nodes,
GhostType ghost_type = _not_ghost);
/* ------------------------------------------------------------------------ */
/* Integration method bridges */
/* ------------------------------------------------------------------------ */
/// integrate f for all elements of type "type"
void
- integrate(const Array<Real> & f, Array<Real> & intf,
- UInt nb_degree_of_freedom, ElementType type,
- GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ integrate(const Array<Real> & f, Array<Real> & intf, Int nb_degree_of_freedom,
+ ElementType type, GhostType ghost_type = _not_ghost,
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// integrate a scalar value on all elements of type "type"
Real
integrate(const Array<Real> & f, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// integrate one element scalar value on all elements of type "type"
- Real integrate(const Vector<Real> & f, ElementType type, UInt index,
+ Real integrate(const Ref<const VectorXr> f, ElementType type, Int index,
GhostType ghost_type = _not_ghost) const override;
/// integrate partially around an integration point (@f$ intf_q = f_q * J_q *
/// w_q @f$)
void integrateOnIntegrationPoints(
- const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom,
+ const Array<Real> & f, Array<Real> & intf, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ const Array<Idx> & filter_elements = empty_filter) const override;
+private:
+ template <ElementKind kind_ = kind, typename D1, typename D2, typename D3,
+ std::enable_if_t<aka::are_vectors<D1, D3>::value and
+ kind_ == _ek_regular> * = nullptr>
+ inline void interpolateImpl(const Eigen::MatrixBase<D1> & real_coords,
+ const Eigen::MatrixBase<D2> & nodal_values,
+ Eigen::MatrixBase<D3> & interpolated,
+ const Element & element) const;
+
+ template <ElementKind kind_ = kind, typename D1, typename D2, typename D3,
+ std::enable_if_t<aka::are_vectors<D1, D3>::value and
+ kind_ != _ek_regular> * = nullptr>
+ inline void interpolateImpl(const Eigen::MatrixBase<D1> & /*real_coords*/,
+ const Eigen::MatrixBase<D2> & /*nodal_values*/,
+ Eigen::MatrixBase<D3> & /*interpolated*/,
+ const Element & /*element*/) const {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+public:
/// interpolate on a phyiscal point inside an element
- void interpolate(const Vector<Real> & real_coords,
- const Matrix<Real> & nodal_values,
- Vector<Real> & interpolated,
+ void interpolate(const Ref<const VectorXr> real_coords,
+ const Ref<const MatrixXr> nodal_values,
+ Ref<VectorXr> interpolated,
const Element & element) const override;
/// get the number of integration points
- UInt getNbIntegrationPoints(ElementType type,
- GhostType ghost_type = _not_ghost) const override;
+ Int getNbIntegrationPoints(ElementType type,
+ GhostType ghost_type = _not_ghost) const override;
/// get shapes precomputed
const Array<Real> & getShapes(ElementType type,
GhostType ghost_type = _not_ghost,
- UInt id = 0) const override;
+ Int id = 0) const override;
/// get the derivatives of shapes
const Array<Real> & getShapesDerivatives(ElementType type,
GhostType ghost_type = _not_ghost,
- UInt id = 0) const override;
+ Int id = 0) const override;
/// get integration points
- const inline Matrix<Real> &
+ inline const Matrix<Real> &
getIntegrationPoints(ElementType type,
GhostType ghost_type = _not_ghost) const override;
/* ------------------------------------------------------------------------ */
/* Shape method bridges */
/* ------------------------------------------------------------------------ */
/// compute the gradient of a nodal field on the integration points
void gradientOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & nablauq, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// interpolate a nodal field on the integration points
void interpolateOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & uq, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// interpolate a nodal field on the integration points given a
/// by_element_type
void interpolateOnIntegrationPoints(
const Array<Real> & u, ElementTypeMapArray<Real> & uq,
- const ElementTypeMapArray<UInt> * filter_elements =
+ const ElementTypeMapArray<Idx> * filter_elements =
nullptr) const override;
/// pre multiplies a tensor by the shapes derivaties
void
computeBtD(const Array<Real> & Ds, Array<Real> & BtDs, ElementType type,
GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// left and right multiplies a tensor by the shapes derivaties
- void computeBtDB(
- const Array<Real> & Ds, Array<Real> & BtDBs, UInt order_d,
- ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ void
+ computeBtDB(const Array<Real> & Ds, Array<Real> & BtDBs, Int order_d,
+ ElementType type, GhostType ghost_type,
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// left multiples a vector by the shape functions
- void
- computeNtb(const Array<Real> & bs, Array<Real> & Ntbs, ElementType type,
- GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ void computeNtb(const Array<Real> & bs, Array<Real> & Ntbs, ElementType type,
+ GhostType ghost_type,
+ const Array<Idx> & filter_elements) const override;
/// left and right multiplies a tensor by the shapes
- void computeNtbN(
- const Array<Real> & bs, Array<Real> & NtbNs, ElementType type,
- GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ void
+ computeNtbN(const Array<Real> & bs, Array<Real> & NtbNs, ElementType type,
+ GhostType ghost_type,
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// compute the position of integration points given by an element_type_map
/// from nodes position
inline void computeIntegrationPointsCoordinates(
ElementTypeMapArray<Real> & quadrature_points_coordinates,
- const ElementTypeMapArray<UInt> * filter_elements =
+ const ElementTypeMapArray<Idx> * filter_elements =
nullptr) const override;
/// compute the position of integration points from nodes position
inline void computeIntegrationPointsCoordinates(
Array<Real> & quadrature_points_coordinates, ElementType type,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const override;
+ const Array<Idx> & filter_elements = empty_filter) const override;
/// interpolate field at given position (interpolation_points) from given
/// values of this field at integration points (field)
inline void interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const override;
+ const ElementTypeMapArray<Idx> * element_filter) const override;
/// Interpolate field at given position from given values of this field at
/// integration points (field)
/// using matrices precomputed with
/// initElementalFieldInterplationFromIntegrationPoints
inline void interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> &
interpolation_points_coordinates_matrices,
const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const override;
+ const ElementTypeMapArray<Idx> * element_filter) const override;
/// Build pre-computed matrices for interpolation of field form integration
/// points at other given positions (interpolation_points)
inline void initElementalFieldInterpolationFromIntegrationPoints(
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
- const ElementTypeMapArray<UInt> * element_filter =
- nullptr) const override;
+ const ElementTypeMapArray<Idx> * element_filter = nullptr) const override;
/// find natural coords from real coords provided an element
- void inverseMap(const Vector<Real> & real_coords, UInt element,
- ElementType type, Vector<Real> & natural_coords,
+ void inverseMap(const Ref<const VectorXr> real_coords, Int element,
+ ElementType type, Ref<VectorXr> natural_coords,
GhostType ghost_type = _not_ghost) const;
/// return true if the coordinates provided are inside the element, false
/// otherwise
- inline bool contains(const Vector<Real> & real_coords, UInt element,
+ inline bool contains(const Vector<Real> & real_coords, Int element,
ElementType type,
GhostType ghost_type = _not_ghost) const;
+private:
+ template <ElementKind kind_ = kind, typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors<D1, D2>::value and
+ kind_ != _ek_cohesive> * = nullptr>
+ inline void computeShapesImpl(const Eigen::MatrixBase<D1> & real_coords,
+ Int element, ElementType type,
+ Eigen::MatrixBase<D2> & shapes,
+ GhostType ghost_type = _not_ghost) const;
+
+ template <ElementKind kind_ = kind, typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors<D1, D2>::value and
+ kind_ == _ek_cohesive> * = nullptr>
+ inline void computeShapesImpl(const Eigen::MatrixBase<D1> & /*real_coords*/,
+ Int /*element*/, ElementType /*type*/,
+ Eigen::MatrixBase<D2> & /*shapes*/,
+ GhostType /*ghost_type*/ = _not_ghost) const {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+ template <ElementKind kind_ = kind, typename D1, typename D2,
+ std::enable_if_t<aka::is_vector_v<D1> and kind_ != _ek_cohesive> * =
+ nullptr>
+ inline void
+ computeShapeDerivativesImpl(const Eigen::MatrixBase<D1> & real_coords,
+ Int element, ElementType type,
+ Eigen::MatrixBase<D2> & shape_derivatives,
+ GhostType ghost_type = _not_ghost) const;
+
+ template <ElementKind kind_ = kind, typename D1, typename D2,
+ std::enable_if_t<aka::is_vector_v<D1> and kind_ == _ek_cohesive> * =
+ nullptr>
+ inline void
+ computeShapeDerivativesImpl(const Eigen::MatrixBase<D1> & /*real_coords*/,
+ Int /*element*/, ElementType /*type*/,
+ Eigen::MatrixBase<D2> & /*shape_derivatives*/,
+ GhostType /*ghost_type*/ = _not_ghost) const {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+public:
/// compute the shape on a provided point
- inline void computeShapes(const Vector<Real> & real_coords, UInt element,
- ElementType type, Vector<Real> & shapes,
- GhostType ghost_type = _not_ghost) const override;
+ inline void computeShapes(const Ref<const VectorXr> real_coords, Int element,
+ ElementType type, Ref<VectorXr> shapes,
+ GhostType ghost_type = _not_ghost) const override {
+ this->template computeShapesImpl(real_coords, element, type, shapes,
+ ghost_type);
+ }
/// compute the shape derivatives on a provided point
inline void
- computeShapeDerivatives(const Vector<Real> & real_coords, UInt element,
- ElementType type, Matrix<Real> & shape_derivatives,
- GhostType ghost_type = _not_ghost) const override;
+ computeShapeDerivatives(const Ref<const VectorXr> real_coords, Int element,
+ ElementType type, Ref<MatrixXr> shape_derivatives,
+ GhostType ghost_type = _not_ghost) const override {
+ this->template computeShapeDerivativesImpl<kind>(
+ real_coords, element, type, shape_derivatives, ghost_type);
+ }
/* ------------------------------------------------------------------------ */
/* Other methods */
/* ------------------------------------------------------------------------ */
/// pre-compute normals on integration points
void
computeNormalsOnIntegrationPoints(GhostType ghost_type = _not_ghost) override;
void
computeNormalsOnIntegrationPoints(const Array<Real> & field,
GhostType ghost_type = _not_ghost) override;
void computeNormalsOnIntegrationPoints(
const Array<Real> & field, Array<Real> & normal, ElementType type,
GhostType ghost_type = _not_ghost) const override;
- template <ElementType type>
+
+ template <ElementType type, ElementKind kind_ = kind,
+ std::enable_if_t<kind_ != _ek_regular> * = nullptr>
+ void computeNormalsOnIntegrationPoints(const Array<Real> & /*field*/,
+ Array<Real> & /*normal*/,
+ GhostType /*ghost_type*/) const {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+ template <
+ ElementType type, ElementKind kind_ = kind,
+ std::enable_if_t<kind_ == _ek_regular and type != _point_1> * = nullptr>
void computeNormalsOnIntegrationPoints(const Array<Real> & field,
Array<Real> & normal,
GhostType ghost_type) const;
-private:
- // To avoid a weird full specialization of a method in a non specalized class
- void computeNormalsOnIntegrationPointsPoint1(const Array<Real> & /*unused*/,
- Array<Real> & normal,
- GhostType ghost_type) const;
+ template <
+ ElementType type, ElementKind kind_ = kind,
+ std::enable_if_t<kind_ == _ek_regular and type == _point_1> * = nullptr>
+ void computeNormalsOnIntegrationPoints(const Array<Real> & field,
+ Array<Real> & normal,
+ GhostType ghost_type) const;
public:
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override;
void assembleFieldLumped(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
ElementType type, GhostType ghost_type) const override;
+private:
+ template <ElementKind kind_ = kind,
+ std::enable_if_t<kind_ != _ek_cohesive> * = nullptr>
+ void assembleFieldMatrixImpl(
+ const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
+ const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
+ ElementType type, GhostType ghost_type) const;
+
+ template <ElementKind kind_ = kind,
+ std::enable_if_t<kind_ == _ek_cohesive> * = nullptr>
+ void assembleFieldMatrixImpl(
+ const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
+ const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
+ ElementType type, GhostType ghost_type) const;
+
+public:
/// assemble a field as a matrix (ex. rho to mass matrix)
void assembleFieldMatrix(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
- ElementType type, GhostType ghost_type) const override;
-
- /// assemble a field as a lumped matrix (ex. rho in lumped mass)
- // template <class Functor>
- // void assembleFieldLumped(const Functor & field_funct, const ID & matrix_id,
- // const ID & dof_id, DOFManager & dof_manager,
- // ElementType type,
- // GhostType ghost_type) const;
-
- // /// assemble a field as a matrix (ex. rho to mass matrix)
- // template <class Functor>
- // void assembleFieldMatrix(const Functor & field_funct, const ID & matrix_id,
- // const ID & dof_id, DOFManager & dof_manager,
- // ElementType type,
- // GhostType ghost_type) const;
-
- // #ifdef AKANTU_STRUCTURAL_MECHANICS
- // /// assemble a field as a matrix (ex. rho to mass matrix)
- // void assembleFieldMatrix(const Array<Real> & field_1,
- // UInt nb_degree_of_freedom, SparseMatrix & M,
- // Array<Real> * n,
- // ElementTypeMapArray<Real> & rotation_mat,
- // ElementType type,
- // GhostType ghost_type = _not_ghost)
- // const;
-
- // /// compute shapes function in a matrix for structural elements
- // void
- // computeShapesMatrix(ElementType type, UInt nb_degree_of_freedom,
- // UInt nb_nodes_per_element, Array<Real> * n, UInt id,
- // UInt degree_to_interpolate, UInt degree_interpolated,
- // const bool sign,
- // GhostType ghost_type = _not_ghost) const
- // override;
- // #endif
+ ElementType type, GhostType ghost_type) const override {
+ this->assembleFieldMatrixImpl(field_funct, matrix_id, dof_id, dof_manager,
+ type, ghost_type);
+ }
private:
friend struct fe_engine::details::AssembleLumpedTemplateHelper<kind>;
friend struct fe_engine::details::AssembleFieldMatrixHelper<kind>;
friend struct AssembleFieldMatrixStructHelper<kind, void>;
/// templated function to compute the scaling to assemble a lumped matrix
template <ElementType type>
void assembleFieldLumped(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
GhostType ghost_type) const;
/// @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j
/// dV = \int \rho \varphi_i dV @f$
template <ElementType type>
void assembleLumpedRowSum(const Array<Real> & field, const ID & matrix_id,
const ID & dof_id, DOFManager & dof_manager,
GhostType ghost_type) const;
/// @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$
template <ElementType type>
void assembleLumpedDiagonalScaling(const Array<Real> & field,
const ID & matrix_id, const ID & dof_id,
DOFManager & dof_manager,
GhostType ghost_type) const;
/// assemble a field as a matrix (ex. rho to mass matrix)
template <ElementType type>
void assembleFieldMatrix(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
GhostType ghost_type) const;
#ifdef AKANTU_STRUCTURAL_MECHANICS
/// assemble a field as a matrix for structural elements (ex. rho to mass
/// matrix)
template <ElementType type>
void assembleFieldMatrix(const Array<Real> & field_1,
- UInt nb_degree_of_freedom, SparseMatrix & M,
+ Int nb_degree_of_freedom, SparseMatrix & M,
Array<Real> * n,
ElementTypeMapArray<Real> & rotation_mat,
- __attribute__((unused)) GhostType ghost_type) const;
-
+ GhostType ghost_type) const;
#endif
/* ------------------------------------------------------------------------ */
/* Mesh Event Handler interface */
/* ------------------------------------------------------------------------ */
public:
void onElementsAdded(const Array<Element> & /*new_elements*/,
const NewElementsEvent & /*unused*/) override;
void onElementsRemoved(const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
+ const ElementTypeMapArray<Idx> & /*unused*/,
const RemovedElementsEvent & /*unused*/) override;
void onElementsChanged(const Array<Element> & /*unused*/,
const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
+ const ElementTypeMapArray<Idx> & /*unused*/,
const ChangedElementsEvent & /*unused*/) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the shape class (probably useless: see getShapeFunction)
const ShapeFunctions & getShapeFunctionsInterface() const override {
return shape_functions;
};
/// get the shape class
const Shape & getShapeFunctions() const { return shape_functions; };
/// get the integrator class (probably useless: see getIntegrator)
const Integrator & getIntegratorInterface() const override {
return integrator;
};
/// get the integrator class
const Integ & getIntegrator() const { return integrator; };
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
Integ integrator;
Shape shape_functions;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "fe_engine_template_tmpl.hh"
#include "fe_engine_template_tmpl_field.hh"
/* -------------------------------------------------------------------------- */
/* Shape Linked specialization */
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_STRUCTURAL_MECHANICS)
#include "fe_engine_template_tmpl_struct.hh"
#endif
/* -------------------------------------------------------------------------- */
/* Shape IGFEM specialization */
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_IGFEM)
#include "fe_engine_template_tmpl_igfem.hh"
#endif
#endif /* AKANTU_FE_ENGINE_TEMPLATE_HH_ */
diff --git a/src/fe_engine/fe_engine_template_cohesive.cc b/src/fe_engine/fe_engine_template_cohesive.cc
index 0ad4f6bd3..f5911390b 100644
--- a/src/fe_engine/fe_engine_template_cohesive.cc
+++ b/src/fe_engine/fe_engine_template_cohesive.cc
@@ -1,135 +1,137 @@
/**
* @file fe_engine_template_cohesive.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Oct 31 2012
* @date last modification: Tue Sep 29 2020
*
* @brief Specialization of the FEEngineTemplate for cohesive element
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "fe_engine_template.hh"
#include "integrator_gauss.hh"
#include "shape_cohesive.hh"
/* -------------------------------------------------------------------------- */
+#include "fe_engine_template.hh"
+/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/* compatibility functions */
/* -------------------------------------------------------------------------- */
template <>
Real FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive,
DefaultIntegrationOrderFunctor>::
integrate(const Array<Real> & f, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
#ifndef AKANTU_NDEBUG
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
- UInt nb_quadrature_points = getNbIntegrationPoints(type);
+ auto nb_quadrature_points = getNbIntegrationPoints(type);
AKANTU_DEBUG_ASSERT(f.size() == nb_element * nb_quadrature_points,
"The vector f(" << f.getID()
<< ") has not the good size.");
AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1,
"The vector f("
<< f.getID()
<< ") has not the good number of component.");
#endif
- Real integral = 0.;
-
-#define INTEGRATE(type) \
- integral = integrator.integrate<type>(f, ghost_type, filter_elements);
-
- AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INTEGRATE);
-#undef INTEGRATE
+ Real integral = tuple_dispatch<ElementTypes_t<_ek_cohesive>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return integrator.integrate<type>(f, ghost_type, filter_elements);
+ },
+ type);
AKANTU_DEBUG_OUT();
return integral;
}
/* -------------------------------------------------------------------------- */
template <>
void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive,
DefaultIntegrationOrderFunctor>::
integrate(const Array<Real> & f, Array<Real> & intf,
- UInt nb_degree_of_freedom, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ Int nb_degree_of_freedom, ElementType type, GhostType ghost_type,
+ const Array<Idx> & filter_elements) const {
#ifndef AKANTU_NDEBUG
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
- UInt nb_quadrature_points = getNbIntegrationPoints(type);
+ auto nb_quadrature_points = getNbIntegrationPoints(type);
- AKANTU_DEBUG_ASSERT(f.size() == nb_element * nb_quadrature_points,
+ AKANTU_DEBUG_ASSERT(f.size() == Int(nb_element * nb_quadrature_points),
"The vector f(" << f.getID() << " size " << f.size()
<< ") has not the good size ("
<< nb_element << ").");
- AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom,
+ AKANTU_DEBUG_ASSERT(f.getNbComponent() == Int(nb_degree_of_freedom),
"The vector f("
<< f.getID()
<< ") has not the good number of component.");
- AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
+ AKANTU_DEBUG_ASSERT(intf.getNbComponent() == Int(nb_degree_of_freedom),
"The vector intf("
<< intf.getID()
<< ") has not the good number of component.");
AKANTU_DEBUG_ASSERT(intf.size() == nb_element,
"The vector intf(" << intf.getID()
<< ") has not the good size.");
#endif
-#define INTEGRATE(type) \
- integrator.integrate<type>(f, intf, nb_degree_of_freedom, ghost_type, \
- filter_elements);
-
- AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INTEGRATE);
-#undef INTEGRATE
+ tuple_dispatch<ElementTypes_t<_ek_cohesive>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ integrator.integrate<type>(f, intf, nb_degree_of_freedom, ghost_type,
+ filter_elements);
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
template <>
void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive,
DefaultIntegrationOrderFunctor>::
- gradientOnIntegrationPoints(
- const Array<Real> & /* u */, Array<Real> & /* nablauq */,
- UInt /* nb_degree_of_freedom */, ElementType /* type */,
- GhostType /* ghost_type */,
- const Array<UInt> & /* filter_elements */) const {
+ gradientOnIntegrationPoints(const Array<Real> & /* u */,
+ Array<Real> & /* nablauq */,
+ Int /* nb_degree_of_freedom */,
+ ElementType /* type */,
+ GhostType /* ghost_type */,
+ const Array<Idx> &) const {
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/fe_engine/fe_engine_template_tmpl.hh b/src/fe_engine/fe_engine_template_tmpl.hh
index 5cf4758ce..21928d7ae 100644
--- a/src/fe_engine/fe_engine_template_tmpl.hh
+++ b/src/fe_engine/fe_engine_template_tmpl.hh
@@ -1,1449 +1,856 @@
/**
* @file fe_engine_template_tmpl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@gmail.com>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Feb 15 2011
* @date last modification: Fri May 14 2021
*
* @brief Template implementation of FEEngineTemplate
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dof_manager.hh"
#include "fe_engine_template.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::FEEngineTemplate(
- Mesh & mesh, UInt spatial_dimension, const ID & id)
+ Mesh & mesh, Int spatial_dimension, const ID & id)
: FEEngine(mesh, spatial_dimension, id),
integrator(mesh, spatial_dimension, id),
shape_functions(mesh, spatial_dimension, id) {}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::~FEEngineTemplate() =
default;
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct GradientOnIntegrationPointsHelper {
- template <class S>
- static void call(const S & /*unused*/, Mesh & /*unused*/,
- const Array<Real> & /*unused*/, Array<Real> & /*unused*/,
- const UInt /*unused*/, ElementType /*unused*/,
- GhostType /*unused*/, const Array<UInt> & /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define COMPUTE_GRADIENT(type) \
- if (element_dimension == ElementClass<type>::getSpatialDimension()) \
- shape_functions.template gradientOnIntegrationPoints<type>( \
- u, nablauq, nb_degree_of_freedom, ghost_type, filter_elements);
-
-#define AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER(kind) \
- template <> struct GradientOnIntegrationPointsHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, Mesh & mesh, \
- const Array<Real> & u, Array<Real> & nablauq, \
- const UInt nb_degree_of_freedom, ElementType type, \
- GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- UInt element_dimension = mesh.getSpatialDimension(type); \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_GRADIENT, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(
- AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER,
- AKANTU_FE_ENGINE_LIST_GRADIENT_ON_INTEGRATION_POINTS)
-
-#undef AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER
-#undef COMPUTE_GRADIENT
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
gradientOnIntegrationPoints(const Array<Real> & u, Array<Real> & nablauq,
- const UInt nb_degree_of_freedom,
- ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ Int nb_degree_of_freedom, ElementType type,
+ GhostType ghost_type,
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
- UInt nb_points =
+ auto nb_points =
shape_functions.getIntegrationPoints(type, ghost_type).cols();
#ifndef AKANTU_NDEBUG
- UInt element_dimension = mesh.getSpatialDimension(type);
+ auto element_dimension = mesh.getSpatialDimension(type);
AKANTU_DEBUG_ASSERT(u.size() == mesh.getNbNodes(),
"The vector u(" << u.getID()
<< ") has not the good size.");
AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom,
"The vector u("
<< u.getID()
<< ") has not the good number of component.");
AKANTU_DEBUG_ASSERT(
nablauq.getNbComponent() == nb_degree_of_freedom * element_dimension,
"The vector nablauq(" << nablauq.getID()
<< ") has not the good number of component.");
-
-// AKANTU_DEBUG_ASSERT(nablauq.size() == nb_element * nb_points,
-// "The vector nablauq(" << nablauq.getID()
-// << ") has not the good size.");
#endif
nablauq.resize(nb_element * nb_points);
- fe_engine::details::GradientOnIntegrationPointsHelper<kind>::call(
- shape_functions, mesh, u, nablauq, nb_degree_of_freedom, type, ghost_type,
- filter_elements);
+ auto call = [&](auto && integral_type) {
+ constexpr ElementType type = std::decay_t<decltype(integral_type)>::value;
+ if (element_dimension == ElementClass<type>::getSpatialDimension())
+ shape_functions.template gradientOnIntegrationPoints<type>(
+ u, nablauq, nb_degree_of_freedom, ghost_type, filter_elements);
+ };
+
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions(
GhostType ghost_type) {
initShapeFunctions(mesh.getNodes(), ghost_type);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- for (auto & type : mesh.elementTypes(element_dimension, ghost_type, kind)) {
+ for (const auto & type :
+ mesh.elementTypes(element_dimension, ghost_type, kind)) {
integrator.initIntegrator(nodes, type, ghost_type);
const auto & control_points = getIntegrationPoints(type, ghost_type);
shape_functions.initShapeFunctions(nodes, control_points, type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct IntegrateHelper {};
-
-#define INTEGRATE(type) \
- integrator.template integrate<type>(f, intf, nb_degree_of_freedom, \
- ghost_type, filter_elements);
-
-#define AKANTU_SPECIALIZE_INTEGRATE_HELPER(kind) \
- template <> struct IntegrateHelper<kind> { \
- template <class I> \
- static void call(const I & integrator, const Array<Real> & f, \
- Array<Real> & intf, UInt nb_degree_of_freedom, \
- ElementType type, GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_HELPER)
-
-#undef AKANTU_SPECIALIZE_INTEGRATE_HELPER
-#undef INTEGRATE
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate(
- const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom,
+ const Array<Real> & f, Array<Real> & intf, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
#ifndef AKANTU_NDEBUG
- UInt nb_quadrature_points = getNbIntegrationPoints(type);
+ auto nb_quadrature_points = getNbIntegrationPoints(type);
AKANTU_DEBUG_ASSERT(f.size() == nb_element * nb_quadrature_points,
"The vector f(" << f.getID() << " size " << f.size()
<< ") has not the good size ("
<< nb_element << ").");
AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom,
"The vector f("
<< f.getID()
<< ") has not the good number of component.");
AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
"The vector intf("
<< intf.getID()
<< ") has not the good number of component.");
#endif
intf.resize(nb_element);
- fe_engine::details::IntegrateHelper<kind>::call(integrator, f, intf,
- nb_degree_of_freedom, type,
- ghost_type, filter_elements);
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ integrator.template integrate<ElementType(type)>(
+ f, intf, nb_degree_of_freedom, ghost_type, filter_elements);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct IntegrateScalarHelper {};
-
-#define INTEGRATE(type) \
- integral = \
- integrator.template integrate<type>(f, ghost_type, filter_elements);
-
-#define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER(kind) \
- template <> struct IntegrateScalarHelper<kind> { \
- template <class I> \
- static Real call(const I & integrator, const Array<Real> & f, \
- ElementType type, GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- Real integral = 0.; \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \
- return integral; \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER)
-
-#undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER
-#undef INTEGRATE
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate(
const Array<Real> & f, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
#ifndef AKANTU_NDEBUG
- // std::stringstream sstr; sstr << ghost_type;
- // AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
- // "The vector " << nablauq.getID() << " is not taged " <<
- // ghost_type);
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
- UInt nb_quadrature_points = getNbIntegrationPoints(type, ghost_type);
+ auto nb_quadrature_points = getNbIntegrationPoints(type, ghost_type);
AKANTU_DEBUG_ASSERT(
f.size() == nb_element * nb_quadrature_points,
"The vector f(" << f.getID() << ") has not the good size. (" << f.size()
<< "!=" << nb_quadrature_points * nb_element << ")");
AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1,
"The vector f("
<< f.getID()
<< ") has not the good number of component.");
#endif
- Real integral = fe_engine::details::IntegrateScalarHelper<kind>::call(
- integrator, f, type, ghost_type, filter_elements);
- AKANTU_DEBUG_OUT();
- return integral;
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ return integrator.template integrate<type>(f, ghost_type, filter_elements);
+ };
+ return tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct IntegrateScalarOnOneElementHelper {};
-
-#define INTEGRATE(type) \
- res = integrator.template integrate<type>(f, index, ghost_type);
-
-#define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER(kind) \
- template <> struct IntegrateScalarOnOneElementHelper<kind> { \
- template <class I> \
- static Real call(const I & integrator, const Vector<Real> & f, \
- ElementType type, UInt index, GhostType ghost_type) { \
- Real res = 0.; \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \
- return res; \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(
- AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER)
-
-#undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER
-#undef INTEGRATE
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate(
- const Vector<Real> & f, ElementType type, UInt index,
+ const Ref<const VectorXr> f, ElementType type, Int index,
GhostType ghost_type) const {
-
- Real res = fe_engine::details::IntegrateScalarOnOneElementHelper<kind>::call(
- integrator, f, type, index, ghost_type);
- return res;
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ return integrator.template integrate<type>(f, index, ghost_type);
+ };
+ return tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct IntegrateOnIntegrationPointsHelper {};
-
-#define INTEGRATE(type) \
- integrator.template integrateOnIntegrationPoints<type>( \
- f, intf, nb_degree_of_freedom, ghost_type, filter_elements);
-
-#define AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER(kind) \
- template <> struct IntegrateOnIntegrationPointsHelper<kind> { \
- template <class I> \
- static void call(const I & integrator, const Array<Real> & f, \
- Array<Real> & intf, UInt nb_degree_of_freedom, \
- ElementType type, GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(
- AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER)
-
-#undef AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER
-#undef INTEGRATE
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
integrateOnIntegrationPoints(const Array<Real> & f, Array<Real> & intf,
- UInt nb_degree_of_freedom, ElementType type,
+ Int nb_degree_of_freedom, ElementType type,
GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Int> & filter_elements) const {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- if (filter_elements != empty_filter) {
+ auto nb_element = mesh.getNbElement(type, ghost_type);
+ if (filter_elements != empty_filter)
nb_element = filter_elements.size();
- }
- UInt nb_quadrature_points = getNbIntegrationPoints(type);
-#ifndef AKANTU_NDEBUG
- // std::stringstream sstr; sstr << ghost_type;
- // AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
- // "The vector " << nablauq.getID() << " is not taged " <<
- // ghost_type);
+ auto nb_quadrature_points = getNbIntegrationPoints(type);
AKANTU_DEBUG_ASSERT(f.size() == nb_element * nb_quadrature_points,
"The vector f(" << f.getID() << " size " << f.size()
<< ") has not the good size ("
<< nb_element << ").");
AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom,
"The vector f("
<< f.getID()
<< ") has not the good number of component.");
AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
"The vector intf("
<< intf.getID()
<< ") has not the good number of component.");
-#endif
intf.resize(nb_element * nb_quadrature_points);
- fe_engine::details::IntegrateOnIntegrationPointsHelper<kind>::call(
- integrator, f, intf, nb_degree_of_freedom, type, ghost_type,
- filter_elements);
-}
-/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct InterpolateOnIntegrationPointsHelper {
- template <class S>
- static void call(const S & /*unused*/, const Array<Real> & /*unused*/,
- Array<Real> & /*unused*/, const UInt /*unused*/,
- ElementType /*unused*/, GhostType /*unused*/,
- const Array<UInt> & /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define INTERPOLATE(type) \
- shape_functions.template interpolateOnIntegrationPoints<type>( \
- u, uq, nb_degree_of_freedom, ghost_type, filter_elements);
-
-#define AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER(kind) \
- template <> struct InterpolateOnIntegrationPointsHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, const Array<Real> & u, \
- Array<Real> & uq, const UInt nb_degree_of_freedom, \
- ElementType type, GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind); \
- } \
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ integrator.template integrateOnIntegrationPoints<ElementType(type)>(
+ f, intf, nb_degree_of_freedom, ghost_type, filter_elements);
};
- AKANTU_BOOST_ALL_KIND_LIST(
- AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER,
- AKANTU_FE_ENGINE_LIST_INTERPOLATE_ON_INTEGRATION_POINTS)
-
-#undef AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER
-#undef INTERPOLATE
- } // namespace details
-} // namespace fe_engine
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
+}
+/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
interpolateOnIntegrationPoints(const Array<Real> & u, Array<Real> & uq,
- const UInt nb_degree_of_freedom,
- ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ Int nb_degree_of_freedom, ElementType type,
+ GhostType ghost_type,
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt nb_points =
+ auto nb_points =
shape_functions.getIntegrationPoints(type, ghost_type).cols();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
-#ifndef AKANTU_NDEBUG
AKANTU_DEBUG_ASSERT(u.size() == mesh.getNbNodes(),
"The vector u(" << u.getID()
<< ") has not the good size.");
AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom,
"The vector u("
<< u.getID()
<< ") has not the good number of component.");
AKANTU_DEBUG_ASSERT(uq.getNbComponent() == nb_degree_of_freedom,
"The vector uq("
<< uq.getID()
<< ") has not the good number of component.");
-#endif
uq.resize(nb_element * nb_points);
- fe_engine::details::InterpolateOnIntegrationPointsHelper<kind>::call(
- shape_functions, u, uq, nb_degree_of_freedom, type, ghost_type,
- filter_elements);
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template interpolateOnIntegrationPoints<type>(
+ u, uq, nb_degree_of_freedom, ghost_type, filter_elements);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
interpolateOnIntegrationPoints(
const Array<Real> & u, ElementTypeMapArray<Real> & uq,
- const ElementTypeMapArray<UInt> * filter_elements) const {
+ const ElementTypeMapArray<Idx> * filter_elements) const {
AKANTU_DEBUG_IN();
- const Array<UInt> * filter = nullptr;
+ const Array<Idx> * filter = nullptr;
for (auto ghost_type : ghost_types) {
- for (auto && type : uq.elementTypes(_all_dimensions, ghost_type, kind)) {
- UInt nb_quad_per_element = getNbIntegrationPoints(type, ghost_type);
+ for (const auto & type :
+ uq.elementTypes(_all_dimensions, ghost_type, kind)) {
+ auto nb_quad_per_element = getNbIntegrationPoints(type, ghost_type);
- UInt nb_element = 0;
+ Int nb_element = 0;
if (filter_elements != nullptr) {
filter = &((*filter_elements)(type, ghost_type));
nb_element = filter->size();
} else {
filter = &empty_filter;
nb_element = mesh.getNbElement(type, ghost_type);
}
- UInt nb_tot_quad = nb_quad_per_element * nb_element;
+ auto nb_tot_quad = nb_quad_per_element * nb_element;
Array<Real> & quad = uq(type, ghost_type);
quad.resize(nb_tot_quad);
interpolateOnIntegrationPoints(u, quad, quad.getNbComponent(), type,
ghost_type, *filter);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ComputeBtDHelper {};
-
-#define COMPUTE_BTD(type) \
- shape_functions.template computeBtD<type>(Ds, BtDs, ghost_type, \
- filter_elements);
-
-#define AKANTU_SPECIALIZE_COMPUTE_BtD_HELPER(kind) \
- template <> struct ComputeBtDHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, const Array<Real> & Ds, \
- Array<Real> & BtDs, ElementType type, \
- GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_BTD, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_COMPUTE_BtD_HELPER)
-
-#undef AKANTU_SPECIALIZE_COMPUTE_BtD_HELPER
-#undef COMPUTE_BTD
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeBtD(
const Array<Real> & Ds, Array<Real> & BtDs, ElementType type,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
- fe_engine::details::ComputeBtDHelper<kind>::call(
- shape_functions, Ds, BtDs, type, ghost_type, filter_elements);
-}
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
-/* -------------------------------------------------------------------------- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ComputeBtDBHelper {};
-
-#define COMPUTE_BTDB(type) \
- shape_functions.template computeBtDB<type>(Ds, BtDBs, order_d, ghost_type, \
- filter_elements);
-
-#define AKANTU_SPECIALIZE_COMPUTE_BtDB_HELPER(kind) \
- template <> struct ComputeBtDBHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, const Array<Real> & Ds, \
- Array<Real> & BtDBs, UInt order_d, ElementType type, \
- GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_BTDB, kind); \
- } \
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template computeBtD<type>(Ds, BtDs, ghost_type,
+ filter_elements);
};
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
+}
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_COMPUTE_BtDB_HELPER)
-
-#undef AKANTU_SPECIALIZE_COMPUTE_BtDB_HELPER
-#undef COMPUTE_BTDB
- } // namespace details
-} // namespace fe_engine
-
+/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeBtDB(
- const Array<Real> & Ds, Array<Real> & BtDBs, UInt order_d, ElementType type,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
- fe_engine::details::ComputeBtDBHelper<kind>::call(
- shape_functions, Ds, BtDBs, order_d, type, ghost_type, filter_elements);
+ const Array<Real> & Ds, Array<Real> & BtDBs, Int order_d, ElementType type,
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template computeBtDB<type>(Ds, BtDBs, order_d, ghost_type,
+ filter_elements);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ComputeNtbNHelper {};
-
-#define COMPUTE_NtbN(type) \
- shape_functions.template computeNtbN<type>(bs, NtbNs, ghost_type, \
- filter_elements);
-
-#define AKANTU_SPECIALIZE_COMPUTE_NtbN_HELPER(kind) \
- template <> struct ComputeNtbNHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, const Array<Real> & bs, \
- Array<Real> & NtbNs, ElementType type, \
- GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_NtbN, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_COMPUTE_NtbN_HELPER)
-
-#undef AKANTU_SPECIALIZE_COMPUTE_NtbN_HELPER
-#undef COMPUTE_NtbN
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeNtbN(
const Array<Real> & bs, Array<Real> & NtbNs, ElementType type,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
- fe_engine::details::ComputeNtbNHelper<kind>::call(
- shape_functions, bs, NtbNs, type, ghost_type, filter_elements);
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template computeNtbN<type>(bs, NtbNs, ghost_type,
+ filter_elements);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ComputeNtbHelper {};
-
-#define COMPUTE_Ntb(type) \
- shape_functions.template computeNtb<type>(bs, Ntbs, ghost_type, \
- filter_elements);
-
-#define AKANTU_SPECIALIZE_COMPUTE_Ntb_HELPER(kind) \
- template <> struct ComputeNtbHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, const Array<Real> & bs, \
- Array<Real> & Ntbs, ElementType type, \
- GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_Ntb, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_COMPUTE_Ntb_HELPER)
-
-#undef AKANTU_SPECIALIZE_COMPUTE_Ntb_HELPER
-#undef COMPUTE_Ntb
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeNtb(
const Array<Real> & bs, Array<Real> & Ntbs, ElementType type,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
- fe_engine::details::ComputeNtbHelper<kind>::call(
- shape_functions, bs, Ntbs, type, ghost_type, filter_elements);
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template computeNtb<type>(bs, Ntbs, ghost_type,
+ filter_elements);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
computeIntegrationPointsCoordinates(
ElementTypeMapArray<Real> & quadrature_points_coordinates,
- const ElementTypeMapArray<UInt> * filter_elements) const {
+ const ElementTypeMapArray<Idx> * filter_elements) const {
const Array<Real> & nodes_coordinates = mesh.getNodes();
interpolateOnIntegrationPoints(
nodes_coordinates, quadrature_points_coordinates, filter_elements);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
computeIntegrationPointsCoordinates(
Array<Real> & quadrature_points_coordinates, ElementType type,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
-
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
const Array<Real> & nodes_coordinates = mesh.getNodes();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
interpolateOnIntegrationPoints(
nodes_coordinates, quadrature_points_coordinates, spatial_dimension, type,
ghost_type, filter_elements);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
initElementalFieldInterpolationFromIntegrationPoints(
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
- const ElementTypeMapArray<UInt> * element_filter) const {
-
+ const ElementTypeMapArray<Idx> * element_filter) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = this->mesh.getSpatialDimension();
+ auto spatial_dimension = this->mesh.getSpatialDimension();
ElementTypeMapArray<Real> quadrature_points_coordinates(
"quadrature_points_coordinates_for_interpolation", getID());
quadrature_points_coordinates.initialize(*this,
_nb_component = spatial_dimension);
computeIntegrationPointsCoordinates(quadrature_points_coordinates,
element_filter);
shape_functions.initElementalFieldInterpolationFromIntegrationPoints(
interpolation_points_coordinates,
interpolation_points_coordinates_matrices,
quad_points_coordinates_inv_matrices, quadrature_points_coordinates,
element_filter);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
- ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const {
+ ElementTypeMapArray<Real> & result, const GhostType ghost_type,
+ const ElementTypeMapArray<Idx> * element_filter) const {
ElementTypeMapArray<Real> interpolation_points_coordinates_matrices(
"interpolation_points_coordinates_matrices", id);
ElementTypeMapArray<Real> quad_points_coordinates_inv_matrices(
"quad_points_coordinates_inv_matrices", id);
initElementalFieldInterpolationFromIntegrationPoints(
interpolation_points_coordinates,
interpolation_points_coordinates_matrices,
quad_points_coordinates_inv_matrices, element_filter);
interpolateElementalFieldFromIntegrationPoints(
field, interpolation_points_coordinates_matrices,
quad_points_coordinates_inv_matrices, result, ghost_type, element_filter);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> &
interpolation_points_coordinates_matrices,
const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
- ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const {
-
+ ElementTypeMapArray<Real> & result, const GhostType ghost_type,
+ const ElementTypeMapArray<Idx> * element_filter) const {
shape_functions.interpolateElementalFieldFromIntegrationPoints(
field, interpolation_points_coordinates_matrices,
quad_points_coordinates_inv_matrices, result, ghost_type, element_filter);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct InterpolateHelper {
- template <class S>
- static void call(const S & /*unused*/, const Vector<Real> & /*unused*/,
- UInt /*unused*/, const Matrix<Real> & /*unused*/,
- Vector<Real> & /*unused*/, ElementType /*unused*/,
- GhostType /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define INTERPOLATE(type) \
- shape_functions.template interpolate<type>( \
- real_coords, element, nodal_values, interpolated, ghost_type);
-
-#define AKANTU_SPECIALIZE_INTERPOLATE_HELPER(kind) \
- template <> struct InterpolateHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, \
- const Vector<Real> & real_coords, UInt element, \
- const Matrix<Real> & nodal_values, \
- Vector<Real> & interpolated, ElementType type, \
- GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind); \
- } \
+template <template <ElementKind, class> class I, template <ElementKind> class S,
+ ElementKind kind, class IntegrationOrderFunctor>
+template <ElementKind kind_, typename D1, typename D2, typename D3,
+ std::enable_if_t<aka::are_vectors<D1, D3>::value and
+ kind_ == _ek_regular> *>
+inline void
+FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::interpolateImpl(
+ const Eigen::MatrixBase<D1> & real_coords,
+ const Eigen::MatrixBase<D2> & nodal_values,
+ Eigen::MatrixBase<D3> & interpolated, const Element & element) const {
+ /// add sfinea to call only on _ek_regular
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std::decay_t<decltype(enum_type)>::value;
+ shape_functions.template interpolate<type>(real_coords, element.element,
+ nodal_values, interpolated,
+ element.ghost_type);
};
+ tuple_dispatch<ElementTypes_t<kind>>(call, element.type);
+}
- AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INTERPOLATE_HELPER,
- AKANTU_FE_ENGINE_LIST_INTERPOLATE)
-
-#undef AKANTU_SPECIALIZE_INTERPOLATE_HELPER
-#undef INTERPOLATE
- } // namespace details
-} // namespace fe_engine
-
+/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::interpolate(
- const Vector<Real> & real_coords, const Matrix<Real> & nodal_values,
- Vector<Real> & interpolated, const Element & element) const {
-
- AKANTU_DEBUG_IN();
-
- fe_engine::details::InterpolateHelper<kind>::call(
- shape_functions, real_coords, element.element, nodal_values, interpolated,
- element.type, element.ghost_type);
-
- AKANTU_DEBUG_OUT();
+ const Ref<const VectorXr> real_coords,
+ const Ref<const MatrixXr> nodal_values, Ref<VectorXr> interpolated,
+ const Element & element) const {
+ interpolateImpl(real_coords, nodal_values, interpolated, element);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
computeNormalsOnIntegrationPoints(GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
computeNormalsOnIntegrationPoints(mesh.getNodes(), ghost_type);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
computeNormalsOnIntegrationPoints(const Array<Real> & field,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- // Real * coord = mesh.getNodes().storage();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ // Real * coord = mesh.getNodes().data();
+ auto spatial_dimension = mesh.getSpatialDimension();
// allocate the normal arrays
normals_on_integration_points.initialize(
*this, _nb_component = spatial_dimension,
_spatial_dimension = element_dimension, _ghost_type = ghost_type,
_element_kind = kind);
// loop over the type to build the normals
- for (auto & type : mesh.elementTypes(element_dimension, ghost_type, kind)) {
+ for (const auto & type :
+ mesh.elementTypes(element_dimension, ghost_type, kind)) {
auto & normals_on_quad = normals_on_integration_points(type, ghost_type);
computeNormalsOnIntegrationPoints(field, normals_on_quad, type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ComputeNormalsOnIntegrationPoints {
- template <template <ElementKind, class> class I,
- template <ElementKind> class S, ElementKind k, class IOF>
- static void call(const FEEngineTemplate<I, S, k, IOF> & /*unused*/,
- const Array<Real> & /*unused*/, Array<Real> & /*unused*/,
- ElementType /*unused*/, GhostType /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define COMPUTE_NORMALS_ON_INTEGRATION_POINTS(type) \
- fem.template computeNormalsOnIntegrationPoints<type>(field, normal, \
- ghost_type);
-
-#define AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS(kind) \
- template <> struct ComputeNormalsOnIntegrationPoints<kind> { \
- template <template <ElementKind, class> class I, \
- template <ElementKind> class S, ElementKind k, class IOF> \
- static void call(const FEEngineTemplate<I, S, k, IOF> & fem, \
- const Array<Real> & field, Array<Real> & normal, \
- ElementType type, GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_NORMALS_ON_INTEGRATION_POINTS, \
- kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(
- AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS,
- AKANTU_FE_ENGINE_LIST_COMPUTE_NORMALS_ON_INTEGRATION_POINTS)
-
-#undef AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS
-#undef COMPUTE_NORMALS_ON_INTEGRATION_POINTS
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
+template <ElementType type, ElementKind kind_,
+ std::enable_if_t<kind_ == _ek_regular and type != _point_1> *>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
computeNormalsOnIntegrationPoints(const Array<Real> & field,
- Array<Real> & normal, ElementType type,
+ Array<Real> & normal,
GhostType ghost_type) const {
- fe_engine::details::ComputeNormalsOnIntegrationPoints<kind>::call(
- *this, field, normal, type, ghost_type);
+ AKANTU_DEBUG_IN();
+
+ auto spatial_dimension = mesh.getSpatialDimension();
+ constexpr auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_points = getNbIntegrationPoints(type, ghost_type);
+
+ auto nb_element = mesh.getConnectivity(type, ghost_type).size();
+ normal.resize(nb_element * nb_points);
+
+ Array<Real> f_el(0, spatial_dimension * nb_nodes_per_element);
+ FEEngine::extractNodalToElementField(mesh, field, f_el, type, ghost_type);
+
+ const auto & quads =
+ integrator.template getIntegrationPoints<type>(ghost_type);
+
+ for (auto && data : zip(make_view(normal, spatial_dimension, nb_points),
+ make_view<Eigen::Dynamic, nb_nodes_per_element>(
+ f_el, spatial_dimension, nb_nodes_per_element))) {
+ ElementClass<type>::computeNormalsOnNaturalCoordinates(
+ quads, std::get<1>(data), std::get<0>(data));
+ }
+
+ AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
-template <ElementType type>
-void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
- computeNormalsOnIntegrationPoints(const Array<Real> & field,
+template <ElementType type, ElementKind kind_,
+ std::enable_if_t<kind_ == _ek_regular and type == _point_1> *>
+inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
+ computeNormalsOnIntegrationPoints(const Array<Real> & /*field*/,
Array<Real> & normal,
GhostType ghost_type) const {
AKANTU_DEBUG_IN();
- if (type == _point_1) {
- computeNormalsOnIntegrationPointsPoint1(field, normal, ghost_type);
- return;
- }
+ AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == 1,
+ "Mesh dimension must be 1 to compute normals on points!");
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_points = getNbIntegrationPoints(type, ghost_type);
+ auto spatial_dimension = mesh.getSpatialDimension();
+ // Int nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_points = getNbIntegrationPoints(type, ghost_type);
+ const auto & connectivity = mesh.getConnectivity(type, ghost_type);
+ auto nb_element = connectivity.size();
- UInt nb_element = mesh.getConnectivity(type, ghost_type).size();
normal.resize(nb_element * nb_points);
- Array<Real>::matrix_iterator normals_on_quad =
- normal.begin_reinterpret(spatial_dimension, nb_points, nb_element);
- Array<Real> f_el(0, spatial_dimension * nb_nodes_per_element);
- FEEngine::extractNodalToElementField(mesh, field, f_el, type, ghost_type);
+ auto normals_on_quad =
+ make_view(normal, spatial_dimension, nb_points).begin();
+ const auto & segments = mesh.getElementToSubelement(type, ghost_type);
+ const auto & coords = mesh.getNodes();
- const Matrix<Real> & quads =
- integrator.template getIntegrationPoints<type>(ghost_type);
+ const Mesh * mesh_segment;
+ if (mesh.isMeshFacets()) {
+ mesh_segment = &(mesh.getMeshParent());
+ } else {
+ mesh_segment = &mesh;
+ }
+
+ for (Idx elem = 0; elem < nb_element; ++elem) {
+ auto nb_segment = segments(elem).size();
+ AKANTU_DEBUG_ASSERT(
+ nb_segment > 0,
+ "Impossible to compute a normal on a point connected to 0 segments");
+
+ Real normal_value = 1;
+ if (nb_segment == 1) {
+ auto point = connectivity(elem);
+ const auto segment = segments(elem)[0];
+ const auto & segment_connectivity =
+ mesh_segment->getConnectivity(segment.type, segment.ghost_type);
+ Vector<Idx> segment_points = segment_connectivity.begin(
+ Mesh::getNbNodesPerElement(segment.type))[segment.element];
+ Real difference;
+ if (segment_points(0) == point) {
+ difference = coords(elem) - coords(segment_points(1));
+ } else {
+ difference = coords(elem) - coords(segment_points(0));
+ }
- Array<Real>::matrix_iterator f_it =
- f_el.begin(spatial_dimension, nb_nodes_per_element);
+ normal_value = difference / std::abs(difference);
+ }
- for (UInt elem = 0; elem < nb_element; ++elem) {
- ElementClass<type>::computeNormalsOnNaturalCoordinates(quads, *f_it,
- *normals_on_quad);
+ for (Idx n(0); n < nb_points; ++n) {
+ (*normals_on_quad)(0, n) = normal_value;
+ }
++normals_on_quad;
- ++f_it;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-template <ElementKind kind> struct InverseMapHelper {
- template <class S>
- static void call(const S & /*shape_functions*/,
- const Vector<Real> & /*real_coords*/, UInt /*element*/,
- ElementType /*type*/, Vector<Real> & /*natural_coords*/,
- GhostType /*ghost_type*/) {
- AKANTU_TO_IMPLEMENT();
- }
-};
-
-#define INVERSE_MAP(type) \
- shape_functions.template inverseMap<type>(real_coords, element, \
- natural_coords, ghost_type);
-
-#define AKANTU_SPECIALIZE_INVERSE_MAP_HELPER(kind) \
- template <> struct InverseMapHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, \
- const Vector<Real> & real_coords, UInt element, \
- ElementType type, Vector<Real> & natural_coords, \
- GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INVERSE_MAP, kind); \
- } \
+template <template <ElementKind, class> class I, template <ElementKind> class S,
+ ElementKind kind, class IntegrationOrderFunctor>
+void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
+ computeNormalsOnIntegrationPoints(const Array<Real> & field,
+ Array<Real> & normal, ElementType type,
+ GhostType ghost_type) const {
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ this->computeNormalsOnIntegrationPoints<type>(field, normal, ghost_type);
};
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
+}
-AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INVERSE_MAP_HELPER,
- AKANTU_FE_ENGINE_LIST_INVERSE_MAP)
-
-#undef AKANTU_SPECIALIZE_INVERSE_MAP_HELPER
-#undef INVERSE_MAP
-
+/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::inverseMap(
- const Vector<Real> & real_coords, UInt element, ElementType type,
- Vector<Real> & natural_coords, GhostType ghost_type) const {
-
- AKANTU_DEBUG_IN();
-
- InverseMapHelper<kind>::call(shape_functions, real_coords, element, type,
- natural_coords, ghost_type);
-
- AKANTU_DEBUG_OUT();
+ const Ref<const VectorXr> real_coords, Int element, ElementType type,
+ Ref<VectorXr> natural_coords, GhostType ghost_type) const {
+ /// need sfinea to avoid structural
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template inverseMap<type>(real_coords, element,
+ natural_coords, ghost_type);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ContainsHelper {
- template <class S>
- static void call(const S & /*unused*/, const Vector<Real> & /*unused*/,
- UInt /*unused*/, ElementType /*unused*/,
- GhostType /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define CONTAINS(type) \
- contain = shape_functions.template contains<type>(real_coords, element, \
- ghost_type);
-
-#define AKANTU_SPECIALIZE_CONTAINS_HELPER(kind) \
- template <> struct ContainsHelper<kind> { \
- template <template <ElementKind> class S, ElementKind k> \
- static bool call(const S<k> & shape_functions, \
- const Vector<Real> & real_coords, UInt element, \
- ElementType type, GhostType ghost_type) { \
- bool contain = false; \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(CONTAINS, kind); \
- return contain; \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_CONTAINS_HELPER,
- AKANTU_FE_ENGINE_LIST_CONTAINS)
-
-#undef AKANTU_SPECIALIZE_CONTAINS_HELPER
-#undef CONTAINS
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline bool FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::contains(
- const Vector<Real> & real_coords, UInt element, ElementType type,
+ const Vector<Real> & real_coords, Int element, ElementType type,
GhostType ghost_type) const {
- return fe_engine::details::ContainsHelper<kind>::call(
- shape_functions, real_coords, element, type, ghost_type);
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ return shape_functions.template contains<type>(real_coords, element,
+ ghost_type);
+ };
+ return tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ComputeShapesHelper {
- template <class S>
- static void call(const S & /*unused*/, const Vector<Real> & /*unused*/,
- UInt /*unused*/, const ElementType /*unused*/,
- Vector<Real> & /*unused*/, GhostType /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define COMPUTE_SHAPES(type) \
- shape_functions.template computeShapes<type>(real_coords, element, shapes, \
- ghost_type);
-
-#define AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER(kind) \
- template <> struct ComputeShapesHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, \
- const Vector<Real> & real_coords, UInt element, \
- const ElementType type, Vector<Real> & shapes, \
- GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPES, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER,
- AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES)
-
-#undef AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER
-#undef COMPUTE_SHAPES
- } // namespace details
-} // namespace fe_engine
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
+template <ElementKind kind_, typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors<D1, D2>::value and
+ kind_ != _ek_cohesive> *>
inline void
-FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapes(
- const Vector<Real> & real_coords, UInt element, ElementType type,
- Vector<Real> & shapes, GhostType ghost_type) const {
-
- AKANTU_DEBUG_IN();
-
- fe_engine::details::ComputeShapesHelper<kind>::call(
- shape_functions, real_coords, element, type, shapes, ghost_type);
-
- AKANTU_DEBUG_OUT();
+FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapesImpl(
+ const Eigen::MatrixBase<D1> & real_coords, Idx element, ElementType type,
+ Eigen::MatrixBase<D2> & shapes, GhostType ghost_type) const {
+
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ this->shape_functions.template computeShapes<type>(real_coords, element,
+ shapes, ghost_type);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct ComputeShapeDerivativesHelper {
- template <class S>
- static void call(__attribute__((unused)) const S & shape_functions,
- __attribute__((unused)) const Vector<Real> & real_coords,
- __attribute__((unused)) UInt element,
- __attribute__((unused)) const ElementType type,
- __attribute__((unused)) Matrix<Real> & shape_derivatives,
- __attribute__((unused)) GhostType ghost_type) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define COMPUTE_SHAPE_DERIVATIVES(type) \
- Matrix<Real> coords_mat(real_coords.storage(), shape_derivatives.rows(), 1); \
- Tensor3<Real> shapesd_tensor(shape_derivatives.storage(), \
- shape_derivatives.rows(), \
- shape_derivatives.cols(), 1); \
- shape_functions.template computeShapeDerivatives<type>( \
- coords_mat, element, shapesd_tensor, ghost_type);
-
-#define AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER(kind) \
- template <> struct ComputeShapeDerivativesHelper<kind> { \
- template <class S> \
- static void call(const S & shape_functions, \
- const Vector<Real> & real_coords, UInt element, \
- const ElementType type, Matrix<Real> & shape_derivatives, \
- GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPE_DERIVATIVES, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(
- AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER,
- AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES_DERIVATIVES)
-
-#undef AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER
-#undef COMPUTE_SHAPE_DERIVATIVES
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
-inline void
-FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapeDerivatives(
- const Vector<Real> & real_coords, UInt element, ElementType type,
- Matrix<Real> & shape_derivatives, GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- fe_engine::details::ComputeShapeDerivativesHelper<kind>::call(
- shape_functions, real_coords, element, type, shape_derivatives,
- ghost_type);
-
- AKANTU_DEBUG_OUT();
+template <ElementKind kind_, typename D1, typename D2,
+ std::enable_if_t<aka::is_vector_v<D1> and kind_ != _ek_cohesive> *>
+inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
+ computeShapeDerivativesImpl(const Eigen::MatrixBase<D1> & real_coords,
+ Int element, ElementType type,
+ Eigen::MatrixBase<D2> & shape_derivatives,
+ GhostType ghost_type) const {
+ MatrixProxy<const Real> coords_mat(real_coords.derived().data(),
+ shape_derivatives.rows(), 1);
+ Tensor3Proxy<Real> shapesd_tensor(shape_derivatives.derived().data(),
+ shape_derivatives.rows(),
+ shape_derivatives.cols(), 1);
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template computeShapeDerivatives<type>(
+ coords_mat, element, shapesd_tensor, ghost_type);
+ };
+ tuple_dispatch<ElementTypes_t<kind>>(call, type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct GetNbIntegrationPointsHelper {};
-
-#define GET_NB_INTEGRATION_POINTS(type) \
- nb_quad_points = integrator.template getNbIntegrationPoints<type>(ghost_type);
-
-#define AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER(kind) \
- template <> struct GetNbIntegrationPointsHelper<kind> { \
- template <template <ElementKind, class> class I, ElementKind k, class IOF> \
- static UInt call(const I<k, IOF> & integrator, const ElementType type, \
- GhostType ghost_type) { \
- UInt nb_quad_points = 0; \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_NB_INTEGRATION_POINTS, kind); \
- return nb_quad_points; \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER)
-
-#undef AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER
-#undef GET_NB_INTEGRATION
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
-inline UInt
+inline Int
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getNbIntegrationPoints(
ElementType type, GhostType ghost_type) const {
- return fe_engine::details::GetNbIntegrationPointsHelper<kind>::call(
- integrator, type, ghost_type);
+ return tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ return integrator.template getNbIntegrationPoints<type>(ghost_type);
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct GetShapesHelper {};
-
-#define GET_SHAPES(type) ret = &(shape_functions.getShapes(type, ghost_type));
-
-#define AKANTU_SPECIALIZE_GET_SHAPES_HELPER(kind) \
- template <> struct GetShapesHelper<kind> { \
- template <class S> \
- static const Array<Real> & call(const S & shape_functions, \
- const ElementType type, \
- GhostType ghost_type) { \
- const Array<Real> * ret = NULL; \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES, kind); \
- return *ret; \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_SHAPES_HELPER)
-
-#undef AKANTU_SPECIALIZE_GET_SHAPES_HELPER
-#undef GET_SHAPES
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline const Array<Real> &
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapes(
- ElementType type, GhostType ghost_type,
- __attribute__((unused)) UInt id) const {
- return fe_engine::details::GetShapesHelper<kind>::call(shape_functions, type,
- ghost_type);
+ ElementType type, GhostType ghost_type, Int /*id*/) const {
+ return shape_functions.getShapes(type, ghost_type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct GetShapesDerivativesHelper {
- template <template <ElementKind> class S, ElementKind k>
- static const Array<Real> & call(const S<k> & /*unused*/,
- ElementType /*unused*/,
- GhostType /*unused*/, UInt /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define GET_SHAPES_DERIVATIVES(type) \
- ret = &(shape_functions.getShapesDerivatives(type, ghost_type));
-
-#define AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER(kind) \
- template <> struct GetShapesDerivativesHelper<kind> { \
- template <template <ElementKind> class S, ElementKind k> \
- static const Array<Real> & \
- call(const S<k> & shape_functions, const ElementType type, \
- GhostType ghost_type, __attribute__((unused)) UInt id) { \
- const Array<Real> * ret = NULL; \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES_DERIVATIVES, kind); \
- return *ret; \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER,
- AKANTU_FE_ENGINE_LIST_GET_SHAPES_DERIVATIVES)
-
-#undef AKANTU_SPECIALIZE_GET_SHAPE_DERIVATIVES_HELPER
-#undef GET_SHAPES_DERIVATIVES
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline const Array<Real> &
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapesDerivatives(
- ElementType type, GhostType ghost_type,
- __attribute__((unused)) UInt id) const {
- return fe_engine::details::GetShapesDerivativesHelper<kind>::call(
- shape_functions, type, ghost_type, id);
+ ElementType type, GhostType ghost_type, Int /*id*/) const {
+ return shape_functions.getShapesDerivatives(type, ghost_type);
}
/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct GetIntegrationPointsHelper {};
-
-#define GET_INTEGRATION_POINTS(type) \
- ret = &(integrator.template getIntegrationPoints<type>(ghost_type));
-
-#define AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER(kind) \
- template <> struct GetIntegrationPointsHelper<kind> { \
- template <template <ElementKind, class> class I, ElementKind k, class IOF> \
- static const Matrix<Real> & call(const I<k, IOF> & integrator, \
- const ElementType type, \
- GhostType ghost_type) { \
- const Matrix<Real> * ret = NULL; \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_INTEGRATION_POINTS, kind); \
- return *ret; \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER)
-
-#undef AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER
-#undef GET_INTEGRATION_POINTS
- } // namespace details
-} // namespace fe_engine
-
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline const Matrix<Real> &
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getIntegrationPoints(
ElementType type, GhostType ghost_type) const {
- return fe_engine::details::GetIntegrationPointsHelper<kind>::call(
- integrator, type, ghost_type);
+
+ return tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) -> const Matrix<Real> & {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ return (integrator.template getIntegrationPoints<type>(ghost_type));
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::printself(
std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "FEEngineTemplate [" << std::endl;
stream << space << " + parent [" << std::endl;
FEEngine::printself(stream, indent + 3);
stream << space << " ]" << std::endl;
stream << space << " + shape functions [" << std::endl;
shape_functions.printself(stream, indent + 3);
stream << space << " ]" << std::endl;
stream << space << " + integrator [" << std::endl;
integrator.printself(stream, indent + 3);
stream << space << " ]" << std::endl;
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::onElementsAdded(
const Array<Element> & new_elements, const NewElementsEvent & /*unused*/) {
integrator.onElementsAdded(new_elements);
+
+ const auto & points = integrator.getIntegrationPoints();
+ // for each distinct type add missing integration points to shape_functions
+ for (auto ghost_type : ghost_types) {
+ for (const auto & type : points.elementTypes(_ghost_type = ghost_type)) {
+ tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type =
+ std ::decay_t<decltype(enum_type)>::value;
+ shape_functions.template setIntegrationPointsByType<type>(
+ points(type, ghost_type), ghost_type);
+ },
+ type);
+ }
+ }
+
shape_functions.onElementsAdded(new_elements);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::onElementsRemoved(
- const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const RemovedElementsEvent & /*unused*/) {}
+ const Array<Element> & removed_elements,
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent & /*event*/) {
+ integrator.onElementsRemoved(removed_elements, new_numbering);
+ shape_functions.onElementsRemoved(removed_elements, new_numbering);
+}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::onElementsChanged(
const Array<Element> & /*unused*/, const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
+ const ElementTypeMapArray<Idx> & /*unused*/,
const ChangedElementsEvent & /*unused*/) {}
-/* -------------------------------------------------------------------------- */
-template <template <ElementKind, class> class I, template <ElementKind> class S,
- ElementKind kind, class IntegrationOrderFunctor>
-inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
- computeNormalsOnIntegrationPointsPoint1(const Array<Real> & /*unused*/,
- Array<Real> & normal,
- GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == 1,
- "Mesh dimension must be 1 to compute normals on points!");
- const auto type = _point_1;
- auto spatial_dimension = mesh.getSpatialDimension();
- // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- auto nb_points = getNbIntegrationPoints(type, ghost_type);
- const auto & connectivity = mesh.getConnectivity(type, ghost_type);
- auto nb_element = connectivity.size();
-
- normal.resize(nb_element * nb_points);
- auto normals_on_quad =
- normal.begin_reinterpret(spatial_dimension, nb_points, nb_element);
- const auto & segments = mesh.getElementToSubelement(type, ghost_type);
- const auto & coords = mesh.getNodes();
-
- const Mesh * mesh_segment;
- if (mesh.isMeshFacets()) {
- mesh_segment = &(mesh.getMeshParent());
- } else {
- mesh_segment = &mesh;
- }
-
- for (UInt elem = 0; elem < nb_element; ++elem) {
- UInt nb_segment = segments(elem).size();
- AKANTU_DEBUG_ASSERT(
- nb_segment > 0,
- "Impossible to compute a normal on a point connected to 0 segments");
-
- Real normal_value = 1;
- if (nb_segment == 1) {
- auto point = connectivity(elem);
- const auto segment = segments(elem)[0];
- const auto & segment_connectivity =
- mesh_segment->getConnectivity(segment.type, segment.ghost_type);
- Vector<UInt> segment_points = segment_connectivity.begin(
- Mesh::getNbNodesPerElement(segment.type))[segment.element];
- Real difference;
- if (segment_points(0) == point) {
- difference = coords(elem) - coords(segment_points(1));
- } else {
- difference = coords(elem) - coords(segment_points(0));
- }
-
- normal_value = difference / std::abs(difference);
- }
-
- for (UInt n(0); n < nb_points; ++n) {
- (*normals_on_quad)(0, n) = normal_value;
- }
- ++normals_on_quad;
- }
-
- AKANTU_DEBUG_OUT();
-}
-
} // namespace akantu
diff --git a/src/fe_engine/fe_engine_template_tmpl_field.hh b/src/fe_engine/fe_engine_template_tmpl_field.hh
index e30fbc7c2..43af598df 100644
--- a/src/fe_engine/fe_engine_template_tmpl_field.hh
+++ b/src/fe_engine/fe_engine_template_tmpl_field.hh
@@ -1,507 +1,423 @@
/**
* @file fe_engine_template_tmpl_field.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 09 2017
* @date last modification: Sat Mar 13 2021
*
* @brief implementation of the assemble field s functions
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "fe_engine_template.hh"
+//#include "fe_engine_template.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_FE_ENGINE_TEMPLATE_TMPL_FIELD_HH_
#define AKANTU_FE_ENGINE_TEMPLATE_TMPL_FIELD_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Matrix lumping functions */
/* -------------------------------------------------------------------------- */
namespace fe_engine {
namespace details {
namespace {
template <class Functor>
void fillField(const Functor & field_funct, Array<Real> & field,
- UInt nb_element, UInt nb_integration_points,
+ Int nb_element, Int nb_integration_points,
ElementType type, GhostType ghost_type) {
- UInt nb_degree_of_freedom = field.getNbComponent();
+ auto nb_degree_of_freedom = field.getNbComponent();
field.resize(nb_integration_points * nb_element);
- auto field_it = field.begin_reinterpret(
- nb_degree_of_freedom, nb_integration_points, nb_element);
+ Matrix<Real> mat(nb_degree_of_freedom, nb_integration_points);
Element el{type, 0, ghost_type};
- for (; el.element < nb_element; ++el.element, ++field_it) {
- field_funct(*field_it, el);
+ for (auto && data : enumerate(make_view(field, nb_degree_of_freedom,
+ nb_integration_points))) {
+ el.element = std::get<0>(data);
+ mat.zero();
+ field_funct(mat, el);
+ std::get<1>(data) = mat;
}
}
} // namespace
} // namespace details
} // namespace fe_engine
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct AssembleLumpedTemplateHelper {
- template <template <ElementKind, class> class I,
- template <ElementKind> class S, ElementKind k, class IOF>
- static void call(const FEEngineTemplate<I, S, k, IOF> & /*unused*/,
- const std::function<void(Matrix<Real> &,
- const Element &)> & /*unused*/,
- const ID & /*unused*/, const ID & /*unused*/,
- DOFManager & /*unused*/, ElementType /*unused*/,
- GhostType /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define ASSEMBLE_LUMPED(type) \
- fem.template assembleFieldLumped<type>(field_funct, lumped, dof_id, \
- dof_manager, ghost_type)
-
-#define AKANTU_SPECIALIZE_ASSEMBLE_HELPER(kind) \
- template <> struct AssembleLumpedTemplateHelper<kind> { \
- template <template <ElementKind, class> class I, \
- template <ElementKind> class S, ElementKind k, class IOF> \
- static void \
- call(const FEEngineTemplate<I, S, k, IOF> & fem, \
- const std::function<void(Matrix<Real> &, const Element &)> & \
- field_funct, \
- const ID & lumped, const ID & dof_id, DOFManager & dof_manager, \
- ElementType type, GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_LUMPED, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_ASSEMBLE_HELPER,
- AKANTU_FE_ENGINE_LIST_ASSEMBLE_FIELDS)
-
-#undef AKANTU_SPECIALIZE_ASSEMBLE_HELPER
-#undef AKANTU_SPECIALIZE_ASSEMBLE_HELPER_LIST_KIND
-#undef ASSEMBLE_LUMPED
- } // namespace details
-} // namespace fe_engine
-
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IOF>
void FEEngineTemplate<I, S, kind, IOF>::assembleFieldLumped(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
ElementType type, GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- fe_engine::details::AssembleLumpedTemplateHelper<kind>::call(
- *this, field_funct, matrix_id, dof_id, dof_manager, type, ghost_type);
-
- AKANTU_DEBUG_OUT();
+ tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->assembleFieldLumped<type>(field_funct, matrix_id, dof_id,
+ dof_manager, ghost_type);
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldLumped(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- UInt nb_degree_of_freedom = dof_manager.getDOFs(dof_id).getNbComponent();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- UInt nb_integration_points = this->getNbIntegrationPoints(type);
+ auto nb_degree_of_freedom = dof_manager.getDOFs(dof_id).getNbComponent();
+ auto nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_integration_points = this->getNbIntegrationPoints(type);
Array<Real> field(0, nb_degree_of_freedom);
fe_engine::details::fillField(field_funct, field, nb_element,
nb_integration_points, type, ghost_type);
switch (type) {
case _triangle_6:
case _quadrangle_8:
case _tetrahedron_10:
case _hexahedron_20:
case _pentahedron_15:
this->template assembleLumpedDiagonalScaling<type>(field, matrix_id, dof_id,
dof_manager, ghost_type);
break;
default:
this->template assembleLumpedRowSum<type>(field, matrix_id, dof_id,
dof_manager, ghost_type);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV =
* \int \rho \varphi_i dV @f$
*/
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
assembleLumpedRowSum(const Array<Real> & field, const ID & matrix_id,
const ID & dof_id, DOFManager & dof_manager,
GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- UInt shapes_size = ElementClass<type>::getShapeSize();
- UInt nb_degree_of_freedom = field.getNbComponent();
+ auto shapes_size = ElementClass<type>::getShapeSize();
+ auto nb_degree_of_freedom = field.getNbComponent();
- auto * field_times_shapes =
- new Array<Real>(0, shapes_size * nb_degree_of_freedom);
+ auto field_times_shapes =
+ std::make_shared<Array<Real>>(0, shapes_size * nb_degree_of_freedom);
shape_functions.template computeNtb<type>(field, *field_times_shapes,
ghost_type);
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- auto * int_field_times_shapes = new Array<Real>(
+ auto nb_element = mesh.getNbElement(type, ghost_type);
+ auto int_field_times_shapes = std::make_shared<Array<Real>>(
nb_element, shapes_size * nb_degree_of_freedom, "inte_rho_x_shapes");
integrator.template integrate<type>(
*field_times_shapes, *int_field_times_shapes,
nb_degree_of_freedom * shapes_size, ghost_type, empty_filter);
- delete field_times_shapes;
-
dof_manager.assembleElementalArrayToLumpedMatrix(
dof_id, *int_field_times_shapes, matrix_id, type, ghost_type);
-
- delete int_field_times_shapes;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$
*/
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
assembleLumpedDiagonalScaling(const Array<Real> & field,
const ID & matrix_id, const ID & dof_id,
DOFManager & dof_manager,
GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- ElementType type_p1 = ElementClass<type>::getP1ElementType();
- UInt nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(type_p1);
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_degree_of_freedom = field.getNbComponent();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ const auto & type_p1 = ElementClass<type>::getP1ElementType();
+ auto nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(type_p1);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_degree_of_freedom = field.getNbComponent();
+ auto nb_element = mesh.getNbElement(type, ghost_type);
Vector<Real> nodal_factor(nb_nodes_per_element);
-#define ASSIGN_WEIGHT_TO_NODES(corner, mid) \
- { \
- for (UInt n = 0; n < nb_nodes_per_element_p1; n++) \
- nodal_factor(n) = corner; \
- for (UInt n = nb_nodes_per_element_p1; n < nb_nodes_per_element; n++) \
- nodal_factor(n) = mid; \
- }
+ auto assign_weight_to_nodes = [&nodal_factor, nb_nodes_per_element,
+ nb_nodes_per_element_p1](Real corner,
+ Real mid) {
+ for (Int n = 0; n < nb_nodes_per_element_p1; n++) {
+ nodal_factor(n) = corner;
+ }
+ for (Int n = nb_nodes_per_element_p1; n < nb_nodes_per_element; n++) {
+ nodal_factor(n) = mid;
+ }
+ };
- if (type == _triangle_6)
- ASSIGN_WEIGHT_TO_NODES(1. / 12., 1. / 4.);
- if (type == _tetrahedron_10)
- ASSIGN_WEIGHT_TO_NODES(1. / 32., 7. / 48.);
- if (type == _quadrangle_8)
- ASSIGN_WEIGHT_TO_NODES(
+ if (type == _triangle_6) {
+ assign_weight_to_nodes(1. / 12., 1. / 4.);
+ }
+ if (type == _tetrahedron_10) {
+ assign_weight_to_nodes(1. / 32., 7. / 48.);
+ }
+ if (type == _quadrangle_8) {
+ assign_weight_to_nodes(
3. / 76.,
16. / 76.); /** coeff. derived by scaling
* the diagonal terms of the corresponding
* consistent mass computed with 3x3 gauss points;
* coeff. are (1./36., 8./36.) for 2x2 gauss points */
- if (type == _hexahedron_20)
- ASSIGN_WEIGHT_TO_NODES(
+ }
+ if (type == _hexahedron_20) {
+ assign_weight_to_nodes(
7. / 248., 16. / 248.); /** coeff. derived by scaling
* the diagonal terms of the corresponding
* consistent mass computed with 3x3x3 gauss
* points; coeff. are (1./40.,
* 1./15.) for 2x2x2 gauss points */
+ }
if (type == _pentahedron_15) {
// coefficients derived by scaling the diagonal terms of the corresponding
// consistent mass computed with 8 gauss points;
- for (UInt n = 0; n < nb_nodes_per_element_p1; n++) {
+ for (Int n = 0; n < nb_nodes_per_element_p1; n++) {
nodal_factor(n) = 51. / 2358.;
}
Real mid_triangle = 192. / 2358.;
Real mid_quadrangle = 300. / 2358.;
nodal_factor(6) = mid_triangle;
nodal_factor(7) = mid_triangle;
nodal_factor(8) = mid_triangle;
nodal_factor(9) = mid_quadrangle;
nodal_factor(10) = mid_quadrangle;
nodal_factor(11) = mid_quadrangle;
nodal_factor(12) = mid_triangle;
nodal_factor(13) = mid_triangle;
nodal_factor(14) = mid_triangle;
}
if (nb_element == 0) {
- AKANTU_DEBUG_OUT();
return;
}
-#undef ASSIGN_WEIGHT_TO_NODES
/// compute @f$ \int \rho dV = \rho V @f$ for each element
auto int_field = std::make_unique<Array<Real>>(
field.size(), nb_degree_of_freedom, "inte_rho_x");
integrator.template integrate<type>(field, *int_field, nb_degree_of_freedom,
ghost_type, empty_filter);
/// distribute the mass of the element to the nodes
auto lumped_per_node = std::make_unique<Array<Real>>(
nb_element, nb_degree_of_freedom * nb_nodes_per_element, "mass_per_node");
auto int_field_it = int_field->begin(nb_degree_of_freedom);
auto lumped_per_node_it =
lumped_per_node->begin(nb_degree_of_freedom, nb_nodes_per_element);
- for (UInt e = 0; e < nb_element; ++e) {
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- Vector<Real> l = (*lumped_per_node_it)(n);
- l = *int_field_it;
- l *= nodal_factor(n);
+ for (Int e = 0; e < nb_element; ++e) {
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
+ auto && l = (*lumped_per_node_it)(n);
+ l = *int_field_it * nodal_factor(n);
}
++int_field_it;
++lumped_per_node_it;
}
dof_manager.assembleElementalArrayToLumpedMatrix(dof_id, *lumped_per_node,
matrix_id, type, ghost_type);
-
- AKANTU_DEBUG_OUT();
}
-/* -------------------------------------------------------------------------- */
-/**
- * Helper class to be able to write a partial specialization on the element kind
- */
-namespace fe_engine {
- namespace details {
- template <ElementKind kind> struct AssembleFieldMatrixHelper {
- template <template <ElementKind, class> class I,
- template <ElementKind> class S, ElementKind k, class IOF>
- static void call(const FEEngineTemplate<I, S, k, IOF> & /*unused*/,
- const std::function<void(Matrix<Real> &,
- const Element &)> & /*unused*/,
- const ID & /*unused*/, const ID & /*unused*/,
- DOFManager & /*unused*/, ElementType /*unused*/,
- GhostType /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#define ASSEMBLE_MATRIX(type) \
- fem.template assembleFieldMatrix<type>(field_funct, matrix_id, dof_id, \
- dof_manager, ghost_type)
-
-#define AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER(kind) \
- template <> struct AssembleFieldMatrixHelper<kind> { \
- template <template <ElementKind, class> class I, \
- template <ElementKind> class S, ElementKind k, class IOF> \
- static void \
- call(const FEEngineTemplate<I, S, k, IOF> & fem, \
- const std::function<void(Matrix<Real> &, const Element &)> & \
- field_funct, \
- const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, \
- ElementType type, GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_MATRIX, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER,
- AKANTU_FE_ENGINE_LIST_ASSEMBLE_FIELDS)
-
-#undef AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER
-#undef ASSEMBLE_MATRIX
- } // namespace details
-} // namespace fe_engine
-
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IOF>
-void FEEngineTemplate<I, S, kind, IOF>::assembleFieldMatrix(
+template <ElementKind kind_, std::enable_if_t<kind_ != _ek_cohesive> *>
+void FEEngineTemplate<I, S, kind, IOF>::assembleFieldMatrixImpl(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
ElementType type, GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- fe_engine::details::AssembleFieldMatrixHelper<kind>::template call(
- *this, field_funct, matrix_id, dof_id, dof_manager, type, ghost_type);
+ tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->assembleFieldMatrix<type>(field_funct, matrix_id, dof_id,
+ dof_manager, ghost_type);
+ },
+ type);
+}
- AKANTU_DEBUG_OUT();
+template <template <ElementKind, class> class I, template <ElementKind> class S,
+ ElementKind kind, class IOF>
+template <ElementKind kind_, std::enable_if_t<kind_ == _ek_cohesive> *>
+void FEEngineTemplate<I, S, kind, IOF>::assembleFieldMatrixImpl(
+ const std::function<void(Matrix<Real> &,
+ const Element &)> & /*field_funct*/,
+ const ID & /*matrix_id*/, const ID & /*dof_id*/,
+ DOFManager & /*dof_manager*/, ElementType /*type*/,
+ GhostType /*ghost_type*/) const {
+ AKANTU_TO_IMPLEMENT();
}
namespace fe_engine {
namespace details {
template <ElementKind kind> struct ShapesForMassHelper {
template <ElementType type, class ShapeFunctions>
static auto getShapes(ShapeFunctions & shape_functions,
const Matrix<Real> & integration_points,
const Array<Real> & nodes,
- UInt & nb_degree_of_freedom, UInt nb_element,
+ Int & nb_degree_of_freedom, Int nb_element,
GhostType ghost_type) {
- UInt shapes_size = ElementClass<type>::getShapeSize();
+ auto shapes_size = ElementClass<type>::getShapeSize();
Array<Real> shapes(0, shapes_size);
shape_functions.template computeShapesOnIntegrationPoints<type>(
nodes, integration_points, shapes, ghost_type);
- UInt nb_integration_points = integration_points.cols();
- UInt vect_size = nb_integration_points * nb_element;
- UInt lmat_size = nb_degree_of_freedom * shapes_size;
+ auto nb_integration_points = integration_points.cols();
+ auto vect_size = nb_integration_points * nb_element;
+ auto lmat_size = nb_degree_of_freedom * shapes_size;
// Extending the shape functions
/// \todo move this in the shape functions as Voigt format shapes to
/// have the code in common with the structural elements
auto shapes_voigt = std::make_unique<Array<Real>>(
vect_size, lmat_size * nb_degree_of_freedom, 0.);
auto mshapes_it = shapes_voigt->begin(nb_degree_of_freedom, lmat_size);
auto shapes_it = shapes.begin(shapes_size);
- for (UInt q = 0; q < vect_size; ++q, ++mshapes_it, ++shapes_it) {
- for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
- for (UInt s = 0; s < shapes_size; ++s) {
+ for (Int q = 0; q < vect_size; ++q, ++mshapes_it, ++shapes_it) {
+ for (Int d = 0; d < nb_degree_of_freedom; ++d) {
+ for (Int s = 0; s < shapes_size; ++s) {
(*mshapes_it)(d, s * nb_degree_of_freedom + d) = (*shapes_it)(s);
}
}
}
return shapes_voigt;
}
};
#if defined(AKANTU_STRUCTURAL_MECHANICS)
template <> struct ShapesForMassHelper<_ek_structural> {
template <ElementType type, class ShapeFunctions>
static auto getShapes(ShapeFunctions & shape_functions,
const Matrix<Real> & integration_points,
const Array<Real> & nodes,
- UInt & nb_degree_of_freedom, UInt /*nb_element*/,
+ Int & nb_degree_of_freedom, Int /*nb_element*/,
GhostType ghost_type) {
+ static_assert(ElementClass<type>::getKind() == _ek_structural,
+ "getShapes for structural elements called with non "
+ "strutral element type");
auto nb_unknown = ElementClass<type>::getNbStressComponents();
auto nb_degree_of_freedom_ = ElementClass<type>::getNbDegreeOfFreedom();
auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
auto shapes = std::make_unique<Array<Real>>(
0, nb_unknown * nb_nodes_per_element * nb_degree_of_freedom_);
nb_degree_of_freedom = nb_unknown;
shape_functions.template computeShapesMassOnIntegrationPoints<type>(
nodes, integration_points, *shapes, ghost_type);
return shapes;
}
};
#endif
} // namespace details
} // namespace fe_engine
//
/* -------------------------------------------------------------------------- */
/**
* @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV =
* \int \rho \varphi_i dV @f$
*/
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix(
const std::function<void(Matrix<Real> &, const Element &)> & field_funct,
const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager,
GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
+ auto nb_degree_of_freedom = dof_manager.getDOFs(dof_id).getNbComponent();
+ auto nb_element = mesh.getNbElement(type, ghost_type);
// \int N * N so degree 2 * degree of N
- const UInt polynomial_degree =
+ const auto polynomial_degree =
2 * ElementClassProperty<type>::polynomial_degree;
// getting the integration points
- Matrix<Real> integration_points =
+ auto integration_points =
integrator.template getIntegrationPoints<type, polynomial_degree>();
- UInt nb_degree_of_freedom = dof_manager.getDOFs(dof_id).getNbComponent();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_integration_points = integration_points.cols();
+ auto vect_size = nb_integration_points * nb_element;
// getting the shapes on the integration points
auto shapes_voigt =
fe_engine::details::ShapesForMassHelper<kind>::template getShapes<type>(
shape_functions, integration_points, mesh.getNodes(),
nb_degree_of_freedom, nb_element, ghost_type);
- auto vect_size = shapes_voigt->size();
+ auto lmat_size = shapes_voigt->getNbComponent() / nb_degree_of_freedom;
// getting the value to assemble on the integration points
Array<Real> field(vect_size, nb_degree_of_freedom);
fe_engine::details::fillField(field_funct, field, nb_element,
integration_points.cols(), type, ghost_type);
- auto lmat_size = shapes_voigt->getNbComponent() / nb_degree_of_freedom;
-
- // computing \rho * N
Array<Real> local_mat(vect_size, lmat_size * lmat_size);
- auto N_it = shapes_voigt->begin(nb_degree_of_freedom, lmat_size);
- auto lmat_it = local_mat.begin(lmat_size, lmat_size);
- auto field_it = field.begin_reinterpret(nb_degree_of_freedom, field.size());
- for (UInt q = 0; q < vect_size; ++q, ++lmat_it, ++N_it, ++field_it) {
- const auto & rho = *field_it;
- const auto & N = *N_it;
- auto & mat = *lmat_it;
+ // computing \rho * N
+ for (auto && data :
+ zip(make_view(local_mat, lmat_size, lmat_size),
+ make_view(*shapes_voigt, nb_degree_of_freedom, lmat_size),
+ make_view(field, nb_degree_of_freedom))) {
+ const auto & rho = std::get<2>(data);
+ const auto & N = std::get<1>(data);
+ auto & mat = std::get<0>(data);
Matrix<Real> Nt = N.transpose();
- for (UInt d = 0; d < Nt.cols(); ++d) {
+ for (Int d = 0; d < Nt.cols(); ++d) {
Nt(d) *= rho(d);
}
- mat.template mul<false, false>(Nt, N);
+ mat = Nt * N;
}
// integrate the elemental values
Array<Real> int_field_times_shapes(nb_element, lmat_size * lmat_size,
"inte_rho_x_shapes");
this->integrator.template integrate<type, polynomial_degree>(
local_mat, int_field_times_shapes, lmat_size * lmat_size, ghost_type);
// assemble the elemental values to the matrix
dof_manager.assembleElementalMatricesToMatrix(
matrix_id, dof_id, int_field_times_shapes, type, ghost_type);
-
- AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif /* AKANTU_FE_ENGINE_TEMPLATE_TMPL_FIELD_HH_ */
diff --git a/src/fe_engine/fe_engine_template_tmpl_struct.hh b/src/fe_engine/fe_engine_template_tmpl_struct.hh
index 0ac7aa332..578e1e383 100644
--- a/src/fe_engine/fe_engine_template_tmpl_struct.hh
+++ b/src/fe_engine/fe_engine_template_tmpl_struct.hh
@@ -1,103 +1,74 @@
/**
* @file fe_engine_template_tmpl_struct.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jul 07 2014
* @date last modification: Tue Sep 29 2020
*
* @brief Template implementation of FEEngineTemplate for Structural Element
* Kinds
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "shape_structural.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <ElementKind kind, typename = void>
struct AssembleFieldMatrixStructHelper {};
template <ElementKind kind>
struct AssembleFieldMatrixStructHelper<
kind, typename std::enable_if<kind == _ek_structural>::type> {
template <template <ElementKind, class> class I,
template <ElementKind> class S, ElementKind k, class IOF>
static void call(const FEEngineTemplate<I, S, k, IOF> & fem,
- const Array<Real> & field_1, UInt nb_degree_of_freedom,
+ const Array<Real> & field_1, Int nb_degree_of_freedom,
SparseMatrix & M, Array<Real> * n,
ElementTypeMapArray<Real> & rotation_mat, ElementType type,
GhostType ghost_type) {
#define ASSEMBLE_MATRIX(type) \
fem.template assembleFieldMatrix<type>(field_1, nb_degree_of_freedom, M, n, \
rotation_mat, ghost_type)
AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_MATRIX, _ek_structural);
#undef ASSEMBLE_MATRIX
}
};
-// template <template <ElementKind, class> class I, template <ElementKind> class
-// S,
-// ElementKind kind, class IntegrationOrderFunctor>
-// inline void
-// FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix(
-// const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M,
-// Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat,
-// ElementType type, GhostType ghost_type) const {
-// AKANTU_DEBUG_IN();
-
-// AssembleFieldMatrixStructHelper<kind>::template call(
-// *this, field_1, nb_degree_of_freedom, M, n, rotation_mat, type,
-// ghost_type);
-
-// AKANTU_DEBUG_OUT();
-// }
-// /* --------------------------------------------------------------------------
-// */ template <template <ElementKind, class> class I, template <ElementKind>
-// class S,
-// ElementKind kind, class IntegrationOrderFunctor>
-// inline void
-// FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapesMatrix(
-// ElementType, UInt, UInt, Array<Real> *, UInt, UInt, UInt,
-// const bool, GhostType) const {
-
-// AKANTU_TO_IMPLEMENT();
-// }
-
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline void
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix(
- const Array<Real> & /*unused*/, UInt /*unused*/, SparseMatrix & /*unused*/,
- Array<Real> * /*unused*/, ElementTypeMapArray<Real> & /*unused*/,
- GhostType /*unused*/) const {
+ const Array<Real> &, Int, SparseMatrix &, Array<Real> *,
+ ElementTypeMapArray<Real> &, GhostType) const {
AKANTU_TO_IMPLEMENT();
}
} // namespace akantu
diff --git a/src/fe_engine/gauss_integration_tmpl.hh b/src/fe_engine/gauss_integration_tmpl.hh
index 5874b69f9..7e116502d 100644
--- a/src/fe_engine/gauss_integration_tmpl.hh
+++ b/src/fe_engine/gauss_integration_tmpl.hh
@@ -1,278 +1,288 @@
/**
* @file gauss_integration_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue May 10 2016
* @date last modification: Tue Sep 29 2020
*
* @brief implementation of the gauss integration helpers
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "aka_math.hh"
#ifndef AKANTU_GAUSS_INTEGRATION_TMPL_HH_
#define AKANTU_GAUSS_INTEGRATION_TMPL_HH_
+#include "element_class.hh"
+
namespace akantu {
/* -------------------------------------------------------------------------- */
/* GaussIntegrationElement */
/* -------------------------------------------------------------------------- */
namespace _aka_gauss_helpers {
- template <GaussIntegrationType type, UInt n> struct GaussIntegrationNbPoints {
- static const UInt nb_points = 0;
- };
+ template <GaussIntegrationType type, Int n>
+ struct GaussIntegrationNbPoints {};
-#if !defined(DOXYGEN)
- template <UInt n> struct GaussIntegrationNbPoints<_git_not_defined, n> {
- static const UInt nb_points = 0;
+ template <Int n> struct GaussIntegrationNbPoints<_git_not_defined, n> {
+ static constexpr Int nb_points = 0;
};
- template <UInt n> struct GaussIntegrationNbPoints<_git_point, n> {
- static const UInt nb_points = 1;
+ template <Int n> struct GaussIntegrationNbPoints<_git_point, n> {
+ static constexpr Int nb_points = 1;
};
- template <UInt n> struct GaussIntegrationNbPoints<_git_segment, n> {
- static const UInt nb_points = (n + 1) / 2 + (bool((n + 1) % 2) ? 1 : 0);
+ template <Int n> struct GaussIntegrationNbPoints<_git_segment, n> {
+ static constexpr Int nb_points = (n + 1) / 2 + (bool((n + 1) % 2) ? 1 : 0);
};
#define DECLARE_GAUSS_NB_POINTS(type, order, points) \
template <> struct GaussIntegrationNbPoints<type, order> { \
- static const UInt nb_points = points; \
+ static constexpr Int nb_points = points; \
}
#define DECLARE_GAUSS_NB_POINTS_PENT(type, order, xo, yo) \
template <> struct GaussIntegrationNbPoints<type, order> { \
- static const UInt x_order = xo; \
- static const UInt yz_order = yo; \
- static const UInt nb_points = 1; \
+ static constexpr Int x_order = xo; \
+ static constexpr Int yz_order = yo; \
+ static constexpr Int nb_points = 1; \
}
DECLARE_GAUSS_NB_POINTS(_git_triangle, 1, 1);
DECLARE_GAUSS_NB_POINTS(_git_triangle, 2, 3);
DECLARE_GAUSS_NB_POINTS(_git_triangle, 3, 4);
DECLARE_GAUSS_NB_POINTS(_git_triangle, 4, 6);
DECLARE_GAUSS_NB_POINTS(_git_triangle, 5, 7);
DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 1, 1);
DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 2, 4);
DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 3, 5);
DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 4, 15);
DECLARE_GAUSS_NB_POINTS(_git_tetrahedron, 5, 15);
DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 1, 3,
2); // order 3 in x, order 2 in y and z
DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 2, 3,
2); // order 3 in x, order 2 in y and z
DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 3, 3,
3); // order 3 in x, order 3 in y and z
DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 4, 5,
5); // order 5 in x, order 5 in y and z
DECLARE_GAUSS_NB_POINTS_PENT(_git_pentahedron, 5, 5,
5); // order 5 in x, order 5 in y and z
- template <GaussIntegrationType type, UInt n, UInt on = n,
+ template <GaussIntegrationType type, Int n, Int on = n,
bool end_recurse = false>
struct GaussIntegrationNbPointsHelper {
- static const UInt pnp = GaussIntegrationNbPoints<type, n>::nb_points;
- static const UInt order = n;
- static const UInt nb_points = pnp;
+ static constexpr Int pnp = GaussIntegrationNbPoints<type, n>::nb_points;
+ static constexpr Int order = n;
+ static constexpr Int nb_points = pnp;
};
- template <GaussIntegrationType type, UInt n, UInt on>
+ template <GaussIntegrationType type, Int n, Int on>
struct GaussIntegrationNbPointsHelper<type, n, on, true> {
- static const UInt nb_points = 0;
+ static constexpr Int nb_points = 0;
};
-#endif
/* ------------------------------------------------------------------------ */
/* Generic helper */
/* ------------------------------------------------------------------------ */
- template <GaussIntegrationType type, UInt dimension, UInt n>
+ template <GaussIntegrationType type, Int dimension, Int n>
struct GaussIntegrationTypeDataHelper {
using git_np = GaussIntegrationNbPoints<type, n>;
using git_data = GaussIntegrationTypeData<type, git_np::nb_points>;
- static UInt getNbQuadraturePoints() { return git_np::nb_points; }
+ static constexpr Int getNbQuadraturePoints() { return git_np::nb_points; }
- static Matrix<Real> getQuadraturePoints() {
- return Matrix<Real>(git_data::quad_positions, dimension,
- git_np::nb_points);
+ static constexpr auto getQuadraturePoints()
+ -> Matrix<Real, std::max(1, dimension),
+ GaussIntegrationTypeDataHelper::getNbQuadraturePoints()> {
+ constexpr auto nb_points = git_np::nb_points;
+ using Matrix = Eigen::Matrix<Real, std::max(1, dimension), nb_points>;
+ Matrix quads = Eigen::Map<const Matrix>(git_data::quad_positions);
+ return quads;
}
- static Vector<Real> getWeights() {
- return Vector<Real>(git_data::quad_weights, git_np::nb_points);
+ static constexpr auto getWeights()
+ -> Vector<Real,
+ GaussIntegrationTypeDataHelper::getNbQuadraturePoints()> {
+ constexpr auto nb_points = git_np::nb_points;
+ using Vector = Eigen::Matrix<Real, nb_points, 1>;
+ Vector weights = Eigen::Map<const Vector>(git_data::quad_weights);
+ return weights;
}
};
#if !defined(DOXYGEN)
/* ------------------------------------------------------------------------ */
/* helper for _segment _quadrangle _hexahedron */
/* ------------------------------------------------------------------------ */
- template <UInt dimension, UInt dp>
+ template <Int dimension, Int dp>
struct GaussIntegrationTypeDataHelper<_git_segment, dimension, dp> {
using git_np = GaussIntegrationNbPoints<_git_segment, dp>;
using git_data = GaussIntegrationTypeData<_git_segment, git_np::nb_points>;
- static UInt getNbQuadraturePoints() {
- return Math::pow<dimension>(git_np::nb_points);
+ static constexpr Int getNbQuadraturePoints() {
+ return Math::pow(git_np::nb_points, dimension);
}
- static Matrix<Real> getQuadraturePoints() {
- UInt tot_nquad = getNbQuadraturePoints();
- UInt nquad = git_np::nb_points;
+ static constexpr auto getQuadraturePoints()
+ -> Matrix<Real, dimension,
+ GaussIntegrationTypeDataHelper::getNbQuadraturePoints()> {
+ const auto tot_nquad = getNbQuadraturePoints();
+ const auto nquad = git_np::nb_points;
- Matrix<Real> quads(dimension, tot_nquad);
- Vector<Real> pos(git_data::quad_positions, nquad);
+ Eigen::Matrix<Real, dimension, tot_nquad> quads;
+ Eigen::Map<const Eigen::Matrix<Real, nquad, 1>> pos(
+ git_data::quad_positions);
- UInt offset = 1;
- for (UInt d = 0; d < dimension; ++d) {
- for (UInt n = 0, q = 0; n < tot_nquad; ++n, q += offset) {
- UInt rq = q % tot_nquad + q / tot_nquad;
+ Int offset = 1;
+ for (Int d = 0; d < dimension; ++d) {
+ for (Int n = 0, q = 0; n < tot_nquad; ++n, q += offset) {
+ Int rq = q % tot_nquad + q / tot_nquad;
quads(d, rq) = pos(n % nquad);
}
offset *= nquad;
}
return quads;
}
- static Vector<Real> getWeights() {
- UInt tot_nquad = getNbQuadraturePoints();
- UInt nquad = git_np::nb_points;
-
- Vector<Real> quads_weights(tot_nquad, 1.);
- Vector<Real> weights(git_data::quad_weights, nquad);
-
- UInt offset = 1;
- for (UInt d = 0; d < dimension; ++d) {
- for (UInt n = 0, q = 0; n < tot_nquad; ++n, q += offset) {
- UInt rq = q % tot_nquad + q / tot_nquad;
+ static constexpr Vector<
+ Real, GaussIntegrationTypeDataHelper::getNbQuadraturePoints()>
+ getWeights() {
+ const auto tot_nquad = getNbQuadraturePoints();
+ const auto nquad = git_np::nb_points;
+
+ Eigen::Matrix<Real, tot_nquad, 1> quads_weights;
+ quads_weights.fill(1);
+ Eigen::Map<const Eigen::Matrix<Real, nquad, 1>> weights(
+ git_data::quad_weights);
+
+ Int offset = 1;
+ for (Int d = 0; d < dimension; ++d) {
+ for (Int n = 0, q = 0; n < tot_nquad; ++n, q += offset) {
+ Int rq = q % tot_nquad + q / tot_nquad;
quads_weights(rq) *= weights(n % nquad);
}
offset *= nquad;
}
return quads_weights;
}
};
/* ------------------------------------------------------------------------ */
/* helper for _pentahedron */
/* ------------------------------------------------------------------------ */
- template <UInt dimension, UInt dp>
+ template <Int dimension, Int dp>
struct GaussIntegrationTypeDataHelper<_git_pentahedron, dimension, dp> {
using git_info = GaussIntegrationNbPoints<_git_pentahedron, dp>;
using git_np_seg =
GaussIntegrationNbPoints<_git_segment, git_info::x_order>;
using git_np_tri =
GaussIntegrationNbPoints<_git_triangle, git_info::yz_order>;
using git_data_seg =
GaussIntegrationTypeData<_git_segment, git_np_seg::nb_points>;
using git_data_tri =
GaussIntegrationTypeData<_git_triangle, git_np_tri::nb_points>;
- static UInt getNbQuadraturePoints() {
+ static constexpr Int getNbQuadraturePoints() {
return git_np_seg::nb_points * git_np_tri::nb_points;
}
- static Matrix<Real> getQuadraturePoints() {
- UInt tot_nquad = getNbQuadraturePoints();
- UInt nquad_seg = git_np_seg::nb_points;
- UInt nquad_tri = git_np_tri::nb_points;
-
- Matrix<Real> quads(dimension, tot_nquad);
- Matrix<Real> pos_seg_w(git_data_seg::quad_positions, 1, nquad_seg);
- Matrix<Real> pos_tri_w(git_data_tri::quad_positions, 2, nquad_tri);
-
- for (UInt ns = 0, q = 0; ns < nquad_seg; ++ns) {
- Vector<Real> pos_seg = pos_seg_w(ns);
- for (UInt nt = 0; nt < nquad_tri; ++nt, ++q) {
- Vector<Real> pos_tri = pos_tri_w(nt);
- Vector<Real> quad = quads(q);
- quad(_x) = pos_seg(_x);
- quad(_y) = pos_tri(_x);
- quad(_z) = pos_tri(_y);
+ static constexpr auto getQuadraturePoints()
+ -> Matrix<Real, dimension,
+ GaussIntegrationTypeDataHelper::getNbQuadraturePoints()> {
+ constexpr auto tot_nquad = getNbQuadraturePoints();
+ constexpr auto nquad_seg = git_np_seg::nb_points;
+ constexpr auto nquad_tri = git_np_tri::nb_points;
+
+ Matrix<Real, dimension, tot_nquad> quads;
+ Eigen::Map<Vector<Real, nquad_seg>> pos_seg(git_data_seg::quad_positions);
+ Eigen::Map<Matrix<Real, 2, nquad_tri>> pos_tri(
+ git_data_tri::quad_positions);
+
+ for (Int ns = 0, q = 0; ns < nquad_seg; ++ns) {
+ for (Int nt = 0; nt < nquad_tri; ++nt, ++q) {
+ auto && quad = quads(q);
+ quad(_x) = pos_seg(ns);
+ quad(_y) = pos_tri(_x, nt);
+ quad(_z) = pos_tri(_y, nt);
}
}
return quads;
}
- static Vector<Real> getWeights() {
- UInt tot_nquad = getNbQuadraturePoints();
- UInt nquad_seg = git_np_seg::nb_points;
- UInt nquad_tri = git_np_tri::nb_points;
-
- Vector<Real> quads_weights(tot_nquad);
-
- Vector<Real> weight_seg(git_data_seg::quad_weights, nquad_seg);
- Vector<Real> weight_tri(git_data_tri::quad_weights, nquad_tri);
-
- for (UInt ns = 0, q = 0; ns < nquad_seg; ++ns) {
- for (UInt nt = 0; nt < nquad_tri; ++nt, ++q) {
+ static constexpr auto getWeights()
+ -> Vector<Real,
+ GaussIntegrationTypeDataHelper::getNbQuadraturePoints()> {
+ constexpr auto tot_nquad = getNbQuadraturePoints();
+ constexpr auto nquad_seg = git_np_seg::nb_points;
+ constexpr auto nquad_tri = git_np_tri::nb_points;
+
+ Vector<Real, tot_nquad> quads_weights;
+ Eigen::Map<const Vector<Real, nquad_seg>> weight_seg(
+ git_data_seg::quad_weights);
+ Eigen::Map<const Vector<Real, nquad_tri>> weight_tri(
+ git_data_tri::quad_weights);
+
+ for (Int ns = 0, q = 0; ns < nquad_seg; ++ns) {
+ for (Int nt = 0; nt < nquad_tri; ++nt, ++q) {
quads_weights(q) = weight_seg(ns) * weight_tri(nt);
}
}
return quads_weights;
}
};
#endif
} // namespace _aka_gauss_helpers
-template <ElementType element_type, UInt n>
-Matrix<Real> GaussIntegrationElement<element_type, n>::getQuadraturePoints() {
- const InterpolationType itp_type =
- ElementClassProperty<element_type>::interpolation_type;
- using interpolation_property = InterpolationProperty<itp_type>;
+/* -------------------------------------------------------------------------- */
+template <ElementType element_type, Int n>
+constexpr Int
+GaussIntegrationElement<element_type, n>::getNbQuadraturePoints() {
using data_helper = _aka_gauss_helpers::GaussIntegrationTypeDataHelper<
ElementClassProperty<element_type>::gauss_integration_type,
interpolation_property::natural_space_dimension, n>;
- Matrix<Real> tmp(data_helper::getQuadraturePoints());
- return tmp;
+ return data_helper::getNbQuadraturePoints();
}
/* -------------------------------------------------------------------------- */
-template <ElementType element_type, UInt n>
-Vector<Real> GaussIntegrationElement<element_type, n>::getWeights() {
- const InterpolationType itp_type =
- ElementClassProperty<element_type>::interpolation_type;
- using interpolation_property = InterpolationProperty<itp_type>;
+template <ElementType element_type, Int n>
+constexpr auto GaussIntegrationElement<element_type, n>::getWeights() {
using data_helper = _aka_gauss_helpers::GaussIntegrationTypeDataHelper<
ElementClassProperty<element_type>::gauss_integration_type,
interpolation_property::natural_space_dimension, n>;
- Vector<Real> tmp(data_helper::getWeights());
- return tmp;
+ return data_helper::getWeights();
}
-/* -------------------------------------------------------------------------- */
-template <ElementType element_type, UInt n>
-UInt GaussIntegrationElement<element_type, n>::getNbQuadraturePoints() {
- const InterpolationType itp_type =
- ElementClassProperty<element_type>::interpolation_type;
- using interpolation_property = InterpolationProperty<itp_type>;
+template <ElementType type, Int n>
+constexpr auto GaussIntegrationElement<type, n>::getQuadraturePoints() {
using data_helper = _aka_gauss_helpers::GaussIntegrationTypeDataHelper<
- ElementClassProperty<element_type>::gauss_integration_type,
+ ElementClassProperty<type>::gauss_integration_type,
interpolation_property::natural_space_dimension, n>;
- return data_helper::getNbQuadraturePoints();
+ return data_helper::getQuadraturePoints();
}
} // namespace akantu
#endif /* AKANTU_GAUSS_INTEGRATION_TMPL_HH_ */
diff --git a/src/fe_engine/geometrical_element_property.cc b/src/fe_engine/geometrical_element_property.cc
index 3a279cad3..f1faeb14a 100644
--- a/src/fe_engine/geometrical_element_property.cc
+++ b/src/fe_engine/geometrical_element_property.cc
@@ -1,63 +1,63 @@
/**
* @file geometrical_element_property.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 29 2017
* @date last modification: Thu Feb 20 2020
*
* @brief Specialization of the geometrical types
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
#include <boost/preprocessor.hpp>
/* -------------------------------------------------------------------------- */
namespace akantu {
#define AKANTU_INSTANTIATE_TYPES(r, data, type) \
- constexpr std::array<UInt, ElementClass<type>::getNbFacetTypes()> \
+ constexpr std::array<Int, ElementClass<type>::getNbFacetTypes()> \
GeometricalElementProperty< \
ElementClassProperty<type>::geometrical_type>::nb_facets; \
- constexpr std::array<UInt, ElementClass<type>::getNbFacetTypes()> \
+ constexpr std::array<Int, ElementClass<type>::getNbFacetTypes()> \
GeometricalElementProperty< \
ElementClassProperty<type>::geometrical_type>::nb_nodes_per_facet; \
constexpr std::array< \
- UInt, detail::sizeFacetConnectivity<GeometricalElementProperty< \
- ElementClassProperty<type>::geometrical_type>>()> \
+ Int, detail::sizeFacetConnectivity<GeometricalElementProperty< \
+ ElementClassProperty<type>::geometrical_type>>()> \
GeometricalElementProperty<ElementClassProperty< \
type>::geometrical_type>::facet_connectivity_vect; \
constexpr std::array<ElementType, ElementClass<type>::getNbFacetTypes()> \
ElementClassExtraGeometryProperties<type>::facet_type;
BOOST_PP_SEQ_FOR_EACH(AKANTU_INSTANTIATE_TYPES, _,
(_not_defined)AKANTU_ek_regular_ELEMENT_TYPE)
#if defined(AKANTU_COHESIVE_ELEMENT)
BOOST_PP_SEQ_FOR_EACH(AKANTU_INSTANTIATE_TYPES, _,
AKANTU_ek_cohesive_ELEMENT_TYPE)
#endif
} // namespace akantu
diff --git a/src/fe_engine/geometrical_element_property.hh b/src/fe_engine/geometrical_element_property.hh
index aea6ef7f6..ad2821f16 100644
--- a/src/fe_engine/geometrical_element_property.hh
+++ b/src/fe_engine/geometrical_element_property.hh
@@ -1,481 +1,481 @@
/**
* @file geometrical_element_property.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Thomas Menouillard <tmenouillard@stucky.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 29 2017
* @date last modification: Thu Feb 20 2020
*
* @brief Specialization of the geometrical types
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "element_class.hh"
+//#include "element_class.hh"
/* -------------------------------------------------------------------------- */
#include <array>
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace detail {
template <typename properties> constexpr size_t sizeFacetConnectivity() {
size_t s = 0;
for (size_t n = 0; n < properties::nb_facet_types; ++n) {
s += properties::nb_facets[n] * properties::nb_nodes_per_facet[n];
}
return s == 0 ? 1 : s;
}
} // namespace detail
#if !defined(DOXYGEN)
template <> struct GeometricalElementProperty<_gt_not_defined> {
- static constexpr UInt spatial_dimension{0};
- static constexpr UInt nb_nodes_per_element{0};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{0}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{0}};
- static constexpr std::array<UInt, 1> facet_connectivity_vect{{0}};
+ static constexpr Int spatial_dimension{0};
+ static constexpr Int nb_nodes_per_element{0};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{0}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{0}};
+ static constexpr std::array<Int, 1> facet_connectivity_vect{{0}};
};
template <> struct GeometricalElementProperty<_gt_point> {
- static constexpr UInt spatial_dimension{0};
- static constexpr UInt nb_nodes_per_element{1};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{1}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{1}};
- static constexpr std::array<UInt, 1> facet_connectivity_vect{{0}};
+ static constexpr Int spatial_dimension{0};
+ static constexpr Int nb_nodes_per_element{1};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{1}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{1}};
+ static constexpr std::array<Int, 1> facet_connectivity_vect{{0}};
};
template <> struct GeometricalElementProperty<_gt_segment_2> {
- static constexpr UInt spatial_dimension{1};
- static constexpr UInt nb_nodes_per_element{2};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{1}};
- static constexpr std::array<UInt, 2> facet_connectivity_vect{{0, 1}};
+ static constexpr Int spatial_dimension{1};
+ static constexpr Int nb_nodes_per_element{2};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{1}};
+ static constexpr std::array<Int, 2> facet_connectivity_vect{{0, 1}};
};
template <> struct GeometricalElementProperty<_gt_segment_3> {
- static constexpr UInt spatial_dimension{1};
- static constexpr UInt nb_nodes_per_element{3};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{1}};
+ static constexpr Int spatial_dimension{1};
+ static constexpr Int nb_nodes_per_element{3};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{1}};
// clang-format off
- static constexpr std::array<UInt, 2> facet_connectivity_vect{{0, 1}};
+ static constexpr std::array<Int, 2> facet_connectivity_vect{{0, 1}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_triangle_3> {
- static constexpr UInt spatial_dimension{2};
- static constexpr UInt nb_nodes_per_element{3};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{3}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{2}};
+ static constexpr Int spatial_dimension{2};
+ static constexpr Int nb_nodes_per_element{3};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{3}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{2}};
// clang-format off
- static constexpr std::array<UInt, 6> facet_connectivity_vect{{
+ static constexpr std::array<Int, 6> facet_connectivity_vect{{
0, 1, 2,
1, 2, 0}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_triangle_6> {
- static constexpr UInt spatial_dimension{2};
- static constexpr UInt nb_nodes_per_element{6};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{3}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{3}};
+ static constexpr Int spatial_dimension{2};
+ static constexpr Int nb_nodes_per_element{6};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{3}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{3}};
// clang-format off
- static constexpr std::array<UInt, 9> facet_connectivity_vect{{
+ static constexpr std::array<Int, 9> facet_connectivity_vect{{
0, 1, 2,
1, 2, 0,
3, 4, 5}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_tetrahedron_4> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{4};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{4}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{3}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{4};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{4}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{3}};
// clang-format off
- static constexpr std::array<UInt, 12> facet_connectivity_vect{{
+ static constexpr std::array<Int, 12> facet_connectivity_vect{{
0, 1, 2, 0,
2, 2, 0, 1,
1, 3, 3, 3}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_tetrahedron_10> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{10};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{4}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{6}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{10};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{4}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{6}};
// clang-format off
- static constexpr std::array<UInt, 6*4> facet_connectivity_vect{{
+ static constexpr std::array<Int, 6*4> facet_connectivity_vect{{
0, 1, 2, 0,
2, 2, 0, 1,
1, 3, 3, 3,
6, 5, 6, 4,
5, 9, 7, 8,
4, 8, 9, 7}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_quadrangle_4> {
- static constexpr UInt spatial_dimension{2};
- static constexpr UInt nb_nodes_per_element{4};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{4}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{2}};
+ static constexpr Int spatial_dimension{2};
+ static constexpr Int nb_nodes_per_element{4};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{4}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{2}};
// clang-format off
- static constexpr std::array<UInt, 2*4> facet_connectivity_vect{{
+ static constexpr std::array<Int, 2*4> facet_connectivity_vect{{
0, 1, 2, 3,
1, 2, 3, 0}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_quadrangle_8> {
- static constexpr UInt spatial_dimension{2};
- static constexpr UInt nb_nodes_per_element{8};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{4}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{3}};
+ static constexpr Int spatial_dimension{2};
+ static constexpr Int nb_nodes_per_element{8};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{4}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{3}};
// clang-format off
- static constexpr std::array<UInt, 4*3> facet_connectivity_vect{{
+ static constexpr std::array<Int, 4*3> facet_connectivity_vect{{
0, 1, 2, 3,
1, 2, 3, 0,
4, 5, 6, 7}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_hexahedron_8> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{8};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{6}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{4}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{8};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{6}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{4}};
// clang-format off
- static constexpr std::array<UInt, 4*6> facet_connectivity_vect{{
+ static constexpr std::array<Int, 4*6> facet_connectivity_vect{{
0, 0, 1, 2, 3, 4,
3, 1, 2, 3, 0, 5,
2, 5, 6, 7, 4, 6,
1, 4, 5, 6, 7, 7}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_hexahedron_20> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{20};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{6}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{8}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{20};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{6}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{8}};
// clang-format off
- static constexpr std::array<UInt, 8*6> facet_connectivity_vect{{
+ static constexpr std::array<Int, 8*6> facet_connectivity_vect{{
0, 1, 2, 3, 0, 4,
1, 2, 3, 0, 3, 5,
5, 6, 7, 4, 2, 6,
4, 5, 6, 7, 1, 7,
8, 9, 10, 11, 11, 16,
13, 14, 15, 12, 10, 17,
16, 17, 18, 19, 9, 18,
12, 13, 14, 15, 8, 19}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_pentahedron_6> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{6};
- static constexpr UInt nb_facet_types{2};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2, 3}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{3, 4}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{6};
+ static constexpr Int nb_facet_types{2};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2, 3}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{3, 4}};
// clang-format off
- static constexpr std::array<UInt, 3*2 + 4*3> facet_connectivity_vect{{
+ static constexpr std::array<Int, 3*2 + 4*3> facet_connectivity_vect{{
// first type
0, 3,
2, 4,
1, 5,
// second type
0, 0, 1,
1, 3, 2,
4, 5, 5,
3, 2, 4}};
// clang-format on
};
template <> struct GeometricalElementProperty<_gt_pentahedron_15> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{15};
- static constexpr UInt nb_facet_types{2};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2, 3}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{6, 8}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{15};
+ static constexpr Int nb_facet_types{2};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2, 3}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{6, 8}};
// clang-format off
- static constexpr std::array<UInt, 6*2 + 8*3> facet_connectivity_vect{{
+ static constexpr std::array<Int, 6*2 + 8*3> facet_connectivity_vect{{
// first type
0, 3,
2, 4,
1, 5,
8, 12,
7, 13,
6, 14,
// second type
0, 0, 1,
1, 3, 2,
4, 5, 5,
3, 2, 4,
6, 9, 7,
10, 14, 11,
12, 11, 13,
9, 8, 10}};
// clang-format on
};
#if defined(AKANTU_COHESIVE_ELEMENT)
/* -------------------------------------------------------------------------- */
template <> struct GeometricalElementProperty<_gt_cohesive_2d_4> {
- static constexpr UInt spatial_dimension{2};
- static constexpr UInt nb_nodes_per_element{4};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{2}};
+ static constexpr Int spatial_dimension{2};
+ static constexpr Int nb_nodes_per_element{4};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{2}};
// clang-format off
- static constexpr std::array<UInt, 2 * 2> facet_connectivity_vect{{
+ static constexpr std::array<Int, 2 * 2> facet_connectivity_vect{{
0, 2,
1, 3}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
template <> struct GeometricalElementProperty<_gt_cohesive_2d_6> {
- static constexpr UInt spatial_dimension{2};
- static constexpr UInt nb_nodes_per_element{6};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{3}};
+ static constexpr Int spatial_dimension{2};
+ static constexpr Int nb_nodes_per_element{6};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{3}};
// clang-format off
- static constexpr std::array<UInt, 3*2> facet_connectivity_vect{{
+ static constexpr std::array<Int, 3*2> facet_connectivity_vect{{
0, 3,
1, 4,
2, 5}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
template <> struct GeometricalElementProperty<_gt_cohesive_1d_2> {
- static constexpr UInt spatial_dimension{1};
- static constexpr UInt nb_nodes_per_element{2};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{1}};
+ static constexpr Int spatial_dimension{1};
+ static constexpr Int nb_nodes_per_element{2};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{1}};
// clang-format off
- static constexpr std::array<UInt, 2> facet_connectivity_vect{{0, 1}};
+ static constexpr std::array<Int, 2> facet_connectivity_vect{{0, 1}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
template <> struct GeometricalElementProperty<_gt_cohesive_3d_6> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{6};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{3}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{6};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{3}};
// clang-format off
- static constexpr std::array<UInt, 3*2> facet_connectivity_vect{{
+ static constexpr std::array<Int, 3*2> facet_connectivity_vect{{
0, 3,
1, 4,
2, 5}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
template <> struct GeometricalElementProperty<_gt_cohesive_3d_12> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{12};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{6}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{12};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{6}};
// clang-format off
- static constexpr std::array<UInt, 6*2> facet_connectivity_vect{{
+ static constexpr std::array<Int, 6*2> facet_connectivity_vect{{
0, 6,
1, 7,
2, 8,
3, 9,
4, 10,
5, 11}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
template <> struct GeometricalElementProperty<_gt_cohesive_3d_8> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{8};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{4}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{8};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{4}};
// clang-format off
- static constexpr std::array<UInt, 4*2> facet_connectivity_vect{{
+ static constexpr std::array<Int, 4*2> facet_connectivity_vect{{
0, 4,
1, 5,
2, 6,
3, 7}};
// clang-format on
};
/* -------------------------------------------------------------------------- */
template <> struct GeometricalElementProperty<_gt_cohesive_3d_16> {
- static constexpr UInt spatial_dimension{3};
- static constexpr UInt nb_nodes_per_element{16};
- static constexpr UInt nb_facet_types{1};
- static constexpr std::array<UInt, nb_facet_types> nb_facets{{2}};
- static constexpr std::array<UInt, nb_facet_types> nb_nodes_per_facet{{8}};
+ static constexpr Int spatial_dimension{3};
+ static constexpr Int nb_nodes_per_element{16};
+ static constexpr Int nb_facet_types{1};
+ static constexpr std::array<Int, nb_facet_types> nb_facets{{2}};
+ static constexpr std::array<Int, nb_facet_types> nb_nodes_per_facet{{8}};
// clang-format off
- static constexpr std::array<UInt, 8*2> facet_connectivity_vect{{
+ static constexpr std::array<Int, 8*2> facet_connectivity_vect{{
0, 8,
1, 9,
2, 10,
3, 11,
4, 12,
5, 13,
6, 14,
7, 15}};
// clang-format on
};
#endif // AKANTU_COHESIVE_ELEMENT
/* -------------------------------------------------------------------------- */
template <> struct ElementClassExtraGeometryProperties<_not_defined> {
static constexpr ElementType p1_type{_not_defined};
static constexpr std::array<ElementType, 1> facet_type{{_not_defined}};
};
template <> struct ElementClassExtraGeometryProperties<_point_1> {
static constexpr ElementType p1_type{_point_1};
static constexpr std::array<ElementType, 1> facet_type{{_point_1}};
};
template <> struct ElementClassExtraGeometryProperties<_segment_2> {
static constexpr ElementType p1_type{_segment_2};
static constexpr std::array<ElementType, 1> facet_type{{_point_1}};
};
template <> struct ElementClassExtraGeometryProperties<_segment_3> {
static constexpr ElementType p1_type{_segment_2};
static constexpr std::array<ElementType, 1> facet_type{{_point_1}};
};
template <> struct ElementClassExtraGeometryProperties<_triangle_3> {
static constexpr ElementType p1_type{_triangle_3};
static constexpr std::array<ElementType, 1> facet_type{{_segment_2}};
};
template <> struct ElementClassExtraGeometryProperties<_triangle_6> {
static constexpr ElementType p1_type{_triangle_3};
static constexpr std::array<ElementType, 1> facet_type{{_segment_3}};
};
template <> struct ElementClassExtraGeometryProperties<_tetrahedron_4> {
static constexpr ElementType p1_type{_tetrahedron_4};
static constexpr std::array<ElementType, 1> facet_type{{_triangle_3}};
};
template <> struct ElementClassExtraGeometryProperties<_tetrahedron_10> {
static constexpr ElementType p1_type{_tetrahedron_4};
static constexpr std::array<ElementType, 1> facet_type{{_triangle_6}};
};
template <> struct ElementClassExtraGeometryProperties<_quadrangle_4> {
static constexpr ElementType p1_type{_quadrangle_4};
static constexpr std::array<ElementType, 1> facet_type{{_segment_2}};
};
template <> struct ElementClassExtraGeometryProperties<_quadrangle_8> {
static constexpr ElementType p1_type{_quadrangle_4};
static constexpr std::array<ElementType, 1> facet_type{{_segment_3}};
};
template <> struct ElementClassExtraGeometryProperties<_hexahedron_8> {
static constexpr ElementType p1_type{_hexahedron_8};
static constexpr std::array<ElementType, 1> facet_type{{_quadrangle_4}};
};
template <> struct ElementClassExtraGeometryProperties<_hexahedron_20> {
static constexpr ElementType p1_type{_hexahedron_8};
static constexpr std::array<ElementType, 1> facet_type{{_quadrangle_8}};
};
template <> struct ElementClassExtraGeometryProperties<_pentahedron_6> {
static constexpr ElementType p1_type{_pentahedron_6};
static constexpr std::array<ElementType, 2> facet_type{
{_triangle_3, _quadrangle_4}};
};
template <> struct ElementClassExtraGeometryProperties<_pentahedron_15> {
static constexpr ElementType p1_type{_pentahedron_6};
static constexpr std::array<ElementType, 2> facet_type{
{_triangle_6, _quadrangle_8}};
};
#if defined(AKANTU_COHESIVE_ELEMENT)
template <> struct ElementClassExtraGeometryProperties<_cohesive_2d_4> {
static constexpr ElementType p1_type{_cohesive_2d_4};
static constexpr std::array<ElementType, 1> facet_type{{_segment_2}};
};
template <> struct ElementClassExtraGeometryProperties<_cohesive_2d_6> {
static constexpr ElementType p1_type{_cohesive_2d_4};
static constexpr std::array<ElementType, 1> facet_type{{_segment_3}};
};
template <> struct ElementClassExtraGeometryProperties<_cohesive_1d_2> {
static constexpr ElementType p1_type{_cohesive_1d_2};
static constexpr std::array<ElementType, 1> facet_type{{_point_1}};
};
template <> struct ElementClassExtraGeometryProperties<_cohesive_3d_6> {
static constexpr ElementType p1_type{_cohesive_3d_6};
static constexpr std::array<ElementType, 1> facet_type{{_triangle_3}};
};
template <> struct ElementClassExtraGeometryProperties<_cohesive_3d_12> {
static constexpr ElementType p1_type{_cohesive_3d_6};
static constexpr std::array<ElementType, 1> facet_type{{_triangle_6}};
};
template <> struct ElementClassExtraGeometryProperties<_cohesive_3d_8> {
static constexpr ElementType p1_type{_cohesive_3d_8};
static constexpr std::array<ElementType, 1> facet_type{{_quadrangle_4}};
};
template <> struct ElementClassExtraGeometryProperties<_cohesive_3d_16> {
static constexpr ElementType p1_type{_cohesive_3d_8};
static constexpr std::array<ElementType, 1> facet_type{{_quadrangle_8}};
};
#endif // AKANTU_COHESIVE_ELEMENT
#endif // !defined(DOXYGEN)
} // namespace akantu
diff --git a/src/fe_engine/integration_point.hh b/src/fe_engine/integration_point.hh
index 5e82c2e69..d48a08760 100644
--- a/src/fe_engine/integration_point.hh
+++ b/src/fe_engine/integration_point.hh
@@ -1,172 +1,121 @@
/**
* @file integration_point.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Jun 17 2015
* @date last modification: Tue Sep 29 2020
*
* @brief definition of the class IntegrationPoint
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_types.hh"
#include "element.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_QUADRATURE_POINT_H
#define AKANTU_QUADRATURE_POINT_H
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
class IntegrationPoint;
extern const IntegrationPoint IntegrationPointNull;
/* -------------------------------------------------------------------------- */
class IntegrationPoint : public Element {
-
- /* ------------------------------------------------------------------------ */
- /* Typedefs */
- /* ------------------------------------------------------------------------ */
-
-public:
- using position_type = Vector<Real>;
-
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
-
public:
- IntegrationPoint(const Element & element, UInt num_point = 0,
- UInt nb_quad_per_element = 0)
+ IntegrationPoint(const Element & element = ElementNull, Int num_point = 0,
+ Int nb_quad_per_element = 0)
: Element(element), num_point(num_point),
- global_num(element.element * nb_quad_per_element + num_point),
- position(nullptr, 0){};
-
- IntegrationPoint(ElementType type = _not_defined, UInt element = 0,
- UInt num_point = 0, GhostType ghost_type = _not_ghost)
- : Element{type, element, ghost_type}, num_point(num_point),
- position(nullptr, 0){};
-
- IntegrationPoint(UInt element, UInt num_point, UInt global_num,
- const position_type & position, ElementType type,
- GhostType ghost_type = _not_ghost)
- : Element{type, element, ghost_type}, num_point(num_point),
- global_num(global_num), position(nullptr, 0) {
- this->position.shallowCopy(position);
- };
-
- IntegrationPoint(const IntegrationPoint & quad)
- : Element(quad), num_point(quad.num_point), global_num(quad.global_num),
- position(nullptr, 0) {
- position.shallowCopy(quad.position);
- };
-
- virtual ~IntegrationPoint() = default;
+ global_num(element.element * nb_quad_per_element + num_point) {}
+
+ constexpr IntegrationPoint(const IntegrationPoint & quad) = default;
+ constexpr IntegrationPoint(IntegrationPoint && quad) = default;
+
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
-
- inline bool operator==(const IntegrationPoint & quad) const {
+public:
+ inline auto operator==(const IntegrationPoint & quad) const -> bool {
return Element::operator==(quad) && this->num_point == quad.num_point;
}
- inline bool operator!=(const IntegrationPoint & quad) const {
+ inline auto operator!=(const IntegrationPoint & quad) const -> bool {
return Element::operator!=(quad) || (num_point != quad.num_point) ||
(global_num != quad.global_num);
}
- bool operator<(const IntegrationPoint & rhs) const {
+ auto operator<(const IntegrationPoint & rhs) const -> bool {
bool res = Element::operator<(rhs) ||
(Element::operator==(rhs) && this->num_point < rhs.num_point);
return res;
}
- inline IntegrationPoint & operator=(const IntegrationPoint & q) {
- if (this != &q) {
- element = q.element;
- type = q.type;
- ghost_type = q.ghost_type;
- num_point = q.num_point;
- global_num = q.global_num;
- position.shallowCopy(q.position);
- }
-
- return *this;
- }
-
- /// get the position of the integration point
- AKANTU_GET_MACRO(Position, position, const position_type &);
-
- /// set the position of the integration point
- void setPosition(const position_type & position) {
- this->position.shallowCopy(position);
- }
-
- /// deep copy of the position of the integration point
- void copyPosition(const position_type & position) {
- this->position.deepCopy(position);
- }
-
- /// function to print the containt of the class
- virtual void printself(std::ostream & stream, int indent = 0) const {
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
- stream << space << "IntegrationPoint [";
- stream << *static_cast<const Element *>(this);
- stream << ", " << num_point << "(" << global_num << ")"
- << "]";
- }
+ inline auto operator=(const IntegrationPoint & q)
+ -> IntegrationPoint & = default;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
public:
/// number of quadrature point in the element
- UInt num_point;
+ Int num_point{0};
/// global number of the quadrature point
- UInt global_num{0};
- // TODO might be temporary: however this class should be tought maybe...
- std::string material_id;
-
-private:
- /// position of the quadrature point
- position_type position;
+ Int global_num{0};
};
+} // namespace akantu
+
+namespace std {
+inline auto to_string(const akantu::IntegrationPoint & _this) -> string {
+ if (static_cast<const akantu::Element &>(_this) == akantu::ElementNull) {
+ return "IntegrationPoint[ElementNull]";
+ }
+
+ string str = "IntegrationPoint[ " +
+ to_string(static_cast<const akantu::Element &>(_this)) + ", " +
+ to_string(_this.num_point) + ": " + to_string(_this.global_num) +
+ "]";
+ return str;
+}
+} // namespace std
+
+namespace akantu {
+
/// standard output stream operator
-inline std::ostream & operator<<(std::ostream & stream,
- const IntegrationPoint & _this) {
- _this.printself(stream);
+inline auto operator<<(std::ostream & stream, const IntegrationPoint & _this)
+ -> std::ostream & {
+ stream << std::to_string(_this);
return stream;
}
-
} // namespace akantu
#endif /* AKANTU_QUADRATURE_POINT_H */
diff --git a/src/fe_engine/integrator.hh b/src/fe_engine/integrator.hh
index 123acf8d3..df5c59b90 100644
--- a/src/fe_engine/integrator.hh
+++ b/src/fe_engine/integrator.hh
@@ -1,138 +1,134 @@
/**
* @file integrator.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief interface for integrator classes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_INTEGRATOR_HH_
#define AKANTU_INTEGRATOR_HH_
/* -------------------------------------------------------------------------- */
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class Integrator {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- Integrator(const Mesh & mesh, UInt spatial_dimension,
+ Integrator(const Mesh & mesh, Int spatial_dimension,
const ID & id = "integrator")
: mesh(mesh), _spatial_dimension(spatial_dimension),
jacobians("jacobians", id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
};
virtual ~Integrator() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// empty method
template <ElementType type>
- inline void precomputeJacobiansOnQuadraturePoints(__attribute__((unused))
- GhostType ghost_type) {}
+ inline void precomputeJacobiansOnQuadraturePoints(GhostType /*ghost_type*/) {}
/// empty method
void integrateOnElement(const Array<Real> & /*f*/, Real * /*intf*/,
- UInt /*nb_degree_of_freedom*/,
+ Int /*nb_degree_of_freedom*/,
const Element & /*elem*/,
GhostType /*ghost_type*/) const {};
/// function to print the contain of the class
virtual void printself(std::ostream & stream, int indent = 0) const {
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(indent, AKANTU_INDENT);
stream << space << "Integrator [" << std::endl;
jacobians.printself(stream, indent + 1);
stream << space << "]" << std::endl;
};
/* ------------------------------------------------------------------------ */
public:
virtual void onElementsAdded(const Array<Element> & /*unused*/) {}
virtual void
- onElementsRemoved(const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & new_numbering) {
+ onElementsRemoved(const Array<Element> & /*removed_elements*/,
+ const ElementTypeMapArray<Idx> & new_numbering) {
jacobians.onElementsRemoved(new_numbering);
}
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// access to the jacobians
Array<Real> & getJacobians(ElementType type,
GhostType ghost_type = _not_ghost) {
return jacobians(type, ghost_type);
};
/// access to the jacobians const
const Array<Real> & getJacobians(ElementType type,
GhostType ghost_type = _not_ghost) const {
return jacobians(type, ghost_type);
};
AKANTU_GET_MACRO(Jacobians, jacobians, const ElementTypeMapArray<Real> &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// mesh associated to the integrator
const Mesh & mesh;
// spatial dimension of the elements to consider
- UInt _spatial_dimension;
+ Int _spatial_dimension;
/// jacobians for all elements
ElementTypeMapArray<Real> jacobians;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
//#include "integrator_inline_impl.hh"
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const Integrator & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#endif /* AKANTU_INTEGRATOR_HH_ */
diff --git a/src/fe_engine/integrator_gauss.hh b/src/fe_engine/integrator_gauss.hh
index 7dfe4745c..a63ecbec5 100644
--- a/src/fe_engine/integrator_gauss.hh
+++ b/src/fe_engine/integrator_gauss.hh
@@ -1,201 +1,208 @@
/**
* @file integrator_gauss.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief Gauss integration facilities
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "integrator.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_INTEGRATOR_GAUSS_HH_
#define AKANTU_INTEGRATOR_GAUSS_HH_
namespace akantu {
namespace integrator {
namespace details {
template <ElementKind> struct GaussIntegratorComputeJacobiansHelper;
} // namespace details
} // namespace integrator
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
class IntegratorGauss : public Integrator {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- IntegratorGauss(const Mesh & mesh, UInt spatial_dimension,
+ IntegratorGauss(const Mesh & mesh, Int spatial_dimension,
const ID & id = "integrator_gauss");
~IntegratorGauss() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initIntegrator(const Array<Real> & nodes, ElementType type,
GhostType ghost_type);
template <ElementType type>
inline void initIntegrator(const Array<Real> & nodes, GhostType ghost_type);
/// integrate f on the element "elem" of type "type"
template <ElementType type>
inline void integrateOnElement(const Array<Real> & f, Real * intf,
- UInt nb_degree_of_freedom, UInt elem,
+ Int nb_degree_of_freedom, const Idx elem,
GhostType ghost_type) const;
/// integrate f for all elements of type "type"
template <ElementType type>
void integrate(const Array<Real> & in_f, Array<Real> & intf,
- UInt nb_degree_of_freedom, GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ Int nb_degree_of_freedom, GhostType ghost_type,
+ const Array<Idx> & filter_elements) const;
/// integrate scalar field in_f
- template <ElementType type, UInt polynomial_degree>
+ template <ElementType type, Int polynomial_degree>
Real integrate(const Array<Real> & in_f,
GhostType ghost_type = _not_ghost) const;
/// integrate partially around a quadrature point (@f$ intf_q = f_q * J_q *
/// w_q @f$)
template <ElementType type>
- Real integrate(const Vector<Real> & in_f, UInt index,
+ Real integrate(const Vector<Real> & in_f, Idx index,
GhostType ghost_type) const;
/// integrate scalar field in_f
template <ElementType type>
Real integrate(const Array<Real> & in_f, GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ const Array<Idx> & filter_elements) const;
/// integrate a field without using the pre-computed values
- template <ElementType type, UInt polynomial_degree>
+ template <ElementType type, Int polynomial_degree>
void integrate(const Array<Real> & in_f, Array<Real> & intf,
- UInt nb_degree_of_freedom, GhostType ghost_type) const;
+ Int nb_degree_of_freedom, GhostType ghost_type) const;
/// integrate partially around a quadrature point (@f$ intf_q = f_q * J_q *
/// w_q @f$)
template <ElementType type>
void
integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf,
- UInt nb_degree_of_freedom, GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ Int nb_degree_of_freedom, GhostType ghost_type,
+ const Array<Idx> & filter_elements) const;
/// return a matrix with quadrature points natural coordinates
template <ElementType type>
const Matrix<Real> & getIntegrationPoints(GhostType ghost_type) const;
/// return number of quadrature points
template <ElementType type>
- UInt getNbIntegrationPoints(GhostType ghost_type) const;
+ Int getNbIntegrationPoints(GhostType ghost_type) const;
- template <ElementType type, UInt n> Matrix<Real> getIntegrationPoints() const;
- template <ElementType type, UInt n>
- Vector<Real> getIntegrationWeights() const;
+ template <ElementType type, Int n> Matrix<Real> getIntegrationPoints() const;
+ template <ElementType type, Int n> Vector<Real> getIntegrationWeights() const;
protected:
friend struct integrator::details::GaussIntegratorComputeJacobiansHelper<
kind>;
template <ElementType type>
void computeJacobiansOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & quad_points,
Array<Real> & jacobians, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
void computeJacobiansOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & quad_points,
Array<Real> & jacobians, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// precompute jacobians on elements of type "type"
template <ElementType type>
void precomputeJacobiansOnQuadraturePoints(const Array<Real> & nodes,
GhostType ghost_type);
// multiply the jacobians by the integration weights and stores the results in
// jacobians
- template <ElementType type, UInt polynomial_degree>
+ template <ElementType type, Int polynomial_degree>
void multiplyJacobiansByWeights(
Array<Real> & jacobians,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// compute the vector of quadrature points natural coordinates
template <ElementType type>
void computeQuadraturePoints(GhostType ghost_type);
/// check that the jacobians are not negative
template <ElementType type> void checkJacobians(GhostType ghost_type) const;
/// internal integrate partially around a quadrature point (@f$ intf_q = f_q *
/// J_q *
/// w_q @f$)
void integrateOnIntegrationPoints(const Array<Real> & in_f,
Array<Real> & intf,
- UInt nb_degree_of_freedom,
+ Int nb_degree_of_freedom,
const Array<Real> & jacobians,
- UInt nb_element) const;
+ Int nb_element) const;
void integrate(const Array<Real> & in_f, Array<Real> & intf,
- UInt nb_degree_of_freedom, const Array<Real> & jacobians,
- UInt nb_element) const;
+ Int nb_degree_of_freedom, const Array<Real> & jacobians,
+ Int nb_element) const;
public:
/// compute the jacobians on quad points for a given element
- template <ElementType type>
- void computeJacobianOnQuadPointsByElement(const Matrix<Real> & node_coords,
- const Matrix<Real> & quad,
- Vector<Real> & jacobians) const;
+ template <ElementType type, class D1, class D2, class D3>
+ inline void computeJacobianOnQuadPointsByElement(
+ const Eigen::MatrixBase<D1> & node_coords,
+ const Eigen::MatrixBase<D2> & quad,
+ Eigen::MatrixBase<D3> & jacobians) const;
public:
void onElementsAdded(const Array<Element> & elements) override;
+protected:
template <ElementType type>
- void onElementsAddedByType(const Array<UInt> & new_elements,
+ void onElementsAddedByType(const Array<Idx> & new_elements,
GhostType ghost_type);
+ decltype(auto) getIntegrationPoints() { return (quadrature_points); }
+
+ template <template <ElementKind, class> class, template <ElementKind> class,
+ ElementKind, class>
+ friend class FEEngineTemplate;
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// integrate the field f with the jacobian jac -> inte
- inline void integrate(Real * f, Real * jac, Real * inte,
- UInt nb_degree_of_freedom,
- UInt nb_quadrature_points) const;
+ inline void integrate(const Real * f, const Real * jac, Real * inte,
+ Int nb_degree_of_freedom,
+ Int nb_quadrature_points) const;
private:
/// ElementTypeMap of the quadrature points
ElementTypeMap<Matrix<Real>> quadrature_points;
};
} // namespace akantu
#include "integrator_gauss_inline_impl.hh"
#endif /* AKANTU_INTEGRATOR_GAUSS_HH_ */
diff --git a/src/fe_engine/integrator_gauss_inline_impl.hh b/src/fe_engine/integrator_gauss_inline_impl.hh
index dc3787092..cea0c630a 100644
--- a/src/fe_engine/integrator_gauss_inline_impl.hh
+++ b/src/fe_engine/integrator_gauss_inline_impl.hh
@@ -1,765 +1,637 @@
/**
* @file integrator_gauss_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Feb 15 2011
* @date last modification: Tue Oct 27 2020
*
* @brief inline function of gauss integrator
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "mesh_iterators.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace debug {
struct IntegratorGaussException : public Exception {};
} // namespace debug
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::integrateOnElement(
- const Array<Real> & f, Real * intf, UInt nb_degree_of_freedom,
- const UInt elem, GhostType ghost_type) const {
- Array<Real> & jac_loc = jacobians(type, ghost_type);
+ const Array<Real> & f, Real * intf, Int nb_degree_of_freedom,
+ const Idx elem, GhostType ghost_type) const {
+ auto & jac_loc = jacobians(type, ghost_type);
- UInt nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints();
+ auto nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints();
AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom,
"The vector f do not have the good number of component.");
- Real * f_val = f.storage() + elem * f.getNbComponent();
- Real * jac_val = jac_loc.storage() + elem * nb_quadrature_points;
+ auto * f_val = f.data() + elem * f.getNbComponent();
+ auto * jac_val = jac_loc.data() + elem * nb_quadrature_points;
integrate(f_val, jac_val, intf, nb_degree_of_freedom, nb_quadrature_points);
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline Real IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
- const Vector<Real> & in_f, UInt index, GhostType ghost_type) const {
+ const Vector<Real> & in_f, Idx index, GhostType ghost_type) const {
const Array<Real> & jac_loc = jacobians(type, ghost_type);
- UInt nb_quadrature_points =
+ auto nb_quadrature_points =
GaussIntegrationElement<type>::getNbQuadraturePoints();
AKANTU_DEBUG_ASSERT(in_f.size() == nb_quadrature_points,
"The vector f do not have nb_quadrature_points entries.");
- Real * jac_val = jac_loc.storage() + index * nb_quadrature_points;
+ auto * jac_val = jac_loc.data() + index * nb_quadrature_points;
Real intf;
- integrate(in_f.storage(), jac_val, &intf, 1, nb_quadrature_points);
+ integrate(in_f.data(), jac_val, &intf, 1, nb_quadrature_points);
return intf;
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
- Real * f, Real * jac, Real * inte, UInt nb_degree_of_freedom,
- UInt nb_quadrature_points) const {
- std::fill_n(inte, nb_degree_of_freedom, 0.);
-
- Real * cjac = jac;
- for (UInt q = 0; q < nb_quadrature_points; ++q) {
- for (UInt dof = 0; dof < nb_degree_of_freedom; ++dof) {
- inte[dof] += *f * *cjac;
- ++f;
- }
- ++cjac;
- }
+ const Real * f, const Real * jac, Real * inte, Int nb_degree_of_freedom,
+ Int nb_quadrature_points) const {
+ Eigen::Map<VectorXr> inte_v(inte, nb_quadrature_points);
+ Eigen::Map<const VectorXr> cjac(jac, nb_quadrature_points);
+
+ Eigen::Map<const MatrixXr> fq(f, nb_degree_of_freedom, nb_quadrature_points);
+
+ inte_v.zero();
+ inte_v = fq * cjac;
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline const Matrix<Real> &
IntegratorGauss<kind, IntegrationOrderFunctor>::getIntegrationPoints(
GhostType ghost_type) const {
AKANTU_DEBUG_ASSERT(
quadrature_points.exists(type, ghost_type),
"Quadrature points for type "
<< quadrature_points.printType(type, ghost_type)
<< " have not been initialized."
<< " Did you use 'computeQuadraturePoints' function ?");
- return quadrature_points(type, ghost_type);
+ return (quadrature_points(type, ghost_type));
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
-inline UInt
+inline Int
IntegratorGauss<kind, IntegrationOrderFunctor>::getNbIntegrationPoints(
GhostType ghost_type) const {
AKANTU_DEBUG_ASSERT(
quadrature_points.exists(type, ghost_type),
"Quadrature points for type "
<< quadrature_points.printType(type, ghost_type)
<< " have not been initialized."
<< " Did you use 'computeQuadraturePoints' function ?");
return quadrature_points(type, ghost_type).cols();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
-template <ElementType type, UInt polynomial_degree>
+template <ElementType type, Int polynomial_degree>
inline Matrix<Real>
IntegratorGauss<kind, IntegrationOrderFunctor>::getIntegrationPoints() const {
return GaussIntegrationElement<type,
polynomial_degree>::getQuadraturePoints();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
-template <ElementType type, UInt polynomial_degree>
+template <ElementType type, Int polynomial_degree>
inline Vector<Real>
IntegratorGauss<kind, IntegrationOrderFunctor>::getIntegrationWeights() const {
return GaussIntegrationElement<type, polynomial_degree>::getWeights();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline void
IntegratorGauss<kind, IntegrationOrderFunctor>::computeQuadraturePoints(
GhostType ghost_type) {
- Matrix<Real> & quads = quadrature_points(type, ghost_type);
- const UInt polynomial_degree =
+ auto & quads = quadrature_points(type, ghost_type);
+ constexpr auto polynomial_degree =
IntegrationOrderFunctor::template getOrder<type>();
quads =
GaussIntegrationElement<type, polynomial_degree>::getQuadraturePoints();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
-template <ElementType type>
+template <ElementType type, class D1, class D2, class D3>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::
- computeJacobianOnQuadPointsByElement(const Matrix<Real> & node_coords,
- const Matrix<Real> & quad,
- Vector<Real> & jacobians) const {
+ computeJacobianOnQuadPointsByElement(
+ const Eigen::MatrixBase<D1> & node_coords,
+ const Eigen::MatrixBase<D2> & quad,
+ Eigen::MatrixBase<D3> & jacobians) const {
// jacobian
ElementClass<type>::computeJacobian(quad, node_coords, jacobians);
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
IntegratorGauss<kind, IntegrationOrderFunctor>::IntegratorGauss(
- const Mesh & mesh, UInt spatial_dimension, const ID & id)
- : Integrator(mesh, spatial_dimension, id) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
-}
+ const Mesh & mesh, Int spatial_dimension, const ID & id)
+ : Integrator(mesh, spatial_dimension, id) {}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::checkJacobians(
GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- UInt nb_quadrature_points = this->quadrature_points(type, ghost_type).cols();
-
- UInt nb_element = mesh.getConnectivity(type, ghost_type).size();
-
- Real * jacobians_val = jacobians(type, ghost_type).storage();
+ auto nb_quadrature_points = this->quadrature_points(type, ghost_type).cols();
+ auto nb_element = mesh.getConnectivity(type, ghost_type).size();
+ auto * jacobians_val = jacobians(type, ghost_type).data();
- for (UInt i = 0; i < nb_element * nb_quadrature_points;
- ++i, ++jacobians_val) {
+ for (Idx i = 0; i < nb_element * nb_quadrature_points; ++i, ++jacobians_val) {
if (*jacobians_val < 0) {
AKANTU_CUSTOM_EXCEPTION_INFO(debug::IntegratorGaussException{},
"Negative jacobian computed,"
<< " possible problem in the element "
"node ordering (Quadrature Point "
<< i % nb_quadrature_points << ":"
<< i / nb_quadrature_points << ":"
<< type << ":" << ghost_type << ")");
}
}
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::
computeJacobiansOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & quad_points,
Array<Real> & jacobians, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
- AKANTU_DEBUG_IN();
+ const Array<Idx> & filter_elements) const {
+ auto spatial_dimension = mesh.getSpatialDimension();
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_quadrature_points = quad_points.cols();
+ auto nb_element = mesh.getNbElement(type, ghost_type);
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_quadrature_points = quad_points.cols();
-
- UInt nb_element = mesh.getNbElement(type, ghost_type);
jacobians.resize(nb_element * nb_quadrature_points);
- auto jacobians_it =
- jacobians.begin_reinterpret(nb_quadrature_points, nb_element);
+ auto jacobians_it = make_view(jacobians, nb_quadrature_points).begin();
auto jacobians_begin = jacobians_it;
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type,
filter_elements);
- auto x_it = x_el.begin(spatial_dimension, nb_nodes_per_element);
+ auto x_it = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin();
nb_element = x_el.size();
// Matrix<Real> local_coord(spatial_dimension, nb_nodes_per_element);
- for (UInt elem = 0; elem < nb_element; ++elem, ++x_it) {
- const Matrix<Real> & x = *x_it;
-
+ for (Idx elem = 0; elem < nb_element; ++elem, ++x_it) {
+ const auto & x = *x_it;
if (filter_elements != empty_filter) {
jacobians_it = jacobians_begin + filter_elements(elem);
}
- Vector<Real> & J = *jacobians_it;
- computeJacobianOnQuadPointsByElement<type>(x, quad_points, J);
+ computeJacobianOnQuadPointsByElement<type>(x, quad_points, *jacobians_it);
if (filter_elements == empty_filter) {
++jacobians_it;
}
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_STRUCTURAL_MECHANICS)
template <>
template <ElementType type>
void IntegratorGauss<_ek_structural, DefaultIntegrationOrderFunctor>::
computeJacobiansOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & quad_points,
Array<Real> & jacobians, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
- AKANTU_DEBUG_IN();
-
- const UInt spatial_dimension = mesh.getSpatialDimension();
- const UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- const UInt nb_quadrature_points = quad_points.cols();
- const UInt nb_dofs = ElementClass<type>::getNbDegreeOfFreedom();
+ const Array<Int> & filter_elements) const {
+ const auto spatial_dimension = mesh.getSpatialDimension();
+ const auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ const auto nb_quadrature_points = quad_points.cols();
+ const auto nb_dofs = ElementClass<type>::getNbDegreeOfFreedom();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
jacobians.resize(nb_element * nb_quadrature_points);
- auto jacobians_it =
- jacobians.begin_reinterpret(nb_quadrature_points, nb_element);
+ auto jacobians_it = make_view(jacobians, nb_quadrature_points).begin();
auto jacobians_begin = jacobians_it;
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type,
filter_elements);
- auto x_it = x_el.begin(spatial_dimension, nb_nodes_per_element);
+ auto x_it = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin();
nb_element = x_el.size();
- const bool has_extra_normal =
+ Array<Real> zeros(nb_element, spatial_dimension, 0.);
+
+ const auto has_extra_normal =
mesh.hasData<Real>("extra_normal", type, ghost_type);
- Array<Real>::const_vector_iterator extra_normal;
- Array<Real>::const_vector_iterator extra_normal_begin;
+ auto extra_normal_begin = make_const_view(zeros, spatial_dimension).begin();
+
if (has_extra_normal) {
- extra_normal = mesh.getData<Real>("extra_normal", type, ghost_type)
- .begin(spatial_dimension);
- extra_normal_begin = extra_normal;
+ extra_normal_begin =
+ make_const_view(mesh.getData<Real>("extra_normal", type, ghost_type),
+ spatial_dimension)
+ .begin();
}
+ auto extra_normal = extra_normal_begin;
+
// Matrix<Real> local_coord(spatial_dimension, nb_nodes_per_element);
- for (UInt elem = 0; elem < nb_element; ++elem, ++x_it) {
+ for (Idx elem = 0; elem < nb_element; ++elem, ++x_it) {
if (filter_elements != empty_filter) {
jacobians_it = jacobians_begin + filter_elements(elem);
- extra_normal = extra_normal_begin + filter_elements(elem);
+ if (has_extra_normal) {
+ extra_normal = extra_normal_begin + filter_elements(elem);
+ }
}
- const Matrix<Real> & X = *x_it;
- Vector<Real> & J = *jacobians_it;
- Matrix<Real> R(nb_dofs, nb_dofs);
+ const auto & X = *x_it;
+ auto & J = *jacobians_it;
+ Matrix<Real, nb_dofs, nb_dofs> R;
- if (has_extra_normal) {
- ElementClass<type>::computeRotationMatrix(R, X, *extra_normal);
- } else {
- ElementClass<type>::computeRotationMatrix(R, X, Vector<Real>(X.rows()));
- }
+ ElementClass<type>::computeRotationMatrix(R, X, *extra_normal);
+
+ const Int natural_space = ElementClass<type>::getNaturalSpaceDimension();
+ const Int nb_nodes = ElementClass<type>::getNbNodesPerElement();
// Extracting relevant lines
- auto x = (R.block(0, 0, spatial_dimension, spatial_dimension) * X)
- .block(0, 0, ElementClass<type>::getNaturalSpaceDimension(),
- ElementClass<type>::getNbNodesPerElement());
+
+ Matrix<Real> RX = R.block(0, 0, spatial_dimension, spatial_dimension) * X;
+
+ auto x = RX.template block<natural_space, nb_nodes>(0, 0);
computeJacobianOnQuadPointsByElement<type>(x, quad_points, J);
if (filter_elements == empty_filter) {
++jacobians_it;
- ++extra_normal;
+ if (has_extra_normal) {
+ ++extra_normal;
+ }
}
}
-
- AKANTU_DEBUG_OUT();
}
#endif
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_COHESIVE_ELEMENT)
template <>
template <ElementType type>
void IntegratorGauss<_ek_cohesive, DefaultIntegrationOrderFunctor>::
computeJacobiansOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & quad_points,
Array<Real> & jacobians, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
- AKANTU_DEBUG_IN();
+ const Array<Int> & filter_elements) const {
+ auto spatial_dimension = mesh.getSpatialDimension();
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_quadrature_points = quad_points.cols();
+ auto nb_element = mesh.getNbElement(type, ghost_type);
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_quadrature_points = quad_points.cols();
-
- UInt nb_element = mesh.getNbElement(type, ghost_type);
jacobians.resize(nb_element * nb_quadrature_points);
- auto jacobians_begin =
- jacobians.begin_reinterpret(nb_quadrature_points, nb_element);
+ auto jacobians_begin = make_view(jacobians, nb_quadrature_points).begin();
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type,
filter_elements);
- auto x_it = x_el.begin(spatial_dimension, nb_nodes_per_element);
+ auto x_it = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin();
- UInt nb_nodes_per_subelement = nb_nodes_per_element / 2;
+ auto nb_nodes_per_subelement = nb_nodes_per_element / 2;
Matrix<Real> x(spatial_dimension, nb_nodes_per_subelement);
nb_element = x_el.size();
- UInt l_el = 0;
+ Idx l_el = 0;
+
auto compute = [&](const auto & el) {
- Vector<Real> J(jacobians_begin[el]);
- Matrix<Real> X(x_it[l_el]);
+ auto && J = jacobians_begin[el];
+ auto && X = x_it[l_el];
++l_el;
- for (UInt n = 0; n < nb_nodes_per_subelement; ++n) {
- Vector<Real>(x(n)) =
- (Vector<Real>(X(n)) + Vector<Real>(X(n + nb_nodes_per_subelement))) /
- 2.;
- }
+ for (Int n = 0; n < nb_nodes_per_subelement; ++n)
+ x(n) = (X(n) + X(n + nb_nodes_per_subelement)) / 2.;
if (type == _cohesive_1d_2) {
J(0) = 1;
} else {
this->computeJacobianOnQuadPointsByElement<type>(x, quad_points, J);
}
};
for_each_element(nb_element, filter_elements, compute);
-
- AKANTU_DEBUG_OUT();
}
#endif
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::
precomputeJacobiansOnQuadraturePoints(const Array<Real> & nodes,
GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- Array<Real> & jacobians_tmp = jacobians.alloc(0, 1, type, ghost_type);
+ auto & jacobians_tmp = jacobians.alloc(0, 1, type, ghost_type);
this->computeJacobiansOnIntegrationPoints<type>(
nodes, quadrature_points(type, ghost_type), jacobians_tmp, ghost_type);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
-template <ElementType type, UInt polynomial_degree>
+template <ElementType type, Int polynomial_degree>
void IntegratorGauss<kind, IntegrationOrderFunctor>::multiplyJacobiansByWeights(
- Array<Real> & jacobians, const Array<UInt> & filter_elements) const {
- AKANTU_DEBUG_IN();
-
- UInt nb_quadrature_points =
+ Array<Real> & jacobians, const Array<Int> & filter_elements) const {
+ constexpr auto nb_quadrature_points =
GaussIntegrationElement<type, polynomial_degree>::getNbQuadraturePoints();
-
- Vector<Real> weights =
+ auto && weights =
GaussIntegrationElement<type, polynomial_degree>::getWeights();
- auto && view = make_view(jacobians, nb_quadrature_points);
+ auto && view = make_view<nb_quadrature_points>(jacobians);
if (filter_elements != empty_filter) {
- auto J_it = view.begin();
- for (auto el : filter_elements) {
- Vector<Real> J(J_it[el]);
- J *= weights;
- }
+ for (auto && J : filter(filter_elements, view))
+ J.array() *= weights.array();
} else {
- for (auto & J : make_view(jacobians, nb_quadrature_points)) {
- J *= weights;
- }
+ for (auto && J : view)
+ J.array() *= weights.array();
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
- const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom,
- const Array<Real> & jacobians, UInt nb_element) const {
- AKANTU_DEBUG_IN();
-
+ const Array<Real> & in_f, Array<Real> & intf, Int nb_degree_of_freedom,
+ const Array<Real> & jacobians, Int nb_element) const {
intf.resize(nb_element);
if (nb_element == 0) {
return;
}
- UInt nb_points = jacobians.size() / nb_element;
-
- Array<Real>::const_matrix_iterator J_it;
- Array<Real>::matrix_iterator inte_it;
- Array<Real>::const_matrix_iterator f_it;
+ auto nb_points = jacobians.size() / nb_element;
- f_it = in_f.begin_reinterpret(nb_degree_of_freedom, nb_points, nb_element);
- inte_it = intf.begin_reinterpret(nb_degree_of_freedom, 1, nb_element);
- J_it = jacobians.begin_reinterpret(nb_points, 1, nb_element);
+ for (auto && data : zip(make_view(in_f, nb_degree_of_freedom, nb_points),
+ make_view(intf, nb_degree_of_freedom),
+ make_view(jacobians, nb_points))) {
+ auto && f = std::get<0>(data);
+ auto && int_f = std::get<1>(data);
+ auto && J = std::get<2>(data);
- for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) {
- const Matrix<Real> & f = *f_it;
- const Matrix<Real> & J = *J_it;
- Matrix<Real> & inte_f = *inte_it;
-
- inte_f.mul<false, false>(f, J);
+ int_f = f * J;
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
- const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
- AKANTU_DEBUG_IN();
-
+ const Array<Real> & in_f, Array<Real> & intf, Int nb_degree_of_freedom,
+ GhostType ghost_type, const Array<Int> & filter_elements) const {
AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
"No jacobians for the type "
<< jacobians.printType(type, ghost_type));
- const Array<Real> & jac_loc = jacobians(type, ghost_type);
+ const auto & jac_loc = jacobians(type, ghost_type);
if (filter_elements != empty_filter) {
- UInt nb_element = filter_elements.size();
- auto * filtered_J = new Array<Real>(0, jac_loc.getNbComponent());
- FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type,
+ auto nb_element = filter_elements.size();
+ Array<Real> filtered_J(0, jac_loc.getNbComponent());
+ FEEngine::filterElementalData(mesh, jac_loc, filtered_J, type, ghost_type,
filter_elements);
- this->integrate(in_f, intf, nb_degree_of_freedom, *filtered_J, nb_element);
- delete filtered_J;
+ this->integrate(in_f, intf, nb_degree_of_freedom, filtered_J, nb_element);
} else {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
this->integrate(in_f, intf, nb_degree_of_freedom, jac_loc, nb_element);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
-template <ElementType type, UInt polynomial_degree>
+template <ElementType type, Int polynomial_degree>
void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
- const Array<Real> & in_f, Array<Real> & intf, UInt nb_degree_of_freedom,
+ const Array<Real> & in_f, Array<Real> & intf, Int nb_degree_of_freedom,
GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
- Matrix<Real> quads = this->getIntegrationPoints<type, polynomial_degree>();
+ auto quads = this->getIntegrationPoints<type, polynomial_degree>();
Array<Real> jacobians;
this->computeJacobiansOnIntegrationPoints<type>(mesh.getNodes(), quads,
jacobians, ghost_type);
this->multiplyJacobiansByWeights<type, polynomial_degree>(jacobians);
this->integrate(in_f, intf, nb_degree_of_freedom, jacobians,
mesh.getNbElement(type, ghost_type));
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
-template <ElementType type, UInt polynomial_degree>
+template <ElementType type, Int polynomial_degree>
Real IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
const Array<Real> & in_f, GhostType ghost_type) const {
- AKANTU_DEBUG_IN();
-
Array<Real> intfv(0, 1);
integrate<type, polynomial_degree>(in_f, intfv, 1, ghost_type);
- Real res = Math::reduce(intfv);
-
- AKANTU_DEBUG_OUT();
+ auto res = Math::reduce(intfv);
return res;
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
Real IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
const Array<Real> & in_f, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
- AKANTU_DEBUG_IN();
-
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
"No jacobians for the type "
<< jacobians.printType(type, ghost_type));
Array<Real> intfv(0, 1);
integrate<type>(in_f, intfv, 1, ghost_type, filter_elements);
- Real res = Math::reduce(intfv);
-
- AKANTU_DEBUG_OUT();
+ auto res = Math::reduce(intfv);
return res;
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
void IntegratorGauss<kind, IntegrationOrderFunctor>::
integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf,
- UInt nb_degree_of_freedom,
+ Int nb_degree_of_freedom,
const Array<Real> & jacobians,
- UInt nb_element) const {
- AKANTU_DEBUG_IN();
-
- UInt nb_points = jacobians.size() / nb_element;
+ Int nb_element) const {
+ auto nb_points = jacobians.size() / nb_element;
intf.resize(nb_element * nb_points);
auto J_it = jacobians.begin();
auto f_it = in_f.begin(nb_degree_of_freedom);
auto inte_it = intf.begin(nb_degree_of_freedom);
- for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) {
- const Real & J = *J_it;
- const Vector<Real> & f = *f_it;
- Vector<Real> & inte_f = *inte_it;
+ for (Idx el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) {
+ const auto & J = *J_it;
+ const auto & f = *f_it;
+ auto & inte_f = *inte_it;
inte_f = f;
inte_f *= J;
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::
integrateOnIntegrationPoints(const Array<Real> & in_f, Array<Real> & intf,
- UInt nb_degree_of_freedom,
- GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
- AKANTU_DEBUG_IN();
-
+ Int nb_degree_of_freedom, GhostType ghost_type,
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
"No jacobians for the type "
<< jacobians.printType(type, ghost_type));
- const Array<Real> & jac_loc = this->jacobians(type, ghost_type);
+ const auto & jac_loc = this->jacobians(type, ghost_type);
if (filter_elements != empty_filter) {
- UInt nb_element = filter_elements.size();
- auto * filtered_J = new Array<Real>(0, jac_loc.getNbComponent());
+ auto nb_element = filter_elements.size();
+ auto filtered_J =
+ std::make_shared<Array<Real>>(0, jac_loc.getNbComponent());
FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type,
filter_elements);
this->integrateOnIntegrationPoints(in_f, intf, nb_degree_of_freedom,
*filtered_J, nb_element);
} else {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
this->integrateOnIntegrationPoints(in_f, intf, nb_degree_of_freedom,
jac_loc, nb_element);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline void
IntegratorGauss<kind, IntegrationOrderFunctor>::onElementsAddedByType(
- const Array<UInt> & elements, GhostType ghost_type) {
+ const Array<Idx> & elements, GhostType ghost_type) {
const auto & nodes = mesh.getNodes();
- if (not quadrature_points.exists(type, ghost_type)) {
- computeQuadraturePoints<type>(ghost_type);
- }
+ computeQuadraturePoints<type>(ghost_type);
if (not jacobians.exists(type, ghost_type)) {
jacobians.alloc(0, 1, type, ghost_type);
}
this->computeJacobiansOnIntegrationPoints(
nodes, quadrature_points(type, ghost_type), jacobians(type, ghost_type),
type, ghost_type, elements);
- constexpr UInt polynomial_degree =
+ constexpr auto polynomial_degree =
IntegrationOrderFunctor::template getOrder<type>();
- multiplyJacobiansByWeights<type, polynomial_degree>(
+ this->multiplyJacobiansByWeights<type, polynomial_degree>(
this->jacobians(type, ghost_type), elements);
}
-/* -------------------------------------------------------------------------- */
-namespace integrator {
- namespace details {
- template <ElementKind kind> struct IntegratorOnElementsAddedHelper {};
-
-#define ON_ELEMENT_ADDED(type) \
- integrator.template onElementsAddedByType<type>(elements, ghost_type);
-
-#define AKANTU_SPECIALIZE_ON_ELEMENT_ADDED_HELPER(kind) \
- template <> struct IntegratorOnElementsAddedHelper<kind> { \
- template <class I> \
- static void call(I & integrator, const Array<UInt> & elements, \
- ElementType type, GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(ON_ELEMENT_ADDED, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_ON_ELEMENT_ADDED_HELPER)
-
-#undef AKANTU_SPECIALIZE_ON_ELEMENT_ADDED_HELPER
-#undef ON_ELEMENT_ADDED
- } // namespace details
-} // namespace integrator
-
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
void IntegratorGauss<kind, IntegrationOrderFunctor>::onElementsAdded(
const Array<Element> & new_elements) {
for (auto elements_range : MeshElementsByTypes(new_elements)) {
auto type = elements_range.getType();
auto ghost_type = elements_range.getGhostType();
if (mesh.getSpatialDimension(type) != _spatial_dimension) {
continue;
}
- if (mesh.getKind(type) != kind) {
+ if (Mesh::getKind(type) != kind) {
continue;
}
- integrator::details::IntegratorOnElementsAddedHelper<kind>::call(
- *this, elements_range.getElements(), type, ghost_type);
+ tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
+
+ this->template onElementsAddedByType<type>(
+ elements_range.getElements(), ghost_type);
+ },
+ type);
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::initIntegrator(
const Array<Real> & nodes, GhostType ghost_type) {
computeQuadraturePoints<type>(ghost_type);
precomputeJacobiansOnQuadraturePoints<type>(nodes, ghost_type);
checkJacobians<type>(ghost_type);
- constexpr UInt polynomial_degree =
+ constexpr auto polynomial_degree =
IntegrationOrderFunctor::template getOrder<type>();
multiplyJacobiansByWeights<type, polynomial_degree>(
this->jacobians(type, ghost_type));
}
-namespace integrator {
- namespace details {
- template <ElementKind kind> struct GaussIntegratorInitHelper {};
-
-#define INIT_INTEGRATOR(type) \
- _int.template initIntegrator<type>(nodes, ghost_type)
-
-#define AKANTU_GAUSS_INTERGRATOR_INIT_HELPER(kind) \
- template <> struct GaussIntegratorInitHelper<kind> { \
- template <ElementKind k, class IOF> \
- static void call(IntegratorGauss<k, IOF> & _int, \
- const Array<Real> & nodes, ElementType type, \
- GhostType ghost_type) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(INIT_INTEGRATOR, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_GAUSS_INTERGRATOR_INIT_HELPER)
-
-#undef AKANTU_GAUSS_INTERGRATOR_INIT_HELPER
-#undef INIT_INTEGRATOR
- } // namespace details
-} // namespace integrator
-
+/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::initIntegrator(
const Array<Real> & nodes, ElementType type, GhostType ghost_type) {
- integrator::details::GaussIntegratorInitHelper<kind>::call(*this, nodes, type,
- ghost_type);
-}
+ tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
-namespace integrator {
- namespace details {
- template <ElementKind kind> struct GaussIntegratorComputeJacobiansHelper {};
-
-#define AKANTU_COMPUTE_JACOBIANS(type) \
- _int.template computeJacobiansOnIntegrationPoints<type>( \
- nodes, quad_points, jacobians, ghost_type, filter_elements);
-
-#define AKANTU_GAUSS_INTERGRATOR_COMPUTE_JACOBIANS(kind) \
- template <> struct GaussIntegratorComputeJacobiansHelper<kind> { \
- template <ElementKind k, class IOF> \
- static void \
- call(const IntegratorGauss<k, IOF> & _int, const Array<Real> & nodes, \
- const Matrix<Real> & quad_points, Array<Real> & jacobians, \
- ElementType type, GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(AKANTU_COMPUTE_JACOBIANS, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND(AKANTU_GAUSS_INTERGRATOR_COMPUTE_JACOBIANS)
-
-#undef AKANTU_GAUSS_INTERGRATOR_COMPUTE_JACOBIANS
-#undef AKANTU_COMPUTE_JACOBIANS
- } // namespace details
-} // namespace integrator
+ this->template initIntegrator<type>(nodes, ghost_type);
+ },
+ type);
+}
+/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
void IntegratorGauss<kind, IntegrationOrderFunctor>::
computeJacobiansOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & quad_points,
Array<Real> & jacobians, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
- integrator::details::GaussIntegratorComputeJacobiansHelper<kind>::call(
- *this, nodes, quad_points, jacobians, type, ghost_type, filter_elements);
+ const Array<Idx> & filter_elements) const {
+ tuple_dispatch<ElementTypes_t<kind>>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
+
+ this->template computeJacobiansOnIntegrationPoints<type>(
+ nodes, quad_points, jacobians, ghost_type, filter_elements);
+ },
+ type);
}
} // namespace akantu
diff --git a/src/fe_engine/interpolation_element_tmpl.hh b/src/fe_engine/interpolation_element_tmpl.hh
index 74afdfeeb..ea0217e7b 100644
--- a/src/fe_engine/interpolation_element_tmpl.hh
+++ b/src/fe_engine/interpolation_element_tmpl.hh
@@ -1,74 +1,115 @@
/**
* @file interpolation_element_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Jun 06 2013
* @date last modification: Tue Sep 29 2020
*
* @brief interpolation property description
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_INTERPOLATION_ELEMENT_TMPL_HH_
#define AKANTU_INTERPOLATION_ELEMENT_TMPL_HH_
namespace akantu {
-
/* -------------------------------------------------------------------------- */
/* Regular Elements */
/* -------------------------------------------------------------------------- */
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_not_defined, _itk_not_defined, 0,
- 0);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_point_1,
- _itk_lagrangian, 1, 0);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_segment_2,
- _itk_lagrangian, 2, 1);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_segment_3,
- _itk_lagrangian, 3, 1);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_triangle_3,
- _itk_lagrangian, 3, 2);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_triangle_6,
- _itk_lagrangian, 6, 2);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_tetrahedron_4,
- _itk_lagrangian, 4, 3);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_tetrahedron_10,
- _itk_lagrangian, 10, 3);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_quadrangle_4,
- _itk_lagrangian, 4, 2);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_serendip_quadrangle_8,
- _itk_lagrangian, 8, 2);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_hexahedron_8,
- _itk_lagrangian, 8, 3);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_serendip_hexahedron_20,
- _itk_lagrangian, 20, 3);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_pentahedron_6,
- _itk_lagrangian, 6, 3);
-AKANTU_DEFINE_INTERPOLATION_TYPE_PROPERTY(_itp_lagrange_pentahedron_15,
- _itk_lagrangian, 15, 3);
+template <> struct InterpolationProperty<_itp_not_defined> {
+ static constexpr InterpolationKind kind{_itk_not_defined};
+ static constexpr Int nb_nodes_per_element{0};
+ static constexpr Int natural_space_dimension{0};
+};
+template <> struct InterpolationProperty<_itp_lagrange_point_1> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{1};
+ static constexpr Int natural_space_dimension{0};
+};
+template <> struct InterpolationProperty<_itp_lagrange_segment_2> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{2};
+ static constexpr Int natural_space_dimension{1};
+};
+template <> struct InterpolationProperty<_itp_lagrange_segment_3> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{3};
+ static constexpr Int natural_space_dimension{1};
+};
+template <> struct InterpolationProperty<_itp_lagrange_triangle_3> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{3};
+ static constexpr Int natural_space_dimension{2};
+};
+template <> struct InterpolationProperty<_itp_lagrange_triangle_6> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{6};
+ static constexpr Int natural_space_dimension{2};
+};
+template <> struct InterpolationProperty<_itp_lagrange_tetrahedron_4> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{4};
+ static constexpr Int natural_space_dimension{3};
+};
+template <> struct InterpolationProperty<_itp_lagrange_tetrahedron_10> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{10};
+ static constexpr Int natural_space_dimension{3};
+};
+template <> struct InterpolationProperty<_itp_lagrange_quadrangle_4> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{4};
+ static constexpr Int natural_space_dimension{2};
+};
+template <> struct InterpolationProperty<_itp_serendip_quadrangle_8> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{8};
+ static constexpr Int natural_space_dimension{2};
+};
+template <> struct InterpolationProperty<_itp_lagrange_hexahedron_8> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{8};
+ static constexpr Int natural_space_dimension{3};
+};
+template <> struct InterpolationProperty<_itp_serendip_hexahedron_20> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{20};
+ static constexpr Int natural_space_dimension{3};
+};
+template <> struct InterpolationProperty<_itp_lagrange_pentahedron_6> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{6};
+ static constexpr Int natural_space_dimension{3};
+};
+template <> struct InterpolationProperty<_itp_lagrange_pentahedron_15> {
+ static constexpr InterpolationKind kind{_itk_lagrangian};
+ static constexpr Int nb_nodes_per_element{15};
+ static constexpr Int natural_space_dimension{3};
+};
} // namespace akantu
#endif /* AKANTU_INTERPOLATION_ELEMENT_TMPL_HH_ */
diff --git a/src/fe_engine/shape_cohesive.hh b/src/fe_engine/shape_cohesive.hh
index 570c179cd..cb0ec0e33 100644
--- a/src/fe_engine/shape_cohesive.hh
+++ b/src/fe_engine/shape_cohesive.hh
@@ -1,191 +1,192 @@
/**
* @file shape_cohesive.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Feb 15 2011
* @date last modification: Fri May 14 2021
*
* @brief shape functions for cohesive elements description
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_COHESIVE_HH_
#define AKANTU_SHAPE_COHESIVE_HH_
namespace akantu {
struct CohesiveReduceFunctionMean {
- inline Real operator()(Real u_plus, Real u_minus) {
+ template <typename T1, typename T2>
+ inline decltype(auto) operator()(T1 u_plus, T2 u_minus) {
return .5 * (u_plus + u_minus);
}
};
struct CohesiveReduceFunctionOpening {
- inline Real operator()(Real u_plus, Real u_minus) {
+ template <typename T1, typename T2>
+ inline decltype(auto) operator()(T1 u_plus, T2 u_minus) {
return (u_plus - u_minus);
}
};
template <> class ShapeLagrange<_ek_cohesive> : public ShapeLagrangeBase {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- ShapeLagrange(const Mesh & mesh, UInt spatial_dimension,
+ ShapeLagrange(const Mesh & mesh, Int spatial_dimension,
const ID & id = "shape_cohesive");
~ShapeLagrange() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
inline void initShapeFunctions(const Array<Real> & nodes,
const Matrix<Real> & integration_points,
ElementType type, GhostType ghost_type);
/// extract the nodal values and store them per element
template <ElementType type, class ReduceFunction>
void extractNodalToElementField(
const Array<Real> & nodal_f, Array<Real> & elemental_f,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// computes the shape functions derivatives for given interpolation points
template <ElementType type>
void computeShapeDerivativesOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & integration_points,
Array<Real> & shape_derivatives, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
void computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shape_derivatives, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const override;
+ const Array<Idx> & filter_elements) const override;
/// pre compute all shapes on the element integration points from natural
/// coordinates
template <ElementType type>
void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// pre compute all shape derivatives on the element integration points from
/// natural coordinates
template <ElementType type>
void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// interpolate nodal values on the integration points
template <ElementType type, class ReduceFunction>
void interpolateOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom,
- GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Real> & u, Array<Real> & uq, Int nb_degree_of_freedom,
+ const GhostType ghost_type = _not_ghost,
+ const Array<Idx> & filter_elements = empty_filter) const;
template <ElementType type>
void interpolateOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom,
- GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const {
+ const Array<Real> & u, Array<Real> & uq, Int nb_degree_of_freedom,
+ const GhostType ghost_type = _not_ghost,
+ const Array<Idx> & filter_elements = empty_filter) const {
interpolateOnIntegrationPoints<type, CohesiveReduceFunctionMean>(
u, uq, nb_degree_of_freedom, ghost_type, filter_elements);
}
/// compute the gradient of u on the integration points in the natural
/// coordinates
template <ElementType type>
void gradientOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & nablauq, Int nb_degree_of_freedom,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const {
+ const Array<Idx> & filter_elements = empty_filter) const {
variationOnIntegrationPoints<type, CohesiveReduceFunctionMean>(
u, nablauq, nb_degree_of_freedom, ghost_type, filter_elements);
}
/* ------------------------------------------------------------------------ */
template <ElementType type>
void computeBtD(const Array<Real> & /*Ds*/, Array<Real> & /*BtDs*/,
GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/) const {
+ const Array<Idx> & /*filter_elements*/) const {
AKANTU_TO_IMPLEMENT();
}
template <ElementType type>
void computeBtDB(const Array<Real> & /*Ds*/, Array<Real> & /*BtDBs*/,
- UInt /*order_d*/, GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/) const {
+ Int /*order_d*/, GhostType /*ghost_type*/,
+ const Array<Idx> & /*filter_elements*/) const {
AKANTU_TO_IMPLEMENT();
}
/// multiply a field by shape functions
template <ElementType type>
- void
- computeNtb(const Array<Real> & /*bs*/, Array<Real> & /*Ntbs*/,
- GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/ = empty_filter) const {
+ void computeNtb(const Array<Real> & /*bs*/, Array<Real> & /*Ntbs*/,
+ GhostType /*ghost_type*/,
+ const Array<Idx> & /*filter_elements*/ = empty_filter) const {
AKANTU_TO_IMPLEMENT();
}
template <ElementType type>
void computeNtbN(const Array<Real> & /*bs*/, Array<Real> & /*NtbNs*/,
GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/) const {
+ const Array<Idx> & /*filter_elements*/) const {
AKANTU_TO_IMPLEMENT();
}
/* ------------------------------------------------------------------------ */
/// compute the gradient of u on the integration points
template <ElementType type, class ReduceFunction>
void variationOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & nablauq, Int nb_degree_of_freedom,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// compute the normals to the field u on integration points
template <ElementType type, class ReduceFunction>
void computeNormalsOnIntegrationPoints(
const Array<Real> & u, Array<Real> & normals_u,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
};
/// standard output stream operator
template <class ShapeFunction>
inline std::ostream & operator<<(std::ostream & stream,
const ShapeCohesive<ShapeFunction> & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "shape_cohesive_inline_impl.hh"
#endif /* AKANTU_SHAPE_COHESIVE_HH_ */
diff --git a/src/fe_engine/shape_cohesive_inline_impl.hh b/src/fe_engine/shape_cohesive_inline_impl.hh
index 4373a08a0..944640bbb 100644
--- a/src/fe_engine/shape_cohesive_inline_impl.hh
+++ b/src/fe_engine/shape_cohesive_inline_impl.hh
@@ -1,333 +1,331 @@
/**
* @file shape_cohesive_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Feb 03 2012
* @date last modification: Tue Sep 29 2020
*
* @brief ShapeCohesive inline implementation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_iterators.hh"
-#include "shape_cohesive.hh"
+//#include "shape_cohesive.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_COHESIVE_INLINE_IMPL_HH_
#define AKANTU_SHAPE_COHESIVE_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline ShapeLagrange<_ek_cohesive>::ShapeLagrange(const Mesh & mesh,
- UInt spatial_dimension,
+ Int spatial_dimension,
const ID & id)
: ShapeLagrangeBase(mesh, spatial_dimension, _ek_cohesive, id) {}
-#define INIT_SHAPE_FUNCTIONS(type) \
- setIntegrationPointsByType<type>(integration_points, ghost_type); \
- precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type); \
- precomputeShapeDerivativesOnIntegrationPoints<type>(nodes, ghost_type);
-
/* -------------------------------------------------------------------------- */
inline void ShapeLagrange<_ek_cohesive>::initShapeFunctions(
const Array<Real> & nodes, const Matrix<Real> & integration_points,
ElementType type, GhostType ghost_type) {
- AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
+ tuple_dispatch<ElementTypes_t<_ek_cohesive>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->setIntegrationPointsByType<type>(integration_points, ghost_type);
+ this->precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type);
+ this->precomputeShapeDerivativesOnIntegrationPoints<type>(nodes,
+ ghost_type);
+ },
+ type);
}
-/* -------------------------------------------------------------------------- */
-
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_cohesive>::computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & /*unused*/, const Matrix<Real> & integration_points,
+ const Array<Real> &, const Matrix<Real> & integration_points,
Array<Real> & shape_derivatives, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
- UInt spatial_dimension = ElementClass<type>::getNaturalSpaceDimension();
- UInt nb_nodes_per_element =
+ auto size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
+ auto spatial_dimension = ElementClass<type>::getNaturalSpaceDimension();
+ auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
- UInt nb_points = integration_points.cols();
- UInt nb_element = mesh.getConnectivity(type, ghost_type).size();
+ auto nb_points = integration_points.cols();
+ auto nb_element = mesh.getConnectivity(type, ghost_type).size();
AKANTU_DEBUG_ASSERT(shape_derivatives.getNbComponent() == size_of_shapesd,
"The shapes_derivatives array does not have the correct "
<< "number of component");
shape_derivatives.resize(nb_element * nb_points);
- Real * shapesd_val = shape_derivatives.storage();
+ auto * shapesd_val = shape_derivatives.data();
auto compute = [&](const auto & el) {
auto ptr = shapesd_val + el * nb_points * size_of_shapesd;
- Tensor3<Real> B(ptr, spatial_dimension, nb_nodes_per_element, nb_points);
+ Tensor3Proxy<Real> B(ptr, spatial_dimension, nb_nodes_per_element,
+ nb_points);
ElementClass<type>::computeDNDS(integration_points, B);
};
for_each_element(nb_element, filter_elements, compute);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
inline void
ShapeLagrange<_ek_cohesive>::computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shape_derivatives, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
-#define AKANTU_COMPUTE_SHAPES(type) \
- computeShapeDerivativesOnIntegrationPoints<type>( \
- nodes, integration_points, shape_derivatives, ghost_type, \
- filter_elements);
-
- AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(AKANTU_COMPUTE_SHAPES);
-
-#undef AKANTU_COMPUTE_SHAPES
+ const Array<Idx> & filter_elements) const {
+ tuple_dispatch<ElementTypes_t<_ek_cohesive>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->computeShapeDerivativesOnIntegrationPoints<type>(
+ nodes, integration_points, shape_derivatives, ghost_type,
+ filter_elements);
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_cohesive>::precomputeShapesOnIntegrationPoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
- Matrix<Real> & natural_coords = integration_points(type, ghost_type);
- UInt size_of_shapes = ElementClass<type>::getShapeSize();
+ auto itp_type = ElementClassProperty<type>::interpolation_type;
+ auto & natural_coords = integration_points(type, ghost_type);
+ auto size_of_shapes = ElementClass<type>::getShapeSize();
- Array<Real> & shapes_tmp =
- shapes.alloc(0, size_of_shapes, itp_type, ghost_type);
+ auto & shapes_tmp = shapes.alloc(0, size_of_shapes, itp_type, ghost_type);
this->computeShapesOnIntegrationPoints<type>(nodes, natural_coords,
shapes_tmp, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrange<_ek_cohesive>::precomputeShapeDerivativesOnIntegrationPoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
- Matrix<Real> & natural_coords = integration_points(type, ghost_type);
- UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
+ auto itp_type = ElementClassProperty<type>::interpolation_type;
+ auto & natural_coords = integration_points(type, ghost_type);
+ auto size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
- Array<Real> & shapes_derivatives_tmp =
+ auto & shapes_derivatives_tmp =
shapes_derivatives.alloc(0, size_of_shapesd, itp_type, ghost_type);
this->computeShapeDerivativesOnIntegrationPoints<type>(
nodes, natural_coords, shapes_derivatives_tmp, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type, class ReduceFunction>
void ShapeLagrange<_ek_cohesive>::extractNodalToElementField(
const Array<Real> & nodal_f, Array<Real> & elemental_f,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt nb_nodes_per_itp_element =
+ auto nb_nodes_per_itp_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
- UInt nb_degree_of_freedom = nodal_f.getNbComponent();
- UInt nb_element = this->mesh.getNbElement(type, ghost_type);
+ auto nb_degree_of_freedom = nodal_f.getNbComponent();
+ auto nb_element = this->mesh.getNbElement(type, ghost_type);
const auto & conn_array = this->mesh.getConnectivity(type, ghost_type);
- auto conn = conn_array.begin(conn_array.getNbComponent() / 2, 2);
+ auto conn = make_view(conn_array, conn_array.getNbComponent() / 2, 2).begin();
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
elemental_f.resize(nb_element);
- Array<Real>::matrix_iterator u_it =
- elemental_f.begin(nb_degree_of_freedom, nb_nodes_per_itp_element);
+ auto u_it =
+ make_view(elemental_f, nb_degree_of_freedom, nb_nodes_per_itp_element)
+ .begin();
+
+ auto nodal_f_it = make_view(nodal_f, nb_degree_of_freedom).begin();
ReduceFunction reduce_function;
auto compute = [&](const auto & el) {
- Matrix<Real> & u = *u_it;
- Matrix<UInt> el_conn(conn[el]);
+ auto && u = *u_it;
+ auto && el_conn = conn[el];
// compute the average/difference of the nodal field loaded from cohesive
// element
- for (UInt n = 0; n < el_conn.rows(); ++n) {
- UInt node_plus = el_conn(n, 0);
- UInt node_minus = el_conn(n, 1);
- for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
- Real u_plus = nodal_f(node_plus, d);
- Real u_minus = nodal_f(node_minus, d);
- u(d, n) = reduce_function(u_plus, u_minus);
- }
+ for (Int n = 0; n < el_conn.rows(); ++n) {
+ auto node_plus = el_conn(n, 0);
+ auto node_minus = el_conn(n, 1);
+
+ u(n) = reduce_function(nodal_f_it[node_plus], nodal_f_it[node_minus]);
}
++u_it;
};
for_each_element(nb_element, filter_elements, compute);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type, class ReduceFunction>
void ShapeLagrange<_ek_cohesive>::interpolateOnIntegrationPoints(
- const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ const Array<Real> & in_u, Array<Real> & out_uq, Int nb_degree_of_freedom,
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
- InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
+ auto itp_type = ElementClassProperty<type>::interpolation_type;
AKANTU_DEBUG_ASSERT(this->shapes.exists(itp_type, ghost_type),
"No shapes for the type "
<< this->shapes.printType(itp_type, ghost_type));
- UInt nb_nodes_per_element =
+ auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element);
this->extractNodalToElementField<type, ReduceFunction>(in_u, u_el, ghost_type,
filter_elements);
this->template interpolateElementalFieldOnIntegrationPoints<type>(
u_el, out_uq, ghost_type, shapes(itp_type, ghost_type), filter_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type, class ReduceFunction>
void ShapeLagrange<_ek_cohesive>::variationOnIntegrationPoints(
- const Array<Real> & in_u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ const Array<Real> & in_u, Array<Real> & nablauq, Int nb_degree_of_freedom,
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
AKANTU_DEBUG_ASSERT(
this->shapes_derivatives.exists(itp_type, ghost_type),
"No shapes for the type "
<< this->shapes_derivatives.printType(itp_type, ghost_type));
- UInt nb_nodes_per_element =
+ auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element);
this->extractNodalToElementField<type, ReduceFunction>(in_u, u_el, ghost_type,
filter_elements);
this->template gradientElementalFieldOnIntegrationPoints<type>(
u_el, nablauq, ghost_type, shapes_derivatives(itp_type, ghost_type),
filter_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type, class ReduceFunction>
void ShapeLagrange<_ek_cohesive>::computeNormalsOnIntegrationPoints(
const Array<Real> & u, Array<Real> & normals_u, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt nb_element = this->mesh.getNbElement(type, ghost_type);
- UInt nb_points = this->integration_points(type, ghost_type).cols();
- UInt spatial_dimension = this->mesh.getSpatialDimension();
+ auto nb_element = this->mesh.getNbElement(type, ghost_type);
+ auto nb_points = this->integration_points(type, ghost_type).cols();
+ auto spatial_dimension = this->mesh.getSpatialDimension();
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
normals_u.resize(nb_points * nb_element);
Array<Real> tangents_u(0, (spatial_dimension * (spatial_dimension - 1)));
if (spatial_dimension > 1) {
tangents_u.resize(nb_element * nb_points);
this->template variationOnIntegrationPoints<type, ReduceFunction>(
u, tangents_u, spatial_dimension, ghost_type, filter_elements);
}
- Real * tangent = tangents_u.storage();
-
if (spatial_dimension == 3) {
- for (auto & normal : make_view(normals_u, spatial_dimension)) {
- Math::vectorProduct3(tangent, tangent + spatial_dimension,
- normal.storage());
+ for (auto && data :
+ zip(make_view<3>(normals_u), make_view<3, 2>(tangents_u))) {
+ auto && n = std::get<0>(data);
+ auto && ts = std::get<1>(data);
- normal /= normal.norm();
- tangent += spatial_dimension * 2;
+ n = (ts(0).cross(ts(1))).normalized();
}
} else if (spatial_dimension == 2) {
- for (auto & normal : make_view(normals_u, spatial_dimension)) {
- Vector<Real> a1(tangent, spatial_dimension);
-
- normal(0) = -a1(1);
- normal(1) = a1(0);
- normal.normalize();
-
- tangent += spatial_dimension;
+ for (auto && data :
+ zip(make_view<2>(normals_u), make_view<2>(tangents_u))) {
+ auto && n = std::get<0>(data);
+ auto && t = std::get<1>(data);
+
+ n(0) = -t(1);
+ n(1) = t(0);
+ n.normalize();
}
} else if (spatial_dimension == 1) {
const auto facet_type = Mesh::getFacetType(type);
const auto & mesh_facets = mesh.getMeshFacets();
const auto & facets = mesh_facets.getSubelementToElement(type, ghost_type);
const auto & segments =
mesh_facets.getElementToSubelement(facet_type, ghost_type);
- Real values[2];
+ Matrix<Real> barycenter(1, 2);
for (auto el : arange(nb_element)) {
if (filter_elements != empty_filter) {
el = filter_elements(el);
}
- for (UInt p = 0; p < 2; ++p) {
- Element facet = facets(el, p);
- Element segment = segments(facet.element)[0];
- Vector<Real> barycenter(values + p, 1);
- mesh.getBarycenter(segment, barycenter);
+ for (Int p = 0; p < 2; ++p) {
+ const Element & facet = facets(el, p);
+ const Element & segment = segments(facet.element)[0];
+ mesh.getBarycenter(segment, barycenter(p));
}
- Real difference = values[0] - values[1];
+ Real difference = barycenter(0, 0) - barycenter(0, 1);
AKANTU_DEBUG_ASSERT(difference != 0.,
"Error in normal computation for cohesive elements");
normals_u(el) = difference / std::abs(difference);
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif /* AKANTU_SHAPE_COHESIVE_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/shape_functions.cc b/src/fe_engine/shape_functions.cc
index 9d64c58bb..fa4e13d5e 100644
--- a/src/fe_engine/shape_functions.cc
+++ b/src/fe_engine/shape_functions.cc
@@ -1,243 +1,237 @@
/**
* @file shape_functions.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 09 2017
* @date last modification: Tue Feb 09 2021
*
* @brief implementation of th shape functions interface
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "shape_functions.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-ShapeFunctions::ShapeFunctions(const Mesh & mesh, UInt spatial_dimension,
+ShapeFunctions::ShapeFunctions(const Mesh & mesh, Int spatial_dimension,
const ID & id)
: shapes("shapes_generic", id),
shapes_derivatives("shapes_derivatives_generic", id), mesh(mesh),
_spatial_dimension(spatial_dimension) {}
/* -------------------------------------------------------------------------- */
template <ElementType type>
inline void
ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints(
const Array<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
const Array<Real> & quadrature_points_coordinates, GhostType ghost_type,
- const Array<UInt> & element_filter) const {
-
+ const Array<Idx> & element_filter) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = this->mesh.getSpatialDimension();
- UInt nb_element = this->mesh.getNbElement(type, ghost_type);
- UInt nb_element_filter;
+ auto spatial_dimension = this->mesh.getSpatialDimension();
+ auto nb_element = this->mesh.getNbElement(type, ghost_type);
+ decltype(nb_element) nb_element_filter;
if (element_filter == empty_filter) {
nb_element_filter = nb_element;
} else {
nb_element_filter = element_filter.size();
}
- auto nb_quad_per_element =
+ constexpr auto nb_quad_per_element =
GaussIntegrationElement<type>::getNbQuadraturePoints();
auto nb_interpolation_points_per_elem =
interpolation_points_coordinates.size() / nb_element;
AKANTU_DEBUG_ASSERT(interpolation_points_coordinates.size() % nb_element == 0,
"Number of interpolation points should be a multiple of "
"total number of elements");
if (not quad_points_coordinates_inv_matrices.exists(type, ghost_type)) {
quad_points_coordinates_inv_matrices.alloc(
nb_element_filter, nb_quad_per_element * nb_quad_per_element, type,
ghost_type);
} else {
quad_points_coordinates_inv_matrices(type, ghost_type)
.resize(nb_element_filter);
}
if (!interpolation_points_coordinates_matrices.exists(type, ghost_type)) {
interpolation_points_coordinates_matrices.alloc(
nb_element_filter,
nb_interpolation_points_per_elem * nb_quad_per_element, type,
ghost_type);
} else {
interpolation_points_coordinates_matrices(type, ghost_type)
.resize(nb_element_filter);
}
- Array<Real> & quad_inv_mat =
- quad_points_coordinates_inv_matrices(type, ghost_type);
- Array<Real> & interp_points_mat =
+ auto & quad_inv_mat = quad_points_coordinates_inv_matrices(type, ghost_type);
+ auto & interp_points_mat =
interpolation_points_coordinates_matrices(type, ghost_type);
- Matrix<Real> quad_coord_matrix(nb_quad_per_element, nb_quad_per_element);
-
- Array<Real>::const_matrix_iterator quad_coords_it =
- quadrature_points_coordinates.begin_reinterpret(
- spatial_dimension, nb_quad_per_element, nb_element_filter);
-
- Array<Real>::const_matrix_iterator points_coords_begin =
- interpolation_points_coordinates.begin_reinterpret(
- spatial_dimension, nb_interpolation_points_per_elem, nb_element);
-
- Array<Real>::matrix_iterator inv_quad_coord_it =
- quad_inv_mat.begin(nb_quad_per_element, nb_quad_per_element);
+ Matrix<Real, nb_quad_per_element, nb_quad_per_element> quad_coord_matrix;
- Array<Real>::matrix_iterator int_points_mat_it = interp_points_mat.begin(
- nb_interpolation_points_per_elem, nb_quad_per_element);
+ auto points_coords_begin =
+ make_view(interpolation_points_coordinates, spatial_dimension,
+ nb_interpolation_points_per_elem)
+ .begin();
/// loop over the elements of the current material and element type
- for (UInt el = 0; el < nb_element_filter;
- ++el, ++inv_quad_coord_it, ++int_points_mat_it, ++quad_coords_it) {
- /// matrix containing the quadrature points coordinates
- const Matrix<Real> & quad_coords = *quad_coords_it;
+ for (auto && data :
+ zip(element_filter,
+ make_view<nb_quad_per_element, nb_quad_per_element>(quad_inv_mat),
+ make_view(interp_points_mat, nb_interpolation_points_per_elem,
+ nb_quad_per_element),
+ make_view(quadrature_points_coordinates, spatial_dimension,
+ nb_quad_per_element))) {
+
+ auto element = std::get<0>(data);
/// matrix to store the matrix inversion result
- Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it;
+ auto & inv_quad_coord_matrix = std::get<1>(data);
+ /// matrix to store the interpolation points coordinates
+ /// compatible with these functions
+ auto & inv_points_coord_matrix = std::get<2>(data);
+ /// matrix containing the quadrature points coordinates
+ auto & quad_coords = std::get<3>(data);
+ /// matrix containing the interpolation points coordinates
+ auto && points_coords = points_coords_begin[element];
/// insert the quad coordinates in a matrix compatible with the
/// interpolation
buildElementalFieldInterpolationMatrix<type>(quad_coords,
quad_coord_matrix);
/// invert the interpolation matrix
- inv_quad_coord_matrix.inverse(quad_coord_matrix);
-
- /// matrix containing the interpolation points coordinates
- const Matrix<Real> & points_coords =
- points_coords_begin[element_filter(el)];
- /// matrix to store the interpolation points coordinates
- /// compatible with these functions
- Matrix<Real> & inv_points_coord_matrix = *int_points_mat_it;
+ inv_quad_coord_matrix = quad_coord_matrix.inverse();
/// insert the quad coordinates in a matrix compatible with the
/// interpolation
buildElementalFieldInterpolationMatrix<type>(points_coords,
inv_points_coord_matrix);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints(
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
const ElementTypeMapArray<Real> & quadrature_points_coordinates,
- const ElementTypeMapArray<UInt> * element_filter) const {
+ const ElementTypeMapArray<Idx> * element_filter) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = this->mesh.getSpatialDimension();
+ auto spatial_dimension = this->mesh.getSpatialDimension();
for (auto ghost_type : ghost_types) {
auto types_iterable = mesh.elementTypes(spatial_dimension, ghost_type);
if (element_filter != nullptr) {
types_iterable =
element_filter->elementTypes(spatial_dimension, ghost_type);
}
for (auto type : types_iterable) {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (nb_element == 0) {
continue;
}
- const Array<UInt> * elem_filter;
+ const Array<Idx> * elem_filter;
if (element_filter != nullptr) {
elem_filter = &((*element_filter)(type, ghost_type));
} else {
elem_filter = &(empty_filter);
}
-#define AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS(type) \
- this->initElementalFieldInterpolationFromIntegrationPoints<type>( \
- interpolation_points_coordinates(type, ghost_type), \
- interpolation_points_coordinates_matrices, \
- quad_points_coordinates_inv_matrices, \
- quadrature_points_coordinates(type, ghost_type), ghost_type, \
- *elem_filter)
-
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(
- AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS);
-#undef AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS
+ tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->initElementalFieldInterpolationFromIntegrationPoints<type>(
+ interpolation_points_coordinates(type, ghost_type),
+ interpolation_points_coordinates_matrices,
+ quad_points_coordinates_inv_matrices,
+ quadrature_points_coordinates(type, ghost_type), ghost_type,
+ *elem_filter);
+ },
+ type);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ShapeFunctions::interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const {
+ const ElementTypeMapArray<Idx> * element_filter) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = this->mesh.getSpatialDimension();
+ auto spatial_dimension = this->mesh.getSpatialDimension();
auto types_iterable = mesh.elementTypes(spatial_dimension, ghost_type);
if (element_filter != nullptr) {
types_iterable =
element_filter->elementTypes(spatial_dimension, ghost_type);
}
for (auto type : types_iterable) {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
if (nb_element == 0) {
continue;
}
- const Array<UInt> * elem_filter;
+ const Array<Idx> * elem_filter;
if (element_filter != nullptr) {
elem_filter = &((*element_filter)(type, ghost_type));
} else {
elem_filter = &(empty_filter);
}
-#define AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS(type) \
- interpolateElementalFieldFromIntegrationPoints<type>( \
- field(type, ghost_type), \
- interpolation_points_coordinates_matrices(type, ghost_type), \
- quad_points_coordinates_inv_matrices(type, ghost_type), result, \
- ghost_type, *elem_filter)
-
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(
- AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS);
-#undef AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS
+ tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->interpolateElementalFieldFromIntegrationPoints<type>(
+ field(type, ghost_type),
+ interpolation_points_coordinates_matrices(type, ghost_type),
+ quad_points_coordinates_inv_matrices(type, ghost_type), result,
+ ghost_type, *elem_filter);
+ },
+ type);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/fe_engine/shape_functions.hh b/src/fe_engine/shape_functions.hh
index 66429fd4a..2100e1599 100644
--- a/src/fe_engine/shape_functions.hh
+++ b/src/fe_engine/shape_functions.hh
@@ -1,214 +1,235 @@
/**
* @file shape_functions.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 29 2020
*
* @brief shape function class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_FUNCTIONS_HH_
#define AKANTU_SHAPE_FUNCTIONS_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
class ShapeFunctions {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- ShapeFunctions(const Mesh & mesh, UInt spatial_dimension,
+ ShapeFunctions(const Mesh & mesh, Int spatial_dimension,
const ID & id = "shape");
virtual ~ShapeFunctions() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// function to print the contain of the class
virtual void printself(std::ostream & stream, int indent = 0) const {
- std::string space;
- for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
- ;
- }
+ std::string space(indent, AKANTU_INDENT);
+
stream << space << "Shapes [" << std::endl;
integration_points.printself(stream, indent + 1);
// shapes.printself(stream, indent + 1);
// shapes_derivatives.printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
/// set the integration points for a given element
- template <ElementType type>
- void setIntegrationPointsByType(const Matrix<Real> & integration_points,
- GhostType ghost_type);
+ template <ElementType type, class D1>
+ void
+ setIntegrationPointsByType(const Eigen::MatrixBase<D1> & integration_points,
+ GhostType ghost_type);
/// Build pre-computed matrices for interpolation of field form integration
/// points at other given positions (interpolation_points)
void initElementalFieldInterpolationFromIntegrationPoints(
const ElementTypeMapArray<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
const ElementTypeMapArray<Real> & quadrature_points_coordinates,
- const ElementTypeMapArray<UInt> * element_filter) const;
+ const ElementTypeMapArray<Idx> * element_filter) const;
/// Interpolate field at given position from given values of this field at
/// integration points (field)
/// using matrices precomputed with
/// initElementalFieldInterplationFromIntegrationPoints
void interpolateElementalFieldFromIntegrationPoints(
const ElementTypeMapArray<Real> & field,
const ElementTypeMapArray<Real> &
interpolation_points_coordinates_matrices,
const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const ElementTypeMapArray<UInt> * element_filter) const;
+ const ElementTypeMapArray<Idx> * element_filter) const;
protected:
/// interpolate nodal values stored by element on the integration points
template <ElementType type>
void interpolateElementalFieldOnIntegrationPoints(
const Array<Real> & u_el, Array<Real> & uq, GhostType ghost_type,
const Array<Real> & shapes,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// gradient of nodal values stored by element on the control points
- template <ElementType type>
+ template <ElementType type,
+ std::enable_if_t<ElementClass<type>::getNaturalSpaceDimension() !=
+ 0> * = nullptr>
void gradientElementalFieldOnIntegrationPoints(
const Array<Real> & u_el, Array<Real> & out_nablauq, GhostType ghost_type,
const Array<Real> & shapes_derivatives,
- const Array<UInt> & filter_elements) const;
+ const Array<Idx> & filter_elements) const;
+
+ template <ElementType type,
+ std::enable_if_t<ElementClass<type>::getNaturalSpaceDimension() ==
+ 0> * = nullptr>
+ void gradientElementalFieldOnIntegrationPoints(
+ const Array<Real> & /*u_el*/, Array<Real> & out_nablauq,
+ GhostType ghost_type, const Array<Real> & /*shapes_derivatives*/,
+ const Array<Idx> & /*filter_elements*/) const {
+ auto nb_points = integration_points(type, ghost_type).cols();
+ auto nb_element = mesh.getNbElement(type, ghost_type);
+
+ out_nablauq.resize(nb_element * nb_points);
+ out_nablauq.zero();
+ }
protected:
/// By element versions of non-templated eponym methods
template <ElementType type>
inline void interpolateElementalFieldFromIntegrationPoints(
const Array<Real> & field,
const Array<Real> & interpolation_points_coordinates_matrices,
const Array<Real> & quad_points_coordinates_inv_matrices,
ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const Array<UInt> & element_filter) const;
+ const Array<Idx> & element_filter) const;
/// Interpolate field at given position from given values of this field at
/// integration points (field)
/// using matrices precomputed with
/// initElementalFieldInterplationFromIntegrationPoints
template <ElementType type>
inline void initElementalFieldInterpolationFromIntegrationPoints(
const Array<Real> & interpolation_points_coordinates,
ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
const Array<Real> & quadrature_points_coordinates, GhostType ghost_type,
- const Array<UInt> & element_filter) const;
+ const Array<Idx> & element_filter) const;
/// build matrix for the interpolation of field form integration points
- template <ElementType type>
+ template <ElementType type, typename D1, typename D2>
inline void buildElementalFieldInterpolationMatrix(
- const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
- UInt integration_order =
+ const Eigen::MatrixBase<D1> & coordinates,
+ Eigen::MatrixBase<D2> & coordMatrix,
+ Int integration_order =
ElementClassProperty<type>::polynomial_degree) const;
/// build the so called interpolation matrix (first collumn is 1, then the
/// other collumns are the traansposed coordinates)
- static inline void buildInterpolationMatrix(const Matrix<Real> & coordinates,
- Matrix<Real> & coordMatrix,
- UInt integration_order);
+ template <typename D1, typename D2>
+ inline void
+ buildInterpolationMatrix(const Eigen::MatrixBase<D1> & coordinates,
+ Eigen::MatrixBase<D2> & coordMatrix,
+ Int integration_order) const;
+
+ template <ElementType type>
+ friend struct BuildElementalFieldInterpolationMatrix;
public:
virtual void onElementsAdded(const Array<Element> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
virtual void onElementsRemoved(const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/) {
+ const ElementTypeMapArray<Idx> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the size of the shapes returned by the element class
- static inline UInt getShapeSize(ElementType type);
+ static inline Int getShapeSize(ElementType type);
/// get the size of the shapes derivatives returned by the element class
- static inline UInt getShapeDerivativesSize(ElementType type);
+ static inline Int getShapeDerivativesSize(ElementType type);
inline const Matrix<Real> & getIntegrationPoints(ElementType type,
GhostType ghost_type) const {
return integration_points(type, ghost_type);
}
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get a the shapes vector
inline const Array<Real> & getShapes(ElementType el_type,
GhostType ghost_type = _not_ghost) const;
/// get a the shapes derivatives vector
inline const Array<Real> &
getShapesDerivatives(ElementType el_type,
GhostType ghost_type = _not_ghost) const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// shape functions for all elements
ElementTypeMapArray<Real, InterpolationType> shapes;
/// shape functions derivatives for all elements
ElementTypeMapArray<Real, InterpolationType> shapes_derivatives;
/// associated mesh
const Mesh & mesh;
// spatial dimension of the elements to consider
- UInt _spatial_dimension;
+ Int _spatial_dimension;
/// shape functions for all elements
ElementTypeMap<Matrix<Real>> integration_points;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const ShapeFunctions & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "shape_functions_inline_impl.hh"
#endif /* AKANTU_SHAPE_FUNCTIONS_HH_ */
diff --git a/src/fe_engine/shape_functions_inline_impl.hh b/src/fe_engine/shape_functions_inline_impl.hh
index 26e313d94..6308a9b19 100644
--- a/src/fe_engine/shape_functions_inline_impl.hh
+++ b/src/fe_engine/shape_functions_inline_impl.hh
@@ -1,415 +1,350 @@
/**
* @file shape_functions_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Oct 27 2010
* @date last modification: Sat Dec 19 2020
*
* @brief ShapeFunctions inline implementation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "shape_functions.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_HH_
-#define AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_HH_
+//#ifndef AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_HH_
+//#define AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline const Array<Real> &
ShapeFunctions::getShapes(ElementType el_type, GhostType ghost_type) const {
return shapes(FEEngine::getInterpolationType(el_type), ghost_type);
}
/* -------------------------------------------------------------------------- */
inline const Array<Real> &
ShapeFunctions::getShapesDerivatives(ElementType el_type,
GhostType ghost_type) const {
return shapes_derivatives(FEEngine::getInterpolationType(el_type),
ghost_type);
}
/* -------------------------------------------------------------------------- */
-inline UInt ShapeFunctions::getShapeSize(ElementType type) {
- AKANTU_DEBUG_IN();
-
- UInt shape_size = 0;
-#define GET_SHAPE_SIZE(type) shape_size = ElementClass<type>::getShapeSize()
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SHAPE_SIZE); // ,
-
-#undef GET_SHAPE_SIZE
-
- AKANTU_DEBUG_OUT();
- return shape_size;
+inline Int ShapeFunctions::getShapeSize(ElementType type) {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getShapeSize();
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
-inline UInt ShapeFunctions::getShapeDerivativesSize(ElementType type) {
- AKANTU_DEBUG_IN();
-
- UInt shape_derivatives_size = 0;
-#define GET_SHAPE_DERIVATIVES_SIZE(type) \
- shape_derivatives_size = ElementClass<type>::getShapeDerivativesSize()
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SHAPE_DERIVATIVES_SIZE); // ,
-
-#undef GET_SHAPE_DERIVATIVES_SIZE
-
- AKANTU_DEBUG_OUT();
- return shape_derivatives_size;
+inline Int ShapeFunctions::getShapeDerivativesSize(ElementType type) {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getShapeDerivativesSize();
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
-template <ElementType type>
-void ShapeFunctions::setIntegrationPointsByType(const Matrix<Real> & points,
- GhostType ghost_type) {
- if (not this->integration_points.exists(type, ghost_type)) {
- this->integration_points(type, ghost_type).shallowCopy(points);
- }
+template <ElementType type, class D1>
+void ShapeFunctions::setIntegrationPointsByType(
+ const Eigen::MatrixBase<D1> & points, GhostType ghost_type) {
+ this->integration_points(type, ghost_type) = points;
}
/* -------------------------------------------------------------------------- */
-inline void
-ShapeFunctions::buildInterpolationMatrix(const Matrix<Real> & coordinates,
- Matrix<Real> & coordMatrix,
- UInt integration_order) {
+template <typename D1, typename D2>
+inline void ShapeFunctions::buildInterpolationMatrix(
+ const Eigen::MatrixBase<D1> & coordinates,
+ Eigen::MatrixBase<D2> & coordMatrix, Int integration_order) const {
switch (integration_order) {
case 1: {
- for (UInt i = 0; i < coordinates.cols(); ++i) {
+ for (Int i = 0; i < coordinates.cols(); ++i) {
coordMatrix(i, 0) = 1;
}
break;
}
case 2: {
- UInt nb_quadrature_points = coordMatrix.cols();
+ auto nb_quadrature_points = coordMatrix.cols();
- for (UInt i = 0; i < coordinates.cols(); ++i) {
+ for (Int i = 0; i < coordinates.cols(); ++i) {
coordMatrix(i, 0) = 1;
- for (UInt j = 1; j < nb_quadrature_points; ++j) {
+ for (Int j = 1; j < nb_quadrature_points; ++j) {
coordMatrix(i, j) = coordinates(j - 1, i);
}
}
break;
}
default: {
AKANTU_TO_IMPLEMENT();
break;
}
}
}
/* -------------------------------------------------------------------------- */
-template <ElementType type>
-inline void ShapeFunctions::buildElementalFieldInterpolationMatrix(
- const Matrix<Real> & /*unused*/, Matrix<Real> & /*unused*/,
- UInt /*unused*/) const {
- AKANTU_TO_IMPLEMENT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_segment_2>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
- buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_segment_3>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
- buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_triangle_3>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
- buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_triangle_6>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
- buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void
-ShapeFunctions::buildElementalFieldInterpolationMatrix<_tetrahedron_4>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
- buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void
-ShapeFunctions::buildElementalFieldInterpolationMatrix<_tetrahedron_10>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
- buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
-}
+template <ElementType type> struct BuildElementalFieldInterpolationMatrix {
+ template <typename ShapeFunction, typename D1, typename D2>
+ static inline void
+ call(ShapeFunction && func, const Eigen::MatrixBase<D1> & coordinates,
+ Eigen::MatrixBase<D2> & coord_matrix, Int integration_order) {
+ func.buildInterpolationMatrix(coordinates, coord_matrix, integration_order);
+ }
+};
/**
* @todo Write a more efficient interpolation for quadrangles by
* dropping unnecessary quadrature points
*
*/
-
/* -------------------------------------------------------------------------- */
-template <>
-inline void
-ShapeFunctions::buildElementalFieldInterpolationMatrix<_quadrangle_4>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
-
- if (integration_order !=
- ElementClassProperty<_quadrangle_4>::polynomial_degree) {
- AKANTU_TO_IMPLEMENT();
- } else {
- for (UInt i = 0; i < coordinates.cols(); ++i) {
- Real x = coordinates(0, i);
- Real y = coordinates(1, i);
-
- coordMatrix(i, 0) = 1;
- coordMatrix(i, 1) = x;
- coordMatrix(i, 2) = y;
- coordMatrix(i, 3) = x * y;
+template <> struct BuildElementalFieldInterpolationMatrix<_quadrangle_4> {
+ template <typename ShapeFunction, typename D1, typename D2>
+ static inline void
+ call(ShapeFunction && /*func*/, const Eigen::MatrixBase<D1> & coordinates,
+ Eigen::MatrixBase<D2> & coord_matrix, Int integration_order) {
+
+ if (integration_order !=
+ ElementClassProperty<_quadrangle_4>::polynomial_degree) {
+ AKANTU_TO_IMPLEMENT();
+ } else {
+ for (Int i = 0; i < coordinates.cols(); ++i) {
+ auto x = coordinates(0, i);
+ auto y = coordinates(1, i);
+
+ coord_matrix(i, 0) = 1;
+ coord_matrix(i, 1) = x;
+ coord_matrix(i, 2) = y;
+ coord_matrix(i, 3) = x * y;
+ }
}
}
-}
+};
/* -------------------------------------------------------------------------- */
-template <>
-inline void
-ShapeFunctions::buildElementalFieldInterpolationMatrix<_quadrangle_8>(
- const Matrix<Real> & /*unused*/ coordinates,
- Matrix<Real> & /*unused*/ coordMatrix,
- UInt /*unused*/ integration_order) const {
-
- if (integration_order !=
- ElementClassProperty<_quadrangle_8>::polynomial_degree) {
- AKANTU_TO_IMPLEMENT();
- } else {
- for (UInt i = 0; i < coordinates.cols(); ++i) {
- // UInt j = 0;
- Real x = coordinates(0, i);
- Real y = coordinates(1, i);
-
- coordMatrix(i, 0) = 1;
- coordMatrix(i, 1) = x;
- coordMatrix(i, 2) = y;
- coordMatrix(i, 3) = x * y;
- // for (UInt e = 0; e <= 2; ++e) {
- // for (UInt n = 0; n <= 2; ++n) {
- // coordMatrix(i, j) = std::pow(x, e) * std::pow(y, n);
- // ++j;
- // }
- // }
+template <> struct BuildElementalFieldInterpolationMatrix<_quadrangle_8> {
+ template <typename ShapeFunction, typename D1, typename D2>
+ static inline void
+ call(ShapeFunction && /*func*/, const Eigen::MatrixBase<D1> & coordinates,
+ Eigen::MatrixBase<D2> & coordMatrix, Int integration_order) {
+
+ if (integration_order !=
+ ElementClassProperty<_quadrangle_8>::polynomial_degree) {
+ AKANTU_TO_IMPLEMENT();
+ } else {
+ for (Int i = 0; i < coordinates.cols(); ++i) {
+ // Int j = 0;
+ auto x = coordinates(0, i);
+ auto y = coordinates(1, i);
+
+ coordMatrix(i, 0) = 1;
+ coordMatrix(i, 1) = x;
+ coordMatrix(i, 2) = y;
+ coordMatrix(i, 3) = x * y;
+ }
}
}
+};
+
+/* -------------------------------------------------------------------------- */
+template <ElementType type, typename D1, typename D2>
+inline void ShapeFunctions::buildElementalFieldInterpolationMatrix(
+ const Eigen::MatrixBase<D1> & coordinates,
+ Eigen::MatrixBase<D2> & coordMatrix, Int integration_order) const {
+ BuildElementalFieldInterpolationMatrix<type>::call(
+ *this, coordinates, coordMatrix, integration_order);
}
+
/* -------------------------------------------------------------------------- */
template <ElementType type>
inline void ShapeFunctions::interpolateElementalFieldFromIntegrationPoints(
const Array<Real> & field,
const Array<Real> & interpolation_points_coordinates_matrices,
const Array<Real> & quad_points_coordinates_inv_matrices,
ElementTypeMapArray<Real> & result, GhostType ghost_type,
- const Array<UInt> & element_filter) const {
+ const Array<Int> & element_filter) const {
AKANTU_DEBUG_IN();
- auto nb_element = this->mesh.getNbElement(type, ghost_type);
-
- auto nb_quad_per_element =
+ constexpr auto nb_quad_per_element =
GaussIntegrationElement<type>::getNbQuadraturePoints();
auto nb_interpolation_points_per_elem =
interpolation_points_coordinates_matrices.getNbComponent() /
nb_quad_per_element;
if (not result.exists(type, ghost_type)) {
+ auto nb_element = this->mesh.getNbElement(type, ghost_type);
result.alloc(nb_element * nb_interpolation_points_per_elem,
field.getNbComponent(), type, ghost_type);
}
- if (element_filter != empty_filter) {
- nb_element = element_filter.size();
- }
+ AKANTU_DEBUG_ASSERT(element_filter != empty_filter,
+ "This function does not work without an element_filter");
+ // auto nb_element = element_filter.size();
Matrix<Real> coefficients(nb_quad_per_element, field.getNbComponent());
- auto & result_vec = result(type, ghost_type);
-
- auto field_it = field.begin_reinterpret(field.getNbComponent(),
- nb_quad_per_element, nb_element);
-
- auto interpolation_points_coordinates_it =
- interpolation_points_coordinates_matrices.begin(
- nb_interpolation_points_per_elem, nb_quad_per_element);
-
- auto result_begin = result_vec.begin_reinterpret(
- field.getNbComponent(), nb_interpolation_points_per_elem,
- result_vec.size() / nb_interpolation_points_per_elem);
-
- auto inv_quad_coord_it = quad_points_coordinates_inv_matrices.begin(
- nb_quad_per_element, nb_quad_per_element);
+ auto result_begin =
+ make_view(result(type, ghost_type), field.getNbComponent(),
+ nb_interpolation_points_per_elem)
+ .begin();
/// loop over the elements of the current filter and element type
- for (UInt el = 0; el < nb_element; ++el, ++field_it, ++inv_quad_coord_it,
- ++interpolation_points_coordinates_it) {
+ for (auto && data :
+ zip(element_filter,
+ make_view(field, field.getNbComponent(), nb_quad_per_element),
+ make_view(interpolation_points_coordinates_matrices,
+ nb_interpolation_points_per_elem, nb_quad_per_element),
+ make_view(quad_points_coordinates_inv_matrices, nb_quad_per_element,
+ nb_quad_per_element))) {
/**
* matrix containing the inversion of the quadrature points'
* coordinates
*/
- const auto & inv_quad_coord_matrix = *inv_quad_coord_it;
+ auto && inv_quad_coord_matrix = std::get<3>(data);
/**
* multiply it by the field values over quadrature points to get
* the interpolation coefficients
*/
- coefficients.mul<false, true>(inv_quad_coord_matrix, *field_it);
+ coefficients = inv_quad_coord_matrix * std::get<1>(data).transpose();
/// matrix containing the points' coordinates
- const auto & coord = *interpolation_points_coordinates_it;
+ auto && coord = std::get<2>(data);
+ auto el = std::get<0>(data);
/// multiply the coordinates matrix by the coefficients matrix and store the
/// result
- Matrix<Real> res(result_begin[element_filter(el)]);
- res.mul<true, true>(coefficients, coord);
+ result_begin[el] = coefficients.transpose() * coord.transpose();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
inline void ShapeFunctions::interpolateElementalFieldOnIntegrationPoints(
const Array<Real> & u_el, Array<Real> & uq, GhostType ghost_type,
- const Array<Real> & shapes, const Array<UInt> & filter_elements) const {
+ const Array<Real> & shapes, const Array<Int> & filter_elements) const {
auto nb_element = mesh.getNbElement(type, ghost_type);
+
+ if (nb_element == 0) {
+ return;
+ }
+
auto nb_nodes_per_element = ElementClass<type>::getShapeSize();
- auto nb_points = shapes.size() / mesh.getNbElement(type, ghost_type);
+ auto nb_points = shapes.size() / nb_element;
auto nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
- Array<Real>::const_matrix_iterator N_it;
- Array<Real> * filtered_N = nullptr;
+ auto N_view = make_view(shapes, nb_nodes_per_element, nb_points);
+ std::unique_ptr<Array<Real>> filtered_N;
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
- filtered_N = new Array<Real>(0, shapes.getNbComponent());
+ filtered_N = std::make_unique<Array<Real>>(0, shapes.getNbComponent());
FEEngine::filterElementalData(mesh, shapes, *filtered_N, type, ghost_type,
filter_elements);
- N_it = filtered_N->begin_reinterpret(nb_nodes_per_element, nb_points,
- nb_element);
- } else {
- N_it =
- shapes.begin_reinterpret(nb_nodes_per_element, nb_points, nb_element);
+ N_view = make_const_view(*filtered_N, nb_nodes_per_element, nb_points);
}
uq.resize(nb_element * nb_points);
- auto u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element);
- auto inter_u_it =
- uq.begin_reinterpret(nb_degree_of_freedom, nb_points, nb_element);
+ for (auto && data :
+ zip(N_view, make_view(uq, nb_degree_of_freedom, nb_points),
+ make_view(u_el, nb_degree_of_freedom, nb_nodes_per_element))) {
+ const auto & u = std::get<2>(data);
+ const auto & N = std::get<0>(data);
+ auto & uq = std::get<1>(data);
- for (UInt el = 0; el < nb_element; ++el, ++N_it, ++u_it, ++inter_u_it) {
- const auto & u = *u_it;
- const auto & N = *N_it;
- auto & inter_u = *inter_u_it;
-
- inter_u.template mul<false, false>(u, N);
+ uq.noalias() = u * N;
}
-
- delete filtered_N;
}
/* -------------------------------------------------------------------------- */
-template <ElementType type>
+template <
+ ElementType type,
+ std::enable_if_t<ElementClass<type>::getNaturalSpaceDimension() != 0> *>
void ShapeFunctions::gradientElementalFieldOnIntegrationPoints(
const Array<Real> & u_el, Array<Real> & out_nablauq, GhostType ghost_type,
const Array<Real> & shapes_derivatives,
- const Array<UInt> & filter_elements) const {
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
- auto nb_nodes_per_element =
+ constexpr auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
+ constexpr auto element_dimension =
+ ElementClass<type>::getNaturalSpaceDimension();
+
auto nb_points = integration_points(type, ghost_type).cols();
- auto element_dimension = ElementClass<type>::getNaturalSpaceDimension();
- auto nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
auto nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
- Array<Real>::const_matrix_iterator B_it;
+ auto B_it =
+ make_view<element_dimension, nb_nodes_per_element>(shapes_derivatives)
+ .begin();
Array<Real> * filtered_B = nullptr;
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
filtered_B = new Array<Real>(0, shapes_derivatives.getNbComponent());
FEEngine::filterElementalData(mesh, shapes_derivatives, *filtered_B, type,
ghost_type, filter_elements);
- B_it = filtered_B->begin(element_dimension, nb_nodes_per_element);
- } else {
- B_it = shapes_derivatives.begin(element_dimension, nb_nodes_per_element);
+ B_it =
+ make_view<element_dimension, nb_nodes_per_element>(*filtered_B).begin();
}
out_nablauq.resize(nb_element * nb_points);
- auto u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element);
- auto nabla_u_it = out_nablauq.begin(nb_degree_of_freedom, element_dimension);
-
- for (UInt el = 0; el < nb_element; ++el, ++u_it) {
+ auto u_it = make_view<Eigen::Dynamic, nb_nodes_per_element>(
+ u_el, nb_degree_of_freedom, nb_nodes_per_element)
+ .begin();
+ auto nabla_u_it = make_view<Eigen::Dynamic, element_dimension>(
+ out_nablauq, nb_degree_of_freedom, element_dimension)
+ .begin();
+
+ for (Int el = 0; el < nb_element; ++el, ++u_it) {
const auto & u = *u_it;
- for (UInt q = 0; q < nb_points; ++q, ++B_it, ++nabla_u_it) {
+ for (Int q = 0; q < nb_points; ++q, ++B_it, ++nabla_u_it) {
const auto & B = *B_it;
auto & nabla_u = *nabla_u_it;
- nabla_u.template mul<false, true>(u, B);
+ nabla_u.noalias() = u * B.transpose();
}
}
delete filtered_B;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
-#endif /* AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_HH_ */
+//#endif /* AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/shape_lagrange.hh b/src/fe_engine/shape_lagrange.hh
index 7d3877dcc..eb2c04b12 100644
--- a/src/fe_engine/shape_lagrange.hh
+++ b/src/fe_engine/shape_lagrange.hh
@@ -1,176 +1,194 @@
/**
* @file shape_lagrange.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Feb 15 2011
* @date last modification: Fri May 14 2021
*
* @brief lagrangian shape functions class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "shape_lagrange_base.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_LAGRANGE_HH_
#define AKANTU_SHAPE_LAGRANGE_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Shape> class ShapeCohesive;
class ShapeIGFEM;
template <ElementKind kind> class ShapeLagrange : public ShapeLagrangeBase {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- ShapeLagrange(const Mesh & mesh, UInt spatial_dimension,
+ ShapeLagrange(const Mesh & mesh, Int spatial_dimension,
const ID & id = "shape_lagrange");
~ShapeLagrange() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialization function for structural elements not yet implemented
- inline void initShapeFunctions(const Array<Real> & nodes,
- const Matrix<Real> & integration_points,
- ElementType type, GhostType ghost_type);
+ template <typename D>
+ inline void
+ initShapeFunctions(const Array<Real> & nodes,
+ const Eigen::MatrixBase<D> & integration_points,
+ ElementType type, GhostType ghost_type);
/// computes the shape functions derivatives for given interpolation points
- template <ElementType type>
+ template <ElementType type, typename D>
void computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes,
+ const Eigen::MatrixBase<D> & integration_points,
Array<Real> & shape_derivatives, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
void computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shape_derivatives, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const override;
+ const Array<Idx> & filter_elements) const override;
/// pre compute all shapes on the element integration points from natural
/// coordinates
template <ElementType type>
void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// pre compute all shape derivatives on the element integration points from
/// natural coordinates
template <ElementType type>
void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// interpolate nodal values on the integration points
template <ElementType type>
void interpolateOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & uq, Int nb_degree_of_freedom,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
template <ElementType type>
void interpolateOnIntegrationPoints(
- const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom,
+ const Array<Real> & in_u, Array<Real> & out_uq, Int nb_degree_of_freedom,
const Array<Real> & shapes, GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// interpolate on physical point
- template <ElementType type>
- void interpolate(const Vector<Real> & real_coords, UInt elem,
- const Matrix<Real> & nodal_values,
- Vector<Real> & interpolated, GhostType ghost_type) const;
+ template <ElementType type, typename D1, typename D2, typename D3,
+ std::enable_if_t<aka::are_vectors<D1, D3>::value> * = nullptr>
+ void interpolate(const Eigen::MatrixBase<D1> & real_coords, Idx elem,
+ const Eigen::MatrixBase<D2> & nodal_values,
+ Eigen::MatrixBase<D3> & interpolated,
+ GhostType ghost_type) const;
/// compute the gradient of u on the integration points
template <ElementType type>
void gradientOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
+ const Array<Real> & u, Array<Real> & nablauq, Int nb_degree_of_freedom,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
template <ElementType type>
void computeBtD(const Array<Real> & Ds, Array<Real> & BtDs,
GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ const Array<Idx> & filter_elements) const;
- template <ElementType type>
- void computeBtDB(const Array<Real> & Ds, Array<Real> & BtDBs, UInt order_d,
+ template <ElementType type,
+ std::enable_if_t<ElementClass<type>::getNaturalSpaceDimension() !=
+ 0> * = nullptr>
+ void computeBtDB(const Array<Real> & Ds, Array<Real> & BtDBs, Int order_d,
GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ const Array<Idx> & filter_elements) const;
+
+ template <ElementType type,
+ std::enable_if_t<ElementClass<type>::getNaturalSpaceDimension() ==
+ 0> * = nullptr>
+ void computeBtDB(const Array<Real> & /*Ds*/, Array<Real> & /*BtDBs*/,
+ Int /*order_d*/, GhostType /*ghost_type*/,
+ const Array<Idx> & /*filter_elements*/) const {
+ AKANTU_TO_IMPLEMENT();
+ }
/// multiply a field by shape functions @f$ fts_{ij} = f_i * \varphi_j @f$
template <ElementType type>
void computeNtb(const Array<Real> & bs, Array<Real> & Ntbs,
GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
template <ElementType type>
void computeNtbN(const Array<Real> & bs, Array<Real> & NtbNs,
GhostType ghost_type,
- const Array<UInt> & filter_elements) const;
+ const Array<Idx> & filter_elements) const;
/// find natural coords from real coords provided an element
- template <ElementType type>
- void inverseMap(const Vector<Real> & real_coords, UInt element,
- Vector<Real> & natural_coords,
+ template <ElementType type, typename D1, typename D2>
+ void inverseMap(const Eigen::MatrixBase<D1> & real_coords, Idx element,
+ const Eigen::MatrixBase<D2> & natural_coords,
GhostType ghost_type = _not_ghost) const;
/// return true if the coordinates provided are inside the element, false
/// otherwise
- template <ElementType type>
- bool contains(const Vector<Real> & real_coords, UInt elem,
+ template <ElementType type, typename D,
+ std::enable_if_t<aka::is_vector_v<D>> *>
+ bool contains(const Eigen::MatrixBase<D> & real_coords, Idx elem,
GhostType ghost_type) const;
/// compute the shape on a provided point
- template <ElementType type>
- void computeShapes(const Vector<Real> & real_coords, UInt elem,
- Vector<Real> & shapes, GhostType ghost_type) const;
+ template <ElementType type, typename D1, typename D2>
+ void computeShapes(const Eigen::MatrixBase<D1> & real_coords, Idx elem,
+ Eigen::MatrixBase<D2> & shapes,
+ GhostType ghost_type) const;
/// compute the shape derivatives on a provided point
- template <ElementType type>
- void computeShapeDerivatives(const Matrix<Real> & real_coords, UInt elem,
- Tensor3<Real> & shapes,
+ template <ElementType type, typename D>
+ void computeShapeDerivatives(const Eigen::MatrixBase<D> & real_coords,
+ Idx elem, Tensor3Base<Real> & shapes,
GhostType ghost_type) const;
protected:
/// compute the shape derivatives on integration points for a given element
- template <ElementType type>
- inline void
- computeShapeDerivativesOnCPointsByElement(const Matrix<Real> & node_coords,
- const Matrix<Real> & natural_coords,
- Tensor3<Real> & shapesd) const;
+ template <ElementType type, typename D1, typename D2>
+ inline void computeShapeDerivativesOnCPointsByElement(
+ const Eigen::MatrixBase<D1> & node_coords,
+ const Eigen::MatrixBase<D2> & natural_coords,
+ Tensor3Base<Real> & shapesd) const;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "shape_lagrange_inline_impl.hh"
#endif /* AKANTU_SHAPE_LAGRANGE_HH_ */
diff --git a/src/fe_engine/shape_lagrange_base.cc b/src/fe_engine/shape_lagrange_base.cc
index eea7946b5..33579f783 100644
--- a/src/fe_engine/shape_lagrange_base.cc
+++ b/src/fe_engine/shape_lagrange_base.cc
@@ -1,173 +1,128 @@
/**
* @file shape_lagrange_base.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 09 2017
* @date last modification: Wed Dec 09 2020
*
* @brief common part for the shape lagrange
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "shape_lagrange_base.hh"
#include "mesh_iterators.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
-ShapeLagrangeBase::ShapeLagrangeBase(const Mesh & mesh, UInt spatial_dimension,
+ShapeLagrangeBase::ShapeLagrangeBase(const Mesh & mesh, Int spatial_dimension,
ElementKind kind, const ID & id)
: ShapeFunctions(mesh, spatial_dimension, id), _kind(kind) {}
/* -------------------------------------------------------------------------- */
ShapeLagrangeBase::~ShapeLagrangeBase() = default;
-/* -------------------------------------------------------------------------- */
-#define AKANTU_COMPUTE_SHAPES(type) \
- _this.template computeShapesOnIntegrationPoints<type>( \
- nodes, integration_points, shapes, ghost_type, filter_elements)
-
-namespace shape_lagrange {
- namespace details {
- template <ElementKind kind> struct Helper {
- template <class S>
- static void call(const S & /*unused*/, const Array<Real> & /*unused*/,
- const Matrix<Real> & /*unused*/,
- Array<Real> & /*unused*/, ElementType /*unused*/,
- GhostType /*unused*/, const Array<UInt> & /*unused*/) {
- AKANTU_TO_IMPLEMENT();
- }
- };
-
-#if !defined(DOXYGEN)
-#define AKANTU_COMPUTE_SHAPES_KIND(kind) \
- template <> struct Helper<kind> { \
- template <class S> \
- static void call(const S & _this, const Array<Real> & nodes, \
- const Matrix<Real> & integration_points, \
- Array<Real> & shapes, ElementType type, \
- GhostType ghost_type, \
- const Array<UInt> & filter_elements) { \
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(AKANTU_COMPUTE_SHAPES, kind); \
- } \
- };
-
- AKANTU_BOOST_ALL_KIND_LIST(AKANTU_COMPUTE_SHAPES_KIND,
- AKANTU_FE_ENGINE_LIST_LAGRANGE_BASE)
-
- } // namespace details
-} // namespace shape_lagrange
-#endif
-
/* -------------------------------------------------------------------------- */
void ShapeLagrangeBase::computeShapesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shapes, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
-
- auto kind = Mesh::getKind(type);
-
-#define AKANTU_COMPUTE_SHAPES_KIND_SWITCH(kind) \
- shape_lagrange::details::Helper<kind>::call( \
- *this, nodes, integration_points, shapes, type, ghost_type, \
- filter_elements);
-
- AKANTU_BOOST_LIST_SWITCH(
- AKANTU_COMPUTE_SHAPES_KIND_SWITCH,
- BOOST_PP_LIST_TO_SEQ(AKANTU_FE_ENGINE_LIST_LAGRANGE_BASE), kind);
-
-#undef AKANTU_COMPUTE_SHAPES
-#undef AKANTU_COMPUTE_SHAPES_KIND
-#undef AKANTU_COMPUTE_SHAPES_KIND_SWITCH
+ const Array<Idx> & filter_elements) const {
+ auto && call = [&](auto && enum_type) {
+ constexpr ElementType type = std ::decay_t<decltype(enum_type)>::value;
+ this->computeShapesOnIntegrationPoints<type>(
+ nodes, integration_points, shapes, ghost_type, filter_elements);
+ };
+ tuple_dispatch<
+ tuple::cat_t<ElementTypes_t<_ek_regular>, ElementTypes_t<_ek_cohesive>>>(
+ call, type);
}
/* -------------------------------------------------------------------------- */
void ShapeLagrangeBase::onElementsAdded(const Array<Element> & new_elements) {
AKANTU_DEBUG_IN();
const auto & nodes = mesh.getNodes();
for (auto elements_range : MeshElementsByTypes(new_elements)) {
auto type = elements_range.getType();
auto ghost_type = elements_range.getGhostType();
if (mesh.getSpatialDimension(type) != _spatial_dimension) {
continue;
}
- if (mesh.getKind(type) != _kind) {
+ if (Mesh::getKind(type) != _kind) {
continue;
}
const auto & elements = elements_range.getElements();
auto itp_type = FEEngine::getInterpolationType(type);
if (not shapes.exists(itp_type, ghost_type)) {
auto size_of_shapes = this->getShapeSize(type);
this->shapes.alloc(0, size_of_shapes, itp_type, ghost_type);
}
const auto & natural_coords = integration_points(type, ghost_type);
computeShapesOnIntegrationPoints(nodes, natural_coords,
shapes(itp_type, ghost_type), type,
ghost_type, elements);
if (_spatial_dimension != mesh.getSpatialDimension()) {
continue;
}
if (not this->shapes_derivatives.exists(itp_type, ghost_type)) {
auto size_of_shapesd = this->getShapeDerivativesSize(type);
this->shapes_derivatives.alloc(0, size_of_shapesd, itp_type, ghost_type);
}
computeShapeDerivativesOnIntegrationPoints(
nodes, natural_coords, shapes_derivatives(itp_type, ghost_type), type,
ghost_type, elements);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ShapeLagrangeBase::onElementsRemoved(
- const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & new_numbering) {
+ const Array<Element> &, const ElementTypeMapArray<Idx> & new_numbering) {
this->shapes.onElementsRemoved(new_numbering);
this->shapes_derivatives.onElementsRemoved(new_numbering);
}
/* -------------------------------------------------------------------------- */
void ShapeLagrangeBase::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "Shapes Lagrange [" << std::endl;
ShapeFunctions::printself(stream, indent + 1);
shapes.printself(stream, indent + 1);
shapes_derivatives.printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
} // namespace akantu
diff --git a/src/fe_engine/shape_lagrange_base.hh b/src/fe_engine/shape_lagrange_base.hh
index f6515b983..1cbbeade9 100644
--- a/src/fe_engine/shape_lagrange_base.hh
+++ b/src/fe_engine/shape_lagrange_base.hh
@@ -1,90 +1,90 @@
/**
* @file shape_lagrange_base.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 09 2017
* @date last modification: Tue Sep 29 2020
*
* @brief Base class for the shape lagrange
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "shape_functions.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_LAGRANGE_BASE_HH_
#define AKANTU_SHAPE_LAGRANGE_BASE_HH_
namespace akantu {
class ShapeLagrangeBase : public ShapeFunctions {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- ShapeLagrangeBase(const Mesh & mesh, UInt spatial_dimension, ElementKind kind,
+ ShapeLagrangeBase(const Mesh & mesh, Int spatial_dimension, ElementKind kind,
const ID & id = "shape_lagrange");
~ShapeLagrangeBase() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// computes the shape functions for given interpolation points
virtual void computeShapesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shapes, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Int> & filter_elements = empty_filter) const;
/// computes the shape functions derivatives for given interpolation points
virtual void computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shape_derivatives, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const = 0;
+ const Array<Int> & filter_elements = empty_filter) const = 0;
/// function to print the containt of the class
void printself(std::ostream & stream, int indent = 0) const override;
template <ElementType type>
void computeShapesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shapes, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Int> & filter_elements = empty_filter) const;
public:
void onElementsAdded(const Array<Element> & elements) override;
void
onElementsRemoved(const Array<Element> & elements,
- const ElementTypeMapArray<UInt> & new_numbering) override;
+ const ElementTypeMapArray<Idx> & new_numbering) override;
protected:
/// The kind to consider
ElementKind _kind;
};
} // namespace akantu
#include "shape_lagrange_base_inline_impl.hh"
#endif /* AKANTU_SHAPE_LAGRANGE_BASE_HH_ */
diff --git a/src/fe_engine/shape_lagrange_base_inline_impl.hh b/src/fe_engine/shape_lagrange_base_inline_impl.hh
index 7eab6e3ab..ec9922ab1 100644
--- a/src/fe_engine/shape_lagrange_base_inline_impl.hh
+++ b/src/fe_engine/shape_lagrange_base_inline_impl.hh
@@ -1,87 +1,88 @@
/**
* @file shape_lagrange_base_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 09 2017
* @date last modification: Tue Sep 29 2020
*
* @brief common part for the shape lagrange
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "shape_lagrange_base.hh"
+//#include "shape_lagrange_base.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_LAGRANGE_BASE_INLINE_IMPL_HH_
#define AKANTU_SHAPE_LAGRANGE_BASE_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <ElementType type>
void ShapeLagrangeBase::computeShapesOnIntegrationPoints(
- const Array<Real> & /*unused*/, const Matrix<Real> & integration_points,
+ const Array<Real> &, const Ref<const MatrixXr> integration_points,
Array<Real> & shapes, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt nb_points = integration_points.cols();
- UInt nb_element = mesh.getConnectivity(type, ghost_type).size();
+ auto nb_points = integration_points.cols();
+ auto nb_element = mesh.getConnectivity(type, ghost_type).size();
shapes.resize(nb_element * nb_points);
#if !defined(AKANTU_NDEBUG)
- UInt size_of_shapes = ElementClass<type>::getShapeSize();
+ auto size_of_shapes = ElementClass<type>::getShapeSize();
AKANTU_DEBUG_ASSERT(shapes.getNbComponent() == size_of_shapes,
"The shapes array does not have the correct "
<< "number of component");
#endif
- auto shapes_it = shapes.begin_reinterpret(
- ElementClass<type>::getNbNodesPerInterpolationElement(), nb_points,
- nb_element);
+ auto shapes_it =
+ make_view(shapes, ElementClass<type>::getNbNodesPerInterpolationElement(),
+ nb_points)
+ .begin();
auto shapes_begin = shapes_it;
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
- for (UInt elem = 0; elem < nb_element; ++elem) {
+ for (Int elem = 0; elem < nb_element; ++elem) {
if (filter_elements != empty_filter) {
shapes_it = shapes_begin + filter_elements(elem);
}
- Matrix<Real> & N = *shapes_it;
+ auto && N = *shapes_it;
ElementClass<type>::computeShapes(integration_points, N);
if (filter_elements == empty_filter) {
++shapes_it;
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif /* AKANTU_SHAPE_LAGRANGE_BASE_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/shape_lagrange_inline_impl.hh b/src/fe_engine/shape_lagrange_inline_impl.hh
index 199ce5c70..110323bb9 100644
--- a/src/fe_engine/shape_lagrange_inline_impl.hh
+++ b/src/fe_engine/shape_lagrange_inline_impl.hh
@@ -1,582 +1,553 @@
/**
* @file shape_lagrange_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Oct 27 2010
* @date last modification: Fri May 14 2021
*
* @brief ShapeLagrange inline implementation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "aka_voigthelper.hh"
#include "fe_engine.hh"
-#include "shape_lagrange.hh"
+//#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_LAGRANGE_INLINE_IMPL_HH_
#define AKANTU_SHAPE_LAGRANGE_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-#define INIT_SHAPE_FUNCTIONS(type) \
- setIntegrationPointsByType<type>(integration_points, ghost_type); \
- precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type); \
- if (ElementClass<type>::getNaturalSpaceDimension() == \
- mesh.getSpatialDimension() || \
- kind != _ek_regular) \
- precomputeShapeDerivativesOnIntegrationPoints<type>(nodes, ghost_type);
-
template <ElementKind kind>
+template <typename D>
inline void ShapeLagrange<kind>::initShapeFunctions(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & /*nodes*/,
+ const Eigen::MatrixBase<D> & /*integration_points*/, ElementType /*type*/,
+ GhostType /*ghost_type*/) {}
+
+/* -------------------------------------------------------------------------- */
+template <>
+template <typename D>
+inline void ShapeLagrange<_ek_regular>::initShapeFunctions(
+ const Array<Real> & nodes, const Eigen::MatrixBase<D> & integration_points,
ElementType type, GhostType ghost_type) {
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
+ tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = std::decay_t<decltype(enum_type)>::value;
+ this->setIntegrationPointsByType<type>(integration_points, ghost_type);
+ this->precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type);
+ if (ElementClass<type>::getNaturalSpaceDimension() ==
+ mesh.getSpatialDimension()) {
+ this->precomputeShapeDerivativesOnIntegrationPoints<type>(nodes,
+ ghost_type);
+ }
+ },
+ type);
}
-#undef INIT_SHAPE_FUNCTIONS
-
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
+template <ElementType type, typename D1, typename D2>
inline void ShapeLagrange<kind>::computeShapeDerivativesOnCPointsByElement(
- const Matrix<Real> & node_coords, const Matrix<Real> & natural_coords,
- Tensor3<Real> & shapesd) const {
+ const Eigen::MatrixBase<D1> & node_coords,
+ const Eigen::MatrixBase<D2> & natural_coords,
+ Tensor3Base<Real> & shapesd) const {
AKANTU_DEBUG_IN();
// compute dnds
Tensor3<Real> dnds(node_coords.rows(), node_coords.cols(),
natural_coords.cols());
ElementClass<type>::computeDNDS(natural_coords, dnds);
// compute jacobian
Tensor3<Real> J(node_coords.rows(), natural_coords.rows(),
natural_coords.cols());
ElementClass<type>::computeJMat(dnds, node_coords, J);
// compute dndx
ElementClass<type>::computeShapeDerivatives(J, dnds, shapesd);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
-void ShapeLagrange<kind>::inverseMap(const Vector<Real> & real_coords,
- UInt elem, Vector<Real> & natural_coords,
- GhostType ghost_type) const {
-
+template <ElementType type, typename D1, typename D2>
+void ShapeLagrange<kind>::inverseMap(
+ const Eigen::MatrixBase<D1> & real_coords, Int elem,
+ const Eigen::MatrixBase<D2> & natural_coords_, GhostType ghost_type) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt nb_nodes_per_element =
- ElementClass<type>::getNbNodesPerInterpolationElement();
-
- UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage();
- Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
+ // as advised by the Eigen developers even though this is a UB
+ auto & natural_coords = const_cast<Eigen::MatrixBase<D2> &>(natural_coords_);
- mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.storage(),
- elem_val + elem * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
+ auto nodes_coord = mesh.extractNodalValuesFromElement(
+ mesh.getNodes(), Element{type, elem, ghost_type});
ElementClass<type>::inverseMap(real_coords, nodes_coord, natural_coords);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
-bool ShapeLagrange<kind>::contains(const Vector<Real> & real_coords, UInt elem,
- GhostType ghost_type) const {
-
- UInt spatial_dimension = mesh.getSpatialDimension();
+template <ElementType type, typename D, std::enable_if_t<aka::is_vector_v<D>> *>
+bool ShapeLagrange<kind>::contains(const Eigen::MatrixBase<D> & real_coords,
+ Idx elem, GhostType ghost_type) const {
+ auto spatial_dimension = mesh.getSpatialDimension();
Vector<Real> natural_coords(spatial_dimension);
inverseMap<type>(real_coords, elem, natural_coords, ghost_type);
return ElementClass<type>::contains(natural_coords);
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
-void ShapeLagrange<kind>::interpolate(const Vector<Real> & real_coords,
- UInt elem,
- const Matrix<Real> & nodal_values,
- Vector<Real> & interpolated,
- GhostType ghost_type) const {
- UInt nb_shapes = ElementClass<type>::getShapeSize();
- Vector<Real> shapes(nb_shapes);
+template <ElementType type, typename D1, typename D2, typename D3,
+ std::enable_if_t<aka::are_vectors<D1, D3>::value> *>
+void ShapeLagrange<kind>::interpolate(
+ const Eigen::MatrixBase<D1> & real_coords, Idx elem,
+ const Eigen::MatrixBase<D2> & nodal_values,
+ Eigen::MatrixBase<D3> & interpolated, GhostType ghost_type) const {
+ constexpr auto nb_shapes = ElementClass<type>::getShapeSize();
+ Vector<Real, nb_shapes> shapes;
computeShapes<type>(real_coords, elem, shapes, ghost_type);
ElementClass<type>::interpolate(nodal_values, shapes, interpolated);
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
-void ShapeLagrange<kind>::computeShapes(const Vector<Real> & real_coords,
- UInt elem, Vector<Real> & shapes,
- GhostType ghost_type) const {
-
+template <ElementType type, typename D1, typename D2>
+void ShapeLagrange<kind>::computeShapes(
+ const Eigen::MatrixBase<D1> & real_coords, Idx elem,
+ Eigen::MatrixBase<D2> & shapes, GhostType ghost_type) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
Vector<Real> natural_coords(spatial_dimension);
inverseMap<type>(real_coords, elem, natural_coords, ghost_type);
ElementClass<type>::computeShapes(natural_coords, shapes);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
+template <ElementType type, typename D>
void ShapeLagrange<kind>::computeShapeDerivatives(
- const Matrix<Real> & real_coords, UInt elem, Tensor3<Real> & shapesd,
- GhostType ghost_type) const {
-
+ const Eigen::MatrixBase<D> & real_coords, Idx elem,
+ Tensor3Base<Real> & shapesd, GhostType ghost_type) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt nb_points = real_coords.cols();
- UInt nb_nodes_per_element =
- ElementClass<type>::getNbNodesPerInterpolationElement();
+ auto spatial_dimension = mesh.getSpatialDimension();
+ auto nb_points = real_coords.cols();
+#if !defined(AKANTU_NDEBUG)
+ const auto nb_nodes_per_element =
+ ElementClass<type>::getNbNodesPerInterpolationElement();
AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == shapesd.size(0) &&
nb_nodes_per_element == shapesd.size(1),
"Shape size doesn't match");
AKANTU_DEBUG_ASSERT(nb_points == shapesd.size(2),
"Number of points doesn't match shapes size");
+#endif
Matrix<Real> natural_coords(spatial_dimension, nb_points);
// Creates the matrix of natural coordinates
- for (UInt i = 0; i < nb_points; i++) {
- Vector<Real> real_point = real_coords(i);
- Vector<Real> natural_point = natural_coords(i);
-
- inverseMap<type>(real_point, elem, natural_point, ghost_type);
+ for (Int i = 0; i < nb_points; i++) {
+ inverseMap<type>(real_coords(i), elem, natural_coords(i), ghost_type);
}
- UInt * elem_val = mesh.getConnectivity(type, ghost_type).storage();
- Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
-
- mesh.extractNodalValuesFromElement(mesh.getNodes(), nodes_coord.storage(),
- elem_val + elem * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
+ auto nodes_coord = mesh.extractNodalValuesFromElement(
+ mesh.getNodes(), Element{type, elem, ghost_type});
computeShapeDerivativesOnCPointsByElement<type>(nodes_coord, natural_coords,
shapesd);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-ShapeLagrange<kind>::ShapeLagrange(const Mesh & mesh, UInt spatial_dimension,
+ShapeLagrange<kind>::ShapeLagrange(const Mesh & mesh, Int spatial_dimension,
const ID & id)
: ShapeLagrangeBase(mesh, spatial_dimension, kind, id) {}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
+template <ElementType type, typename D>
void ShapeLagrange<kind>::computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Eigen::MatrixBase<D> & integration_points,
Array<Real> & shape_derivatives, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
- UInt nb_nodes_per_element =
+ auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
- UInt nb_points = integration_points.cols();
- UInt nb_element = mesh.getConnectivity(type, ghost_type).size();
+ auto nb_points = integration_points.cols();
+ auto nb_element = mesh.getConnectivity(type, ghost_type).size();
- UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
+ auto size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
AKANTU_DEBUG_ASSERT(shape_derivatives.getNbComponent() == size_of_shapesd,
"The shapes_derivatives array does not have the correct "
<< "number of component");
shape_derivatives.resize(nb_element * nb_points);
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type,
filter_elements);
- Real * shapesd_val = shape_derivatives.storage();
- Array<Real>::matrix_iterator x_it =
- x_el.begin(spatial_dimension, nb_nodes_per_element);
+ auto * shapesd_val = shape_derivatives.data();
+ auto x_it = x_el.begin(spatial_dimension, nb_nodes_per_element);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
- for (UInt elem = 0; elem < nb_element; ++elem, ++x_it) {
+ for (Int elem = 0; elem < nb_element; ++elem, ++x_it) {
if (filter_elements != empty_filter) {
- shapesd_val = shape_derivatives.storage() +
+ shapesd_val = shape_derivatives.data() +
filter_elements(elem) * size_of_shapesd * nb_points;
}
- Matrix<Real> & X = *x_it;
- Tensor3<Real> B(shapesd_val, spatial_dimension, nb_nodes_per_element,
- nb_points);
+ auto & X = *x_it;
+ Tensor3Proxy<Real> B(shapesd_val, spatial_dimension, nb_nodes_per_element,
+ nb_points);
computeShapeDerivativesOnCPointsByElement<type>(X, integration_points, B);
if (filter_elements == empty_filter) {
shapesd_val += size_of_shapesd * nb_points;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
void ShapeLagrange<kind>::computeShapeDerivativesOnIntegrationPoints(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ const Array<Real> & nodes, const Ref<const MatrixXr> integration_points,
Array<Real> & shape_derivatives, ElementType type, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
-#define AKANTU_COMPUTE_SHAPES(type) \
- computeShapeDerivativesOnIntegrationPoints<type>( \
- nodes, integration_points, shape_derivatives, ghost_type, \
- filter_elements);
-
- AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(AKANTU_COMPUTE_SHAPES);
-
-#undef AKANTU_COMPUTE_SHAPES
+ const Array<Idx> & filter_elements) const {
+ tuple_dispatch<ElementTypes_t<_ek_regular>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->computeShapeDerivativesOnIntegrationPoints<type>(
+ nodes, integration_points, shape_derivatives, ghost_type,
+ filter_elements);
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeLagrange<kind>::precomputeShapesOnIntegrationPoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
Matrix<Real> & natural_coords = integration_points(type, ghost_type);
- UInt size_of_shapes = ElementClass<type>::getShapeSize();
+ auto size_of_shapes = ElementClass<type>::getShapeSize();
Array<Real> & shapes_tmp =
shapes.alloc(0, size_of_shapes, itp_type, ghost_type);
this->computeShapesOnIntegrationPoints<type>(nodes, natural_coords,
shapes_tmp, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeLagrange<kind>::precomputeShapeDerivativesOnIntegrationPoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
Matrix<Real> & natural_coords = integration_points(type, ghost_type);
- UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
+ auto size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
Array<Real> & shapes_derivatives_tmp =
shapes_derivatives.alloc(0, size_of_shapesd, itp_type, ghost_type);
this->computeShapeDerivativesOnIntegrationPoints<type>(
nodes, natural_coords, shapes_derivatives_tmp, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeLagrange<kind>::interpolateOnIntegrationPoints(
- const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom,
+ const Array<Real> & in_u, Array<Real> & out_uq, Int nb_degree_of_freedom,
const Array<Real> & shapes, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
- UInt nb_nodes_per_element =
+ auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type,
filter_elements);
this->interpolateElementalFieldOnIntegrationPoints<type>(
u_el, out_uq, ghost_type, shapes, filter_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeLagrange<kind>::interpolateOnIntegrationPoints(
- const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_degree_of_freedom,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ const Array<Real> & in_u, Array<Real> & out_uq, Int nb_degree_of_freedom,
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
AKANTU_DEBUG_ASSERT(shapes.exists(itp_type, ghost_type),
"No shapes for the type "
<< shapes.printType(itp_type, ghost_type));
this->interpolateOnIntegrationPoints<type>(in_u, out_uq, nb_degree_of_freedom,
shapes(itp_type, ghost_type),
ghost_type, filter_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeLagrange<kind>::gradientOnIntegrationPoints(
const Array<Real> & in_u, Array<Real> & out_nablauq,
- UInt nb_degree_of_freedom, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ Int nb_degree_of_freedom, GhostType ghost_type,
+ const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
InterpolationType itp_type = ElementClassProperty<type>::interpolation_type;
AKANTU_DEBUG_ASSERT(
shapes_derivatives.exists(itp_type, ghost_type),
"No shapes derivatives for the type "
<< shapes_derivatives.printType(itp_type, ghost_type));
- UInt nb_nodes_per_element =
+ auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
Array<Real> u_el(0, nb_degree_of_freedom * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type,
filter_elements);
this->gradientElementalFieldOnIntegrationPoints<type>(
u_el, out_nablauq, ghost_type, shapes_derivatives(itp_type, ghost_type),
filter_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
-void ShapeLagrange<kind>::computeBtD(
- const Array<Real> & Ds, Array<Real> & BtDs, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+void ShapeLagrange<kind>::computeBtD(const Array<Real> & Ds, Array<Real> & BtDs,
+ GhostType ghost_type,
+ const Array<Idx> & filter_elements) const {
auto itp_type = ElementClassProperty<type>::interpolation_type;
const auto & shapes_derivatives =
this->shapes_derivatives(itp_type, ghost_type);
auto spatial_dimension = mesh.getSpatialDimension();
auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> shapes_derivatives_filtered(0,
shapes_derivatives.getNbComponent());
- auto && view =
- make_view(shapes_derivatives, spatial_dimension, nb_nodes_per_element);
- auto B_it = view.begin();
- auto B_end = view.end();
+ auto view = make_const_view(shapes_derivatives, spatial_dimension,
+ nb_nodes_per_element);
if (filter_elements != empty_filter) {
FEEngine::filterElementalData(this->mesh, shapes_derivatives,
shapes_derivatives_filtered, type, ghost_type,
filter_elements);
- auto && view = make_view(shapes_derivatives_filtered, spatial_dimension,
- nb_nodes_per_element);
- B_it = view.begin();
- B_end = view.end();
+ view = make_const_view(shapes_derivatives_filtered, spatial_dimension,
+ nb_nodes_per_element);
}
for (auto && values :
- zip(range(B_it, B_end),
+ zip(view,
make_view(Ds, Ds.getNbComponent() / spatial_dimension,
spatial_dimension),
make_view(BtDs, BtDs.getNbComponent() / nb_nodes_per_element,
nb_nodes_per_element))) {
const auto & B = std::get<0>(values);
const auto & D = std::get<1>(values);
auto & Bt_D = std::get<2>(values);
// transposed due to the storage layout of B
- Bt_D.template mul<false, false>(D, B);
+ Bt_D.noalias() = D * B;
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
-template <ElementType type>
+template <
+ ElementType type,
+ std::enable_if_t<ElementClass<type>::getNaturalSpaceDimension() != 0> *>
void ShapeLagrange<kind>::computeBtDB(
- const Array<Real> & Ds, Array<Real> & BtDBs, UInt order_d,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ const Array<Real> & Ds, Array<Real> & BtDBs, Int order_d,
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
auto itp_type = ElementClassProperty<type>::interpolation_type;
const auto & shapes_derivatives =
this->shapes_derivatives(itp_type, ghost_type);
constexpr auto dim = ElementClass<type>::getSpatialDimension();
auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> shapes_derivatives_filtered(0,
shapes_derivatives.getNbComponent());
- auto && view = make_view(shapes_derivatives, dim, nb_nodes_per_element);
- auto B_it = view.begin();
- auto B_end = view.end();
+ auto && view = make_const_view(shapes_derivatives, dim, nb_nodes_per_element);
if (filter_elements != empty_filter) {
FEEngine::filterElementalData(this->mesh, shapes_derivatives,
shapes_derivatives_filtered, type, ghost_type,
filter_elements);
- auto && view =
- make_view(shapes_derivatives_filtered, dim, nb_nodes_per_element);
- B_it = view.begin();
- B_end = view.end();
+ view =
+ make_const_view(shapes_derivatives_filtered, dim, nb_nodes_per_element);
}
if (order_d == 4) {
- UInt tangent_size = VoigtHelper<dim>::size;
+ auto tangent_size = VoigtHelper<dim>::size;
Matrix<Real> B(tangent_size, dim * nb_nodes_per_element);
- Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size);
- for (auto && values :
- zip(range(B_it, B_end), make_view(Ds, tangent_size, tangent_size),
- make_view(BtDBs, dim * nb_nodes_per_element,
- dim * nb_nodes_per_element))) {
+ for (auto && values : zip(view, make_view(Ds, tangent_size, tangent_size),
+ make_view(BtDBs, dim * nb_nodes_per_element,
+ dim * nb_nodes_per_element))) {
const auto & Bfull = std::get<0>(values);
const auto & D = std::get<1>(values);
auto & Bt_D_B = std::get<2>(values);
VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(Bfull, B,
nb_nodes_per_element);
- Bt_D.template mul<true, false>(B, D);
- Bt_D_B.template mul<false, false>(Bt_D, B);
+ Bt_D_B.noalias() = B.transpose() * D * B;
}
} else if (order_d == 2) {
- Matrix<Real> Bt_D(nb_nodes_per_element, dim);
for (auto && values :
- zip(range(B_it, B_end), make_view(Ds, dim, dim),
+ zip(view, make_view(Ds, dim, dim),
make_view(BtDBs, nb_nodes_per_element, nb_nodes_per_element))) {
const auto & B = std::get<0>(values);
const auto & D = std::get<1>(values);
auto & Bt_D_B = std::get<2>(values);
- Bt_D.template mul<true, false>(B, D);
- Bt_D_B.template mul<false, false>(Bt_D, B);
+ Bt_D_B.noalias() = B.transpose() * D * B;
}
}
}
-template <>
-template <>
-inline void ShapeLagrange<_ek_regular>::computeBtDB<_point_1>(
- const Array<Real> & /*Ds*/, Array<Real> & /*BtDBs*/, UInt /*order_d*/,
- GhostType /*ghost_type*/, const Array<UInt> & /*filter_elements*/) const {
- AKANTU_TO_IMPLEMENT();
-}
-
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeLagrange<kind>::computeNtbN(
const Array<Real> & bs, Array<Real> & NtbNs, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
auto itp_type = ElementClassProperty<type>::interpolation_type;
auto size_of_shapes = ElementClass<type>::getShapeSize();
auto nb_degree_of_freedom = bs.getNbComponent();
auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> shapes_filtered(0, size_of_shapes);
- auto && view = make_view(shapes(itp_type, ghost_type), 1, size_of_shapes);
- auto N_it = view.begin();
- auto N_end = view.end();
+ auto && view =
+ make_const_view(shapes(itp_type, ghost_type), 1, size_of_shapes);
if (filter_elements != empty_filter) {
FEEngine::filterElementalData(this->mesh, shapes(itp_type, ghost_type),
shapes_filtered, type, ghost_type,
filter_elements);
- auto && view = make_view(shapes_filtered, 1, size_of_shapes);
- N_it = view.begin();
- N_end = view.end();
+ view = make_const_view(shapes_filtered, 1, size_of_shapes);
}
Matrix<Real> Nt_b(nb_nodes_per_element, nb_degree_of_freedom);
for (auto && values :
- zip(range(N_it, N_end), make_view(bs, nb_degree_of_freedom, 1),
+ zip(view, make_view(bs, nb_degree_of_freedom, 1),
make_view(NtbNs, nb_nodes_per_element, nb_nodes_per_element))) {
const auto & N = std::get<0>(values);
const auto & b = std::get<1>(values);
auto & Nt_b_N = std::get<2>(values);
- Nt_b.template mul<true, false>(N, b);
- Nt_b_N.template mul<false, false>(Nt_b, N);
+
+ Nt_b_N.noalias() = N.transpose() * b * N;
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
-void ShapeLagrange<kind>::computeNtb(
- const Array<Real> & bs, Array<Real> & Ntbs, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+void ShapeLagrange<kind>::computeNtb(const Array<Real> & bs, Array<Real> & Ntbs,
+ GhostType ghost_type,
+ const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
Ntbs.resize(bs.size());
auto size_of_shapes = ElementClass<type>::getShapeSize();
auto itp_type = ElementClassProperty<type>::interpolation_type;
auto nb_degree_of_freedom = bs.getNbComponent();
Array<Real> shapes_filtered(0, size_of_shapes);
- auto && view = make_view(shapes(itp_type, ghost_type), 1, size_of_shapes);
- auto N_it = view.begin();
- auto N_end = view.end();
+ auto && view =
+ make_const_view(shapes(itp_type, ghost_type), 1, size_of_shapes);
if (filter_elements != empty_filter) {
FEEngine::filterElementalData(this->mesh, shapes(itp_type, ghost_type),
shapes_filtered, type, ghost_type,
filter_elements);
- auto && view = make_view(shapes_filtered, 1, size_of_shapes);
- N_it = view.begin();
- N_end = view.end();
+ view = make_const_view(shapes_filtered, 1, size_of_shapes);
}
for (auto && values :
- zip(make_view(bs, nb_degree_of_freedom, 1), range(N_it, N_end),
+ zip(make_view(bs, nb_degree_of_freedom, 1), view,
make_view(Ntbs, nb_degree_of_freedom, size_of_shapes))) {
const auto & b = std::get<0>(values);
const auto & N = std::get<1>(values);
auto & Ntb = std::get<2>(values);
- Ntb.template mul<false, false>(b, N);
+ Ntb.noalias() = b * N;
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif /* AKANTU_SHAPE_LAGRANGE_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/shape_structural.cc b/src/fe_engine/shape_structural.cc
index 7eb5af079..86e2fda16 100644
--- a/src/fe_engine/shape_structural.cc
+++ b/src/fe_engine/shape_structural.cc
@@ -1,54 +1,54 @@
/**
* @file shape_structural.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Tue Aug 27 2019
*
* @brief ShapeStructural implementation
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "shape_structural.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <>
ShapeStructural<_ek_structural>::ShapeStructural(Mesh & mesh,
- UInt spatial_dimension,
+ Int spatial_dimension,
const ID & id)
: ShapeFunctions(mesh, spatial_dimension, id),
rotation_matrices("rotation_matrices", id) {}
/* -------------------------------------------------------------------------- */
template <> ShapeStructural<_ek_structural>::~ShapeStructural() = default;
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/fe_engine/shape_structural.hh b/src/fe_engine/shape_structural.hh
index d2fd99cea..b8e730620 100644
--- a/src/fe_engine/shape_structural.hh
+++ b/src/fe_engine/shape_structural.hh
@@ -1,201 +1,202 @@
/**
* @file shape_structural.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Feb 15 2011
* @date last modification: Fri May 14 2021
*
* @brief shape class for element with different set of shapes functions
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "shape_functions.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SHAPE_STRUCTURAL_HH_
#define AKANTU_SHAPE_STRUCTURAL_HH_
namespace akantu {
template <ElementKind kind> class ShapeStructural : public ShapeFunctions {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
// Ctors/Dtors should be explicitely implemented for _ek_structural
public:
- ShapeStructural(Mesh & mesh, UInt spatial_dimension,
+ ShapeStructural(Mesh & mesh, Int spatial_dimension,
const ID & id = "shape_structural");
~ShapeStructural() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override {
std::string space(indent, AKANTU_INDENT);
stream << space << "ShapesStructural [" << std::endl;
rotation_matrices.printself(stream, indent + 1);
ShapeFunctions::printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
private:
template <ElementType type>
void computeShapesOnIntegrationPointsInternal(
const Array<Real> & nodes, const Matrix<Real> & integration_points,
Array<Real> & shapes, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter,
+ const Array<Idx> & filter_elements = empty_filter,
bool mass = false) const;
public:
/// compute shape functions on given integration points
template <ElementType type>
void computeShapesOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & integration_points,
Array<Real> & shapes, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const {
+ const Array<Idx> & filter_elements = empty_filter) const {
this->template computeShapesOnIntegrationPointsInternal<type>(
nodes, integration_points, shapes, ghost_type, filter_elements, false);
}
template <ElementType type>
void computeShapesMassOnIntegrationPoints(
const Array<Real> & nodes, const Matrix<Real> & integration_points,
Array<Real> & shapes, GhostType ghost_type,
- const Array<UInt> & filter_elements = empty_filter) const {
+ const Array<Idx> & filter_elements = empty_filter) const {
this->template computeShapesOnIntegrationPointsInternal<type>(
nodes, integration_points, shapes, ghost_type, filter_elements, true);
}
/// initialization function for structural elements
inline void initShapeFunctions(const Array<Real> & nodes,
const Matrix<Real> & integration_points,
ElementType type, GhostType ghost_type);
/// precompute the rotation matrices for the elements dofs
template <ElementType type>
void precomputeRotationMatrices(const Array<Real> & nodes,
GhostType ghost_type);
/// pre compute all shapes on the element integration points from natural
/// coordinates
template <ElementType type>
void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// pre compute all shapes on the element integration points from natural
/// coordinates
template <ElementType type>
void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes,
GhostType ghost_type);
/// interpolate nodal values on the integration points
template <ElementType type>
void interpolateOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & uq, UInt nb_dof,
+ const Array<Real> & u, Array<Real> & uq, Int nb_dof,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// compute the gradient of u on the integration points
template <ElementType type>
void gradientOnIntegrationPoints(
- const Array<Real> & u, Array<Real> & nablauq, UInt nb_dof,
+ const Array<Real> & u, Array<Real> & nablauq, Int nb_dof,
GhostType ghost_type = _not_ghost,
- const Array<UInt> & filter_elements = empty_filter) const;
+ const Array<Idx> & filter_elements = empty_filter) const;
/// interpolate on physical point
- template <ElementType type>
- void interpolate(const Vector<Real> & /*real_coords*/, UInt /*elem*/,
- const Matrix<Real> & /*nodal_values*/,
- Vector<Real> & /*interpolated*/,
+ template <ElementType type, typename D1, typename D2, typename D3,
+ aka::enable_if_t<aka::are_vectors<D1, D3>::value> * = nullptr>
+ void interpolate(const Eigen::MatrixBase<D1> & /*real_coords*/, Idx /*elem*/,
+ const Eigen::MatrixBase<D2> & /*nodal_values*/,
+ Eigen::MatrixBase<D3> & /*interpolated*/,
GhostType /*ghost_type*/) const {
AKANTU_TO_IMPLEMENT();
}
/// compute the shapes on a provided point
- template <ElementType type>
- void computeShapes(const Vector<Real> & /*real_coords*/, UInt /*elem*/,
- Vector<Real> & /*shapes*/,
+ template <ElementType type, typename D1, typename D2,
+ aka::enable_if_t<aka::are_vectors<D1, D2>::value> * = nullptr>
+ void computeShapes(const Eigen::MatrixBase<D1> & /*real_coords*/,
+ Idx /*elem*/, Eigen::MatrixBase<D2> & /*shapes*/,
GhostType /*ghost_type*/) const {
AKANTU_TO_IMPLEMENT();
}
/// compute the shape derivatives on a provided point
- template <ElementType type>
- void computeShapeDerivatives(const Matrix<Real> & /*real_coords*/,
- UInt /*elem*/, Tensor3<Real> & /*shapes*/,
+ template <ElementType type, typename D1>
+ void computeShapeDerivatives(const Eigen::MatrixBase<D1> & /*real_coords*/,
+ Idx /*elem*/, Tensor3Base<Real> & /*shapes*/,
GhostType /*ghost_type*/) const {
AKANTU_TO_IMPLEMENT();
}
/// get the rotations vector
inline const Array<Real> &
getRotations(ElementType el_type,
GhostType /*ghost_type*/ = _not_ghost) const {
return rotation_matrices(el_type);
}
/* ------------------------------------------------------------------------ */
template <ElementType type>
void computeBtD(const Array<Real> & /*Ds*/, Array<Real> & /*BtDs*/,
GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/) const {
+ const Array<Idx> & /*filter_elements*/) const {
AKANTU_TO_IMPLEMENT();
}
template <ElementType type>
void computeBtDB(const Array<Real> & /*Ds*/, Array<Real> & /*BtDBs*/,
- UInt /*order_d*/, GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/) const {
+ Int /*order_d*/, GhostType /*ghost_type*/,
+ const Array<Idx> & /*filter_elements*/) const {
AKANTU_TO_IMPLEMENT();
}
template <ElementType type>
void computeNtbN(const Array<Real> & /*bs*/, Array<Real> & /*NtbNs*/,
GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/) const {
+ const Array<Idx> & /*filter_elements*/) const {
AKANTU_TO_IMPLEMENT();
}
/// multiply a field by shape functions
template <ElementType type>
- void
- computeNtb(const Array<Real> & /*bs*/, Array<Real> & /*Ntbs*/,
- GhostType /*ghost_type*/,
- const Array<UInt> & /*filter_elements*/ = empty_filter) const {
+ void computeNtb(const Array<Real> & /*bs*/, Array<Real> & /*Ntbs*/,
+ GhostType /*ghost_type*/,
+ const Array<Idx> & /*filter_elements*/ = empty_filter) const {
AKANTU_TO_IMPLEMENT();
}
protected:
ElementTypeMapArray<Real> rotation_matrices;
};
} // namespace akantu
#include "shape_structural_inline_impl.hh"
#endif /* AKANTU_SHAPE_STRUCTURAL_HH_ */
diff --git a/src/fe_engine/shape_structural_inline_impl.hh b/src/fe_engine/shape_structural_inline_impl.hh
index d43c18e10..6518494ab 100644
--- a/src/fe_engine/shape_structural_inline_impl.hh
+++ b/src/fe_engine/shape_structural_inline_impl.hh
@@ -1,511 +1,504 @@
/**
* @file shape_structural_inline_impl.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Oct 11 2017
* @date last modification: Mon Feb 01 2021
*
* @brief ShapeStructural inline implementation
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_iterators.hh"
#include "shape_structural.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_HH_
-#define AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_HH_
+//#ifndef AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_HH_
+//#define AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_HH_
namespace akantu {
namespace {
/// Extract nodal coordinates per elements
template <ElementType type>
std::unique_ptr<Array<Real>> getNodesPerElement(const Mesh & mesh,
const Array<Real> & nodes,
GhostType ghost_type) {
const auto dim = ElementClass<type>::getSpatialDimension();
const auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto nodes_per_element =
std::make_unique<Array<Real>>(0, dim * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, *nodes_per_element, type,
ghost_type);
return nodes_per_element;
}
} // namespace
-template <ElementKind kind>
-inline void ShapeStructural<kind>::initShapeFunctions(
- const Array<Real> & /* unused */, const Matrix<Real> & /* unused */,
- ElementType /* unused */, GhostType /* unused */) {
- AKANTU_TO_IMPLEMENT();
-}
-
-/* -------------------------------------------------------------------------- */
-#define INIT_SHAPE_FUNCTIONS(type) \
- setIntegrationPointsByType<type>(integration_points, ghost_type); \
- precomputeRotationMatrices<type>(nodes, ghost_type); \
- precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type); \
- precomputeShapeDerivativesOnIntegrationPoints<type>(nodes, ghost_type);
-
-template <>
-inline void ShapeStructural<_ek_structural>::initShapeFunctions(
- const Array<Real> & nodes, const Matrix<Real> & integration_points,
- ElementType type, GhostType ghost_type) {
- AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
-}
-
-#undef INIT_SHAPE_FUNCTIONS
-
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeStructural<kind>::computeShapesOnIntegrationPointsInternal(
const Array<Real> & nodes, const Matrix<Real> & integration_points,
Array<Real> & shapes, GhostType ghost_type,
- const Array<UInt> & filter_elements, bool mass) const {
+ const Array<Idx> & filter_elements, bool mass) const {
auto nb_points = integration_points.cols();
auto nb_element = mesh.getConnectivity(type, ghost_type).size();
- auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
+ const auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
shapes.resize(nb_element * nb_points);
- auto nb_dofs = ElementClass<type>::getNbDegreeOfFreedom();
+ const auto nb_dofs = ElementClass<type>::getNbDegreeOfFreedom();
auto nb_rows = nb_dofs;
+
if (mass) {
nb_rows = ElementClass<type>::getNbStressComponents();
}
#if !defined(AKANTU_NDEBUG)
- UInt size_of_shapes = nb_rows * nb_dofs * nb_nodes_per_element;
+ Int size_of_shapes = nb_rows * nb_dofs * nb_nodes_per_element;
AKANTU_DEBUG_ASSERT(shapes.getNbComponent() == size_of_shapes,
"The shapes array does not have the correct "
<< "number of component");
#endif
- auto shapes_it = shapes.begin_reinterpret(
- nb_rows,
- ElementClass<type>::getNbNodesPerInterpolationElement() * nb_dofs,
- nb_points, nb_element);
- auto shapes_begin = shapes_it;
- if (filter_elements != empty_filter) {
- nb_element = filter_elements.size();
- }
-
+ const auto nb_cols_shapes =
+ ElementClass<type>::getNbNodesPerInterpolationElement() * nb_dofs;
auto nodes_per_element = getNodesPerElement<type>(mesh, nodes, ghost_type);
- auto nodes_it = nodes_per_element->begin(mesh.getSpatialDimension(),
- Mesh::getNbNodesPerElement(type));
- auto nodes_begin = nodes_it;
- auto rot_matrix_it =
- make_view(rotation_matrices(type, ghost_type), nb_dofs, nb_dofs).begin();
- auto rot_matrix_begin = rot_matrix_it;
-
- for (UInt elem = 0; elem < nb_element; ++elem) {
- if (filter_elements != empty_filter) {
- shapes_it = shapes_begin + filter_elements(elem);
- nodes_it = nodes_begin + filter_elements(elem);
- rot_matrix_it = rot_matrix_begin + filter_elements(elem);
- }
- Tensor3<Real> & N = *shapes_it;
- auto & real_coord = *nodes_it;
+ auto shapes_view = make_view(shapes, nb_rows, nb_cols_shapes, nb_points);
+ auto nodes_view = make_view<Eigen::Dynamic, nb_nodes_per_element>(
+ *nodes_per_element, mesh.getSpatialDimension(), nb_nodes_per_element);
+ auto R_view =
+ make_view<nb_dofs, nb_dofs>(rotation_matrices(type, ghost_type));
- auto & RDOFs = *rot_matrix_it;
+ auto loop_core = [&](auto && data) {
+ auto & N = std::get<0>(data);
+ auto & X = std::get<1>(data);
+ auto & R = std::get<2>(data);
- Matrix<Real> T(N.size(1), N.size(1), 0);
+ Matrix<Real, nb_cols_shapes, nb_cols_shapes> T;
+ T.zero();
- for (UInt i = 0; i < nb_nodes_per_element; ++i) {
- T.block(RDOFs, i * RDOFs.rows(), i * RDOFs.rows());
+ for (Int i = 0; i < nb_nodes_per_element; ++i) {
+ T.template block<nb_dofs, nb_dofs>(i * nb_dofs, i * nb_dofs) = R;
}
if (not mass) {
- ElementClass<type>::computeShapes(integration_points, real_coord, T, N);
+ ElementClass<type>::computeShapes(integration_points, X, T, N);
} else {
- ElementClass<type>::computeShapesMass(integration_points, real_coord, T,
- N);
+ ElementClass<type>::computeShapesMass(integration_points, X, T, N);
+ }
+ };
+
+ if (filter_elements == empty_filter) {
+ for (auto && data : zip(shapes_view, nodes_view, R_view)) {
+ loop_core(data);
}
- if (filter_elements == empty_filter) {
- ++shapes_it;
- ++nodes_it;
+
+ } else {
+ for (auto && data :
+ filter(filter_elements, zip(shapes_view, nodes_view, R_view))) {
+ loop_core(data);
}
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeStructural<kind>::precomputeRotationMatrices(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
const auto spatial_dimension = mesh.getSpatialDimension();
const auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
const auto nb_element = mesh.getNbElement(type, ghost_type);
const auto nb_dof = ElementClass<type>::getNbDegreeOfFreedom();
if (not this->rotation_matrices.exists(type, ghost_type)) {
this->rotation_matrices.alloc(0, nb_dof * nb_dof, type, ghost_type);
}
auto & rot_matrices = this->rotation_matrices(type, ghost_type);
rot_matrices.resize(nb_element);
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
bool has_extra_normal = mesh.hasData<Real>("extra_normal", type, ghost_type);
Array<Real>::const_vector_iterator extra_normal;
if (has_extra_normal) {
extra_normal = mesh.getData<Real>("extra_normal", type, ghost_type)
.begin(spatial_dimension);
}
for (auto && tuple :
zip(make_view(x_el, spatial_dimension, nb_nodes_per_element),
make_view(rot_matrices, nb_dof, nb_dof))) {
// compute shape derivatives
auto & X = std::get<0>(tuple);
auto & R = std::get<1>(tuple);
if (has_extra_normal) {
ElementClass<type>::computeRotationMatrix(R, X, *extra_normal);
++extra_normal;
} else {
ElementClass<type>::computeRotationMatrix(
R, X, Vector<Real>(spatial_dimension));
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeStructural<kind>::precomputeShapesOnIntegrationPoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
const auto & natural_coords = integration_points(type, ghost_type);
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto nb_points = integration_points(type, ghost_type).cols();
auto nb_element = mesh.getNbElement(type, ghost_type);
auto nb_dof = ElementClass<type>::getNbDegreeOfFreedom();
const auto dim = ElementClass<type>::getSpatialDimension();
const auto spatial_dimension = mesh.getSpatialDimension();
const auto natural_spatial_dimension =
ElementClass<type>::getNaturalSpaceDimension();
auto itp_type = FEEngine::getInterpolationType(type);
if (not shapes.exists(itp_type, ghost_type)) {
auto size_of_shapes = this->getShapeSize(type);
this->shapes.alloc(0, size_of_shapes, itp_type, ghost_type);
}
auto & rot_matrices = this->rotation_matrices(type, ghost_type);
auto & shapes_ = this->shapes(itp_type, ghost_type);
shapes_.resize(nb_element * nb_points);
auto nodes_per_element = getNodesPerElement<type>(mesh, nodes, ghost_type);
for (auto && tuple :
zip(make_view(shapes_, nb_dof, nb_dof * nb_nodes_per_element, nb_points),
make_view(*nodes_per_element, dim, nb_nodes_per_element),
make_view(rot_matrices, nb_dof, nb_dof))) {
- auto & N = std::get<0>(tuple);
- auto & X = std::get<1>(tuple);
- auto & RDOFs = std::get<2>(tuple);
+ auto && N = std::get<0>(tuple);
+ auto && X = std::get<1>(tuple);
+ auto && RDOFs = std::get<2>(tuple);
- Matrix<Real> T(N.size(1), N.size(1), 0);
+ Matrix<Real> T(N.size(1), N.size(1));
+ T.zero();
- for (UInt i = 0; i < nb_nodes_per_element; ++i) {
- T.block(RDOFs, i * RDOFs.rows(), i * RDOFs.rows());
+ for (Idx i = 0; i < nb_nodes_per_element; ++i) {
+ T.block(i * RDOFs.rows(), i * RDOFs.cols(), RDOFs.rows(), RDOFs.cols()) =
+ RDOFs;
}
auto R = RDOFs.block(0, 0, spatial_dimension, spatial_dimension);
// Rotate to local basis
auto x =
(R * X).block(0, 0, natural_spatial_dimension, nb_nodes_per_element);
ElementClass<type>::computeShapes(natural_coords, x, T, N);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeStructural<kind>::precomputeShapeDerivativesOnIntegrationPoints(
const Array<Real> & nodes, GhostType ghost_type) {
AKANTU_DEBUG_IN();
const auto & natural_coords = integration_points(type, ghost_type);
const auto spatial_dimension = mesh.getSpatialDimension();
const auto natural_spatial_dimension =
ElementClass<type>::getNaturalSpaceDimension();
const auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
const auto nb_points = natural_coords.cols();
const auto nb_dof = ElementClass<type>::getNbDegreeOfFreedom();
const auto nb_element = mesh.getNbElement(type, ghost_type);
const auto nb_stress_components = ElementClass<type>::getNbStressComponents();
+ const auto nb_cols_shaped = nb_dof * nb_nodes_per_element;
auto itp_type = FEEngine::getInterpolationType(type);
if (not this->shapes_derivatives.exists(itp_type, ghost_type)) {
auto size_of_shapesd = this->getShapeDerivativesSize(type);
this->shapes_derivatives.alloc(0, size_of_shapesd, itp_type, ghost_type);
}
auto & rot_matrices = this->rotation_matrices(type, ghost_type);
Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
auto & shapesd = this->shapes_derivatives(itp_type, ghost_type);
shapesd.resize(nb_element * nb_points);
for (auto && tuple :
zip(make_view(x_el, spatial_dimension, nb_nodes_per_element),
- make_view(shapesd, nb_stress_components,
- nb_nodes_per_element * nb_dof, nb_points),
- make_view(rot_matrices, nb_dof, nb_dof))) {
+ make_view(shapesd, nb_stress_components, nb_cols_shaped, nb_points),
+ make_view<nb_dof, nb_dof>(rot_matrices))) {
// compute shape derivatives
auto & X = std::get<0>(tuple);
auto & B = std::get<1>(tuple);
auto & RDOFs = std::get<2>(tuple);
Tensor3<Real> dnds(natural_spatial_dimension,
ElementClass<type>::interpolation_property::dnds_columns,
B.size(2));
ElementClass<type>::computeDNDS(natural_coords, X, dnds);
Tensor3<Real> J(natural_spatial_dimension, natural_spatial_dimension,
natural_coords.cols());
// Computing the coordinates of the element in the natural space
- auto R = RDOFs.block(0, 0, spatial_dimension, spatial_dimension);
- Matrix<Real> T(B.size(1), B.size(1), 0);
+ Matrix<Real, nb_cols_shaped, nb_cols_shaped> T;
+ T.zero();
- for (UInt i = 0; i < nb_nodes_per_element; ++i) {
- T.block(RDOFs, i * RDOFs.rows(), i * RDOFs.rows());
+ for (Int i = 0; i < nb_nodes_per_element; ++i) {
+ T.template block<nb_dof, nb_dof>(i * nb_dof, i * nb_dof) = RDOFs;
}
+ auto && R = RDOFs.block(0, 0, spatial_dimension, spatial_dimension);
// Rotate to local basis
auto x =
- (R * X).block(0, 0, natural_spatial_dimension, nb_nodes_per_element);
+ (R * X).template block<natural_spatial_dimension, nb_nodes_per_element>(
+ 0, 0);
ElementClass<type>::computeJMat(natural_coords, x, J);
ElementClass<type>::computeShapeDerivatives(J, dnds, T, B);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeStructural<kind>::interpolateOnIntegrationPoints(
- const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_dof,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ const Array<Real> & in_u, Array<Real> & out_uq, Int nb_dof,
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(out_uq.getNbComponent() == nb_dof,
"The output array shape is not correct");
auto itp_type = FEEngine::getInterpolationType(type);
const auto & shapes_ = shapes(itp_type, ghost_type);
auto nb_element = mesh.getNbElement(type, ghost_type);
auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
auto nb_quad_points_per_element = integration_points(type, ghost_type).cols();
Array<Real> u_el(0, nb_nodes_per_element * nb_dof);
FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type,
filter_elements);
auto nb_quad_points = nb_quad_points_per_element * u_el.size();
out_uq.resize(nb_quad_points);
- auto out_it = out_uq.begin_reinterpret(nb_dof, 1, nb_quad_points_per_element,
- u_el.size());
- auto shapes_it =
- shapes_.begin_reinterpret(nb_dof, nb_dof * nb_nodes_per_element,
- nb_quad_points_per_element, nb_element);
- auto u_it = u_el.begin_reinterpret(nb_dof * nb_nodes_per_element, 1,
- nb_quad_points_per_element, u_el.size());
+ auto out_it =
+ make_view(out_uq, nb_dof, 1, nb_quad_points_per_element).begin();
+ auto shapes_it = make_view(shapes_, nb_dof, nb_dof * nb_nodes_per_element,
+ nb_quad_points_per_element)
+ .begin();
+ auto u_it = make_view(u_el, nb_dof * nb_nodes_per_element, 1,
+ nb_quad_points_per_element)
+ .begin();
for_each_element(nb_element, filter_elements, [&](auto && el) {
auto & uq = *out_it;
const auto & u = *u_it;
- auto N = Tensor3<Real>(shapes_it[el]);
+ auto && N = shapes_it[el];
for (auto && q : arange(uq.size(2))) {
- auto uq_q = Matrix<Real>(uq(q));
- auto u_q = Matrix<Real>(u(q));
- auto N_q = Matrix<Real>(N(q));
-
- uq_q.mul<false, false>(N_q, u_q);
+ uq(q) = N(q) * u(q);
}
++out_it;
++u_it;
});
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeStructural<kind>::gradientOnIntegrationPoints(
- const Array<Real> & in_u, Array<Real> & out_nablauq, UInt nb_dof,
- GhostType ghost_type, const Array<UInt> & filter_elements) const {
+ const Array<Real> & in_u, Array<Real> & out_nablauq, Int nb_dof,
+ GhostType ghost_type, const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
auto itp_type = FEEngine::getInterpolationType(type);
const auto & shapesd = shapes_derivatives(itp_type, ghost_type);
auto nb_element = mesh.getNbElement(type, ghost_type);
auto element_dimension = ElementClass<type>::getSpatialDimension();
auto nb_quad_points_per_element = integration_points(type, ghost_type).cols();
auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
Array<Real> u_el(0, nb_nodes_per_element * nb_dof);
FEEngine::extractNodalToElementField(mesh, in_u, u_el, type, ghost_type,
filter_elements);
auto nb_quad_points = nb_quad_points_per_element * u_el.size();
out_nablauq.resize(nb_quad_points);
- auto out_it = out_nablauq.begin_reinterpret(
- element_dimension, 1, nb_quad_points_per_element, u_el.size());
- auto shapesd_it = shapesd.begin_reinterpret(
- element_dimension, nb_dof * nb_nodes_per_element,
- nb_quad_points_per_element, nb_element);
- auto u_it = u_el.begin_reinterpret(nb_dof * nb_nodes_per_element, 1,
- nb_quad_points_per_element, u_el.size());
+ auto out_it =
+ make_view(out_nablauq, element_dimension, 1, nb_quad_points_per_element)
+ .begin();
+ auto shapesd_it =
+ make_view(shapesd, element_dimension, nb_dof * nb_nodes_per_element,
+ nb_quad_points_per_element)
+ .begin();
+ auto u_it = make_view(u_el, nb_dof * nb_nodes_per_element, 1,
+ nb_quad_points_per_element)
+ .begin();
for_each_element(nb_element, filter_elements, [&](auto && el) {
auto & nablau = *out_it;
const auto & u = *u_it;
- auto B = Tensor3<Real>(shapesd_it[el]);
+ auto B = shapesd_it[el];
for (auto && q : arange(nablau.size(2))) {
- auto nablau_q = Matrix<Real>(nablau(q));
- auto u_q = Matrix<Real>(u(q));
- auto B_q = Matrix<Real>(B(q));
-
- nablau_q.mul<false, false>(B_q, u_q);
+ nablau(q) = B(q) * u(q);
}
++out_it;
++u_it;
});
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <>
template <ElementType type>
void ShapeStructural<_ek_structural>::computeBtD(
const Array<Real> & Ds, Array<Real> & BtDs, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
+ const Array<Idx> & filter_elements) const {
auto itp_type = ElementClassProperty<type>::interpolation_type;
auto nb_stress = ElementClass<type>::getNbStressComponents();
auto nb_dof_per_element = ElementClass<type>::getNbDegreeOfFreedom() *
mesh.getNbNodesPerElement(type);
const auto & shapes_derivatives =
this->shapes_derivatives(itp_type, ghost_type);
Array<Real> shapes_derivatives_filtered(0,
shapes_derivatives.getNbComponent());
auto && view = make_view(shapes_derivatives, nb_stress, nb_dof_per_element);
auto B_it = view.begin();
auto B_end = view.end();
if (filter_elements != empty_filter) {
FEEngine::filterElementalData(this->mesh, shapes_derivatives,
shapes_derivatives_filtered, type, ghost_type,
filter_elements);
auto && view =
make_view(shapes_derivatives_filtered, nb_stress, nb_dof_per_element);
B_it = view.begin();
B_end = view.end();
}
for (auto && values : zip(range(B_it, B_end), make_view(Ds, nb_stress),
make_view(BtDs, BtDs.getNbComponent()))) {
const auto & B = std::get<0>(values);
const auto & D = std::get<1>(values);
auto & Bt_D = std::get<2>(values);
- Bt_D.template mul<true>(B, D);
+ Bt_D = B.transpose() * D;
}
}
/* -------------------------------------------------------------------------- */
template <>
template <ElementType type>
void ShapeStructural<_ek_structural>::computeNtb(
const Array<Real> & bs, Array<Real> & Ntbs, GhostType ghost_type,
- const Array<UInt> & filter_elements) const {
- auto itp_type = ElementClassProperty<type>::interpolation_type;
-
- auto nb_dof = ElementClass<type>::getNbDegreeOfFreedom();
- auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ const Array<Idx> & filter_elements) const {
+ constexpr auto itp_type = ElementClassProperty<type>::interpolation_type;
+ constexpr auto nb_dof = ElementClass<type>::getNbDegreeOfFreedom();
+ constexpr auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
const auto & shapes = this->shapes(itp_type, ghost_type);
Array<Real> shapes_filtered(0, shapes.getNbComponent());
- auto && view = make_view(shapes, nb_dof, nb_dof * nb_nodes_per_element);
+ auto && view = make_view<nb_dof, nb_dof * nb_nodes_per_element>(shapes);
auto N_it = view.begin();
auto N_end = view.end();
if (filter_elements != empty_filter) {
FEEngine::filterElementalData(this->mesh, shapes, shapes_filtered, type,
ghost_type, filter_elements);
auto && view =
- make_view(shapes_filtered, nb_dof, nb_dof * nb_nodes_per_element);
+ make_view<nb_dof, nb_dof * nb_nodes_per_element>(shapes_filtered);
N_it = view.begin();
N_end = view.end();
}
- for (auto && values : zip(range(N_it, N_end), make_view(bs, nb_dof),
- make_view(Ntbs, nb_dof * nb_nodes_per_element))) {
- const auto & N = std::get<0>(values);
- const auto & b = std::get<1>(values);
- auto & Nt_b = std::get<2>(values);
- Nt_b.template mul<true>(N, b);
+ for (auto && [N, b, Nt_b] :
+ zip(range(N_it, N_end), make_view<nb_dof>(bs),
+ make_view<nb_dof * nb_nodes_per_element>(Ntbs))) {
+ Nt_b = N.transpose() * b;
}
}
+/* -------------------------------------------------------------------------- */
+template <ElementKind kind>
+inline void ShapeStructural<kind>::initShapeFunctions(
+ const Array<Real> & /* unused */, const Matrix<Real> & /* unused */,
+ ElementType /* unused */, GhostType /* unused */) {
+ AKANTU_TO_IMPLEMENT();
+}
+
+template <>
+inline void ShapeStructural<_ek_structural>::initShapeFunctions(
+ const Array<Real> & nodes, const Matrix<Real> & integration_points,
+ ElementType type, GhostType ghost_type) {
+ tuple_dispatch<ElementTypes_t<_ek_structural>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->setIntegrationPointsByType<type>(integration_points, ghost_type);
+ this->precomputeRotationMatrices<type>(nodes, ghost_type);
+ this->precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type);
+ this->precomputeShapeDerivativesOnIntegrationPoints<type>(nodes,
+ ghost_type);
+ },
+ type);
+}
+/* -------------------------------------------------------------------------- */
} // namespace akantu
-#endif /* AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_HH_ */
+//#endif /* AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_HH_ */
diff --git a/src/geometry/geom_helper_functions.hh b/src/geometry/geom_helper_functions.hh
index 955bee773..113d9955d 100644
--- a/src/geometry/geom_helper_functions.hh
+++ b/src/geometry/geom_helper_functions.hh
@@ -1,115 +1,115 @@
/**
* @file geom_helper_functions.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
*
* @date creation: Fri Jan 04 2013
* @date last modification: Wed Jan 31 2018
*
* @brief Helper functions for the computational geometry algorithms
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_GEOM_HELPER_FUNCTIONS_HH_
#define AKANTU_GEOM_HELPER_FUNCTIONS_HH_
#include "aka_common.hh"
#include "aka_math.hh"
#include "tree_type_helper.hh"
#include "mesh_geom_common.hh"
namespace akantu {
/// Fuzzy compare of two points
template <class Point>
inline bool comparePoints(const Point & a, const Point & b) {
return Math::are_float_equal(a.x(), b.x()) &&
Math::are_float_equal(a.y(), b.y()) &&
Math::are_float_equal(a.z(), b.z());
}
template <>
inline bool comparePoints(const cgal::Spherical::Circular_arc_point_3 & a,
const cgal::Spherical::Circular_arc_point_3 & b) {
return Math::are_float_equal(CGAL::to_double(a.x()),
CGAL::to_double(b.x())) &&
Math::are_float_equal(CGAL::to_double(a.y()),
CGAL::to_double(b.y())) &&
Math::are_float_equal(CGAL::to_double(a.z()), CGAL::to_double(b.z()));
}
/// Fuzzy compare of two segments
template <class K>
inline bool compareSegments(const CGAL::Segment_3<K> & a,
const CGAL::Segment_3<K> & b) {
return (comparePoints(a.source(), b.source()) &&
comparePoints(a.target(), b.target())) ||
(comparePoints(a.source(), b.target()) &&
comparePoints(a.target(), b.source()));
}
/// Compare segment pairs
inline bool
compareSegmentPairs(const std::pair<cgal::Cartesian::Segment_3, UInt> & a,
const std::pair<cgal::Cartesian::Segment_3, UInt> & b) {
return compareSegments(a.first, b.first);
}
/// Pair ordering operator based on first member
struct segmentPairsLess {
inline bool
operator()(const std::pair<cgal::Cartesian::Segment_3, UInt> & a,
- const std::pair<cgal::Cartesian::Segment_3, UInt> & b) {
+ const std::pair<cgal::Cartesian::Segment_3, UInt> & b) const {
return static_cast<bool>(
CGAL::compare_lexicographically(a.first.min(), b.first.min())) or
static_cast<bool>(
CGAL::compare_lexicographically(a.first.max(), b.first.max()));
}
};
/* -------------------------------------------------------------------------- */
/* Predicates */
/* -------------------------------------------------------------------------- */
/// Predicate used to determine if two segments are equal
class IsSameSegment {
public:
IsSameSegment(const cgal::Cartesian::Segment_3 & segment)
: segment(segment) {}
bool
operator()(const std::pair<cgal::Cartesian::Segment_3, UInt> & test_pair) {
return compareSegments(segment, test_pair.first);
}
protected:
const cgal::Cartesian::Segment_3 segment;
};
} // namespace akantu
#endif // AKANTU_GEOM_HELPER_FUNCTIONS_HH_
diff --git a/src/geometry/mesh_abstract_intersector.hh b/src/geometry/mesh_abstract_intersector.hh
index 88db3e062..b5ace8461 100644
--- a/src/geometry/mesh_abstract_intersector.hh
+++ b/src/geometry/mesh_abstract_intersector.hh
@@ -1,122 +1,122 @@
/**
* @file mesh_abstract_intersector.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Apr 29 2015
* @date last modification: Sat Apr 02 2016
*
* @brief Abstract class for intersection computations
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_ABSTRACT_INTERSECTOR_HH_
#define AKANTU_MESH_ABSTRACT_INTERSECTOR_HH_
#include "aka_common.hh"
#include "mesh_geom_abstract.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* @brief Class used to perform intersections on a mesh and construct output
* data
*/
template <class Query> class MeshAbstractIntersector : public MeshGeomAbstract {
public:
/// Construct from mesh
explicit MeshAbstractIntersector(Mesh & mesh);
/// Destructor
~MeshAbstractIntersector() override = default;
public:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the new_node_per_elem array
- AKANTU_GET_MACRO(NewNodePerElem, *new_node_per_elem, const Array<UInt> &);
+ AKANTU_GET_MACRO(NewNodePerElem, *new_node_per_elem, const Array<Int> &);
/// get the intersection_points array
- AKANTU_GET_MACRO(IntersectionPoints, intersection_points,
- const Array<Real> *);
+ AKANTU_GET_MACRO(IntersectionPoints, *intersection_points,
+ const Array<Real> &);
/// get the nb_seg_by_el UInt
- AKANTU_GET_MACRO(NbSegByEl, nb_seg_by_el, UInt);
+ AKANTU_GET_MACRO(NbSegByEl, nb_seg_by_el, Int);
/**
* @brief Compute the intersection with a query object
*
* This function needs to be implemented for every subclass. It computes the
* intersections
* with the tree of primitives and creates the data for the user.
*
* @param query the CGAL primitive of the query object
*/
virtual void computeIntersectionQuery(const Query & query) = 0;
/// Compute intersection points between the mesh primitives (segments) and a
/// query (surface in 3D or a curve in 2D), double intersection points for the
/// same primitives are not considered. A maximum intersection node per
/// element is set : 2 in 2D and 4 in 3D
virtual void computeMeshQueryIntersectionPoint(const Query & query,
- UInt nb_old_nodes) = 0;
+ Int nb_old_nodes) = 0;
/// Compute intersection between the mesh and a list of queries
virtual void
computeIntersectionQueryList(const std::list<Query> & query_list);
/// Compute intersection points between the mesh and a list of queries
virtual void
computeMeshQueryListIntersectionPoint(const std::list<Query> & query_list,
- UInt nb_old_nodes);
+ Int nb_old_nodes);
/// Compute whatever result is needed from the user (should be move to the
/// appropriate specific classe for genericity)
virtual void
buildResultFromQueryList(const std::list<Query> & query_list) = 0;
protected:
/// new node per element (column 0: number of new nodes, then odd is the
/// intersection node number and even the ID of the intersected segment)
- Array<UInt> * new_node_per_elem{nullptr};
+ std::unique_ptr<Array<Int>> new_node_per_elem;
/// intersection output: new intersection points
/// (computeMeshQueryListIntersectionPoint)
- Array<Real> * intersection_points{nullptr};
+ std::unique_ptr<Array<Real>> intersection_points;
/// number of segment in a considered element of the templated type of element
/// specialized intersector
- const UInt nb_seg_by_el{0};
+ const Int nb_seg_by_el{0};
};
} // namespace akantu
#include "mesh_abstract_intersector_tmpl.hh"
#endif // AKANTU_MESH_ABSTRACT_INTERSECTOR_HH_
diff --git a/src/geometry/mesh_abstract_intersector_tmpl.hh b/src/geometry/mesh_abstract_intersector_tmpl.hh
index 6733566a9..98495d47f 100644
--- a/src/geometry/mesh_abstract_intersector_tmpl.hh
+++ b/src/geometry/mesh_abstract_intersector_tmpl.hh
@@ -1,80 +1,66 @@
/**
* @file mesh_abstract_intersector_tmpl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Apr 29 2015
* @date last modification: Sat Jan 23 2016
*
* @brief General class for intersection computations
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_ABSTRACT_INTERSECTOR_TMPL_HH_
#define AKANTU_MESH_ABSTRACT_INTERSECTOR_TMPL_HH_
#include "aka_common.hh"
#include "mesh_abstract_intersector.hh"
namespace akantu {
template <class Query>
MeshAbstractIntersector<Query>::MeshAbstractIntersector(Mesh & mesh)
: MeshGeomAbstract(mesh) {}
template <class Query>
void MeshAbstractIntersector<Query>::computeIntersectionQueryList(
const std::list<Query> & query_list) {
- AKANTU_DEBUG_IN();
-
- auto query_it = query_list.begin();
- auto query_end = query_list.end();
-
- for (; query_it != query_end; ++query_it) {
- computeIntersectionQuery(*query_it);
+ for (auto && query : query_list) {
+ computeIntersectionQuery(query);
}
-
- AKANTU_DEBUG_OUT();
}
template <class Query>
void MeshAbstractIntersector<Query>::computeMeshQueryListIntersectionPoint(
- const std::list<Query> & query_list, UInt nb_old_nodes) {
- AKANTU_DEBUG_IN();
-
- auto query_it = query_list.begin();
- auto query_end = query_list.end();
-
- for (; query_it != query_end; ++query_it) {
- computeMeshQueryIntersectionPoint(*query_it, nb_old_nodes);
+ const std::list<Query> & query_list, Int nb_old_nodes) {
+ for (auto && query : query_list) {
+ computeMeshQueryIntersectionPoint(query, nb_old_nodes);
}
-
- AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif // AKANTU_MESH_ABSTRACT_INTERSECTOR_TMPL_HH_
diff --git a/src/geometry/mesh_geom_factory.hh b/src/geometry/mesh_geom_factory.hh
index d9d0a4b07..028d8c077 100644
--- a/src/geometry/mesh_geom_factory.hh
+++ b/src/geometry/mesh_geom_factory.hh
@@ -1,107 +1,107 @@
/**
* @file mesh_geom_factory.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Feb 27 2015
* @date last modification: Tue Sep 08 2020
*
* @brief Class for constructing the CGAL primitives of a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
#include "geom_helper_functions.hh"
#include "mesh.hh"
#include "mesh_geom_abstract.hh"
#include "tree_type_helper.hh"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_GEOM_FACTORY_HH_
#define AKANTU_MESH_GEOM_FACTORY_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* @brief Class used to construct AABB tree for intersection computations
*
* This class constructs a CGAL AABB tree of one type of element in a mesh
* for fast intersection computations.
*/
-template <UInt dim, ElementType el_type, class Primitive, class Kernel>
+template <Int dim, ElementType el_type, class Primitive, class Kernel>
class MeshGeomFactory : public MeshGeomAbstract {
public:
/// Construct from mesh
explicit MeshGeomFactory(Mesh & mesh);
/// Desctructor
~MeshGeomFactory() override;
using TreeTypeHelper_ = TreeTypeHelper<Primitive, Kernel>;
using TreeType = typename TreeTypeHelper_::tree;
using ContainerType = typename TreeTypeHelper_::container_type;
public:
/// Construct AABB tree for fast intersection computing
void constructData(GhostType ghost_type = _not_ghost) override;
/**
* @brief Construct a primitive and add it to a list of primitives
*
* This function needs to be specialized for every type that is wished to be
* supported.
* @param node_coordinates coordinates of the nodes making up the element
* @param id element number
* @param list the primitive list (not used inside MeshGeomFactory)
*/
inline void addPrimitive(const Matrix<Real> & /*node_coordinates*/,
- UInt /*id*/, ContainerType & /*list*/);
+ Idx /*id*/, ContainerType & /*list*/);
- inline void addPrimitive(const Matrix<Real> & node_coordinates, UInt id);
+ inline void addPrimitive(const Matrix<Real> & node_coordinates, Idx id);
/// Getter for the AABB tree
auto getTree() const -> const TreeType & { return *data_tree; }
/// Getter for primitive list
auto getPrimitiveList() const -> const ContainerType & {
return primitive_list;
}
protected:
/// AABB data tree
- TreeType * data_tree{nullptr};
+ std::unique_ptr<TreeType> data_tree;
/// Primitive list
ContainerType primitive_list;
};
} // namespace akantu
#include "mesh_geom_factory_tmpl.hh"
#endif // AKANTU_MESH_GEOM_FACTORY_HH_
diff --git a/src/geometry/mesh_geom_factory_tmpl.hh b/src/geometry/mesh_geom_factory_tmpl.hh
index ea87cb406..f4e80e91d 100644
--- a/src/geometry/mesh_geom_factory_tmpl.hh
+++ b/src/geometry/mesh_geom_factory_tmpl.hh
@@ -1,245 +1,229 @@
/**
* @file mesh_geom_factory_tmpl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Feb 27 2015
* @date last modification: Tue Sep 08 2020
*
* @brief Class for constructing the CGAL primitives of a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_geom_common.hh"
#include "mesh_geom_factory.hh"
+#include "mesh_iterators.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_GEOM_FACTORY_TMPL_HH_
#define AKANTU_MESH_GEOM_FACTORY_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim, ElementType type, class Primitive, class Kernel>
+template <Int dim, ElementType type, class Primitive, class Kernel>
MeshGeomFactory<dim, type, Primitive, Kernel>::MeshGeomFactory(Mesh & mesh)
: MeshGeomAbstract(mesh) {}
/* -------------------------------------------------------------------------- */
-template <UInt dim, ElementType type, class Primitive, class Kernel>
-MeshGeomFactory<dim, type, Primitive, Kernel>::~MeshGeomFactory() {
- delete data_tree;
-}
+template <Int dim, ElementType type, class Primitive, class Kernel>
+MeshGeomFactory<dim, type, Primitive, Kernel>::~MeshGeomFactory() = default;
/* -------------------------------------------------------------------------- */
/**
* This function loops over the elements of `type` in the mesh and creates the
* AABB tree of geometrical primitves (`data_tree`).
*/
-template <UInt dim, ElementType type, class Primitive, class Kernel>
+template <Int dim, ElementType type, class Primitive, class Kernel>
void MeshGeomFactory<dim, type, Primitive, Kernel>::constructData(
GhostType ghost_type) {
AKANTU_DEBUG_IN();
primitive_list.clear();
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
-
- const Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
- const Array<Real> & nodes = mesh.getNodes();
-
- UInt el_index = 0;
- auto it = connectivity.begin(nb_nodes_per_element);
- auto end = connectivity.end(nb_nodes_per_element);
- Matrix<Real> node_coordinates(dim, nb_nodes_per_element);
+ constexpr auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ Matrix<Real, dim, nb_nodes_per_element> node_coordinates;
// This loop builds the list of primitives
- for (; it != end; ++it, ++el_index) {
- const Vector<UInt> & el_connectivity = *it;
-
- for (UInt i = 0; i < nb_nodes_per_element; i++) {
- for (UInt j = 0; j < dim; j++) {
- node_coordinates(j, i) = nodes(el_connectivity(i), j);
- }
- }
-
- // the unique elemental id assigned to the primitive is the
- // linearized element index over ghost type
- addPrimitive(node_coordinates, el_index);
+ for (auto && element :
+ element_range(mesh.getNbElement(type, ghost_type), type)) {
+ node_coordinates =
+ mesh.extractNodalValuesFromElement(mesh.getNodes(), element);
+ this->addPrimitive(node_coordinates, element.element);
}
- delete data_tree;
+ data_tree.reset();
// This condition allows the use of the mesh geom module
// even if types are not compatible with AABB tree algorithm
if (TreeTypeHelper_::is_valid) {
- data_tree = new TreeType(primitive_list.begin(), primitive_list.end());
+ data_tree = std::make_unique<TreeType>(primitive_list.begin(),
+ primitive_list.end());
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-namespace {
- namespace details {
- enum class GeometricalType {
- _triangle,
- _tetrahedron,
- };
- template <ElementType element_type> struct GeometricalTypeHelper {};
-
- template <> struct GeometricalTypeHelper<_triangle_3> {
- static const GeometricalType type{GeometricalType::_triangle};
- };
-
- template <> struct GeometricalTypeHelper<_triangle_6> {
- static const GeometricalType type{GeometricalType::_triangle};
- };
-
- template <> struct GeometricalTypeHelper<_tetrahedron_4> {
- static const GeometricalType type{GeometricalType::_triangle};
- };
+namespace details {
+ enum class GeometricalType {
+ _triangle,
+ _tetrahedron,
+ };
+ template <ElementType element_type> struct GeometricalTypeHelper {};
+
+ template <> struct GeometricalTypeHelper<_triangle_3> {
+ static const GeometricalType type{GeometricalType::_triangle};
+ };
+
+ template <> struct GeometricalTypeHelper<_triangle_6> {
+ static const GeometricalType type{GeometricalType::_triangle};
+ };
+
+ template <> struct GeometricalTypeHelper<_tetrahedron_4> {
+ static const GeometricalType type{GeometricalType::_triangle};
+ };
#if defined(AKANTU_IGFEM)
- template <> struct GeometricalTypeHelper<_igfem_triangle_4> {
- static const GeometricalType type{GeometricalType::_triangle};
- };
- template <> struct GeometricalTypeHelper<_igfem_triangle_5> {
- static const GeometricalType type{GeometricalType::_triangle};
- };
+ template <> struct GeometricalTypeHelper<_igfem_triangle_4> {
+ static const GeometricalType type{GeometricalType::_triangle};
+ };
+ template <> struct GeometricalTypeHelper<_igfem_triangle_5> {
+ static const GeometricalType type{GeometricalType::_triangle};
+ };
#endif
- template <details::GeometricalType geom_type, class Primitive, class Kernel>
- struct AddPrimitiveHelper {};
-
- template <class Primitive>
- struct AddPrimitiveHelper<GeometricalType::_triangle, Primitive,
- cgal::Cartesian> {
- using TreeTypeHelper_ = TreeTypeHelper<Primitive, cgal::Cartesian>;
- using ContainerType = typename TreeTypeHelper_::container_type;
- static void addPrimitive(const Matrix<Real> & node_coordinates, UInt id,
- ContainerType & list) {
- using Point = typename TreeTypeHelper_::point_type;
- Point a(node_coordinates(0, 0), node_coordinates(1, 0), 0.);
- Point b(node_coordinates(0, 1), node_coordinates(1, 1), 0.);
- Point c(node_coordinates(0, 2), node_coordinates(1, 2), 0.);
-
- Triangle<cgal::Cartesian> t(a, b, c);
- t.setId(id);
- list.push_back(t);
- }
- };
-
- template <class Primitive>
- struct AddPrimitiveHelper<GeometricalType::_triangle, Primitive,
- cgal::Spherical> {
- using TreeTypeHelper_ = TreeTypeHelper<Primitive, cgal::Spherical>;
- using ContainerType = typename TreeTypeHelper_::container_type;
- static void addPrimitive(const Matrix<Real> & node_coordinates, UInt id,
- ContainerType & list) {
- using Point = typename TreeTypeHelper_::point_type;
- Point a(node_coordinates(0, 0), node_coordinates(1, 0), 0.);
- Point b(node_coordinates(0, 1), node_coordinates(1, 1), 0.);
- Point c(node_coordinates(0, 2), node_coordinates(1, 2), 0.);
-
- using Line = CGAL::Line_3<cgal::Spherical>;
- Line l1(a, b);
- Line l2(b, c);
- Line l3(c, a);
-
- using Arc = Line_arc<cgal::Spherical>;
- Arc s1(l1, a, b);
- Arc s2(l2, b, c);
- Arc s3(l3, c, a);
-
- s1.setId(id);
- s1.setSegId(0);
- s2.setId(id);
- s2.setSegId(1);
- s3.setId(id);
- s3.setSegId(2);
-
- list.push_back(s1);
- list.push_back(s2);
- list.push_back(s3);
- }
- };
-
- template <class Primitive>
- struct AddPrimitiveHelper<GeometricalType::_tetrahedron, Primitive,
- cgal::Cartesian> {
- using TreeTypeHelper_ = TreeTypeHelper<Primitive, cgal::Cartesian>;
- using ContainerType = typename TreeTypeHelper_::container_type;
- static void addPrimitive(const Matrix<Real> & node_coordinates, UInt id,
- ContainerType & list) {
- using Point = typename TreeTypeHelper_::point_type;
- Point a(node_coordinates(0, 0), node_coordinates(1, 0),
- node_coordinates(2, 0));
- Point b(node_coordinates(0, 1), node_coordinates(1, 1),
- node_coordinates(2, 1));
- Point c(node_coordinates(0, 2), node_coordinates(1, 2),
- node_coordinates(2, 2));
- Point d(node_coordinates(0, 3), node_coordinates(1, 3),
- node_coordinates(2, 3));
-
- Triangle<cgal::Cartesian> t1(a, b, c);
- Triangle<cgal::Cartesian> t2(b, c, d);
- Triangle<cgal::Cartesian> t3(c, d, a);
- Triangle<cgal::Cartesian> t4(d, a, b);
-
- t1.setId(id);
- t2.setId(id);
- t3.setId(id);
- t4.setId(id);
-
- list.push_back(t1);
- list.push_back(t2);
- list.push_back(t3);
- list.push_back(t4);
- }
- };
- } // namespace details
-} // namespace
+ template <details::GeometricalType geom_type, class Primitive, class Kernel>
+ struct AddPrimitiveHelper {};
+
+ template <class Primitive>
+ struct AddPrimitiveHelper<GeometricalType::_triangle, Primitive,
+ cgal::Cartesian> {
+ using TreeTypeHelper_ = TreeTypeHelper<Primitive, cgal::Cartesian>;
+ using ContainerType = typename TreeTypeHelper_::container_type;
+ static void addPrimitive(const Matrix<Real> & node_coordinates, Idx id,
+ ContainerType & list) {
+ using Point = typename TreeTypeHelper_::point_type;
+ Point a(node_coordinates(0, 0), node_coordinates(1, 0), 0.);
+ Point b(node_coordinates(0, 1), node_coordinates(1, 1), 0.);
+ Point c(node_coordinates(0, 2), node_coordinates(1, 2), 0.);
+
+ Triangle<cgal::Cartesian> t(a, b, c);
+ t.setId(id);
+ list.push_back(t);
+ }
+ };
+
+ template <class Primitive>
+ struct AddPrimitiveHelper<GeometricalType::_triangle, Primitive,
+ cgal::Spherical> {
+ using TreeTypeHelper_ = TreeTypeHelper<Primitive, cgal::Spherical>;
+ using ContainerType = typename TreeTypeHelper_::container_type;
+ static void addPrimitive(const Matrix<Real> & node_coordinates, Idx id,
+ ContainerType & list) {
+ using Point = typename TreeTypeHelper_::point_type;
+ Point a(node_coordinates(0, 0), node_coordinates(1, 0), 0.);
+ Point b(node_coordinates(0, 1), node_coordinates(1, 1), 0.);
+ Point c(node_coordinates(0, 2), node_coordinates(1, 2), 0.);
+
+ using Line = CGAL::Line_3<cgal::Spherical>;
+ Line l1(a, b);
+ Line l2(b, c);
+ Line l3(c, a);
+
+ using Arc = Line_arc<cgal::Spherical>;
+ Arc s1(l1, a, b);
+ Arc s2(l2, b, c);
+ Arc s3(l3, c, a);
+
+ s1.setId(id);
+ s1.setSegId(0);
+ s2.setId(id);
+ s2.setSegId(1);
+ s3.setId(id);
+ s3.setSegId(2);
+
+ list.push_back(s1);
+ list.push_back(s2);
+ list.push_back(s3);
+ }
+ };
+
+ template <class Primitive>
+ struct AddPrimitiveHelper<GeometricalType::_tetrahedron, Primitive,
+ cgal::Cartesian> {
+ using TreeTypeHelper_ = TreeTypeHelper<Primitive, cgal::Cartesian>;
+ using ContainerType = typename TreeTypeHelper_::container_type;
+ static void addPrimitive(const Matrix<Real> & node_coordinates, Idx id,
+ ContainerType & list) {
+ using Point = typename TreeTypeHelper_::point_type;
+ Point a(node_coordinates(0, 0), node_coordinates(1, 0),
+ node_coordinates(2, 0));
+ Point b(node_coordinates(0, 1), node_coordinates(1, 1),
+ node_coordinates(2, 1));
+ Point c(node_coordinates(0, 2), node_coordinates(1, 2),
+ node_coordinates(2, 2));
+ Point d(node_coordinates(0, 3), node_coordinates(1, 3),
+ node_coordinates(2, 3));
+
+ Triangle<cgal::Cartesian> t1(a, b, c);
+ Triangle<cgal::Cartesian> t2(b, c, d);
+ Triangle<cgal::Cartesian> t3(c, d, a);
+ Triangle<cgal::Cartesian> t4(d, a, b);
+
+ t1.setId(id);
+ t2.setId(id);
+ t3.setId(id);
+ t4.setId(id);
+
+ list.push_back(t1);
+ list.push_back(t2);
+ list.push_back(t3);
+ list.push_back(t4);
+ }
+ };
+} // namespace details
/* -------------------------------------------------------------------------- */
-template <UInt dim, ElementType type, class Primitive, class Kernel>
+template <Int dim, ElementType type, class Primitive, class Kernel>
void MeshGeomFactory<dim, type, Primitive, Kernel>::addPrimitive(
- const Matrix<Real> & node_coordinates, UInt id, ContainerType & list) {
+ const Matrix<Real> & node_coordinates, Idx id, ContainerType & list) {
details::AddPrimitiveHelper<details::GeometricalTypeHelper<type>::type,
Primitive, Kernel>::addPrimitive(node_coordinates,
id, list);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim, ElementType type, class Primitive, class Kernel>
+template <Int dim, ElementType type, class Primitive, class Kernel>
void MeshGeomFactory<dim, type, Primitive, Kernel>::addPrimitive(
- const Matrix<Real> & node_coordinates, UInt id) {
+ const Matrix<Real> & node_coordinates, Idx id) {
this->addPrimitive(node_coordinates, id, this->primitive_list);
}
} // namespace akantu
#endif // AKANTU_MESH_GEOM_FACTORY_TMPL_HH_
diff --git a/src/geometry/mesh_geom_intersector.hh b/src/geometry/mesh_geom_intersector.hh
index 4b88a49a9..09dfbca6b 100644
--- a/src/geometry/mesh_geom_intersector.hh
+++ b/src/geometry/mesh_geom_intersector.hh
@@ -1,75 +1,74 @@
/**
* @file mesh_geom_intersector.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Apr 29 2015
* @date last modification: Sat Jan 23 2016
*
* @brief General class for intersection computations
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_GEOM_INTERSECTOR_HH_
#define AKANTU_MESH_GEOM_INTERSECTOR_HH_
#include "aka_common.hh"
#include "mesh_abstract_intersector.hh"
#include "mesh_geom_factory.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* @brief Class used to perform intersections on a mesh and construct output
* data
*/
-template <UInt dim, ElementType type, class Primitive, class Query,
- class Kernel>
+template <Int dim, ElementType type, class Primitive, class Query, class Kernel>
class MeshGeomIntersector : public MeshAbstractIntersector<Query> {
public:
/// Construct from mesh
explicit MeshGeomIntersector(Mesh & mesh);
/// Destructor
~MeshGeomIntersector() override = default;
public:
/// Construct the primitive tree object
void constructData(GhostType ghost_type = _not_ghost) override;
protected:
/// Factory object containing the primitive tree
MeshGeomFactory<dim, type, Primitive, Kernel> factory;
};
} // namespace akantu
#include "mesh_geom_intersector_tmpl.hh"
#endif // AKANTU_MESH_GEOM_INTERSECTOR_HH_
diff --git a/src/geometry/mesh_geom_intersector_tmpl.hh b/src/geometry/mesh_geom_intersector_tmpl.hh
index 40bdd45a5..77a9cde19 100644
--- a/src/geometry/mesh_geom_intersector_tmpl.hh
+++ b/src/geometry/mesh_geom_intersector_tmpl.hh
@@ -1,60 +1,58 @@
/**
* @file mesh_geom_intersector_tmpl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Wed Apr 29 2015
* @date last modification: Sat Jan 23 2016
*
* @brief General class for intersection computations
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_GEOM_INTERSECTOR_TMPL_HH_
#define AKANTU_MESH_GEOM_INTERSECTOR_TMPL_HH_
#include "aka_common.hh"
#include "mesh_geom_intersector.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
-template <UInt dim, ElementType type, class Primitive, class Query,
- class Kernel>
+template <Int dim, ElementType type, class Primitive, class Query, class Kernel>
MeshGeomIntersector<dim, type, Primitive, Query, Kernel>::MeshGeomIntersector(
Mesh & mesh)
: MeshAbstractIntersector<Query>(mesh), factory(mesh) {}
-template <UInt dim, ElementType type, class Primitive, class Query,
- class Kernel>
+template <Int dim, ElementType type, class Primitive, class Query, class Kernel>
void MeshGeomIntersector<dim, type, Primitive, Query, Kernel>::constructData(
GhostType ghost_type) {
this->intersection_points->resize(0);
factory.constructData(ghost_type);
}
} // namespace akantu
#endif // AKANTU_MESH_GEOM_INTERSECTOR_TMPL_HH_
diff --git a/src/geometry/mesh_segment_intersector.hh b/src/geometry/mesh_segment_intersector.hh
index 96a00d68b..658c21fce 100644
--- a/src/geometry/mesh_segment_intersector.hh
+++ b/src/geometry/mesh_segment_intersector.hh
@@ -1,110 +1,110 @@
/**
* @file mesh_segment_intersector.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Apr 29 2015
* @date last modification: Wed Jan 31 2018
*
* @brief Computation of mesh intersection with segments
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_SEGMENT_INTERSECTOR_HH_
#define AKANTU_MESH_SEGMENT_INTERSECTOR_HH_
#include "aka_common.hh"
#include "mesh_geom_intersector.hh"
#include "mesh_geom_common.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
class MeshSegmentIntersector
: public MeshGeomIntersector<dim, type, Triangle<cgal::Cartesian>,
cgal::Cartesian::Segment_3, cgal::Cartesian> {
using K = cgal::Cartesian;
/// Parent class type
using parent_type =
MeshGeomIntersector<dim, type, Triangle<K>, K::Segment_3, K>;
/// Result of intersection function type
using result_type =
typename IntersectionTypeHelper<TreeTypeHelper<Triangle<K>, K>,
K::Segment_3>::intersection_type;
/// Pair of segments and element id
- using pair_type = std::pair<K::Segment_3, UInt>;
+ using pair_type = std::pair<K::Segment_3, Idx>;
public:
/// Construct from mesh
explicit MeshSegmentIntersector(Mesh & mesh, Mesh & result_mesh);
/// Destructor
~MeshSegmentIntersector() override = default;
public:
/**
* @brief Computes the intersection of the mesh with a segment
*
* @param query the segment to compute the intersections with the mesh
*/
void computeIntersectionQuery(const K::Segment_3 & query) override;
/// Compute intersection points between the mesh and a query
void computeMeshQueryIntersectionPoint(const K::Segment_3 & query,
- UInt nb_old_nodes) override;
+ Int nb_old_nodes) override;
/// Compute the embedded mesh
void
buildResultFromQueryList(const std::list<K::Segment_3> & query_list) override;
void setPhysicalName(const std::string & other) {
current_physical_name = other;
}
protected:
/// Compute segments from intersection list
void computeSegments(const std::list<result_type> & intersections,
std::set<pair_type, segmentPairsLess> & segments,
const K::Segment_3 & query);
protected:
/// Result mesh
Mesh & result_mesh;
/// Physical name of the current batch of queries
std::string current_physical_name;
};
} // namespace akantu
#include "mesh_segment_intersector_tmpl.hh"
#endif // AKANTU_MESH_SEGMENT_INTERSECTOR_HH_
diff --git a/src/geometry/mesh_segment_intersector_tmpl.hh b/src/geometry/mesh_segment_intersector_tmpl.hh
index f6646e591..76881d314 100644
--- a/src/geometry/mesh_segment_intersector_tmpl.hh
+++ b/src/geometry/mesh_segment_intersector_tmpl.hh
@@ -1,284 +1,271 @@
/**
* @file mesh_segment_intersector_tmpl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Apr 29 2015
* @date last modification: Tue Feb 20 2018
*
* @brief Computation of mesh intersection with segments
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH_
#define AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH_
#include "aka_common.hh"
#include "mesh_geom_common.hh"
#include "tree_type_helper.hh"
namespace akantu {
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
MeshSegmentIntersector<dim, type>::MeshSegmentIntersector(Mesh & mesh,
Mesh & result_mesh)
: parent_type(mesh), result_mesh(result_mesh) {
- this->intersection_points = new Array<Real>(0, dim);
+ this->intersection_points = std::make_unique<Array<Real>>(0, dim);
this->constructData();
}
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
void MeshSegmentIntersector<dim, type>::computeIntersectionQuery(
const K::Segment_3 & query) {
AKANTU_DEBUG_IN();
- result_mesh.addConnectivityType(_segment_2, _not_ghost);
- result_mesh.addConnectivityType(_segment_2, _ghost);
-
std::list<result_type> result_list;
- std::set<std::pair<K::Segment_3, UInt>, segmentPairsLess> segment_set;
+ std::set<std::pair<K::Segment_3, Int>, segmentPairsLess> segment_set;
this->factory.getTree().all_intersections(query,
std::back_inserter(result_list));
this->computeSegments(result_list, segment_set, query);
// Arrays for storing nodes and connectivity
- Array<Real> & nodes = result_mesh.getNodes();
- Array<UInt> & connectivity = result_mesh.getConnectivity(_segment_2);
+ auto & nodes = result_mesh.getNodes();
+ auto & connectivity = result_mesh.getConnectivity(_segment_2);
// Arrays for storing associated element and physical name
bool valid_elemental_data = true;
Array<Element> * associated_element = nullptr;
- Array<std::string> * associated_physical_name = nullptr;
+ Array<ID> * associated_physical_name = nullptr;
+
+ result_mesh.addConnectivityType(_segment_2, _not_ghost);
+ result_mesh.addConnectivityType(_segment_2, _ghost);
try {
associated_element =
&result_mesh.getData<Element>("associated_element", _segment_2);
associated_physical_name =
&result_mesh.getData<std::string>("physical_names", _segment_2);
} catch (debug::Exception & e) {
valid_elemental_data = false;
}
- auto it = segment_set.begin();
- auto end = segment_set.end();
-
// Loop over the segment pairs
- for (; it != end; ++it) {
- if (!it->first.is_degenerate()) {
- Vector<UInt> segment_connectivity(2);
- segment_connectivity(0) = result_mesh.getNbNodes();
- segment_connectivity(1) = result_mesh.getNbNodes() + 1;
- connectivity.push_back(segment_connectivity);
-
- // Copy nodes
- Vector<Real> source(dim);
- Vector<Real> target(dim);
- for (UInt j = 0; j < dim; j++) {
- source(j) = it->first.source()[j];
- target(j) = it->first.target()[j];
- }
+ for (auto && [segment, element] : segment_set) {
+ if (segment.is_degenerate()) {
+ continue;
+ }
- nodes.push_back(source);
- nodes.push_back(target);
+ Vector<Idx, 2> segment_connectivity{result_mesh.getNbNodes(),
+ result_mesh.getNbNodes() + 1};
+ connectivity.push_back(segment_connectivity);
- // Copy associated element info
- if (valid_elemental_data) {
- associated_element->push_back(Element{type, it->second, _not_ghost});
- associated_physical_name->push_back(current_physical_name);
- }
+ // Copy nodes
+ Vector<Real, dim> source;
+ Vector<Real, dim> target;
+ for (Int j = 0; j < dim; j++) {
+ source(j) = segment.source()[j];
+ target(j) = segment.target()[j];
+ }
+
+ nodes.push_back(source);
+ nodes.push_back(target);
+
+ // Copy associated element info
+ if (valid_elemental_data) {
+ associated_element->push_back(Element{type, element, _not_ghost});
+ associated_physical_name->push_back(current_physical_name);
}
}
AKANTU_DEBUG_OUT();
}
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
void MeshSegmentIntersector<dim, type>::computeMeshQueryIntersectionPoint(
- const K::Segment_3 & /*query*/, UInt /*nb_old_nodes*/) {
+ const K::Segment_3 & /*query*/, Int /*nb_old_nodes*/) {
AKANTU_ERROR("The method: computeMeshQueryIntersectionPoint has not "
"been implemented in class MeshSegmentIntersector!");
}
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
void MeshSegmentIntersector<dim, type>::buildResultFromQueryList(
const std::list<K::Segment_3> & query_list) {
AKANTU_DEBUG_IN();
this->computeIntersectionQueryList(query_list);
AKANTU_DEBUG_OUT();
}
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
void MeshSegmentIntersector<dim, type>::computeSegments(
const std::list<result_type> & intersections,
std::set<pair_type, segmentPairsLess> & segments,
const K::Segment_3 & query) {
AKANTU_DEBUG_IN();
/*
* Number of intersections = 0 means
*
* - query is completely outside mesh
* - query is completely inside primitive
*
* We try to determine the case and still construct the segment list
*/
if (intersections.empty()) {
// We look at all the primitives intersected by two rays
// If there is one primitive in common, then query is inside
// that primitive
K::Ray_3 ray1(query.source(), query.target());
K::Ray_3 ray2(query.target(), query.source());
- std::set<UInt> ray1_results;
- std::set<UInt> ray2_results;
+ std::set<Int> ray1_results;
+ std::set<Int> ray2_results;
this->factory.getTree().all_intersected_primitives(
ray1, std::inserter(ray1_results, ray1_results.begin()));
this->factory.getTree().all_intersected_primitives(
ray2, std::inserter(ray2_results, ray2_results.begin()));
bool inside_primitive = false;
- UInt primitive_id = 0;
+ Int primitive_id = 0;
auto ray2_it = ray2_results.begin();
auto ray2_end = ray2_results.end();
// Test if first list contains an element of second list
for (; ray2_it != ray2_end && !inside_primitive; ++ray2_it) {
if (ray1_results.find(*ray2_it) != ray1_results.end()) {
inside_primitive = true;
primitive_id = *ray2_it;
}
}
if (inside_primitive) {
segments.insert(std::make_pair(query, primitive_id));
}
+
+ return;
}
+ for (auto && intersection : intersections) {
+ auto && el = intersection->second;
+ // Result of intersection is a segment
+ if (const K::Segment_3 * segment =
+ boost::get<K::Segment_3>(&intersection->first)) {
+ // Check if the segment was alread created
+ segments.insert(std::make_pair(*segment, el));
+ continue;
+ }
- else {
- auto it = intersections.begin();
- auto end = intersections.end();
+ if (const K::Point_3 * point = boost::get<K::Point_3>(
+ &intersection->first)) { // Result of intersection is a point
+ // We only want to treat points differently if we're in 3D with Tetra4
+ // elements This should be optimized by compilator
+ if constexpr (dim == 3 and type == _tetrahedron_4) {
+ constexpr auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ TreeTypeHelper<Triangle<K>, K>::container_type facets;
+
+ const auto nodes = make_view<dim>(this->mesh.getNodes()).begin();
+ auto connectivity =
+ make_view<nb_nodes_per_element>(this->mesh.getConnectivity(type))
+ .begin();
+
+ Matrix<Real, dim, nb_nodes_per_element> node_coordinates;
+ for (auto && [node_coords, node] :
+ zip(node_coordinates, connectivity[el])) {
+ node_coords = nodes[node];
+ }
- for (; it != end; ++it) {
- UInt el = (*it)->second;
+ this->factory.addPrimitive(node_coordinates, el, facets);
- // Result of intersection is a segment
- if (const K::Segment_3 * segment =
- boost::get<K::Segment_3>(&((*it)->first))) {
- // Check if the segment was alread created
- segments.insert(std::make_pair(*segment, el));
- }
+ // Local tree
+ auto local_tree =
+ std::make_unique<TreeTypeHelper<Triangle<K>, K>::tree>(
+ facets.begin(), facets.end());
- // Result of intersection is a point
- else if (const K::Point_3 * point =
- boost::get<K::Point_3>(&((*it)->first))) {
- // We only want to treat points differently if we're in 3D with Tetra4
- // elements This should be optimized by compilator
- if (dim == 3 && type == _tetrahedron_4) {
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- TreeTypeHelper<Triangle<K>, K>::container_type facets;
-
- const Array<Real> & nodes = this->mesh.getNodes();
- Array<UInt>::const_vector_iterator connectivity_vec =
- this->mesh.getConnectivity(type).begin(nb_nodes_per_element);
-
- const Vector<UInt> & el_connectivity = connectivity_vec[el];
-
- Matrix<Real> node_coordinates(dim, nb_nodes_per_element);
- for (UInt i = 0; i < nb_nodes_per_element; i++) {
- for (UInt j = 0; j < dim; j++) {
- node_coordinates(j, i) = nodes(el_connectivity(i), j);
- }
- }
+ // Compute local intersections (with current element)
+ std::list<result_type> local_intersections;
+ local_tree->all_intersections(query,
+ std::back_inserter(local_intersections));
- this->factory.addPrimitive(node_coordinates, el, facets);
-
- // Local tree
- auto * local_tree = new TreeTypeHelper<Triangle<K>, K>::tree(
- facets.begin(), facets.end());
-
- // Compute local intersections (with current element)
- std::list<result_type> local_intersections;
- local_tree->all_intersections(
- query, std::back_inserter(local_intersections));
-
- bool out_point_found = false;
- auto local_it = local_intersections.begin();
- auto local_end = local_intersections.end();
-
- for (; local_it != local_end; ++local_it) {
- if (const auto * local_point =
- boost::get<K::Point_3>(&((*local_it)->first))) {
- if (!comparePoints(*point, *local_point)) {
- K::Segment_3 seg(*point, *local_point);
- segments.insert(std::make_pair(seg, el));
- out_point_found = true;
- }
+ bool out_point_found = false;
+ for (auto && local_intersection : local_intersections) {
+ if (const auto * local_point =
+ boost::get<K::Point_3>(&local_intersection->first)) {
+ if (!comparePoints(*point, *local_point)) {
+ K::Segment_3 seg(*point, *local_point);
+ segments.insert(std::make_pair(seg, el));
+ out_point_found = true;
}
}
+ }
- if (!out_point_found) {
- using Point = TreeTypeHelper<Triangle<K>, K>::point_type;
- Point a(node_coordinates(0, 0), node_coordinates(1, 0),
- node_coordinates(2, 0));
- Point b(node_coordinates(0, 1), node_coordinates(1, 1),
- node_coordinates(2, 1));
- Point c(node_coordinates(0, 2), node_coordinates(1, 2),
- node_coordinates(2, 2));
- Point d(node_coordinates(0, 3), node_coordinates(1, 3),
- node_coordinates(2, 3));
- K::Tetrahedron_3 tetra(a, b, c, d);
- const K::Point_3 * inside_point = nullptr;
- if (tetra.has_on_bounded_side(query.source()) &&
- !tetra.has_on_boundary(query.source())) {
- inside_point = &query.source();
- } else if (tetra.has_on_bounded_side(query.target()) &&
- !tetra.has_on_boundary(query.target())) {
- inside_point = &query.target();
- }
-
- if (inside_point != nullptr) {
- K::Segment_3 seg(*inside_point, *point);
- segments.insert(std::make_pair(seg, el));
- }
+ if (not out_point_found) {
+ using Point = TreeTypeHelper<Triangle<K>, K>::point_type;
+ Point a(node_coordinates(0, 0), node_coordinates(1, 0),
+ node_coordinates(2, 0));
+ Point b(node_coordinates(0, 1), node_coordinates(1, 1),
+ node_coordinates(2, 1));
+ Point c(node_coordinates(0, 2), node_coordinates(1, 2),
+ node_coordinates(2, 2));
+ Point d(node_coordinates(0, 3), node_coordinates(1, 3),
+ node_coordinates(2, 3));
+ K::Tetrahedron_3 tetra(a, b, c, d);
+ const K::Point_3 * inside_point = nullptr;
+ if (tetra.has_on_bounded_side(query.source()) &&
+ !tetra.has_on_boundary(query.source())) {
+ inside_point = &query.source();
+ } else if (tetra.has_on_bounded_side(query.target()) &&
+ !tetra.has_on_boundary(query.target())) {
+ inside_point = &query.target();
}
- delete local_tree;
+ if (inside_point != nullptr) {
+ K::Segment_3 seg(*inside_point, *point);
+ segments.insert(std::make_pair(seg, el));
+ }
}
}
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif // AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH_
diff --git a/src/geometry/mesh_sphere_intersector.hh b/src/geometry/mesh_sphere_intersector.hh
index cba002d25..6cb14d21d 100644
--- a/src/geometry/mesh_sphere_intersector.hh
+++ b/src/geometry/mesh_sphere_intersector.hh
@@ -1,120 +1,120 @@
/**
* @file mesh_sphere_intersector.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Jun 23 2015
* @date last modification: Tue Feb 20 2018
*
* @brief Computation of mesh intersection with sphere(s)
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_SPHERE_INTERSECTOR_HH_
#define AKANTU_MESH_SPHERE_INTERSECTOR_HH_
#include "aka_common.hh"
#include "mesh_geom_intersector.hh"
#include "mesh_geom_common.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
class MeshSphereIntersector
: public MeshGeomIntersector<dim, type, Line_arc<cgal::Spherical>,
cgal::Spherical::Sphere_3, cgal::Spherical> {
using SK = cgal::Spherical;
using K = cgal::Cartesian;
/// Parent class type
- typedef MeshGeomIntersector<dim, type, Line_arc<SK>, SK::Sphere_3, SK>
- parent_type;
+ using parent_type =
+ MeshGeomIntersector<dim, type, Line_arc<SK>, SK::Sphere_3, SK>;
/// Result of intersection function type
- typedef typename IntersectionTypeHelper<TreeTypeHelper<Triangle<K>, K>,
- K::Segment_3>::intersection_type
- result_type;
+ using result_type =
+ typename IntersectionTypeHelper<TreeTypeHelper<Triangle<K>, K>,
+ K::Segment_3>::intersection_type;
/// Pair of intersection points and element id
- typedef std::pair<SK::Circular_arc_point_3, UInt> pair_type;
+ using pair_type = std::pair<SK::Circular_arc_point_3, Int>;
public:
/// Construct from mesh
explicit MeshSphereIntersector(Mesh & mesh);
/// Destructor
virtual ~MeshSphereIntersector();
public:
/// Construct the primitive tree object
- virtual void constructData(GhostType ghost_type = _not_ghost);
+ void constructData(GhostType ghost_type = _not_ghost) override;
/**
* @brief Computes the intersection of the mesh with a sphere
*/
- virtual void computeIntersectionQuery(const SK::Sphere_3 & /* query */) {
+ void computeIntersectionQuery(const SK::Sphere_3 & /* query */) override {
AKANTU_ERROR("This function is not implemented for spheres (It was "
"to generic and has been replaced by "
"computeMeshQueryIntersectionPoint");
}
/**
* Compute intersection points between the mesh primitives (segments) and a
* query (surface in 3D or a curve in 2D), double intersection points for the
* same primitives are not considered. A maximum is set to the number of
* intersection nodes per element: 2 in 2D and 4 in 3D
*/
- virtual void computeMeshQueryIntersectionPoint(const SK::Sphere_3 & query,
- UInt nb_old_nodes);
+ void computeMeshQueryIntersectionPoint(const SK::Sphere_3 & query,
+ Int nb_old_nodes) override;
/// Build the IGFEM mesh
- virtual void
- buildResultFromQueryList(const std::list<SK::Sphere_3> & /*query*/) {
+ void
+ buildResultFromQueryList(const std::list<SK::Sphere_3> & /*query*/) override {
AKANTU_ERROR("This function is no longer implemented to split "
"geometrical operations and dedicated result "
"construction");
}
/// Set the tolerance
void setToleranceIntersectionOnNode(UInt tol) {
this->tol_intersection_on_node = tol;
}
protected:
/// tolerance for which the intersection is considered on the mesh node
/// (relative to the segment lenght)
Real tol_intersection_on_node;
};
} // namespace akantu
#include "mesh_sphere_intersector_tmpl.hh"
#endif // AKANTU_MESH_SPHERE_INTERSECTOR_HH_
diff --git a/src/geometry/mesh_sphere_intersector_tmpl.hh b/src/geometry/mesh_sphere_intersector_tmpl.hh
index 3a327264d..42f38269e 100644
--- a/src/geometry/mesh_sphere_intersector_tmpl.hh
+++ b/src/geometry/mesh_sphere_intersector_tmpl.hh
@@ -1,216 +1,213 @@
/**
* @file mesh_sphere_intersector_tmpl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Jun 23 2015
* @date last modification: Tue Dec 04 2018
*
* @brief Computation of mesh intersection with spheres
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH_
#define AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH_
#include "aka_common.hh"
#include "mesh_geom_common.hh"
#include "mesh_sphere_intersector.hh"
#include "tree_type_helper.hh"
namespace akantu {
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
MeshSphereIntersector<dim, type>::MeshSphereIntersector(Mesh & mesh)
: parent_type(mesh), tol_intersection_on_node(1e-10) {
#if defined(AKANTU_IGFEM)
- if ((type == _triangle_3) || (type == _igfem_triangle_4) ||
- (type == _igfem_triangle_5)) {
- const_cast<UInt &>(this->nb_seg_by_el) = 3;
+ if constexpr ((type == _triangle_3) or (type == _igfem_triangle_4) or
+ (type == _igfem_triangle_5)) {
+ this->nb_seg_by_el = 3;
} else {
AKANTU_ERROR("Not ready for mesh type " << type);
}
#else
- if ((type != _triangle_3))
+ if (type != _triangle_3) {
AKANTU_ERROR("Not ready for mesh type " << type);
+ }
#endif
// initialize the intersection pointsss array with the spatial dimension
this->intersection_points = new Array<Real>(0, dim);
// A maximum is set to the number of intersection nodes per element to limit
// the size of new_node_per_elem: 2 in 2D and 4 in 3D
this->new_node_per_elem = new Array<UInt>(0, 1 + 4 * (dim - 1));
}
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
MeshSphereIntersector<dim, type>::~MeshSphereIntersector() {
delete this->new_node_per_elem;
delete this->intersection_points;
}
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
void MeshSphereIntersector<dim, type>::constructData(GhostType ghost_type) {
this->new_node_per_elem->resize(this->mesh.getNbElement(type, ghost_type));
this->new_node_per_elem->clear();
MeshGeomIntersector<dim, type, Line_arc<SK>, SK::Sphere_3, SK>::constructData(
ghost_type);
}
-template <UInt dim, ElementType type>
+template <Int dim, ElementType type>
void MeshSphereIntersector<dim, type>::computeMeshQueryIntersectionPoint(
- const SK::Sphere_3 & query, UInt nb_old_nodes) {
+ const SK::Sphere_3 & query, Int nb_old_nodes) {
/// function to replace computeIntersectionQuery in a more generic geometry
/// module version
// The newNodeEvent is not send from this method who only compute the
// intersection points
AKANTU_DEBUG_IN();
- Array<Real> & nodes = this->mesh.getNodes();
- UInt nb_node = nodes.size() + this->intersection_points->size();
+ auto & nodes = this->mesh.getNodes();
+ auto nb_node = nodes.size() + this->intersection_points->size();
// Tolerance for proximity checks should be defined by user
Real global_tolerance = Math::getTolerance();
Math::setTolerance(tol_intersection_on_node);
- typedef boost::variant<pair_type> sk_inter_res;
-
- TreeTypeHelper<Line_arc<cgal::Spherical>, cgal::Spherical>::const_iterator
- it = this->factory.getPrimitiveList().begin(),
- end = this->factory.getPrimitiveList().end();
+ using sk_inter_res = boost::variant<pair_type>;
- for (; it != end; ++it) { // loop on the primitives (segments)
+ // loop on the primitives (segments)
+ for (auto && primitive : this->factory.getPrimitiveList()) {
std::list<sk_inter_res> s_results;
- CGAL::intersection(*it, query, std::back_inserter(s_results));
-
- if (s_results.size() == 1) { // just one point
- if (pair_type * pair = boost::get<pair_type>(&s_results.front())) {
- if (pair->second == 1) { // not a point tangent to the sphere
- // the intersection point written as a vector
- Vector<Real> new_node(dim, 0.0);
- cgal::Cartesian::Point_3 point(CGAL::to_double(pair->first.x()),
- CGAL::to_double(pair->first.y()),
- CGAL::to_double(pair->first.z()));
- for (UInt i = 0; i < dim; i++) {
- new_node(i) = point[i];
- }
-
- /// boolean to decide wheter intersection point is on a standard node
- /// of the mesh or not
- bool is_on_mesh = false;
- /// boolean to decide if this intersection point has been already
- /// computed for a neighbor element
- bool is_new = true;
-
- /// check if intersection point has already been computed
- UInt n = nb_old_nodes;
-
- // check if we already compute this intersection and add it as a node
- // for a neighboor element of another type
- auto existing_node = nodes.begin(dim);
-
- for (; n < nodes.size(); ++n) { // loop on the nodes from nb_old_nodes
- if (Math::are_vector_equal(dim, new_node.storage(),
- existing_node[n].storage())) {
- is_new = false;
- break;
- }
- }
- if (is_new) {
- auto intersection_points_it = this->intersection_points->begin(dim);
- auto intersection_points_end = this->intersection_points->end(dim);
- for (; intersection_points_it != intersection_points_end;
- ++intersection_points_it, ++n) {
- if (Math::are_vector_equal(dim, new_node.storage(),
- intersection_points_it->storage())) {
- is_new = false;
- break;
- }
- }
- }
-
- // get the initial and final points of the primitive (segment) and
- // write them as vectors
- cgal::Cartesian::Point_3 source_cgal(
- CGAL::to_double(it->source().x()),
- CGAL::to_double(it->source().y()),
- CGAL::to_double(it->source().z()));
- cgal::Cartesian::Point_3 target_cgal(
- CGAL::to_double(it->target().x()),
- CGAL::to_double(it->target().y()),
- CGAL::to_double(it->target().z()));
- Vector<Real> source(dim), target(dim);
- for (UInt i = 0; i < dim; i++) {
- source(i) = source_cgal[i];
- target(i) = target_cgal[i];
- }
-
- // Check if we are close from a node of the primitive (segment)
- if (Math::are_vector_equal(dim, source.storage(),
- new_node.storage()) ||
- Math::are_vector_equal(dim, target.storage(),
- new_node.storage())) {
- is_on_mesh = true;
- is_new = false;
- }
-
- if (is_new) { // if the intersection point is a new one add it to the
- // list
- this->intersection_points->push_back(new_node);
- nb_node++;
- }
-
- // deduce the element id
- UInt element_id = it->id();
-
- // fill the new_node_per_elem array
- if (!is_on_mesh) { // if the node is not on a mesh node
- UInt & nb_new_nodes_per_el =
- (*this->new_node_per_elem)(element_id, 0);
- nb_new_nodes_per_el += 1;
- AKANTU_DEBUG_ASSERT(
- 2 * nb_new_nodes_per_el <
- this->new_node_per_elem->getNbComponent(),
- "You might have to interface crossing the same material");
- (*this->new_node_per_elem)(element_id,
- (2 * nb_new_nodes_per_el) - 1) = n;
- (*this->new_node_per_elem)(element_id, 2 * nb_new_nodes_per_el) =
- it->segId();
- }
+ CGAL::intersection(primitive, query, std::back_inserter(s_results));
+
+ if (s_results.size() != 1) { // not just one point
+ continue;
+ }
+
+ auto * pair = boost::get<pair_type>(&s_results.front());
+
+ if (not pair and pair->second != 1) {
+ continue;
+ }
+
+ // the intersection point written as a vector
+ Vector<Real> new_node(dim, 0.0);
+ cgal::Cartesian::Point_3 point(CGAL::to_double(pair->first.x()),
+ CGAL::to_double(pair->first.y()),
+ CGAL::to_double(pair->first.z()));
+ for (Int i = 0; i < dim; i++) {
+ new_node(i) = point[i];
+ }
+
+ /// boolean to decide wheter intersection point is on a standard node
+ /// of the mesh or not
+ bool is_on_mesh = false;
+ /// boolean to decide if this intersection point has been already
+ /// computed for a neighbor element
+ bool is_new = true;
+
+ // check if intersection point has already been computed
+ auto old_node_id = nb_old_nodes;
+ // check if we already compute this intersection and add it as a node
+ // for a neighbor element of another type
+ auto node_view = make_view<dim>(nodes);
+ // loop on the nodes from nb_old_nodes
+ for (auto && existing_node :
+ range(node_view.begin() + nb_old_nodes, node_view.end())) {
+ if (new_node.isApprox(existing_node)) {
+ is_new = false;
+ break;
+ }
+ ++old_node_id;
+ }
+
+ if (is_new) {
+ for (auto && intersection_point :
+ make_view<dim>(*this->intersection_points)) {
+ if (new_node.isApprox(intersection_point)) {
+ is_new = false;
+ break;
}
}
}
+
+ // get the initial and final points of the primitive (segment) and
+ // write them as vectors
+ cgal::Cartesian::Point_3 source_cgal(
+ CGAL::to_double(primitive.source().x()),
+ CGAL::to_double(primitive.source().y()),
+ CGAL::to_double(primitive.source().z()));
+ cgal::Cartesian::Point_3 target_cgal(
+ CGAL::to_double(primitive.target().x()),
+ CGAL::to_double(primitive.target().y()),
+ CGAL::to_double(primitive.target().z()));
+
+ Vector<Real, dim> source, target;
+ for (Int i = 0; i < dim; i++) {
+ source(i) = source_cgal[i];
+ target(i) = target_cgal[i];
+ }
+
+ // Check if we are close from a node of the primitive (segment)
+ if (source.isApprox(new_node) or target.isApprox(new_node)) {
+ is_on_mesh = true;
+ is_new = false;
+ }
+
+ // if the intersection point is a new one add it to the
+ // list
+ if (is_new) {
+ this->intersection_points->push_back(new_node);
+ nb_node++;
+ }
+
+ // deduce the element id
+ auto element_id = primitive.id();
+
+ // fill the new_node_per_elem array
+ if (not is_on_mesh) { // if the node is not on a mesh node
+ auto & nb_new_nodes_per_el = (*this->new_node_per_elem)(element_id, 0);
+ nb_new_nodes_per_el += 1;
+ AKANTU_DEBUG_ASSERT(
+ 2 * nb_new_nodes_per_el < this->new_node_per_elem->getNbComponent(),
+ "You might have to interface crossing the same material");
+ (*this->new_node_per_elem)(element_id, (2 * nb_new_nodes_per_el) - 1) =
+ old_node_id;
+ (*this->new_node_per_elem)(element_id, 2 * nb_new_nodes_per_el) =
+ primitive.segId();
+ }
}
Math::setTolerance(global_tolerance);
AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif // AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH_
diff --git a/src/geometry/tree_type_helper.hh b/src/geometry/tree_type_helper.hh
index cf021feb2..137f853a7 100644
--- a/src/geometry/tree_type_helper.hh
+++ b/src/geometry/tree_type_helper.hh
@@ -1,111 +1,110 @@
/**
* @file tree_type_helper.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri Jan 04 2013
* @date last modification: Thu Feb 01 2018
*
* @brief Converts element types of a mesh to CGAL primitive types
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TREE_TYPE_HELPER_HH_
#define AKANTU_TREE_TYPE_HELPER_HH_
#include "aka_common.hh"
#include "line_arc.hh"
#include "tetrahedron.hh"
#include "triangle.hh"
#include "aabb_primitive.hh"
#include "mesh_geom_common.hh"
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_tree.h>
namespace akantu {
/* -------------------------------------------------------------------------- */
/// Replacement class for algorithm that can't use the AABB tree types
template <typename iterator> struct VoidTree {
VoidTree(const iterator & /*begin*/, const iterator & /*end*/) {}
};
/// Helper class used to ease the use of CGAL AABB tree algorithm
template <class Primitive, class Kernel> struct TreeTypeHelper {
static const bool is_valid = false;
using primitive_type = Primitive;
using container_type = typename std::list<primitive_type>;
using iterator = typename container_type::iterator;
using const_iterator = typename container_type::const_iterator;
using point_type = typename CGAL::Point_3<Kernel>;
using tree = VoidTree<iterator>;
};
/// Helper class used to ease the use of intersections
template <class TTHelper, class Query> struct IntersectionTypeHelper;
/**
* Macro used to specialize TreeTypeHelper
* @param my_primitive associated primitive type
* @param my_query query_type
* @param my_kernel kernel type
*/
#define TREE_TYPE_HELPER_MACRO(my_primitive, my_query, my_kernel) \
template <> \
struct TreeTypeHelper<my_primitive<my_kernel> /*NOLINT*/, my_kernel> { \
static const bool is_valid = true; \
using primitive_type = my_primitive<my_kernel>; /*NOLINT*/ \
using aabb_primitive_type = my_primitive##_primitive; \
using point_type = CGAL::Point_3<my_kernel>; \
using container_type = std::list<primitive_type>; \
using iterator = container_type::iterator; \
using aabb_traits_type = \
CGAL::AABB_traits<my_kernel, aabb_primitive_type>; \
using tree = CGAL::AABB_tree<aabb_traits_type>; \
using id_type = tree::Primitive_id; \
}; \
\
template <> \
struct IntersectionTypeHelper< \
TreeTypeHelper<my_primitive<my_kernel>, /*NOLINT*/ my_kernel>, \
my_query> { \
- typedef boost::optional<TreeTypeHelper< \
+ using intersection_type = boost::optional<TreeTypeHelper< \
my_primitive<my_kernel>, /*NOLINT*/ \
- my_kernel>::tree::Intersection_and_primitive_id<my_query>::Type> \
- intersection_type; \
+ my_kernel>::tree::Intersection_and_primitive_id<my_query>::Type>; \
}
TREE_TYPE_HELPER_MACRO(Triangle, cgal::Cartesian::Segment_3, cgal::Cartesian);
// TREE_TYPE_HELPER_MACRO(Line_arc, cgal::Spherical::Sphere_3, cgal::Spherical);
#undef TREE_TYPE_HELPER_MACRO
} // namespace akantu
#endif // AKANTU_TREE_TYPE_HELPER_HH_
diff --git a/src/io/dumper/dumpable.cc b/src/io/dumper/dumpable.cc
index 9944aa68e..6e6313848 100644
--- a/src/io/dumper/dumpable.cc
+++ b/src/io/dumper/dumpable.cc
@@ -1,273 +1,269 @@
/**
* @file dumpable.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri Feb 28 2020
*
* @brief Implementation of the dumpable interface
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumpable.hh"
/* -------------------------------------------------------------------------- */
#include <io_helper.hh>
#include <utility>
namespace akantu {
/* -------------------------------------------------------------------------- */
Dumpable::Dumpable() = default;
/* -------------------------------------------------------------------------- */
Dumpable::~Dumpable() = default;
/* -------------------------------------------------------------------------- */
void Dumpable::registerExternalDumper(std::shared_ptr<DumperIOHelper> dumper,
const std::string & dumper_name,
const bool is_default) {
this->dumpers[dumper_name] = std::move(dumper);
if (is_default) {
this->default_dumper = dumper_name;
}
}
/* -------------------------------------------------------------------------- */
-void Dumpable::addDumpMesh(const Mesh & mesh, UInt spatial_dimension,
+void Dumpable::addDumpMesh(const Mesh & mesh, Int spatial_dimension,
GhostType ghost_type, ElementKind element_kind) {
this->addDumpMeshToDumper(this->default_dumper, mesh, spatial_dimension,
ghost_type, element_kind);
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpMeshToDumper(const std::string & dumper_name,
- const Mesh & mesh, UInt spatial_dimension,
+ const Mesh & mesh, Int spatial_dimension,
GhostType ghost_type,
ElementKind element_kind) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.registerMesh(mesh, spatial_dimension, ghost_type, element_kind);
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpFilteredMesh(
- const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter, UInt spatial_dimension,
+ const Mesh & mesh, const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter, Int spatial_dimension,
GhostType ghost_type, ElementKind element_kind) {
this->addDumpFilteredMeshToDumper(this->default_dumper, mesh, elements_filter,
nodes_filter, spatial_dimension, ghost_type,
element_kind);
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpFilteredMeshToDumper(
const std::string & dumper_name, const Mesh & mesh,
- const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter, UInt spatial_dimension,
+ const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter, Int spatial_dimension,
GhostType ghost_type, ElementKind element_kind) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.registerFilteredMesh(mesh, elements_filter, nodes_filter,
spatial_dimension, ghost_type, element_kind);
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpField(const std::string & field_id) {
this->addDumpFieldToDumper(this->default_dumper, field_id);
}
/* -------------------------------------------------------------------------- */
-void Dumpable::addDumpFieldToDumper(__attribute__((unused))
- const std::string & dumper_name,
- __attribute__((unused))
- const std::string & field_id) {
+void Dumpable::addDumpFieldToDumper(const std::string & /*dumper_name*/,
+ const std::string & /*field_id*/) {
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpFieldExternal(const std::string & field_id,
std::shared_ptr<dumpers::Field> field) {
this->addDumpFieldExternalToDumper(this->default_dumper, field_id,
std::move(field));
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpFieldExternalToDumper(
const std::string & dumper_name, const std::string & field_id,
std::shared_ptr<dumpers::Field> field) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.registerField(field_id, std::move(field));
}
/* -------------------------------------------------------------------------- */
void Dumpable::removeDumpField(const std::string & field_id) {
this->removeDumpFieldFromDumper(this->default_dumper, field_id);
}
/* -------------------------------------------------------------------------- */
void Dumpable::removeDumpFieldFromDumper(const std::string & dumper_name,
const std::string & field_id) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.unRegisterField(field_id);
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpFieldVector(const std::string & field_id) {
this->addDumpFieldVectorToDumper(this->default_dumper, field_id);
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpFieldVectorToDumper(const std::string & /*dumper_name*/,
const std::string & /*field_id*/) {
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
void Dumpable::addDumpFieldTensor(const std::string & field_id) {
this->addDumpFieldTensorToDumper(this->default_dumper, field_id);
}
/* -------------------------------------------------------------------------- */
-void Dumpable::addDumpFieldTensorToDumper(__attribute__((unused))
- const std::string & dumper_name,
- __attribute__((unused))
- const std::string & field_id) {
+void Dumpable::addDumpFieldTensorToDumper(const std::string & /*dumper_name*/,
+ const std::string & /*field_id*/) {
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
void Dumpable::setDirectory(const std::string & directory) {
this->setDirectoryToDumper(this->default_dumper, directory);
}
/* -------------------------------------------------------------------------- */
void Dumpable::setDirectoryToDumper(const std::string & dumper_name,
const std::string & directory) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.setDirectory(directory);
}
/* -------------------------------------------------------------------------- */
void Dumpable::setBaseName(const std::string & basename) {
this->setBaseNameToDumper(this->default_dumper, basename);
}
/* -------------------------------------------------------------------------- */
void Dumpable::setBaseNameToDumper(const std::string & dumper_name,
const std::string & basename) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.setBaseName(basename);
}
/* -------------------------------------------------------------------------- */
void Dumpable::setTimeStepToDumper(Real time_step) {
this->setTimeStepToDumper(this->default_dumper, time_step);
}
/* -------------------------------------------------------------------------- */
void Dumpable::setTimeStepToDumper(const std::string & dumper_name,
Real time_step) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.setTimeStep(time_step);
}
/* -------------------------------------------------------------------------- */
void Dumpable::setTextModeToDumper(const std::string & dumper_name) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.getDumper().setMode(iohelper::TEXT);
}
/* -------------------------------------------------------------------------- */
void Dumpable::setTextModeToDumper() {
DumperIOHelper & dumper = this->getDumper(this->default_dumper);
dumper.getDumper().setMode(iohelper::TEXT);
}
/* -------------------------------------------------------------------------- */
void Dumpable::dump(const std::string & dumper_name) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.dump();
}
/* -------------------------------------------------------------------------- */
void Dumpable::dump() { this->dump(this->default_dumper); }
/* -------------------------------------------------------------------------- */
-void Dumpable::dump(const std::string & dumper_name, UInt step) {
+void Dumpable::dump(const std::string & dumper_name, Int step) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.dump(step);
}
/* -------------------------------------------------------------------------- */
-void Dumpable::dump(UInt step) { this->dump(this->default_dumper, step); }
+void Dumpable::dump(Int step) { this->dump(this->default_dumper, step); }
/* -------------------------------------------------------------------------- */
-void Dumpable::dump(const std::string & dumper_name, Real time, UInt step) {
+void Dumpable::dump(const std::string & dumper_name, Real time, Int step) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.dump(time, step);
}
/* -------------------------------------------------------------------------- */
-void Dumpable::dump(Real time, UInt step) {
+void Dumpable::dump(Real time, Int step) {
this->dump(this->default_dumper, time, step);
}
/* -------------------------------------------------------------------------- */
void Dumpable::internalAddDumpFieldToDumper(
const std::string & dumper_name, const std::string & field_id,
std::shared_ptr<dumpers::Field> field) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.registerField(field_id, std::move(field));
}
/* -------------------------------------------------------------------------- */
DumperIOHelper & Dumpable::getDumper() {
return this->getDumper(this->default_dumper);
}
/* -------------------------------------------------------------------------- */
DumperIOHelper & Dumpable::getDumper(const std::string & dumper_name) {
auto it = this->dumpers.find(dumper_name);
auto end = this->dumpers.end();
if (it == end) {
AKANTU_EXCEPTION("Dumper \"" << dumper_name
<< "\" has not been registered, yet.");
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
std::string Dumpable::getDefaultDumperName() const {
return this->default_dumper;
}
} // namespace akantu
diff --git a/src/io/dumper/dumpable_dummy.hh b/src/io/dumper/dumpable_dummy.hh
index d5c754532..3c13a97d0 100644
--- a/src/io/dumper/dumpable_dummy.hh
+++ b/src/io/dumper/dumpable_dummy.hh
@@ -1,269 +1,269 @@
/**
* @file dumpable_dummy.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Oct 26 2012
* @date last modification: Thu Feb 20 2020
*
* @brief Interface for object who wants to dump themselves
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#if !defined(DOXYGEN)
#ifndef AKANTU_DUMPABLE_DUMMY_HH_
#define AKANTU_DUMPABLE_DUMMY_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused"
namespace dumpers {
class Field;
}
class DumperIOHelper;
class Mesh;
/* -------------------------------------------------------------------------- */
class Dumpable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
Dumpable(){};
virtual ~Dumpable(){};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
template <class T>
inline void registerDumper(const std::string & dumper_name,
const std::string & file_name = "",
const bool is_default = false) {}
void registerExternalDumper(std::shared_ptr<DumperIOHelper> dumper,
const std::string & dumper_name,
const bool is_default = false) {}
- void addDumpMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions,
+ void addDumpMesh(const Mesh & mesh, Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined) {}
void addDumpMeshToDumper(const std::string & dumper_name, const Mesh & mesh,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined) {}
void addDumpFilteredMesh(const Mesh & mesh,
- const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter,
- UInt spatial_dimension = _all_dimensions,
+ const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined) {}
void
addDumpFilteredMeshToDumper(const std::string & dumper_name,
const Mesh & mesh,
- const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined) {}
+ const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter,
+ Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined) {}
virtual void addDumpField(const std::string & field_id) {
AKANTU_TO_IMPLEMENT();
}
virtual void addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) {
AKANTU_TO_IMPLEMENT();
}
virtual void addDumpFieldExternal(const std::string & field_id,
std::shared_ptr<dumpers::Field> field) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
virtual void
addDumpFieldExternalToDumper(const std::string & dumper_name,
const std::string & field_id,
std::shared_ptr<dumpers::Field> field) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
template <typename T>
void addDumpFieldExternal(const std::string & field_id,
const Array<T> & field) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
template <typename T>
void addDumpFieldExternalToDumper(const std::string & dumper_name,
const std::string & field_id,
const Array<T> & field) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
template <typename T>
void addDumpFieldExternal(const std::string & field_id,
- const ElementTypeMapArray<T> & field,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined) {
+ const ElementTypeMapArray<T> & field,
+ Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
template <typename T>
void
addDumpFieldExternalToDumper(const std::string & dumper_name,
const std::string & field_id,
- const ElementTypeMapArray<T> & field,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined) {
+ const ElementTypeMapArray<T> & field,
+ Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void removeDumpField(const std::string & field_id) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void removeDumpFieldFromDumper(const std::string & dumper_name,
const std::string & field_id) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void setDirecory(const std::string & directory) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void setDirectoryToDumper(const std::string & dumper_name,
const std::string & directory) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void setBaseName(const std::string & basename) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void setBaseNameToDumper(const std::string & dumper_name,
const std::string & basename) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void setTextModeToDumper(const std::string & dumper_name) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void setTextModeToDumper() {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void dump() {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
void dump(const std::string & dumper_name) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
- void dump(UInt step) {
+ void dump(Int step) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
- void dump(const std::string & dumper_name, UInt step) {
+ void dump(const std::string & dumper_name, Int step) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
- void dump(Real current_time, UInt step) {
+ void dump(Real current_time, Int step) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
- void dump(const std::string & dumper_name, Real current_time, UInt step) {
+ void dump(const std::string & dumper_name, Real current_time, Int step) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
protected:
void internalAddDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
std::shared_ptr<dumpers::Field> field) {
AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
protected:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
DumperIOHelper & getDumper() {
AKANTU_ERROR("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
DumperIOHelper & getDumper(const std::string & dumper_name) {
AKANTU_ERROR("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
template <class T> T & getDumper(const std::string & dumper_name) {
AKANTU_ERROR("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
std::string getDefaultDumperName() {
AKANTU_ERROR("No dumper activated at compilation, turn on "
"AKANTU_USE_IOHELPER in cmake.");
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
};
#pragma GCC diagnostic pop
} // namespace akantu
#endif /* AKANTU_DUMPABLE_DUMMY_HH_ */
#endif // DOXYGEN
diff --git a/src/io/dumper/dumpable_inline_impl.hh b/src/io/dumper/dumpable_inline_impl.hh
index 2aa99cabc..9823cb68e 100644
--- a/src/io/dumper/dumpable_inline_impl.hh
+++ b/src/io/dumper/dumpable_inline_impl.hh
@@ -1,134 +1,134 @@
/**
* @file dumpable_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Thu Feb 20 2020
*
* @brief Implementation of the Dumpable class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPABLE_INLINE_IMPL_HH_
#define AKANTU_DUMPABLE_INLINE_IMPL_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_elemental_field.hh"
#include "dumper_nodal_field.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class T>
inline void Dumpable::registerDumper(const std::string & dumper_name,
const std::string & file_name,
const bool is_default) {
if (this->dumpers.find(dumper_name) != this->dumpers.end()) {
AKANTU_DEBUG_INFO("Dumper " + dumper_name + "is already registered.");
}
std::string name = file_name;
if (name.empty()) {
name = dumper_name;
}
this->dumpers[dumper_name] = std::make_shared<T>(name);
if (is_default) {
this->default_dumper = dumper_name;
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void Dumpable::addDumpFieldExternal(const std::string & field_id,
const Array<T> & field) {
this->addDumpFieldExternalToDumper<T>(this->default_dumper, field_id, field);
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void
Dumpable::addDumpFieldExternalToDumper(const std::string & dumper_name,
const std::string & field_id,
const Array<T> & field) {
auto field_cont = std::make_shared<dumpers::NodalField<T>>(field);
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.registerField(field_id, field_cont);
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void Dumpable::addDumpFieldExternal(const std::string & field_id,
const ElementTypeMapArray<T> & field,
- UInt spatial_dimension,
+ Int spatial_dimension,
GhostType ghost_type,
ElementKind element_kind) {
this->addDumpFieldExternalToDumper(this->default_dumper, field_id, field,
spatial_dimension, ghost_type,
element_kind);
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void Dumpable::addDumpFieldExternalToDumper(
const std::string & dumper_name, const std::string & field_id,
- const ElementTypeMapArray<T> & field, UInt spatial_dimension,
+ const ElementTypeMapArray<T> & field, Int spatial_dimension,
GhostType ghost_type, ElementKind element_kind) {
std::shared_ptr<dumpers::Field> field_cont;
#if defined(AKANTU_IGFEM)
if (element_kind == _ek_igfem) {
field_cont = std::make_shared<dumpers::IGFEMElementalField<T>>(
field, spatial_dimension, ghost_type, element_kind);
} else
#endif
field_cont = std::make_shared<dumpers::ElementalField<T>>(
field, spatial_dimension, ghost_type, element_kind);
DumperIOHelper & dumper = this->getDumper(dumper_name);
dumper.registerField(field_id, field_cont);
}
/* -------------------------------------------------------------------------- */
template <class T>
inline T & Dumpable::getDumper(const std::string & dumper_name) {
DumperIOHelper & dumper = this->getDumper(dumper_name);
try {
auto & templated_dumper = aka::as_type<T>(dumper);
return templated_dumper;
} catch (std::bad_cast &) {
AKANTU_EXCEPTION("Dumper " << dumper_name << " is not of type: "
<< debug::demangle(typeid(T).name()));
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_DUMPABLE_INLINE_IMPL_HH_ */
diff --git a/src/io/dumper/dumpable_iohelper.hh b/src/io/dumper/dumpable_iohelper.hh
index d9b1b4318..afa3e4371 100644
--- a/src/io/dumper/dumpable_iohelper.hh
+++ b/src/io/dumper/dumpable_iohelper.hh
@@ -1,195 +1,195 @@
/**
* @file dumpable_iohelper.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 06 2015
* @date last modification: Fri Feb 28 2020
*
* @brief Interface for object who wants to dump themselves
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper.hh"
/* -------------------------------------------------------------------------- */
#include <set>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DUMPABLE_IOHELPER_HH_
#define AKANTU_DUMPABLE_IOHELPER_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class Dumpable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
Dumpable();
virtual ~Dumpable();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// create a new dumper (of templated type T) and register it under
/// dumper_name. file_name is used for construction of T. is default states if
/// this dumper is the default dumper.
template <class T>
inline void registerDumper(const std::string & dumper_name,
const std::string & file_name = "",
bool is_default = false);
/// register an externally created dumper
void registerExternalDumper(std::shared_ptr<DumperIOHelper> dumper,
const std::string & dumper_name,
bool is_default = false);
/// register a mesh to the default dumper
- void addDumpMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions,
+ void addDumpMesh(const Mesh & mesh, Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined);
/// register a mesh to the default identified by its name
void addDumpMeshToDumper(const std::string & dumper_name, const Mesh & mesh,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined);
/// register a filtered mesh as the default dumper
void addDumpFilteredMesh(const Mesh & mesh,
- const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter,
- UInt spatial_dimension = _all_dimensions,
+ const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined);
/// register a filtered mesh and provides a name
void
addDumpFilteredMeshToDumper(const std::string & dumper_name,
const Mesh & mesh,
- const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined);
+ const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter,
+ Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined);
/// to implement
virtual void addDumpField(const std::string & field_id);
/// to implement
virtual void addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id);
/// add a field
virtual void addDumpFieldExternal(const std::string & field_id,
std::shared_ptr<dumpers::Field> field);
virtual void
addDumpFieldExternalToDumper(const std::string & dumper_name,
const std::string & field_id,
std::shared_ptr<dumpers::Field> field);
template <typename T>
inline void addDumpFieldExternal(const std::string & field_id,
const Array<T> & field);
template <typename T>
inline void addDumpFieldExternalToDumper(const std::string & dumper_name,
const std::string & field_id,
const Array<T> & field);
template <typename T>
inline void addDumpFieldExternal(const std::string & field_id,
- const ElementTypeMapArray<T> & field,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined);
+ const ElementTypeMapArray<T> & field,
+ Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined);
template <typename T>
inline void
addDumpFieldExternalToDumper(const std::string & dumper_name,
const std::string & field_id,
- const ElementTypeMapArray<T> & field,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined);
+ const ElementTypeMapArray<T> & field,
+ Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined);
void removeDumpField(const std::string & field_id);
void removeDumpFieldFromDumper(const std::string & dumper_name,
const std::string & field_id);
virtual void addDumpFieldVector(const std::string & field_id);
virtual void addDumpFieldVectorToDumper(const std::string & dumper_name,
const std::string & field_id);
virtual void addDumpFieldTensor(const std::string & field_id);
virtual void addDumpFieldTensorToDumper(const std::string & dumper_name,
const std::string & field_id);
void setDirectory(const std::string & directory);
void setDirectoryToDumper(const std::string & dumper_name,
const std::string & directory);
void setBaseName(const std::string & basename);
void setBaseNameToDumper(const std::string & dumper_name,
const std::string & basename);
void setTimeStepToDumper(Real time_step);
void setTimeStepToDumper(const std::string & dumper_name, Real time_step);
void setTextModeToDumper(const std::string & dumper_name);
void setTextModeToDumper();
virtual void dump();
- virtual void dump(UInt step);
- virtual void dump(Real time, UInt step);
+ virtual void dump(Int step);
+ virtual void dump(Real time, Int step);
virtual void dump(const std::string & dumper_name);
- virtual void dump(const std::string & dumper_name, UInt step);
- virtual void dump(const std::string & dumper_name, Real time, UInt step);
+ virtual void dump(const std::string & dumper_name, Int step);
+ virtual void dump(const std::string & dumper_name, Real time, Int step);
public:
void internalAddDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
std::shared_ptr<dumpers::Field> field);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
DumperIOHelper & getDumper();
DumperIOHelper & getDumper(const std::string & dumper_name);
template <class T> T & getDumper(const std::string & dumper_name);
std::string getDefaultDumperName() const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
using DumperMap = std::map<std::string, std::shared_ptr<DumperIOHelper>>;
using DumperSet = std::set<std::string>;
DumperMap dumpers;
std::string default_dumper;
};
} // namespace akantu
#endif /* AKANTU_DUMPABLE_IOHELPER_HH_ */
diff --git a/src/io/dumper/dumper_compute.hh b/src/io/dumper/dumper_compute.hh
index c67168973..efb581b09 100644
--- a/src/io/dumper/dumper_compute.hh
+++ b/src/io/dumper/dumper_compute.hh
@@ -1,411 +1,411 @@
/**
* @file dumper_compute.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Field that map a function to another field
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_COMPUTE_HH_
#define AKANTU_DUMPER_COMPUTE_HH_
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dumper_field.hh"
#include "dumper_iohelper.hh"
#include "dumper_type_traits.hh"
/* -------------------------------------------------------------------------- */
#include <aka_iterators.hh>
/* -------------------------------------------------------------------------- */
#include <io_helper.hh>
/* -------------------------------------------------------------------------- */
#include <type_traits>
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* ------------------------------------------------------------------------ */
class ComputeFunctorInterface {
public:
virtual ~ComputeFunctorInterface() = default;
- virtual UInt getDim() = 0;
- virtual UInt getNbComponent(UInt old_nb_comp) = 0;
+ virtual Int getDim() = 0;
+ virtual Int getNbComponent(Int old_nb_comp) = 0;
};
/* ------------------------------------------------------------------------ */
template <typename return_type>
class ComputeFunctorOutput : public ComputeFunctorInterface {
public:
ComputeFunctorOutput() = default;
~ComputeFunctorOutput() override = default;
};
/* ------------------------------------------------------------------------ */
template <typename input_type, typename return_type>
class ComputeFunctor : public ComputeFunctorOutput<return_type> {
public:
ComputeFunctor() = default;
~ComputeFunctor() override = default;
virtual return_type func(const input_type & /*d*/,
Element /*global_index*/) {
AKANTU_TO_IMPLEMENT();
}
virtual return_type func(const input_type & /*d*/) {
AKANTU_TO_IMPLEMENT();
}
};
/* ------------------------------------------------------------------------ */
template <class EnumType>
- class ComputeUIntFromEnum
- : public ComputeFunctor<Vector<EnumType>, Vector<UInt>> {
+ class ComputeIntFromEnum
+ : public ComputeFunctor<Vector<EnumType>, Vector<Int>> {
public:
- ComputeUIntFromEnum() = default;
+ ComputeIntFromEnum() = default;
- inline Vector<UInt> func(const Vector<EnumType> & in) override {
- Vector<UInt> out(in.size());
+ inline Vector<Int> func(const Vector<EnumType> & in) override {
+ Vector<Int> out(in.size());
for (auto && data : zip(in, out)) {
std::get<1>(data) =
static_cast<std::underlying_type_t<EnumType>>(std::get<0>(data));
}
return out;
}
- UInt getDim() override { return 1; };
- UInt getNbComponent(UInt old_nb_comp) override { return old_nb_comp; };
+ Int getDim() override { return 1; };
+ Int getNbComponent(Int old_nb_comp) override { return old_nb_comp; };
};
/* ------------------------------------------------------------------------ */
template <typename SubFieldCompute, typename _return_type,
class support_type_ = typename SubFieldCompute::support_type>
class FieldCompute : public Field {
/* ---------------------------------------------------------------------- */
/* Typedefs */
/* ---------------------------------------------------------------------- */
public:
using return_type = _return_type;
using support_type = support_type_;
using sub_iterator = typename SubFieldCompute::iterator;
using sub_types = typename SubFieldCompute::types;
using sub_return_type = typename sub_types::return_type;
using data_type = typename return_type::value_type;
using functor_type = ComputeFunctor<sub_return_type, return_type>;
using types = TypeTraits<data_type, return_type, Array<data_type>>;
public:
class iterator {
public:
iterator(const sub_iterator & it, functor_type & func)
: it(it), func(func) {}
bool operator!=(const iterator & it) const { return it.it != this->it; }
iterator operator++() {
++this->it;
return *this;
}
return_type operator*() { return func.func(*it); }
/// Do to IOHelper the needs it...
- UInt element_type() { return this->it.element_type(); }
+ Int element_type() { return this->it.element_type(); }
protected:
sub_iterator it;
functor_type & func;
};
/* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
/* ---------------------------------------------------------------------- */
public:
FieldCompute(SubFieldCompute & cont,
std::unique_ptr<ComputeFunctorInterface> func)
: sub_field(aka::as_type<SubFieldCompute>(cont.shared_from_this())),
func(aka::as_type<functor_type>(func.release())) {
this->checkHomogeneity();
};
void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) override {
dumper.addNodeDataField(id, *this);
}
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
public:
iterator begin() { return iterator(sub_field->begin(), *func); }
iterator end() { return iterator(sub_field->end(), *func); }
- UInt getDim() { return func->getDim(); }
+ Int getDim() { return func->getDim(); }
- UInt size() {
+ Int size() {
throw;
// return Functor::size();
return 0;
}
void checkHomogeneity() override { this->homogeneous = true; };
iohelper::DataType getDataType() {
return iohelper::getDataType<data_type>();
}
/// for connection to a FieldCompute
inline std::shared_ptr<Field> connect(FieldComputeProxy & proxy) override;
/// for connection to a FieldCompute
std::unique_ptr<ComputeFunctorInterface>
connect(HomogenizerProxy & proxy) override;
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
public:
std::shared_ptr<SubFieldCompute> sub_field;
std::unique_ptr<functor_type> func;
};
/* ------------------------------------------------------------------------ */
template <typename SubFieldCompute, typename _return_type>
class FieldCompute<SubFieldCompute, _return_type, Element> : public Field {
/* ---------------------------------------------------------------------- */
/* Typedefs */
/* ---------------------------------------------------------------------- */
public:
using return_type = _return_type;
using support_type = Element;
using sub_iterator = typename SubFieldCompute::iterator;
using sub_types = typename SubFieldCompute::types;
using sub_return_type = typename sub_types::return_type;
using data_type = typename sub_types::data_type;
using functor_type = ComputeFunctor<sub_return_type, return_type>;
using types =
TypeTraits<data_type, return_type, ElementTypeMapArray<data_type>>;
public:
class iterator {
public:
iterator(const sub_iterator & it, functor_type & func)
: it(it), func(func) {}
bool operator!=(const iterator & it) const { return it.it != this->it; }
iterator operator++() {
++this->it;
return *this;
}
- UInt currentGlobalIndex() { return this->it.currentGlobalIndex(); }
+ Idx currentGlobalIndex() { return this->it.currentGlobalIndex(); }
return_type operator*() { return func.func(*it, it.getCurrentElement()); }
Element getCurrentElement() { return this->it.getCurrentElement(); }
- UInt element_type() { return this->it.element_type(); }
+ Int element_type() { return this->it.element_type(); }
protected:
sub_iterator it;
functor_type & func;
};
/* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
/* ---------------------------------------------------------------------- */
public:
FieldCompute(SubFieldCompute & cont,
std::unique_ptr<ComputeFunctorInterface> func)
: sub_field(aka::as_type<SubFieldCompute>(cont.shared_from_this())),
func(aka::as_type<functor_type>(func.release())) {
this->checkHomogeneity();
};
~FieldCompute() override = default;
void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) override {
dumper.addElemDataField(id, *this);
}
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
public:
iterator begin() { return iterator(sub_field->begin(), *func); }
iterator end() { return iterator(sub_field->end(), *func); }
- UInt getDim() { return func->getDim(); }
+ Int getDim() { return func->getDim(); }
- UInt size() {
+ Int size() {
throw;
// return Functor::size();
return 0;
}
void checkHomogeneity() override { this->homogeneous = true; };
template <class T1 = data_type,
std::enable_if_t<std::is_enum<T1>::value> * = nullptr>
iohelper::DataType getDataType() {
- return iohelper::getDataType<UInt>();
+ return iohelper::getDataType<Int>();
}
template <class T1 = data_type,
std::enable_if_t<not std::is_enum<T1>::value> * = nullptr>
iohelper::DataType getDataType() {
return iohelper::getDataType<data_type>();
}
/// get the number of components of the hosted field
- ElementTypeMap<UInt>
- getNbComponents(UInt dim = _all_dimensions,
+ ElementTypeMap<Int>
+ getNbComponents(Int dim = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_not_defined) override {
- ElementTypeMap<UInt> nb_components;
+ ElementTypeMap<Int> nb_components;
const auto & old_nb_components =
this->sub_field->getNbComponents(dim, ghost_type, kind);
for (auto type : old_nb_components.elementTypes(dim, ghost_type, kind)) {
- UInt nb_comp = old_nb_components(type, ghost_type);
+ auto nb_comp = old_nb_components(type, ghost_type);
nb_components(type, ghost_type) = func->getNbComponent(nb_comp);
}
return nb_components;
};
/// for connection to a FieldCompute
inline std::shared_ptr<Field> connect(FieldComputeProxy & proxy) override;
/// for connection to a FieldCompute
std::unique_ptr<ComputeFunctorInterface>
connect(HomogenizerProxy & proxy) override;
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
public:
std::shared_ptr<SubFieldCompute> sub_field;
std::unique_ptr<functor_type> func;
};
/* ------------------------------------------------------------------------ */
class FieldComputeProxy {
/* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
/* ---------------------------------------------------------------------- */
public:
FieldComputeProxy(std::unique_ptr<ComputeFunctorInterface> func)
: func(std::move(func)){};
inline static std::shared_ptr<Field>
createFieldCompute(std::shared_ptr<Field> & field,
std::unique_ptr<ComputeFunctorInterface> func) {
FieldComputeProxy compute_proxy(std::move(func));
return field->connect(compute_proxy);
}
template <typename T> std::shared_ptr<Field> connectToField(T * ptr) {
if (aka::is_of_type<ComputeFunctorOutput<Vector<Real>>>(func)) {
return this->connectToFunctor<Vector<Real>>(ptr);
}
- if (aka::is_of_type<ComputeFunctorOutput<Vector<UInt>>>(func)) {
- return this->connectToFunctor<Vector<UInt>>(ptr);
+ if (aka::is_of_type<ComputeFunctorOutput<Vector<Int>>>(func)) {
+ return this->connectToFunctor<Vector<Int>>(ptr);
}
- if (aka::is_of_type<ComputeFunctorOutput<Matrix<UInt>>>(func)) {
- return this->connectToFunctor<Matrix<UInt>>(ptr);
+ if (aka::is_of_type<ComputeFunctorOutput<Matrix<Int>>>(func)) {
+ return this->connectToFunctor<Matrix<Int>>(ptr);
}
if (aka::is_of_type<ComputeFunctorOutput<Matrix<Real>>>(func)) {
return this->connectToFunctor<Matrix<Real>>(ptr);
}
throw;
}
template <typename output, typename T>
std::shared_ptr<Field> connectToFunctor(T * ptr) {
return std::make_shared<FieldCompute<T, output>>(*ptr, std::move(func));
}
template <typename output, typename SubFieldCompute, typename return_type1,
typename return_type2>
std::shared_ptr<Field>
connectToFunctor(FieldCompute<FieldCompute<SubFieldCompute, return_type1>,
return_type2> * /*ptr*/) {
throw; // return new FieldCompute<T,output>(*ptr,func);
return nullptr;
}
template <typename output, typename SubFieldCompute, typename return_type1,
typename return_type2, typename return_type3,
typename return_type4>
std::shared_ptr<Field> connectToFunctor(
FieldCompute<FieldCompute<FieldCompute<FieldCompute<SubFieldCompute,
return_type1>,
return_type2>,
return_type3>,
return_type4> * /*ptr*/) {
throw; // return new FieldCompute<T,output>(*ptr,func);
return nullptr;
}
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
public:
std::unique_ptr<ComputeFunctorInterface> func;
};
/* ------------------------------------------------------------------------ */
/// for connection to a FieldCompute
template <typename SubFieldCompute, typename return_type,
typename support_type_>
inline std::shared_ptr<Field>
FieldCompute<SubFieldCompute, return_type, support_type_>::connect(
FieldComputeProxy & proxy) {
return proxy.connectToField(this);
}
template <typename SubFieldCompute, typename return_type>
inline std::shared_ptr<Field>
FieldCompute<SubFieldCompute, return_type, Element>::connect(
FieldComputeProxy & proxy) {
return proxy.connectToField(this);
}
/* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_COMPUTE_HH_ */
diff --git a/src/io/dumper/dumper_element_iterator.hh b/src/io/dumper/dumper_element_iterator.hh
index 6760f3bf9..db11f3a09 100644
--- a/src/io/dumper/dumper_element_iterator.hh
+++ b/src/io/dumper/dumper_element_iterator.hh
@@ -1,197 +1,181 @@
/**
* @file dumper_element_iterator.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Iterators for elemental fields
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_ELEMENT_ITERATOR_HH_
#define AKANTU_DUMPER_ELEMENT_ITERATOR_HH_
/* -------------------------------------------------------------------------- */
#include "element.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
template <class types, template <class> class final_iterator>
class element_iterator {
- /* ------------------------------------------------------------------------
- */
- /* Typedefs */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Typedefs */
+ /* ---------------------------------------------------------------------- */
public:
using it_type = typename types::it_type;
using field_type = typename types::field_type;
using array_type = typename types::array_type;
using array_iterator = typename types::array_iterator;
using iterator = final_iterator<types>;
public:
- /* ------------------------------------------------------------------------
- */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Constructors/Destructors */
+ /* ---------------------------------------------------------------------- */
element_iterator(const field_type & field,
const typename field_type::type_iterator & t_it,
const typename field_type::type_iterator & t_it_end,
const array_iterator & array_it,
const array_iterator & array_it_end,
const GhostType ghost_type = _not_ghost)
: field(field), tit(t_it), tit_end(t_it_end), array_it(array_it),
array_it_end(array_it_end), ghost_type(ghost_type) {}
- /* ------------------------------------------------------------------------
- */
- /* Methods */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Methods */
+ /* ---------------------------------------------------------------------- */
public:
bool operator!=(const iterator & it) const {
return (ghost_type != it.ghost_type) ||
(tit != it.tit || (array_it != it.array_it));
}
iterator & operator++() {
++array_it;
while (array_it == array_it_end && tit != tit_end) {
++tit;
if (tit != tit_end) {
const array_type & vect = field(*tit, ghost_type);
- UInt _nb_data_per_elem = getNbDataPerElem(*tit);
- UInt nb_component = vect.getNbComponent();
- UInt size = (vect.size() * nb_component) / _nb_data_per_elem;
+ auto _nb_data_per_elem = getNbDataPerElem(*tit);
+ // auto nb_component = vect.getNbComponent();
+ // auto size = (vect.size() * nb_component) / _nb_data_per_elem;
- array_it = vect.begin_reinterpret(_nb_data_per_elem, size);
- array_it_end = vect.end_reinterpret(_nb_data_per_elem, size);
+ auto view = make_view(vect, _nb_data_per_elem);
+ array_it = view.begin();
+ array_it_end = view.end();
}
}
return *(static_cast<iterator *>(this));
};
ElementType getType() { return *tit; }
- UInt element_type() { return getIOHelperType(*tit); }
+ Int element_type() { return getIOHelperType(*tit); }
Element getCurrentElement() {
return Element{*tit, array_it.getCurrentIndex(), _not_ghost};
}
- UInt getNbDataPerElem(ElementType type) const {
+ Int getNbDataPerElem(ElementType type) const {
if (!nb_data_per_elem.exists(type, ghost_type)) {
return field(type, ghost_type).getNbComponent();
}
return nb_data_per_elem(type, ghost_type);
}
- void setNbDataPerElem(const ElementTypeMap<UInt> & nb_data) {
+ void setNbDataPerElem(const ElementTypeMap<Int> & nb_data) {
this->nb_data_per_elem = nb_data;
}
- /* ------------------------------------------------------------------------
- */
- /* Class Members */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Class Members */
+ /* ---------------------------------------------------------------------- */
protected:
/// the field to iterate on
const field_type & field;
/// field iterator
typename field_type::type_iterator tit;
/// field iterator end
typename field_type::type_iterator tit_end;
/// array iterator
array_iterator array_it;
/// internal iterator end
array_iterator array_it_end;
/// ghost type identification
const GhostType ghost_type;
/// number of data per element
- ElementTypeMap<UInt> nb_data_per_elem;
+ ElementTypeMap<Int> nb_data_per_elem;
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
template <typename types>
class elemental_field_iterator
: public element_iterator<types, elemental_field_iterator> {
public:
- /* ------------------------------------------------------------------------
- */
- /* Typedefs */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Typedefs */
+ /* ---------------------------------------------------------------------- */
using parent =
element_iterator<types, ::akantu::dumpers::elemental_field_iterator>;
using it_type = typename types::it_type;
using return_type = typename types::return_type;
using field_type = typename types::field_type;
using array_iterator = typename types::array_iterator;
public:
- /* ------------------------------------------------------------------------
- */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Constructors/Destructors */
+ /* ---------------------------------------------------------------------- */
elemental_field_iterator(
const field_type & field,
const typename field_type::type_iterator & t_it,
const typename field_type::type_iterator & t_it_end,
const array_iterator & array_it, const array_iterator & array_it_end,
const GhostType ghost_type = _not_ghost)
: parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) {}
- /* ------------------------------------------------------------------------
- */
- /* Methods */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Methods */
+ /* ---------------------------------------------------------------------- */
return_type operator*() { return *this->array_it; }
private:
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_DUMPER_ELEMENT_ITERATOR_HH_ */
diff --git a/src/io/dumper/dumper_element_partition.hh b/src/io/dumper/dumper_element_partition.hh
index 38889f2cf..099d7faeb 100644
--- a/src/io/dumper/dumper_element_partition.hh
+++ b/src/io/dumper/dumper_element_partition.hh
@@ -1,138 +1,97 @@
/**
* @file dumper_element_partition.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief ElementPartition field
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
#ifdef AKANTU_IGFEM
#include "dumper_igfem_element_partition.hh"
#endif
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
template <class types>
class element_partition_field_iterator
: public element_iterator<types, element_partition_field_iterator> {
-
- /* ------------------------------------------------------------------------
- */
- /* Typedefs */
- /* ------------------------------------------------------------------------
- */
public:
using parent =
element_iterator<types, dumpers::element_partition_field_iterator>;
using return_type =
- typename SingleType<unsigned int, Vector, true>::return_type;
+ typename SingleType<int, Vector<int>, true>::return_type;
using array_iterator = typename types::array_iterator;
using field_type = typename types::field_type;
- /* ------------------------------------------------------------------------
- */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
- public:
element_partition_field_iterator(
const field_type & field,
const typename field_type::type_iterator & t_it,
const typename field_type::type_iterator & t_it_end,
const array_iterator & array_it, const array_iterator & array_it_end,
const GhostType ghost_type = _not_ghost)
: parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) {
prank = Communicator::getStaticCommunicator().whoAmI();
}
- /* ------------------------------------------------------------------------
- */
- /* Methods */
- /* ------------------------------------------------------------------------
- */
- public:
- return_type operator*() { return return_type(1, prank); }
+ return_type operator*() {
+ return_type ret(1);
+ ret.fill(prank);
+ return ret;
+ }
- /* ------------------------------------------------------------------------
- */
- /* Class Members */
- /* ------------------------------------------------------------------------
- */
protected:
- UInt prank;
+ Int prank;
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
template <bool filtered = false>
class ElementPartitionField
- : public GenericElementalField<SingleType<UInt, Vector, filtered>,
+ : public GenericElementalField<SingleType<Int, Vector<Int>, filtered>,
element_partition_field_iterator> {
public:
- /* ------------------------------------------------------------------------
- */
- /* Typedefs */
- /* ------------------------------------------------------------------------
- */
-
- using types = SingleType<UInt, Vector, filtered>;
+ using types = SingleType<Int, Vector<Int>, filtered>;
using iterator = element_partition_field_iterator<types>;
using parent =
GenericElementalField<types, element_partition_field_iterator>;
using field_type = typename types::field_type;
- public:
- /* ------------------------------------------------------------------------
- */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
-
ElementPartitionField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined)
: parent(field, spatial_dimension, ghost_type, element_kind) {
this->homogeneous = true;
}
- /* ------------------------------------------------------------------------
- */
- /* Methods */
- /* ------------------------------------------------------------------------
- */
-
- UInt getDim() override { return 1; }
+ Int getDim() override { return 1; }
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
diff --git a/src/io/dumper/dumper_elemental_field.hh b/src/io/dumper/dumper_elemental_field.hh
index ad740e67c..3c8a1b3d0 100644
--- a/src/io/dumper/dumper_elemental_field.hh
+++ b/src/io/dumper/dumper_elemental_field.hh
@@ -1,83 +1,77 @@
/**
* @file dumper_elemental_field.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Feb 20 2020
*
* @brief description of elemental fields
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_ELEMENTAL_FIELD_HH_
#define AKANTU_DUMPER_ELEMENTAL_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "dumper_field.hh"
#include "dumper_generic_elemental_field.hh"
#ifdef AKANTU_IGFEM
#include "dumper_igfem_elemental_field.hh"
#endif
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
- template <typename T, template <class> class ret = Vector,
+ template <typename T, class ret = Vector<T>,
bool filtered = false>
class ElementalField
: public GenericElementalField<SingleType<T, ret, filtered>,
elemental_field_iterator> {
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Typedefs */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
using types = SingleType<T, ret, filtered>;
using field_type = typename types::field_type;
using iterator = elemental_field_iterator<types>;
using support_type = Element;
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
ElementalField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined)
: GenericElementalField<types, elemental_field_iterator>(
field, spatial_dimension, ghost_type, element_kind) {}
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_ELEMENTAL_FIELD_HH_ */
diff --git a/src/io/dumper/dumper_field.hh b/src/io/dumper/dumper_field.hh
index ea9061dc5..04f7e5061 100644
--- a/src/io/dumper/dumper_field.hh
+++ b/src/io/dumper/dumper_field.hh
@@ -1,147 +1,134 @@
/**
* @file dumper_field.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Common interface for fields
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_FIELD_HH_
#define AKANTU_DUMPER_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
class FieldComputeProxy;
class FieldComputeBaseInterface;
class ComputeFunctorInterface;
class HomogenizerProxy;
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
/// Field interface
class Field : public std::enable_shared_from_this<Field> {
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
Field() = default;
virtual ~Field() = default;
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Methods */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
/// register this to the provided dumper
virtual void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) = 0;
/// set the number of data per item (used for elements fields at the moment)
- virtual void setNbData([[gnu::unused]] UInt nb_data) {
- AKANTU_TO_IMPLEMENT();
- };
+ virtual void setNbData(Int /*nb_data*/) { AKANTU_TO_IMPLEMENT(); };
/// set the number of data per elem (used for elements fields at the moment)
virtual void
- setNbDataPerElem([[gnu::unused]] const ElementTypeMap<UInt> & nb_data) {
+ setNbDataPerElem([[gnu::unused]] const ElementTypeMap<Int> & nb_data) {
AKANTU_TO_IMPLEMENT();
};
/// set the number of data per elem (used for elements fields at the moment)
- virtual void setNbDataPerElem([[gnu::unused]] UInt nb_data) {
+ virtual void setNbDataPerElem([[gnu::unused]] Int nb_data) {
AKANTU_TO_IMPLEMENT();
};
/// get the number of components of the hosted field
- virtual ElementTypeMap<UInt>
- getNbComponents([[gnu::unused]] UInt dim = _all_dimensions,
- [[gnu::unused]] GhostType ghost_type = _not_ghost,
- [[gnu::unused]] ElementKind kind = _ek_not_defined) {
- throw;
+ virtual ElementTypeMap<Int>
+ getNbComponents(Int /*dim*/ = _all_dimensions,
+ GhostType /*ghost_type*/ = _not_ghost,
+ ElementKind /*kind*/ = _ek_not_defined) {
+ AKANTU_TO_IMPLEMENT();
};
/// for connection to a FieldCompute
inline virtual std::shared_ptr<Field>
- connect([[gnu::unused]] FieldComputeProxy & proxy) {
- throw;
+ connect(FieldComputeProxy & /*proxy*/) {
+ AKANTU_TO_IMPLEMENT();
};
/// for connection to a FieldCompute
inline virtual std::unique_ptr<ComputeFunctorInterface>
connect(HomogenizerProxy & /*proxy*/) {
- throw;
+ AKANTU_TO_IMPLEMENT();
};
/// check if the same quantity of data for all element types
virtual void checkHomogeneity() = 0;
/// return the dumper name
std::string getGroupName() { return group_name; };
/// return the id of the field
std::string getID() { return field_id; };
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Accessors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
/// return the flag to know if the field is homogeneous/contiguous
virtual bool isHomogeneous() { return homogeneous; }
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Class Members */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
protected:
/// the flag to know if it is homogeneous
bool homogeneous{false};
/// the name of the group it was associated to
std::string group_name;
/// the name of the dumper it was associated to
std::string field_id;
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_FIELD_HH_ */
diff --git a/src/io/dumper/dumper_filtered_connectivity.hh b/src/io/dumper/dumper_filtered_connectivity.hh
index 1b0546521..deec71846 100644
--- a/src/io/dumper/dumper_filtered_connectivity.hh
+++ b/src/io/dumper/dumper_filtered_connectivity.hh
@@ -1,174 +1,154 @@
/**
* @file dumper_filtered_connectivity.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief FilteredConnectivities field
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "dumper_generic_elemental_field.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
template <class types>
class filtered_connectivity_field_iterator
: public element_iterator<types, filtered_connectivity_field_iterator> {
- /* ------------------------------------------------------------------------
- */
- /* Typedefs */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Typedefs */
+ /* ---------------------------------------------------------------------- */
public:
using parent =
element_iterator<types, dumpers::filtered_connectivity_field_iterator>;
using return_type = typename types::return_type;
using field_type = typename types::field_type;
using array_iterator = typename types::array_iterator;
- /* ------------------------------------------------------------------------
- */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Constructors/Destructors */
+ /* ---------------------------------------------------------------------- */
public:
filtered_connectivity_field_iterator(
const field_type & field,
const typename field_type::type_iterator & t_it,
const typename field_type::type_iterator & t_it_end,
const array_iterator & array_it, const array_iterator & array_it_end,
const GhostType ghost_type = _not_ghost)
: parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) {}
- /* ------------------------------------------------------------------------
- */
- /* Methods */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Methods */
+ /* ---------------------------------------------------------------------- */
public:
return_type operator*() {
- const Vector<UInt> & old_connect = *this->array_it;
- Vector<UInt> new_connect(old_connect.size());
- Array<UInt>::const_iterator<UInt> nodes_begin = nodal_filter->begin();
- Array<UInt>::const_iterator<UInt> nodes_end = nodal_filter->end();
- for (UInt i(0); i < old_connect.size(); ++i) {
- Array<UInt>::const_iterator<UInt> new_id =
- std::find(nodes_begin, nodes_end, old_connect(i));
+ const auto & old_connect = *this->array_it;
+ Vector<Int> new_connect(old_connect.size());
+ auto nodes_begin = nodal_filter->begin();
+ auto nodes_end = nodal_filter->end();
+ for (Int i(0); i < old_connect.size(); ++i) {
+ auto new_id = std::find(nodes_begin, nodes_end, old_connect(i));
if (new_id == nodes_end) {
AKANTU_EXCEPTION("Node not found in the filter!");
}
new_connect(i) = new_id - nodes_begin;
}
return new_connect;
}
- void setNodalFilter(const Array<UInt> & new_nodal_filter) {
+ void setNodalFilter(const Array<Idx> & new_nodal_filter) {
nodal_filter = &new_nodal_filter;
}
- /* ------------------------------------------------------------------------
- */
- /* Class Members */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Class Members */
+ /* ---------------------------------------------------------------------- */
private:
- const Array<UInt> * nodal_filter;
+ const Array<Idx> * nodal_filter;
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
class FilteredConnectivityField
- : public GenericElementalField<SingleType<UInt, Vector, true>,
+ : public GenericElementalField<SingleType<Idx, Vector<Idx>, true>,
filtered_connectivity_field_iterator> {
- /* ------------------------------------------------------------------------
- */
- /* Typedefs */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Typedefs */
+ /* ---------------------------------------------------------------------- */
public:
- using types = SingleType<UInt, Vector, true>;
+ using types = SingleType<Idx, Vector<Idx>, true>;
using iterator = filtered_connectivity_field_iterator<types>;
using field_type = types::field_type;
using parent =
GenericElementalField<types, filtered_connectivity_field_iterator>;
- /* ------------------------------------------------------------------------
- */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Constructors/Destructors */
+ /* ---------------------------------------------------------------------- */
public:
FilteredConnectivityField(const field_type & field,
- const Array<UInt> & nodal_filter,
- UInt spatial_dimension = _all_dimensions,
+ const Array<Idx> & nodal_filter,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined)
: parent(field, spatial_dimension, ghost_type, element_kind),
nodal_filter(nodal_filter) {}
~FilteredConnectivityField() override {
// since the field is created in registerFilteredMesh it is destroyed here
delete const_cast<field_type *>(&this->field);
}
- /* ------------------------------------------------------------------------
- */
- /* Methods */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Methods */
+ /* ---------------------------------------------------------------------- */
public:
iterator begin() override {
- iterator it = parent::begin();
+ auto it = parent::begin();
it.setNodalFilter(nodal_filter);
return it;
}
iterator end() override {
- iterator it = parent::end();
+ auto it = parent::end();
it.setNodalFilter(nodal_filter);
return it;
}
- /* ------------------------------------------------------------------------
- */
- /* Class Members */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
+ /* Class Members */
+ /* ---------------------------------------------------------------------- */
private:
- const Array<UInt> & nodal_filter;
+ const Array<Idx> & nodal_filter;
};
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
/* -------------------------------------------------------------------------- */
diff --git a/src/io/dumper/dumper_generic_elemental_field.hh b/src/io/dumper/dumper_generic_elemental_field.hh
index 9613b942b..a393c3dbf 100644
--- a/src/io/dumper/dumper_generic_elemental_field.hh
+++ b/src/io/dumper/dumper_generic_elemental_field.hh
@@ -1,241 +1,232 @@
/**
* @file dumper_generic_elemental_field.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Generic interface for elemental fields
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_GENERIC_ELEMENTAL_FIELD_HH_
#define AKANTU_DUMPER_GENERIC_ELEMENTAL_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_element_iterator.hh"
#include "dumper_field.hh"
#include "dumper_homogenizing_field.hh"
#include "element_type_map_filter.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
template <class _types, template <class> class iterator_type>
class GenericElementalField : public Field {
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Typedefs */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
// check dumper_type_traits.hh for additional information over these types
using types = _types;
using data_type = typename types::data_type;
using it_type = typename types::it_type;
using field_type = typename types::field_type;
using array_type = typename types::array_type;
using array_iterator = typename types::array_iterator;
using field_type_iterator = typename field_type::type_iterator;
using iterator = iterator_type<types>;
using support_type = Element;
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
GenericElementalField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined)
: field(field), spatial_dimension(spatial_dimension),
ghost_type(ghost_type), element_kind(element_kind) {
this->checkHomogeneity();
}
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Methods */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
/// get the number of components of the hosted field
- ElementTypeMap<UInt>
- getNbComponents(UInt dim = _all_dimensions,
+ ElementTypeMap<Int>
+ getNbComponents(Int dim = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_not_defined) override {
return this->field.getNbComponents(dim, ghost_type, kind);
};
/// return the size of the contained data: i.e. the number of elements ?
- virtual UInt size() {
+ virtual Int size() {
checkHomogeneity();
return this->nb_total_element;
}
/// return the iohelper datatype to be dumped
template <class T1 = data_type,
std::enable_if_t<std::is_enum<T1>::value> * = nullptr>
iohelper::DataType getDataType() {
- return iohelper::getDataType<UInt>();
+ return iohelper::getDataType<Int>();
}
template <class T1 = data_type,
std::enable_if_t<not std::is_enum<T1>::value> * = nullptr>
iohelper::DataType getDataType() {
return iohelper::getDataType<data_type>();
}
protected:
/// return the number of entries per element
- UInt getNbDataPerElem(ElementType type,
- GhostType ghost_type = _not_ghost) const {
- if (!nb_data_per_elem.exists(type, ghost_type)) {
+ Int getNbDataPerElem(ElementType type,
+ GhostType ghost_type = _not_ghost) const {
+ if (not nb_data_per_elem.exists(type, ghost_type)) {
return field(type, ghost_type).getNbComponent();
}
return nb_data_per_elem(type, this->ghost_type);
}
/// check if the same quantity of data for all element types
void checkHomogeneity() override;
public:
void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) override {
dumper.addElemDataField(id, *this);
}
/// for connection to a FieldCompute
inline std::shared_ptr<Field> connect(FieldComputeProxy & proxy) override {
return proxy.connectToField(this);
}
/// for connection to a Homogenizer
inline std::unique_ptr<ComputeFunctorInterface>
connect(HomogenizerProxy & proxy) override {
return proxy.connectToField(this);
}
virtual iterator begin() {
/// type iterators on the elemental field
auto types = this->field.elementTypes(
this->spatial_dimension, this->ghost_type, this->element_kind);
auto tit = types.begin();
auto end = types.end();
/// skip all types without data
for (; tit != end and this->field(*tit, this->ghost_type).empty();
++tit) {
}
auto type = *tit;
if (tit == end) {
return this->end();
}
/// getting information for the field of the given type
const auto & vect = this->field(type, this->ghost_type);
- UInt nb_data_per_elem = this->getNbDataPerElem(type);
+ auto nb_data_per_elem = this->getNbDataPerElem(type);
/// define element-wise iterator
auto view = make_view(vect, nb_data_per_elem);
auto it = view.begin();
auto it_end = view.end();
/// define data iterator
iterator rit =
iterator(this->field, tit, end, it, it_end, this->ghost_type);
rit.setNbDataPerElem(this->nb_data_per_elem);
return rit;
}
virtual iterator end() {
auto types = this->field.elementTypes(
this->spatial_dimension, this->ghost_type, this->element_kind);
auto tit = types.begin();
auto end = types.end();
auto type = *tit;
for (; tit != end; ++tit) {
type = *tit;
}
const array_type & vect = this->field(type, this->ghost_type);
- UInt nb_data = this->getNbDataPerElem(type);
+ Int nb_data = this->getNbDataPerElem(type);
auto it = make_view(vect, nb_data).end();
auto rit = iterator(this->field, end, end, it, it, this->ghost_type);
rit.setNbDataPerElem(this->nb_data_per_elem);
return rit;
}
- virtual UInt getDim() {
+ virtual Int getDim() {
if (this->homogeneous) {
auto tit = this->field
.elementTypes(this->spatial_dimension, this->ghost_type,
this->element_kind)
.begin();
return this->getNbDataPerElem(*tit);
}
throw;
return 0;
}
- void setNbDataPerElem(const ElementTypeMap<UInt> & nb_data) override {
+ void setNbDataPerElem(const ElementTypeMap<Int> & nb_data) override {
nb_data_per_elem = nb_data;
}
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Class Members */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
protected:
/// the ElementTypeMapArray embedded in the field
const field_type & field;
/// total number of elements
- UInt nb_total_element;
+ Int nb_total_element;
/// the spatial dimension of the problem
- UInt spatial_dimension;
+ Int spatial_dimension;
/// whether this is a ghost field or not (for type selection)
GhostType ghost_type;
/// The element kind to operate on
ElementKind element_kind;
/// The number of data per element type
- ElementTypeMap<UInt> nb_data_per_elem;
+ ElementTypeMap<Int> nb_data_per_elem;
};
} // namespace dumpers
} // namespace akantu
/* -------------------------------------------------------------------------- */
#include "dumper_generic_elemental_field_tmpl.hh"
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_DUMPER_GENERIC_ELEMENTAL_FIELD_HH_ */
diff --git a/src/io/dumper/dumper_generic_elemental_field_tmpl.hh b/src/io/dumper/dumper_generic_elemental_field_tmpl.hh
index 9d988650d..40c40c150 100644
--- a/src/io/dumper/dumper_generic_elemental_field_tmpl.hh
+++ b/src/io/dumper/dumper_generic_elemental_field_tmpl.hh
@@ -1,76 +1,76 @@
/**
* @file dumper_generic_elemental_field_tmpl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Implementation of the template functions of the ElementalField
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_generic_elemental_field.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* ------------------------------------------------------------------------ */
template <class types, template <class> class iterator>
void GenericElementalField<types, iterator>::checkHomogeneity() {
auto types =
field.elementTypes(spatial_dimension, ghost_type, element_kind);
auto tit = types.begin();
auto end = types.end();
this->nb_total_element = 0;
- UInt nb_comp = 0;
+ Int nb_comp = 0;
bool homogen = true;
if (tit != end) {
nb_comp = this->field(*tit, ghost_type).getNbComponent();
for (; tit != end; ++tit) {
const auto & vect = this->field(*tit, ghost_type);
auto nb_element = vect.size();
auto nb_comp_cur = vect.getNbComponent();
if (homogen && nb_comp != nb_comp_cur) {
homogen = false;
}
this->nb_total_element += nb_element;
// this->nb_data_per_elem(*tit,this->ghost_type) = nb_comp_cur;
}
if (!homogen) {
nb_comp = 0;
}
}
this->homogeneous = homogen;
}
/* --------------------------------------------------------------------------
*/
} // namespace dumpers
} // namespace akantu
diff --git a/src/io/dumper/dumper_homogenizing_field.hh b/src/io/dumper/dumper_homogenizing_field.hh
index 6c0f428d4..789c5a2c2 100644
--- a/src/io/dumper/dumper_homogenizing_field.hh
+++ b/src/io/dumper/dumper_homogenizing_field.hh
@@ -1,201 +1,195 @@
/**
* @file dumper_homogenizing_field.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief description of field homogenizing field
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_HOMOGENIZING_FIELD_HH_
#define AKANTU_DUMPER_HOMOGENIZING_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_compute.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
- /* ------------------------------------------------------------------------ */
- template <typename type>
- inline type
- typeConverter(const type & input,
- [[gnu::unused]] Vector<typename type::value_type> & res,
- [[gnu::unused]] UInt nb_data) {
- throw;
- return input;
- }
-
- /* ------------------------------------------------------------------------ */
- template <typename type>
- inline Matrix<type> typeConverter(const Matrix<type> & input,
- Vector<type> & res, UInt nb_data) {
-
- Matrix<type> tmp(res.storage(), input.rows(), nb_data / input.rows());
- Matrix<type> tmp2(tmp, true);
- return tmp2;
- }
-
- /* ------------------------------------------------------------------------ */
- template <typename type>
- inline Vector<type> typeConverter(const Vector<type> & /*unused*/,
- Vector<type> & res, UInt /*unused*/) {
- return res;
- }
-
- /* ------------------------------------------------------------------------ */
- template <typename type>
- class AvgHomogenizingFunctor : public ComputeFunctor<type, type> {
- /* ---------------------------------------------------------------------- */
- /* Typedefs */
- /* ---------------------------------------------------------------------- */
- private:
- using value_type = typename type::value_type;
-
- /* ---------------------------------------------------------------------- */
- /* Constructors/Destructors */
- /* ---------------------------------------------------------------------- */
- public:
- AvgHomogenizingFunctor(ElementTypeMap<UInt> & nb_datas) {
-
- auto types = nb_datas.elementTypes();
- auto tit = types.begin();
- auto end = types.end();
-
- nb_data = nb_datas(*tit);
-
- for (; tit != end; ++tit) {
- if (nb_data != nb_datas(*tit)) {
- throw;
- }
- }
- }
-
- /* ---------------------------------------------------------------------- */
- /* Methods */
- /* ---------------------------------------------------------------------- */
- public:
- type func(const type & d, Element /*global_index*/) override {
- Vector<value_type> res(this->nb_data);
-
- if (d.size() % this->nb_data) {
+/* ------------------------------------------------------------------------ */
+template <typename type>
+inline type typeConverter(const type & /*input*/,
+ Vector<typename type::value_type> & /*res*/,
+ Int /*nb_data*/) {
+ throw;
+}
+
+/* ------------------------------------------------------------------------ */
+template <typename type>
+inline Matrix<type> typeConverter(const Matrix<type> &input, Vector<type> &res,
+ Int nb_data) {
+ MatrixProxy<type> tmp(res.data(), input.rows(), nb_data / input.rows());
+ return tmp;
+}
+
+/* ------------------------------------------------------------------------ */
+template <typename type>
+inline Vector<type> typeConverter(const Vector<type> & /*unused*/,
+ Vector<type> &res, Int /*unused*/) {
+ return res;
+}
+
+/* ------------------------------------------------------------------------ */
+template <typename type>
+class AvgHomogenizingFunctor : public ComputeFunctor<type, type> {
+ /* ---------------------------------------------------------------------- */
+ /* Typedefs */
+ /* ---------------------------------------------------------------------- */
+private:
+ using value_type = typename type::value_type;
+
+ /* ---------------------------------------------------------------------- */
+ /* Constructors/Destructors */
+ /* ---------------------------------------------------------------------- */
+public:
+ AvgHomogenizingFunctor(ElementTypeMap<Int> &nb_datas) {
+ auto types = nb_datas.elementTypes();
+ auto tit = types.begin();
+ auto end = types.end();
+
+ nb_data = nb_datas(*tit);
+
+ for (; tit != end; ++tit) {
+ if (nb_data != nb_datas(*tit)) {
throw;
}
- UInt nb_to_average = d.size() / this->nb_data;
-
- value_type * ptr = d.storage();
- for (UInt i = 0; i < nb_to_average; ++i) {
- Vector<value_type> tmp(ptr, this->nb_data);
- res += tmp;
- ptr += this->nb_data;
- }
- res /= nb_to_average;
- return typeConverter(d, res, this->nb_data);
- };
-
- UInt getDim() override { return nb_data; };
- UInt getNbComponent(UInt /*old_nb_comp*/) override { throw; };
-
- /* ---------------------------------------------------------------------- */
- /* Class Members */
- /* ---------------------------------------------------------------------- */
+ }
+ }
- /// The size of data: i.e. the size of the vector to be returned
- UInt nb_data;
- };
- /* ------------------------------------------------------------------------ */
-
- /* ------------------------------------------------------------------------ */
- class HomogenizerProxy {
- /* ---------------------------------------------------------------------- */
- /* Constructors/Destructors */
- /* ---------------------------------------------------------------------- */
- public:
- HomogenizerProxy() = default;
-
- public:
- inline static std::unique_ptr<ComputeFunctorInterface>
- createHomogenizer(Field & field);
-
- template <typename T>
- inline std::unique_ptr<ComputeFunctorInterface> connectToField(T * field) {
- ElementTypeMap<UInt> nb_components = field->getNbComponents();
-
- using ret_type = typename T::types::return_type;
- return this->instantiateHomogenizer<ret_type>(nb_components);
+ /* ---------------------------------------------------------------------- */
+ /* Methods */
+ /* ---------------------------------------------------------------------- */
+public:
+ type func(const type &d, Element /*global_index*/) override {
+ Vector<value_type> res(this->nb_data);
+ res.zero();
+ if (d.size() % this->nb_data) {
+ throw;
}
+ auto nb_to_average = d.size() / this->nb_data;
- template <typename ret_type>
- inline std::unique_ptr<ComputeFunctorInterface>
- instantiateHomogenizer(ElementTypeMap<UInt> & nb_components);
+ auto &&ptr = d.data();
+ for (Int i = 0; i < nb_to_average; ++i) {
+ VectorProxy<const value_type> tmp(ptr, this->nb_data);
+ res += tmp;
+ ptr += this->nb_data;
+ }
+ res /= nb_to_average;
+ return typeConverter(d, res, this->nb_data);
};
- /* ------------------------------------------------------------------------ */
+ Int getDim() override { return nb_data; };
+ Int getNbComponent(Int /*old_nb_comp*/) override { throw; };
- template <typename ret_type>
- inline std::unique_ptr<ComputeFunctorInterface>
- HomogenizerProxy::instantiateHomogenizer(
- ElementTypeMap<UInt> & nb_components) {
- using Homogenizer = dumpers::AvgHomogenizingFunctor<ret_type>;
- return std::make_unique<Homogenizer>(nb_components);
- }
+ /* ---------------------------------------------------------------------- */
+ /* Class Members */
+ /* ---------------------------------------------------------------------- */
- template <>
- inline std::unique_ptr<ComputeFunctorInterface>
- HomogenizerProxy::instantiateHomogenizer<Vector<iohelper::ElemType>>(
- [[gnu::unused]] ElementTypeMap<UInt> & nb_components) {
- throw;
- return nullptr;
- }
+ /// The size of data: i.e. the size of the vector to be returned
+ Int nb_data;
+};
+/* ------------------------------------------------------------------------ */
- /* ------------------------------------------------------------------------ */
- /// for connection to a FieldCompute
- template <typename SubFieldCompute, typename return_type,
- typename support_type_>
- inline std::unique_ptr<ComputeFunctorInterface>
- FieldCompute<SubFieldCompute, return_type, support_type_>::connect(
- HomogenizerProxy & proxy) {
- return proxy.connectToField(this);
- }
+/* ------------------------------------------------------------------------ */
+class HomogenizerProxy {
+ /* ---------------------------------------------------------------------- */
+ /* Constructors/Destructors */
+ /* ---------------------------------------------------------------------- */
+public:
+ HomogenizerProxy() = default;
- template <typename SubFieldCompute, typename return_type>
- inline std::unique_ptr<ComputeFunctorInterface>
- FieldCompute<SubFieldCompute, return_type, Element>::connect(
- HomogenizerProxy & proxy) {
- return proxy.connectToField(this);
+public:
+ inline static std::unique_ptr<ComputeFunctorInterface>
+ createHomogenizer(Field &field);
+
+ template <typename T>
+ inline std::unique_ptr<ComputeFunctorInterface> connectToField(T *field) {
+ ElementTypeMap<Int> nb_components = field->getNbComponents();
+
+ using ret_type = typename T::types::return_type;
+ return this->instantiateHomogenizer<ret_type>(nb_components);
}
- /* ------------------------------------------------------------------------ */
+ template <typename ret_type>
inline std::unique_ptr<ComputeFunctorInterface>
- HomogenizerProxy::createHomogenizer(Field & field) {
- HomogenizerProxy homogenizer_proxy;
- return field.connect(homogenizer_proxy);
- }
+ instantiateHomogenizer(ElementTypeMap<Int> &nb_components);
+};
+
+/* ------------------------------------------------------------------------ */
+
+template <typename ret_type>
+inline std::unique_ptr<ComputeFunctorInterface>
+HomogenizerProxy::instantiateHomogenizer(ElementTypeMap<Int> &nb_components) {
+ using Homogenizer = dumpers::AvgHomogenizingFunctor<ret_type>;
+ return std::make_unique<Homogenizer>(nb_components);
+}
+
+template <>
+inline std::unique_ptr<ComputeFunctorInterface>
+HomogenizerProxy::instantiateHomogenizer<Vector<iohelper::ElemType>>(
+ ElementTypeMap<Int> & /*nb_components*/) {
+ throw;
+ return nullptr;
+}
+
+/* ------------------------------------------------------------------------ */
+/// for connection to a FieldCompute
+template <typename SubFieldCompute, typename return_type,
+ typename support_type_>
+inline std::unique_ptr<ComputeFunctorInterface>
+FieldCompute<SubFieldCompute, return_type, support_type_>::connect(
+ HomogenizerProxy &proxy) {
+ return proxy.connectToField(this);
+}
+
+template <typename SubFieldCompute, typename return_type>
+inline std::unique_ptr<ComputeFunctorInterface>
+FieldCompute<SubFieldCompute, return_type, Element>::connect(
+ HomogenizerProxy &proxy) {
+ return proxy.connectToField(this);
+}
+
+/* ------------------------------------------------------------------------ */
+inline std::unique_ptr<ComputeFunctorInterface>
+HomogenizerProxy::createHomogenizer(Field &field) {
+ HomogenizerProxy homogenizer_proxy;
+ return field.connect(homogenizer_proxy);
+}
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_HOMOGENIZING_FIELD_HH_ */
diff --git a/src/io/dumper/dumper_internal_material_field.hh b/src/io/dumper/dumper_internal_material_field.hh
index 759751ca8..f2a05a36c 100644
--- a/src/io/dumper/dumper_internal_material_field.hh
+++ b/src/io/dumper/dumper_internal_material_field.hh
@@ -1,79 +1,74 @@
/**
* @file dumper_internal_material_field.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Mar 04 2020
*
* @brief description of material internal field
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_INTERNAL_MATERIAL_FIELD_HH_
#define AKANTU_DUMPER_INTERNAL_MATERIAL_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_quadrature_point_iterator.hh"
#ifdef AKANTU_IGFEM
#include "dumper_igfem_material_internal_field.hh"
#endif
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
- /* --------------------------------------------------------------------------
- */
+ /* ------------------------------------------------------------------------ */
template <typename T, bool filtered = false>
class InternalMaterialField
- : public GenericElementalField<SingleType<T, Vector, filtered>,
+ : public GenericElementalField<SingleType<T, Vector<T>, filtered>,
quadrature_point_iterator> {
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Typedefs */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
public:
- using types = SingleType<T, Vector, filtered>;
+ using types = SingleType<T, Vector<T>, filtered>;
using parent = GenericElementalField<types, quadrature_point_iterator>;
using field_type = typename types::field_type;
using support_type = Element;
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
- /* ------------------------------------------------------------------------
- */
+ /* ---------------------------------------------------------------------- */
InternalMaterialField(const field_type & field,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined)
: parent(field, spatial_dimension, ghost_type, element_kind) {}
};
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_INTERNAL_MATERIAL_FIELD_HH_ */
diff --git a/src/io/dumper/dumper_iohelper.cc b/src/io/dumper/dumper_iohelper.cc
index ba750bf45..1a7cc846b 100644
--- a/src/io/dumper/dumper_iohelper.cc
+++ b/src/io/dumper/dumper_iohelper.cc
@@ -1,322 +1,320 @@
/**
* @file dumper_iohelper.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Oct 26 2012
* @date last modification: Fri Jul 24 2020
*
* @brief implementation of DumperIOHelper
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include <io_helper.hh>
+//#include <io_helper.hh>
+#include "dumper_iohelper.hh"
#include "dumper_elemental_field.hh"
#include "dumper_filtered_connectivity.hh"
-#include "dumper_iohelper.hh"
#include "dumper_nodal_field.hh"
#include "dumper_variable.hh"
#include "mesh.hh"
+
#if defined(AKANTU_IGFEM)
#include "dumper_igfem_connectivity.hh"
#endif
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
DumperIOHelper::DumperIOHelper() = default;
/* -------------------------------------------------------------------------- */
DumperIOHelper::~DumperIOHelper() = default;
/* -------------------------------------------------------------------------- */
void DumperIOHelper::setParallelContext(bool is_parallel) {
- UInt whoami = Communicator::getStaticCommunicator().whoAmI();
- UInt nb_proc = Communicator::getStaticCommunicator().getNbProc();
+ auto whoami = Communicator::getStaticCommunicator().whoAmI();
+ auto nb_proc = Communicator::getStaticCommunicator().getNbProc();
if (is_parallel) {
dumper->setParallelContext(whoami, nb_proc);
} else {
dumper->setParallelContext(0, 1);
}
}
/* -------------------------------------------------------------------------- */
void DumperIOHelper::setDirectory(const std::string & directory) {
this->directory = directory;
dumper->setPrefix(directory);
}
/* -------------------------------------------------------------------------- */
void DumperIOHelper::setBaseName(const std::string & basename) {
filename = basename;
}
/* -------------------------------------------------------------------------- */
void DumperIOHelper::setTimeStep(Real time_step) {
if (!time_activated) {
this->dumper->activateTimeDescFiles(time_step);
} else {
this->dumper->setTimeStep(time_step);
}
}
/* -------------------------------------------------------------------------- */
void DumperIOHelper::dump() {
try {
dumper->dump(filename, count);
} catch (iohelper::IOHelperException & e) {
AKANTU_ERROR(
"I was not able to dump your data with a Dumper: " << e.what());
}
++count;
}
/* -------------------------------------------------------------------------- */
-void DumperIOHelper::dump(UInt step) {
+void DumperIOHelper::dump(Int step) {
this->count = step;
this->dump();
}
/* -------------------------------------------------------------------------- */
-void DumperIOHelper::dump(Real current_time, UInt step) {
+void DumperIOHelper::dump(Real current_time, Int step) {
this->dumper->setCurrentTime(current_time);
this->dump(step);
}
-
/* -------------------------------------------------------------------------- */
-void DumperIOHelper::registerMesh(const Mesh & mesh, UInt spatial_dimension,
+void DumperIOHelper::registerMesh(const Mesh & mesh, Int spatial_dimension,
GhostType ghost_type,
ElementKind element_kind) {
#if defined(AKANTU_IGFEM)
if (element_kind == _ek_igfem) {
registerField("connectivities",
new dumpers::IGFEMConnectivityField(
mesh.getConnectivities(), spatial_dimension, ghost_type));
- } else
+ } else {
#endif
-
registerField("connectivities",
- std::make_shared<dumpers::ElementalField<UInt>>(
+ std::make_shared<dumpers::ElementalField<Idx>>(
mesh.getConnectivities(), spatial_dimension, ghost_type,
element_kind));
-
+#if defined(AKANTU_IGFEM)
+ }
+#endif
registerField("positions",
std::make_shared<dumpers::NodalField<Real>>(mesh.getNodes()));
}
/* -------------------------------------------------------------------------- */
void DumperIOHelper::registerFilteredMesh(
- const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter, UInt spatial_dimension,
+ const Mesh & mesh, const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter, Int spatial_dimension,
GhostType ghost_type, ElementKind element_kind) {
- auto * f_connectivities = new ElementTypeMapArrayFilter<UInt>(
+ auto * f_connectivities = new ElementTypeMapArrayFilter<Idx>(
mesh.getConnectivities(), elements_filter);
this->registerField("connectivities",
std::make_shared<dumpers::FilteredConnectivityField>(
*f_connectivities, nodes_filter, spatial_dimension,
ghost_type, element_kind));
this->registerField("positions",
std::make_shared<dumpers::NodalField<Real, true>>(
mesh.getNodes(), 0, 0, &nodes_filter));
}
/* -------------------------------------------------------------------------- */
-void DumperIOHelper::registerField(
- const std::string & field_id,
- std::shared_ptr<dumpers::Field>
- field) // NOLINT(performance-unnecessary-value-param)
-{
+void DumperIOHelper::registerField(const std::string & field_id,
+ std::shared_ptr<dumpers::Field> field) {
auto it = fields.find(field_id);
if (it != fields.end()) {
AKANTU_DEBUG_WARNING(
"The field "
<< field_id << " is already registered in this Dumper. Field ignored.");
return;
}
fields[field_id] = field;
field->registerToDumper(field_id, *dumper);
}
/* -------------------------------------------------------------------------- */
void DumperIOHelper::unRegisterField(const std::string & field_id) {
auto it = fields.find(field_id);
if (it == fields.end()) {
AKANTU_DEBUG_WARNING(
"The field " << field_id
<< " is not registered in this Dumper. Nothing to do.");
return;
}
fields.erase(it);
}
/* -------------------------------------------------------------------------- */
void DumperIOHelper::registerVariable(
const std::string & variable_id,
std::shared_ptr<dumpers::VariableBase>
variable) // NOLINT(performance-unnecessary-value-param)
{
auto it = variables.find(variable_id);
if (it != variables.end()) {
AKANTU_DEBUG_WARNING(
"The Variable "
<< variable_id
<< " is already registered in this Dumper. Variable ignored.");
return;
}
variables[variable_id] = variable;
variable->registerToDumper(variable_id, *dumper);
} // namespace akantu
/* -------------------------------------------------------------------------- */
void DumperIOHelper::unRegisterVariable(const std::string & variable_id) {
auto it = variables.find(variable_id);
if (it == variables.end()) {
AKANTU_DEBUG_WARNING(
"The variable " << variable_id
<< " is not registered in this Dumper. Nothing to do.");
return;
}
variables.erase(it);
}
/* -------------------------------------------------------------------------- */
template <ElementType type> iohelper::ElemType getIOHelperType() {
AKANTU_TO_IMPLEMENT();
return iohelper::MAX_ELEM_TYPE;
}
template <> iohelper::ElemType getIOHelperType<_point_1>() {
return iohelper::POINT_SET;
}
template <> iohelper::ElemType getIOHelperType<_segment_2>() {
return iohelper::LINE1;
}
template <> iohelper::ElemType getIOHelperType<_segment_3>() {
return iohelper::LINE2;
}
template <> iohelper::ElemType getIOHelperType<_triangle_3>() {
return iohelper::TRIANGLE1;
}
template <> iohelper::ElemType getIOHelperType<_triangle_6>() {
return iohelper::TRIANGLE2;
}
template <> iohelper::ElemType getIOHelperType<_quadrangle_4>() {
return iohelper::QUAD1;
}
template <> iohelper::ElemType getIOHelperType<_quadrangle_8>() {
return iohelper::QUAD2;
}
template <> iohelper::ElemType getIOHelperType<_tetrahedron_4>() {
return iohelper::TETRA1;
}
template <> iohelper::ElemType getIOHelperType<_tetrahedron_10>() {
return iohelper::TETRA2;
}
template <> iohelper::ElemType getIOHelperType<_hexahedron_8>() {
return iohelper::HEX1;
}
template <> iohelper::ElemType getIOHelperType<_hexahedron_20>() {
return iohelper::HEX2;
}
template <> iohelper::ElemType getIOHelperType<_pentahedron_6>() {
return iohelper::PRISM1;
}
template <> iohelper::ElemType getIOHelperType<_pentahedron_15>() {
return iohelper::PRISM2;
}
#if defined(AKANTU_COHESIVE_ELEMENT)
template <> iohelper::ElemType getIOHelperType<_cohesive_1d_2>() {
return iohelper::COH1D2;
}
template <> iohelper::ElemType getIOHelperType<_cohesive_2d_4>() {
return iohelper::COH2D4;
}
template <> iohelper::ElemType getIOHelperType<_cohesive_2d_6>() {
return iohelper::COH2D6;
}
template <> iohelper::ElemType getIOHelperType<_cohesive_3d_6>() {
return iohelper::COH3D6;
}
template <> iohelper::ElemType getIOHelperType<_cohesive_3d_12>() {
return iohelper::COH3D12;
}
template <> iohelper::ElemType getIOHelperType<_cohesive_3d_8>() {
return iohelper::COH3D8;
}
// template <>
// iohelper::ElemType getIOHelperType<_cohesive_3d_16>() { return
// iohelper::COH3D16; }
#endif
#if defined(AKANTU_STRUCTURAL_MECHANICS)
template <> iohelper::ElemType getIOHelperType<_bernoulli_beam_2>() {
return iohelper::BEAM2;
}
template <> iohelper::ElemType getIOHelperType<_bernoulli_beam_3>() {
return iohelper::BEAM3;
}
#endif
-
/* -------------------------------------------------------------------------- */
-UInt getIOHelperType(ElementType type) {
- UInt ioh_type = iohelper::MAX_ELEM_TYPE;
-#define GET_IOHELPER_TYPE(type) ioh_type = getIOHelperType<type>();
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_IOHELPER_TYPE);
-#undef GET_IOHELPER_TYPE
- return ioh_type;
+Int getIOHelperType(ElementType type) {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return getIOHelperType<type>();
+ },
+ type);
}
-/* -------------------------------------------------------------------------- */
-
} // namespace akantu
namespace iohelper {
+
template <> DataType getDataType<akantu::NodeFlag>() {
return getDataType<std::underlying_type_t<akantu::NodeFlag>>();
}
+
} // namespace iohelper
diff --git a/src/io/dumper/dumper_iohelper.hh b/src/io/dumper/dumper_iohelper.hh
index 028e5520e..c5b8d526a 100644
--- a/src/io/dumper/dumper_iohelper.hh
+++ b/src/io/dumper/dumper_iohelper.hh
@@ -1,162 +1,179 @@
/**
* @file dumper_iohelper.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Oct 26 2012
* @date last modification: Fri Jul 24 2020
*
* @brief Define the akantu dumper interface for IOhelper dumpers
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "aka_types.hh"
#include "element_type_map.hh"
/* -------------------------------------------------------------------------- */
+#include <io_helper.hh>
#include <memory>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DUMPER_IOHELPER_HH_
#define AKANTU_DUMPER_IOHELPER_HH_
/* -------------------------------------------------------------------------- */
namespace iohelper {
-class Dumper;
-}
+
+template <typename T, Eigen::Index m, Eigen::Index n>
+struct is_vector<Eigen::Matrix<T, m, n>>
+ : public aka::bool_constant<Eigen::Matrix<T, m, n>::IsVectorAtCompileTime> {
+};
+
+template <typename T, Eigen::Index m, Eigen::Index n>
+struct is_matrix<Eigen::Matrix<T, m, n>>
+ : public aka::bool_constant<
+ not Eigen::Matrix<T, m, n>::IsVectorAtCompileTime> {};
+
+template <typename Derived, int MapOptions, typename StrideType>
+struct is_vector<Eigen::Map<Derived, MapOptions, StrideType>>
+ : public aka::bool_constant<Derived::IsVectorAtCompileTime> {};
+
+template <typename Derived, int MapOptions, typename StrideType>
+struct is_matrix<Eigen::Map<Derived, MapOptions, StrideType>>
+ : public aka::bool_constant<not Derived::IsVectorAtCompileTime> {};
+
+} // namespace iohelper
namespace akantu {
-UInt getIOHelperType(ElementType type);
+Int getIOHelperType(ElementType type);
namespace dumpers {
class Field;
class VariableBase;
} // namespace dumpers
class Mesh;
class DumperIOHelper : public std::enable_shared_from_this<DumperIOHelper> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
DumperIOHelper();
virtual ~DumperIOHelper();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// register a given Mesh for the current dumper
virtual void registerMesh(const Mesh & mesh,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined);
/// register a filtered Mesh (provided filter lists) for the current dumper
- virtual void
- registerFilteredMesh(const Mesh & mesh,
- const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined);
+ virtual void registerFilteredMesh(
+ const Mesh & mesh, const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter, Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined);
/// register a Field object identified by name and provided by pointer
void registerField(const std::string & field_id,
std::shared_ptr<dumpers::Field> field);
/// remove the Field identified by name from managed fields
void unRegisterField(const std::string & field_id);
/// register a VariableBase object identified by name and provided by pointer
void registerVariable(const std::string & variable_id,
std::shared_ptr<dumpers::VariableBase> variable);
/// remove a VariableBase identified by name from managed fields
void unRegisterVariable(const std::string & variable_id);
/// request dump: this calls IOHelper dump routine
virtual void dump();
/// request dump: this first set the current step and then calls IOHelper dump
/// routine
- virtual void dump(UInt step);
+ virtual void dump(Int step);
/// request dump: this first set the current step and current time and then
/// calls IOHelper dump routine
- virtual void dump(Real current_time, UInt step);
+ virtual void dump(Real current_time, Int step);
/// set the parallel context for IOHeper
virtual void setParallelContext(bool is_parallel);
/// set the directory where to generate the dumped files
virtual void setDirectory(const std::string & directory);
/// set the base name (needed by most IOHelper dumpers)
virtual void setBaseName(const std::string & basename);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// direct access to the iohelper::Dumper object
AKANTU_GET_MACRO(Dumper, *dumper, iohelper::Dumper &)
/// set the timestep of the iohelper::Dumper
void setTimeStep(Real time_step);
public:
/* ------------------------------------------------------------------------ */
/* Variable wrapper */
template <typename T, bool is_scal = std::is_arithmetic<T>::value>
class Variable;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// internal iohelper::Dumper
std::unique_ptr<iohelper::Dumper> dumper;
using Fields = std::map<std::string, std::shared_ptr<dumpers::Field>>;
using Variables =
std::map<std::string, std::shared_ptr<dumpers::VariableBase>>;
/// list of registered fields to dump
Fields fields;
Variables variables;
/// dump counter
- UInt count{0};
+ Int count{0};
/// directory name
std::string directory;
/// filename prefix
std::string filename;
/// is time tracking activated in the dumper
bool time_activated{false};
};
} // namespace akantu
#endif /* AKANTU_DUMPER_IOHELPER_HH_ */
diff --git a/src/io/dumper/dumper_material_padders.hh b/src/io/dumper/dumper_material_padders.hh
index 3f7e5f7b6..d0bc9f7e3 100644
--- a/src/io/dumper/dumper_material_padders.hh
+++ b/src/io/dumper/dumper_material_padders.hh
@@ -1,307 +1,290 @@
/**
* @file dumper_material_padders.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Material padders for plane stress/ plane strain
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_MATERIAL_PADDERS_HH_
#define AKANTU_DUMPER_MATERIAL_PADDERS_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_padding_helper.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* ------------------------------------------------------------------------ */
class MaterialFunctor {
/* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
/* ---------------------------------------------------------------------- */
public:
MaterialFunctor(const SolidMechanicsModel & model)
: model(model), material_index(model.getMaterialByElement()),
nb_data_per_element("nb_data_per_element", model.getID()),
spatial_dimension(model.getSpatialDimension()) {}
/* ---------------------------------------------------------------------- */
/* Methods */
/* ---------------------------------------------------------------------- */
/// return the material from the global element index
const Material & getMaterialFromGlobalIndex(Element global_index) {
- UInt index = global_index.element;
- UInt material_id = material_index(global_index.type)(index);
+ auto index = global_index.element;
+ auto material_id = material_index(global_index.type)(index);
const Material & material = model.getMaterial(material_id);
return material;
}
/// return the type of the element from global index
ElementType
getElementTypeFromGlobalIndex( // NOLINT(readability-convert-member-functions-to-static)
Element global_index) {
return global_index.type;
}
protected:
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
/// all material padders probably need access to solid mechanics model
const SolidMechanicsModel & model;
/// they also need an access to the map from global ids to material id and
/// local ids
- const ElementTypeMapArray<UInt> & material_index;
+ const ElementTypeMapArray<Idx> & material_index;
/// the number of data per element
- const ElementTypeMapArray<UInt> nb_data_per_element;
+ const ElementTypeMapArray<Idx> nb_data_per_element;
- UInt spatial_dimension;
+ Int spatial_dimension;
};
/* ------------------------------------------------------------------------ */
template <class T, class R>
class MaterialPadder : public MaterialFunctor,
public PadderGeneric<Vector<T>, R> {
public:
MaterialPadder(const SolidMechanicsModel & model)
: MaterialFunctor(model) {}
};
/* ------------------------------------------------------------------------ */
- template <UInt spatial_dimension>
+ template <Int spatial_dimension>
class StressPadder : public MaterialPadder<Real, Matrix<Real>> {
public:
StressPadder(const SolidMechanicsModel & model)
: MaterialPadder<Real, Matrix<Real>>(model) {
this->setPadding(3, 3);
}
inline Matrix<Real> func(const Vector<Real> & in,
Element global_element_id) override {
- UInt nrows = spatial_dimension;
- UInt ncols = in.size() / nrows;
- UInt nb_data = in.size() / (nrows * nrows);
+ auto nrows = spatial_dimension;
+ auto ncols = in.size() / nrows;
+ auto nb_data = in.size() / (nrows * nrows);
Matrix<Real> stress = this->pad(in, nrows, ncols, nb_data);
const Material & material =
this->getMaterialFromGlobalIndex(global_element_id);
bool plane_strain = true;
if (spatial_dimension == 2) {
plane_strain = !((bool)material.getParam("Plane_Stress"));
}
if (plane_strain) {
Real nu = material.getParam("nu");
- for (UInt d = 0; d < nb_data; ++d) {
+ for (Int d = 0; d < nb_data; ++d) {
stress(2, 2 + 3 * d) =
nu * (stress(0, 0 + 3 * d) + stress(1, 1 + 3 * d));
}
}
return stress;
}
- UInt getDim() override { return 9; };
-
- UInt getNbComponent(UInt /*old_nb_comp*/) override {
- return this->getDim();
- };
+ Int getDim() override { return 9; }
+ Int getNbComponent(Int /*old_nb_comp*/) override { return this->getDim(); }
};
/* ------------------------------------------------------------------------ */
- template <UInt spatial_dimension>
+ template <Int spatial_dimension>
class StrainPadder : public MaterialFunctor,
public PadderGeneric<Matrix<Real>, Matrix<Real>> {
public:
StrainPadder(const SolidMechanicsModel & model) : MaterialFunctor(model) {
this->setPadding(3, 3);
}
inline Matrix<Real> func(const Matrix<Real> & in,
Element global_element_id) override {
- UInt nrows = spatial_dimension;
- UInt nb_data = in.size() / (nrows * nrows);
+ auto nrows = spatial_dimension;
+ auto nb_data = in.size() / (nrows * nrows);
Matrix<Real> strain = this->pad(in, nb_data);
const Material & material =
this->getMaterialFromGlobalIndex(global_element_id);
bool plane_stress = material.getParam("Plane_Stress");
if (plane_stress) {
Real nu = material.getParam("nu");
- for (UInt d = 0; d < nb_data; ++d) {
+ for (Int d = 0; d < nb_data; ++d) {
strain(2, 2 + 3 * d) =
nu / (nu - 1) * (strain(0, 0 + 3 * d) + strain(1, 1 + 3 * d));
}
}
return strain;
}
- UInt getDim() override { return 9; };
-
- UInt getNbComponent(UInt /*old_nb_comp*/) override {
- return this->getDim();
- };
+ Int getDim() override { return 9; }
+ Int getNbComponent(Int /*old_nb_comp*/) override { return this->getDim(); }
};
/* ------------------------------------------------------------------------ */
template <bool green_strain>
class ComputeStrain : public MaterialFunctor,
public ComputeFunctor<Vector<Real>, Matrix<Real>> {
public:
ComputeStrain(const SolidMechanicsModel & model) : MaterialFunctor(model) {}
inline Matrix<Real> func(const Vector<Real> & in,
Element /*global_element_id*/) override {
- UInt nrows = spatial_dimension;
- UInt ncols = in.size() / nrows;
- UInt nb_data = in.size() / (nrows * nrows);
+ auto nrows = spatial_dimension;
+ auto ncols = in.size() / nrows;
+ auto nb_data = in.size() / (nrows * nrows);
Matrix<Real> ret_all_strain(nrows, ncols);
- Tensor3<Real> all_grad_u(in.storage(), nrows, nrows, nb_data);
- Tensor3<Real> all_strain(ret_all_strain.storage(), nrows, nrows, nb_data);
+ Tensor3Proxy<const Real> all_grad_u(in.data(), nrows, nrows, nb_data);
+ Tensor3Proxy<Real> all_strain(ret_all_strain.data(), nrows, nrows,
+ nb_data);
- for (UInt d = 0; d < nb_data; ++d) {
- Matrix<Real> grad_u = all_grad_u(d);
- Matrix<Real> strain = all_strain(d);
+ for (Int d = 0; d < nb_data; ++d) {
+ auto && grad_u = all_grad_u(d);
+ auto && strain = all_strain(d);
if (spatial_dimension == 2) {
if (green_strain) {
- Material::gradUToE<2>(grad_u, strain);
+ strain = Material::gradUToE<2>(grad_u);
} else {
- Material::gradUToEpsilon<2>(grad_u, strain);
+ strain = Material::gradUToEpsilon<2>(grad_u);
}
} else if (spatial_dimension == 3) {
if (green_strain) {
- Material::gradUToE<3>(grad_u, strain);
+ strain = Material::gradUToE<3>(grad_u);
} else {
- Material::gradUToEpsilon<3>(grad_u, strain);
+ strain = Material::gradUToEpsilon<3>(grad_u);
}
}
}
return ret_all_strain;
}
- UInt getDim() override { return spatial_dimension * spatial_dimension; };
-
- UInt getNbComponent(UInt /*old_nb_comp*/) override {
- return this->getDim();
- };
+ Int getDim() override { return spatial_dimension * spatial_dimension; }
+ Int getNbComponent(Int /*old_nb_comp*/) override { return this->getDim(); }
};
/* ------------------------------------------------------------------------ */
template <bool green_strain>
class ComputePrincipalStrain
: public MaterialFunctor,
public ComputeFunctor<Vector<Real>, Matrix<Real>> {
public:
ComputePrincipalStrain(const SolidMechanicsModel & model)
: MaterialFunctor(model) {}
inline Matrix<Real> func(const Vector<Real> & in,
Element /*global_element_id*/) override {
- UInt nrows = spatial_dimension;
- UInt nb_data = in.size() / (nrows * nrows);
+ auto nrows = spatial_dimension;
+ auto nb_data = in.size() / (nrows * nrows);
Matrix<Real> ret_all_strain(nrows, nb_data);
- Tensor3<Real> all_grad_u(in.storage(), nrows, nrows, nb_data);
+ Tensor3Proxy<const Real> all_grad_u(in.data(), nrows, nrows, nb_data);
Matrix<Real> strain(nrows, nrows);
- for (UInt d = 0; d < nb_data; ++d) {
+ for (Int d = 0; d < nb_data; ++d) {
Matrix<Real> grad_u = all_grad_u(d);
- if (spatial_dimension == 2) {
- if (green_strain) {
- Material::gradUToE<2>(grad_u, strain);
- } else {
- Material::gradUToEpsilon<2>(grad_u, strain);
- }
- } else if (spatial_dimension == 3) {
- if (green_strain) {
- Material::gradUToE<3>(grad_u, strain);
- } else {
- Material::gradUToEpsilon<3>(grad_u, strain);
- }
- }
-
- Vector<Real> principal_strain(ret_all_strain(d));
+ tuple_dispatch<AllSpatialDimensions>(
+ [&grad_u, &strain](auto && dim_t) {
+ constexpr auto dim = aka::decay_v<decltype(dim_t)>;
+ if (green_strain) {
+ Material::gradUToE<dim>(grad_u, strain);
+ } else {
+ strain = Material::gradUToEpsilon<dim>(grad_u);
+ }
+ },
+ spatial_dimension);
+
+ auto && principal_strain = ret_all_strain(d);
strain.eig(principal_strain);
}
return ret_all_strain;
}
- UInt getDim() override { return spatial_dimension; };
-
- UInt getNbComponent(UInt /*old_nb_comp*/) override {
- return this->getDim();
- };
+ Int getDim() override { return spatial_dimension; }
+ Int getNbComponent(Int /*old_nb_comp*/) override { return this->getDim(); }
};
/* ------------------------------------------------------------------------ */
class ComputeVonMisesStress
: public MaterialFunctor,
public ComputeFunctor<Vector<Real>, Vector<Real>> {
public:
ComputeVonMisesStress(const SolidMechanicsModel & model)
: MaterialFunctor(model) {}
inline Vector<Real> func(const Vector<Real> & in,
Element /*global_element_id*/) override {
- UInt nrows = spatial_dimension;
- UInt nb_data = in.size() / (nrows * nrows);
+ auto nrows = spatial_dimension;
+ auto nb_data = in.size() / (nrows * nrows);
Vector<Real> von_mises_stress(nb_data);
Matrix<Real> deviatoric_stress(3, 3);
- for (UInt d = 0; d < nb_data; ++d) {
- Matrix<Real> cauchy_stress(in.storage() + d * nrows * nrows, nrows,
- nrows);
+ for (Int d = 0; d < nb_data; ++d) {
+ MatrixProxy<const Real> cauchy_stress(in.data() + d * nrows * nrows,
+ nrows, nrows);
von_mises_stress(d) = Material::stressToVonMises(cauchy_stress);
}
return von_mises_stress;
}
- UInt getDim() override { return 1; };
-
- UInt getNbComponent(UInt /*old_nb_comp*/) override {
- return this->getDim();
- };
+ Int getDim() override { return 1; }
+ Int getNbComponent(Int /*old_nb_comp*/) override { return this->getDim(); }
};
/* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_MATERIAL_PADDERS_HH_ */
diff --git a/src/io/dumper/dumper_nodal_field.hh b/src/io/dumper/dumper_nodal_field.hh
index fc701b5fa..e54ee655f 100644
--- a/src/io/dumper/dumper_nodal_field.hh
+++ b/src/io/dumper/dumper_nodal_field.hh
@@ -1,190 +1,189 @@
/**
* @file dumper_nodal_field.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Oct 26 2012
* @date last modification: Fri Jul 24 2020
*
* @brief Description of nodal fields
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DUMPER_NODAL_FIELD_HH_
#define AKANTU_DUMPER_NODAL_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_compute.hh"
#include "dumper_field.hh"
#include <io_helper.hh>
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* ------------------------------------------------------------------------ */
// This represents a iohelper compatible field
template <typename T, bool filtered = false, class Container = Array<T>,
- class Filter = Array<UInt>>
+ class Filter = Array<Idx>>
class NodalField : public dumpers::Field {
/* ---------------------------------------------------------------------- */
/* Typedefs */
/* ---------------------------------------------------------------------- */
public:
- using support_type = UInt;
+ using support_type = Idx;
using types = TypeTraits<T, Vector<T>, Container>;
- class iterator : public iohelper::iterator<T, iterator, Vector<T>> {
+ class iterator : public iohelper::iterator<T, iterator, VectorProxy<T>> {
public:
- iterator(T * vect, UInt _offset, UInt _n, UInt _stride,
- const UInt * filter)
+ iterator(T * vect, Int _offset, Int _n, Int _stride, const Int * filter)
: internal_it(vect), offset(_offset), n(_n), stride(_stride),
filter(filter) {}
bool operator!=(const iterator & it) const override {
if (filter != nullptr) {
return filter != it.filter;
}
return internal_it != it.internal_it;
}
iterator & operator++() override {
if (filter != nullptr) {
++filter;
} else {
internal_it += offset;
}
return *this;
}
- Vector<T> operator*() override {
+ VectorProxy<T> operator*() override {
if (filter != nullptr) {
- return Vector<T>(internal_it + *(filter)*offset + stride, n);
+ return VectorProxy<T>(internal_it + *(filter)*offset + stride, n);
}
- return Vector<T>(internal_it + stride, n);
+ return VectorProxy<T>(internal_it + stride, n);
}
private:
T * internal_it;
- UInt offset, n, stride;
- const UInt * filter{nullptr};
+ Int offset, n, stride;
+ const Int * filter{nullptr};
};
/* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
/* ---------------------------------------------------------------------- */
public:
- NodalField(const Container & _field, UInt _n = 0, UInt _stride = 0,
+ NodalField(const Container & _field, Int _n = 0, Int _stride = 0,
const Filter * filter = nullptr)
: field(_field), n(_n), stride(_stride), filter(filter), padding(0) {
AKANTU_DEBUG_ASSERT(((not filtered) and filter == nullptr) or filtered,
"Filter passed to unfiltered NodalField!");
AKANTU_DEBUG_ASSERT((filtered and this->filter != nullptr) or
(not filtered),
"No filter passed to filtered NodalField!");
AKANTU_DEBUG_ASSERT(
(filter != nullptr and this->filter->getNbComponent() == 1) or
(filter == nullptr),
"Multi-component filter given to NodalField ("
<< this->filter->getNbComponent()
<< " components detected, sould be 1");
if (n == 0) {
this->n = field.getNbComponent() - stride;
}
}
/* ---------------------------------------------------------------------- */
/* Methods */
/* ---------------------------------------------------------------------- */
public:
void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) override {
dumper.addNodeDataField(id, *this);
}
inline iterator begin() {
- return iterator(field.storage(), field.getNbComponent(), n, stride,
- filter == nullptr ? nullptr : filter->storage());
+ return iterator(field.data(), field.getNbComponent(), n, stride,
+ filter == nullptr ? nullptr : filter->data());
}
inline iterator end() {
- return iterator(field.storage() + field.getNbComponent() * field.size(),
+ return iterator(field.data() + field.getNbComponent() * field.size(),
field.getNbComponent(), n, stride,
filter == nullptr ? nullptr
- : filter->storage() + filter->size());
+ : filter->data() + filter->size());
}
bool isHomogeneous() override { return true; }
void checkHomogeneity() override { this->homogeneous = true; }
- virtual UInt getDim() {
+ virtual Int getDim() {
if (this->padding) {
return this->padding;
}
return n;
}
- void setPadding(UInt padding) { this->padding = padding; }
+ void setPadding(Int padding) { this->padding = padding; }
- UInt size() {
+ Int size() {
if (filter != nullptr) {
return filter->size();
}
return field.size();
}
inline std::shared_ptr<Field> connect(FieldComputeProxy & proxy) override {
return proxy.connectToField(this);
}
/// for connection to a Homogenizer
inline std::unique_ptr<ComputeFunctorInterface>
connect(HomogenizerProxy & /*proxy*/) override {
throw;
}
template <class T1 = T,
std::enable_if_t<std::is_enum<T1>::value> * = nullptr>
iohelper::DataType getDataType() {
- return iohelper::getDataType<UInt>();
+ return iohelper::getDataType<Int>();
}
template <class T1 = T,
std::enable_if_t<not std::is_enum<T1>::value> * = nullptr>
iohelper::DataType getDataType() {
return iohelper::getDataType<T>();
}
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
private:
const Container & field;
- UInt n, stride;
+ Int n, stride;
const Filter * filter{nullptr};
- UInt padding;
+ Int padding;
};
} // namespace dumpers
} // namespace akantu
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_DUMPER_NODAL_FIELD_HH_ */
diff --git a/src/io/dumper/dumper_padding_helper.hh b/src/io/dumper/dumper_padding_helper.hh
index 920c40742..68f3cf589 100644
--- a/src/io/dumper/dumper_padding_helper.hh
+++ b/src/io/dumper/dumper_padding_helper.hh
@@ -1,152 +1,151 @@
/**
* @file dumper_padding_helper.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Padding helper for field iterators
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_PADDING_HELPER_HH_
#define AKANTU_DUMPER_PADDING_HELPER_HH_
/* -------------------------------------------------------------------------- */
#include "dumper_compute.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
class PadderInterface {
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
public:
PadderInterface() {
padding_m = 0;
padding_n = 0;
}
/* ------------------------------------------------------------------------
*/
/* Methods */
/* ------------------------------------------------------------------------
*/
public:
- void setPadding(UInt m, UInt n = 0) {
+ void setPadding(Int m, Int n = 0) {
padding_m = m;
padding_n = n;
}
- virtual UInt getPaddedDim(UInt nb_data) { return nb_data; }
+ virtual Int getPaddedDim(Int nb_data) { return nb_data; }
/* ------------------------------------------------------------------------
*/
/* Class Members */
/* ------------------------------------------------------------------------
*/
public:
/// padding informations
- UInt padding_n, padding_m;
+ Int padding_n, padding_m;
};
/* --------------------------------------------------------------------------
*/
template <class input_type, class output_type>
class PadderGeneric : public ComputeFunctor<input_type, output_type>,
public PadderInterface {
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
public:
PadderGeneric() : PadderInterface() {}
/* ------------------------------------------------------------------------
*/
/* Methods */
/* ------------------------------------------------------------------------
*/
public:
- inline output_type pad(const input_type & in,
- __attribute__((unused)) UInt nb_data) {
+ inline output_type pad(const input_type & in, Int /*nb_data*/) {
return in; // trick due to the fact that IOHelper padds the vectors (avoid
// a copy of data)
}
};
/* --------------------------------------------------------------------------
*/
template <class T>
class PadderGeneric<Vector<T>, Matrix<T>>
: public ComputeFunctor<Vector<T>, Matrix<T>>, public PadderInterface {
/* ------------------------------------------------------------------------
*/
/* Constructors/Destructors */
/* ------------------------------------------------------------------------
*/
public:
- inline Matrix<T> pad(const Vector<T> & _in, UInt nrows, UInt ncols,
- UInt nb_data) {
- Matrix<T> in(_in.storage(), nrows, ncols);
+ inline Matrix<T> pad(const Vector<T> & _in, Int nrows, Int ncols,
+ Int nb_data) {
+ MatrixProxy<const T> in(_in.data(), nrows, ncols);
if (padding_m <= nrows && padding_n * nb_data <= ncols) {
return in;
}
Matrix<T> ret(padding_m, padding_n * nb_data);
- UInt nb_cols_per_data = in.cols() / nb_data;
- for (UInt d = 0; d < nb_data; ++d) {
- for (UInt i = 0; i < in.rows(); ++i) {
- for (UInt j = 0; j < nb_cols_per_data; ++j) {
+ auto nb_cols_per_data = in.cols() / nb_data;
+ for (Int d = 0; d < nb_data; ++d) {
+ for (Int i = 0; i < in.rows(); ++i) {
+ for (Int j = 0; j < nb_cols_per_data; ++j) {
ret(i, j + d * padding_n) = in(i, j + d * nb_cols_per_data);
}
}
}
return ret;
}
};
/* --------------------------------------------------------------------------
*/
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_PADDING_HELPER_HH_ */
diff --git a/src/io/dumper/dumper_text.cc b/src/io/dumper/dumper_text.cc
index 9de0872fc..c3faf08d1 100644
--- a/src/io/dumper/dumper_text.cc
+++ b/src/io/dumper/dumper_text.cc
@@ -1,105 +1,105 @@
/**
* @file dumper_text.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief implementation of text dumper
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_text.hh"
#include "communicator.hh"
#include "dumper_compute.hh"
#include "dumper_homogenizing_field.hh"
#include "dumper_nodal_field.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <io_helper.hh>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
DumperText::DumperText(const std::string & basename,
iohelper::TextDumpMode mode, bool parallel) {
this->dumper = std::make_unique<iohelper::DumperText>(mode);
this->setBaseName(basename);
this->setParallelContext(parallel);
}
/* -------------------------------------------------------------------------- */
-void DumperText::registerMesh(const Mesh & mesh, UInt /*spatial_dimension*/,
+void DumperText::registerMesh(const Mesh & mesh, Int /*spatial_dimension*/,
GhostType /*ghost_type*/,
ElementKind /*element_kind*/) {
registerField("position",
std::make_shared<dumpers::NodalField<Real>>(mesh.getNodes()));
// in parallel we need node type
- UInt nb_proc = mesh.getCommunicator().getNbProc();
+ auto nb_proc = mesh.getCommunicator().getNbProc();
if (nb_proc > 1) {
- auto func = std::make_unique<dumpers::ComputeUIntFromEnum<ContactState>>();
+ auto func = std::make_unique<dumpers::ComputeIntFromEnum<ContactState>>();
std::shared_ptr<dumpers::Field> field =
std::make_shared<dumpers::NodalField<NodeFlag>>(mesh.getNodesFlags());
field =
dumpers::FieldComputeProxy::createFieldCompute(field, std::move(func));
registerField("nodes_type", field);
}
}
/* -------------------------------------------------------------------------- */
void DumperText::registerFilteredMesh(
- const Mesh & mesh, const ElementTypeMapArray<UInt> & /*elements_filter*/,
- const Array<UInt> & nodes_filter, UInt /*spatial_dimension*/,
+ const Mesh & mesh, const ElementTypeMapArray<Idx> & /*elements_filter*/,
+ const Array<Idx> & nodes_filter, Idx /*spatial_dimension*/,
GhostType /*ghost_type*/, ElementKind /*element_kind*/) {
registerField("position", std::make_shared<dumpers::NodalField<Real, true>>(
mesh.getNodes(), 0, 0, &nodes_filter));
// in parallel we need node type
- UInt nb_proc = mesh.getCommunicator().getNbProc();
+ auto nb_proc = mesh.getCommunicator().getNbProc();
if (nb_proc > 1) {
- auto func = std::make_unique<dumpers::ComputeUIntFromEnum<ContactState>>();
+ auto func = std::make_unique<dumpers::ComputeIntFromEnum<ContactState>>();
std::shared_ptr<dumpers::Field> field =
std::make_shared<dumpers::NodalField<NodeFlag, true>>(
mesh.getNodesFlags(), 0, 0, &nodes_filter);
field =
dumpers::FieldComputeProxy::createFieldCompute(field, std::move(func));
registerField("nodes_type", field);
}
}
/* -------------------------------------------------------------------------- */
void DumperText::setBaseName(const std::string & basename) {
DumperIOHelper::setBaseName(basename);
static_cast<iohelper::DumperText *>(this->dumper.get())
->setDataSubDirectory(this->filename + "-DataFiles");
}
/* -------------------------------------------------------------------------- */
-void DumperText::setPrecision(UInt prec) {
+void DumperText::setPrecision(Int prec) {
static_cast<iohelper::DumperText *>(this->dumper.get())->setPrecision(prec);
}
} // namespace akantu
diff --git a/src/io/dumper/dumper_text.hh b/src/io/dumper/dumper_text.hh
index 357010b68..af1509726 100644
--- a/src/io/dumper/dumper_text.hh
+++ b/src/io/dumper/dumper_text.hh
@@ -1,85 +1,85 @@
/**
* @file dumper_text.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief to dump into a text file
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DUMPER_TEXT_HH_
#define AKANTU_DUMPER_TEXT_HH_
/* -------------------------------------------------------------------------- */
#include <io_helper.hh>
/* -------------------------------------------------------------------------- */
namespace akantu {
class DumperText : public DumperIOHelper {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
DumperText(const std::string & basename = "dumper_text",
iohelper::TextDumpMode mode = iohelper::_tdm_space,
bool parallel = true);
~DumperText() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- void registerMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined) override;
-
void
- registerFilteredMesh(const Mesh & mesh,
- const ElementTypeMapArray<UInt> & elements_filter,
- const Array<UInt> & nodes_filter,
- UInt spatial_dimension = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined) override;
+ registerMesh(const Mesh & mesh, Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined) override;
+
+ void registerFilteredMesh(
+ const Mesh & mesh, const ElementTypeMapArray<Idx> & elements_filter,
+ const Array<Idx> & nodes_filter,
+ Int spatial_dimension = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind element_kind = _ek_not_defined) override;
void setBaseName(const std::string & basename) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- void setPrecision(UInt prec);
+ void setPrecision(Int prec);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
};
} // namespace akantu
#endif /* AKANTU_DUMPER_TEXT_HH_ */
diff --git a/src/io/dumper/dumper_type_traits.hh b/src/io/dumper/dumper_type_traits.hh
index 6373419f9..98ec5acf6 100644
--- a/src/io/dumper/dumper_type_traits.hh
+++ b/src/io/dumper/dumper_type_traits.hh
@@ -1,90 +1,89 @@
/**
* @file dumper_type_traits.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Thu Feb 20 2020
*
* @brief Type traits for field properties
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AKANTU_DUMPER_TYPE_TRAITS_HH_
#define AKANTU_DUMPER_TYPE_TRAITS_HH_
/* -------------------------------------------------------------------------- */
#include "element_type_map.hh"
#include "element_type_map_filter.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* ------------------------------------------------------------------------ */
template <class data, class ret, class field> struct TypeTraits {
//! the stored data (real, int, uint, ...)
using data_type = data;
//! the type returned by the operator *
using return_type = ret;
//! the field type (ElementTypeMap or ElementTypeMapFilter)
using field_type = field;
//! the type over which we iterate
using it_type = typename field_type::value_type;
//! the type of array (Array<T> or ArrayFilter<T>)
using array_type = typename field_type::array_type;
//! the iterator over the array
using array_iterator = typename array_type::const_vector_iterator;
};
/* ------------------------------------------------------------------------ */
// specialization for the case in which input and output types are the same
- template <class T, template <class> class ret, bool filtered>
- struct SingleType : public TypeTraits<T, ret<T>, ElementTypeMapArray<T>> {};
+ template <class T, class ret, bool filtered>
+ struct SingleType : public TypeTraits<T, ret, ElementTypeMapArray<T>> {};
/* ------------------------------------------------------------------------ */
// same as before but for filtered data
- template <class T, template <class> class ret>
+ template <class T, class ret>
struct SingleType<T, ret, true>
- : public TypeTraits<T, ret<T>, ElementTypeMapArrayFilter<T>> {};
+ : public TypeTraits<T, ret, ElementTypeMapArrayFilter<T>> {};
/* ------------------------------------------------------------------------ */
// specialization for the case in which input and output types are different
- template <class it_type, class data_type, template <class> class ret,
- bool filtered>
- struct DualType : public TypeTraits<data_type, ret<data_type>,
- ElementTypeMapArray<it_type>> {};
+ template <class it_type, class data_type, class ret, bool filtered>
+ struct DualType
+ : public TypeTraits<data_type, ret, ElementTypeMapArray<it_type>> {};
/* ------------------------------------------------------------------------ */
// same as before but for filtered data
- template <class it_type, class data_type, template <class> class ret>
+ template <class it_type, class data_type, class ret>
struct DualType<it_type, data_type, ret, true>
- : public TypeTraits<data_type, ret<data_type>,
- ElementTypeMapArrayFilter<it_type>> {};
+ : public TypeTraits<data_type, ret, ElementTypeMapArrayFilter<it_type>> {
+ };
/* ------------------------------------------------------------------------ */
} // namespace dumpers
} // namespace akantu
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_DUMPER_TYPE_TRAITS_HH_ */
diff --git a/src/io/dumper/dumper_variable.hh b/src/io/dumper/dumper_variable.hh
index 42c362c51..a11e47ebf 100644
--- a/src/io/dumper/dumper_variable.hh
+++ b/src/io/dumper/dumper_variable.hh
@@ -1,121 +1,121 @@
/**
* @file dumper_variable.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Tue Jun 04 2013
* @date last modification: Wed Nov 08 2017
*
* @brief template of variable
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include <type_traits>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DUMPER_IOHELPER_TMPL_VARIABLE_HH_
#define AKANTU_DUMPER_IOHELPER_TMPL_VARIABLE_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace dumpers {
/* --------------------------------------------------------------------------
*/
/// Variable interface
class VariableBase {
public:
VariableBase() = default;
virtual ~VariableBase() = default;
virtual void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) = 0;
};
/* --------------------------------------------------------------------------
*/
template <typename T, bool is_scal = std::is_arithmetic<T>::value>
class Variable : public VariableBase {
public:
Variable(const T & t) : vari(t) {}
void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) override {
dumper.addVariable(id, *this);
}
- const T & operator[](UInt i) const { return vari[i]; }
+ const T & operator[](Idx i) const { return vari[i]; }
- UInt getDim() { return vari.size(); }
+ Int getDim() { return vari.size(); }
iohelper::DataType getDataType() { return iohelper::getDataType<T>(); }
protected:
const T & vari;
};
/* --------------------------------------------------------------------------
*/
template <typename T> class Variable<Vector<T>, false> : public VariableBase {
public:
Variable(const Vector<T> & t) : vari(t) {}
void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) override {
dumper.addVariable(id, *this);
}
- const T & operator[](UInt i) const { return vari[i]; }
+ const T & operator[](Idx i) const { return vari[i]; }
- UInt getDim() { return vari.size(); }
+ Int getDim() { return vari.size(); }
iohelper::DataType getDataType() { return iohelper::getDataType<T>(); }
protected:
const Vector<T> & vari;
};
/* --------------------------------------------------------------------------
*/
template <typename T> class Variable<T, true> : public VariableBase {
public:
Variable(const T & t) : vari(t) {}
void registerToDumper(const std::string & id,
iohelper::Dumper & dumper) override {
dumper.addVariable(id, *this);
}
- const T & operator[](__attribute__((unused)) UInt i) const { return vari; }
+ const T & operator[](Idx /*i*/) const { return vari; }
- UInt getDim() { return 1; }
+ Int getDim() { return 1; }
iohelper::DataType getDataType() { return iohelper::getDataType<T>(); }
protected:
const T & vari;
};
} // namespace dumpers
} // namespace akantu
#endif /* AKANTU_DUMPER_IOHELPER_TMPL_VARIABLE_HH_ */
diff --git a/src/io/mesh_io.cc b/src/io/mesh_io.cc
index 2b2679ff4..c121b172b 100644
--- a/src/io/mesh_io.cc
+++ b/src/io/mesh_io.cc
@@ -1,141 +1,141 @@
/**
* @file mesh_io.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jun 07 2019
*
* @brief common part for all mesh io classes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_io.hh"
#include "aka_common.hh"
#include "aka_iterators.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
MeshIO::MeshIO() {
canReadSurface = false;
canReadExtendedData = false;
}
/* -------------------------------------------------------------------------- */
MeshIO::~MeshIO() = default;
/* -------------------------------------------------------------------------- */
std::unique_ptr<MeshIO> MeshIO::getMeshIO(const std::string & filename,
const MeshIOType & type) {
MeshIOType t = type;
if (type == _miot_auto) {
std::string::size_type idx = filename.rfind('.');
std::string ext;
if (idx != std::string::npos) {
ext = filename.substr(idx + 1);
}
if (ext == "msh") {
t = _miot_gmsh;
} else if (ext == "diana") {
t = _miot_diana;
} else {
AKANTU_EXCEPTION("Cannot guess the type of file of "
<< filename << " (ext " << ext << "). "
<< "Please provide the MeshIOType to the read function");
}
}
switch (t) {
case _miot_gmsh:
return std::make_unique<MeshIOMSH>();
#if defined(AKANTU_STRUCTURAL_MECHANICS)
case _miot_gmsh_struct:
return std::make_unique<MeshIOMSHStruct>();
#endif
case _miot_diana:
return std::make_unique<MeshIODiana>();
default:
return nullptr;
}
}
/* -------------------------------------------------------------------------- */
void MeshIO::read(const std::string & filename, Mesh & mesh,
const MeshIOType & type) {
std::unique_ptr<MeshIO> mesh_io = getMeshIO(filename, type);
mesh_io->read(filename, mesh);
}
/* -------------------------------------------------------------------------- */
void MeshIO::write(const std::string & filename, Mesh & mesh,
const MeshIOType & type) {
std::unique_ptr<MeshIO> mesh_io = getMeshIO(filename, type);
mesh_io->write(filename, mesh);
}
/* -------------------------------------------------------------------------- */
void MeshIO::constructPhysicalNames(const std::string & tag_name, Mesh & mesh) {
if (not physical_names.empty()) {
for (auto type : mesh.elementTypes()) {
auto & name_vec =
mesh.getDataPointer<std::string>("physical_names", type);
- const auto & tags_vec = mesh.getData<UInt>(tag_name, type);
+ const auto & tags_vec = mesh.getData<Int>(tag_name, type);
for (auto && pair : zip(tags_vec, name_vec)) {
auto tag = std::get<0>(pair);
auto & name = std::get<1>(pair);
auto map_it = physical_names.find(tag);
if (map_it == physical_names.end()) {
std::stringstream sstm;
sstm << tag;
name = sstm.str();
} else {
name = map_it->second;
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void MeshIO::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
if (not physical_names.empty()) {
stream << space << "Physical map:" << std::endl;
for (const auto & pair : physical_names) {
stream << space << pair.first << ": " << pair.second << std::endl;
}
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/io/mesh_io/mesh_io_diana.cc b/src/io/mesh_io/mesh_io_diana.cc
index adea68462..2076a210a 100644
--- a/src/io/mesh_io/mesh_io_diana.cc
+++ b/src/io/mesh_io/mesh_io_diana.cc
@@ -1,612 +1,605 @@
/**
* @file mesh_io_diana.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Alodie Schneuwly <alodie.schneuwly@epfl.ch>
*
* @date creation: Sat Mar 26 2011
* @date last modification: Fri Feb 28 2020
*
* @brief handles diana meshes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "mesh_io_diana.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <string.h>
/* -------------------------------------------------------------------------- */
#include <stdio.h>
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Methods Implentations */
/* -------------------------------------------------------------------------- */
MeshIODiana::MeshIODiana() {
canReadSurface = true;
canReadExtendedData = true;
_diana_to_akantu_element_types["T9TM"] = _triangle_3;
_diana_to_akantu_element_types["CT6CM"] = _triangle_6;
_diana_to_akantu_element_types["Q12TM"] = _quadrangle_4;
_diana_to_akantu_element_types["CQ8CM"] = _quadrangle_8;
_diana_to_akantu_element_types["TP18L"] = _pentahedron_6;
_diana_to_akantu_element_types["CTP45"] = _pentahedron_15;
_diana_to_akantu_element_types["TE12L"] = _tetrahedron_4;
_diana_to_akantu_element_types["HX24L"] = _hexahedron_8;
_diana_to_akantu_element_types["CHX60"] = _hexahedron_20;
_diana_to_akantu_mat_prop["YOUNG"] = "E";
_diana_to_akantu_mat_prop["DENSIT"] = "rho";
_diana_to_akantu_mat_prop["POISON"] = "nu";
std::map<std::string, ElementType>::iterator it;
for (it = _diana_to_akantu_element_types.begin();
it != _diana_to_akantu_element_types.end(); ++it) {
- UInt nb_nodes = Mesh::getNbNodesPerElement(it->second);
+ Int nb_nodes = Mesh::getNbNodesPerElement(it->second);
- auto * tmp = new UInt[nb_nodes];
- for (UInt i = 0; i < nb_nodes; ++i) {
+ auto * tmp = new Idx[nb_nodes];
+ for (Int i = 0; i < nb_nodes; ++i) {
tmp[i] = i;
}
switch (it->second) {
case _tetrahedron_10:
tmp[8] = 9;
tmp[9] = 8;
break;
case _pentahedron_15:
tmp[0] = 2;
tmp[1] = 8;
tmp[2] = 0;
tmp[3] = 6;
tmp[4] = 1;
tmp[5] = 7;
tmp[6] = 11;
tmp[7] = 9;
tmp[8] = 10;
tmp[9] = 5;
tmp[10] = 14;
tmp[11] = 3;
tmp[12] = 12;
tmp[13] = 4;
tmp[14] = 13;
break;
case _hexahedron_20:
tmp[0] = 5;
tmp[1] = 16;
tmp[2] = 4;
tmp[3] = 19;
tmp[4] = 7;
tmp[5] = 18;
tmp[6] = 6;
tmp[7] = 17;
tmp[8] = 13;
tmp[9] = 12;
tmp[10] = 15;
tmp[11] = 14;
tmp[12] = 1;
tmp[13] = 8;
tmp[14] = 0;
tmp[15] = 11;
tmp[16] = 3;
tmp[17] = 10;
tmp[18] = 2;
tmp[19] = 9;
break;
default:
// nothing to change
break;
}
_read_order[it->second] = tmp;
}
}
/* -------------------------------------------------------------------------- */
MeshIODiana::~MeshIODiana() = default;
/* -------------------------------------------------------------------------- */
inline void my_getline(std::ifstream & infile, std::string & line) {
std::getline(infile, line); // read the line
size_t pos = line.find('\r'); /// remove the extra \\r if needed
line = line.substr(0, pos);
}
/* -------------------------------------------------------------------------- */
void MeshIODiana::read(const std::string & filename, Mesh & mesh) {
AKANTU_DEBUG_IN();
MeshAccessor mesh_accessor(mesh);
std::ifstream infile;
infile.open(filename.c_str());
std::string line;
- UInt first_node_number = std::numeric_limits<UInt>::max();
+ Idx first_node_number = std::numeric_limits<Idx>::max();
diana_element_number_to_elements.clear();
if (!infile.good()) {
AKANTU_ERROR("Cannot open file " << filename);
}
while (infile.good()) {
my_getline(infile, line);
/// read all nodes
if (line == "'COORDINATES'") {
line = readCoordinates(infile, mesh, first_node_number);
}
/// read all elements
if (line == "'ELEMENTS'") {
line = readElements(infile, mesh, first_node_number);
}
/// read the material properties and write a .dat file
if (line == "'MATERIALS'") {
line = readMaterial(infile, filename);
}
/// read the material properties and write a .dat file
if (line == "'GROUPS'") {
line = readGroups(infile, mesh, first_node_number);
}
}
infile.close();
mesh_accessor.setNbGlobalNodes(mesh.getNbNodes());
MeshUtils::fillElementToSubElementsData(mesh);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshIODiana::write(__attribute__((unused)) const std::string & filename,
__attribute__((unused)) const Mesh & mesh) {
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
std::string MeshIODiana::
readCoordinates( // NOLINT(readability-convert-member-functions-to-static)
- std::ifstream & infile, Mesh & mesh, UInt & first_node_number) {
+ std::ifstream & infile, Mesh & mesh, Idx & first_node_number) {
AKANTU_DEBUG_IN();
MeshAccessor mesh_accessor(mesh);
Array<Real> & nodes = mesh_accessor.getNodes();
std::string line;
- UInt index;
+ Idx index;
Vector<Real> coord(3);
do {
my_getline(infile, line);
if ("'ELEMENTS'" == line) {
break;
}
std::stringstream sstr_node(line);
sstr_node >> index >> coord(0) >> coord(1) >> coord(2);
first_node_number = first_node_number < index ? first_node_number : index;
nodes.push_back(coord);
} while (true);
AKANTU_DEBUG_OUT();
return line;
}
/* -------------------------------------------------------------------------- */
-UInt MeshIODiana::
- readInterval( // NOLINT(readability-convert-member-functions-to-static)
- std::stringstream & line, std::set<UInt> & interval) {
- UInt first;
+Idx MeshIODiana::readInterval(std::stringstream & line,
+ std::set<Idx> & interval) {
+ Idx first;
line >> first;
if (line.fail()) {
return 0;
}
interval.insert(first);
- UInt second;
+ Idx second;
int dash;
dash = line.get();
if (dash == '-') {
line >> second;
interval.insert(second);
return 2;
}
if (line.fail()) {
line.clear(std::ios::eofbit); // in case of get at end of the line
} else {
line.unget();
}
return 1;
}
/* -------------------------------------------------------------------------- */
std::string MeshIODiana::readGroups(std::ifstream & infile, Mesh & mesh,
- UInt first_node_number) {
+ Idx first_node_number) {
AKANTU_DEBUG_IN();
std::string line;
my_getline(infile, line);
bool reading_nodes_group = false;
while (line != "'SUPPORTS'") {
if (line == "NODES") {
reading_nodes_group = true;
my_getline(infile, line);
}
if (line == "ELEMEN") {
reading_nodes_group = false;
my_getline(infile, line);
}
auto * str = new std::stringstream(line);
- UInt id;
+ Idx id;
std::string name;
char c;
*str >> id >> name >> c;
- auto * list_ids = new Array<UInt>(0, 1, name);
+ auto * list_ids = new Array<Idx>(0, 1, name);
- UInt s = 1;
+ Idx s = 1;
bool end = false;
while (!end) {
while (!str->eof() && s != 0) {
- std::set<UInt> interval;
+ std::set<Idx> interval;
s = readInterval(*str, interval);
auto it = interval.begin();
if (s == 1) {
list_ids->push_back(*it);
}
if (s == 2) {
- UInt first = *it;
+ auto first = *it;
++it;
- UInt second = *it;
- for (UInt i = first; i <= second; ++i) {
+ auto second = *it;
+ for (auto i = first; i <= second; ++i) {
list_ids->push_back(i);
}
}
}
if (str->fail()) {
end = true;
} else {
my_getline(infile, line);
delete str;
str = new std::stringstream(line);
}
}
delete str;
if (reading_nodes_group) {
- NodeGroup & ng = mesh.createNodeGroup(name);
- for (UInt i = 0; i < list_ids->size(); ++i) {
- UInt node = (*list_ids)(i)-first_node_number;
+ auto & ng = mesh.createNodeGroup(name);
+ for (Int i = 0; i < list_ids->size(); ++i) {
+ auto node = (*list_ids)(i)-first_node_number;
ng.add(node, false);
}
delete list_ids;
} else {
- ElementGroup & eg = mesh.createElementGroup(name);
- for (UInt i = 0; i < list_ids->size(); ++i) {
- Element & elem = diana_element_number_to_elements[(*list_ids)(i)];
+ auto & eg = mesh.createElementGroup(name);
+ for (Int i = 0; i < list_ids->size(); ++i) {
+ auto & elem = diana_element_number_to_elements[(*list_ids)(i)];
if (elem.type != _not_defined) {
eg.add(elem, false, false);
}
}
eg.optimize();
delete list_ids;
}
my_getline(infile, line);
}
AKANTU_DEBUG_OUT();
return line;
}
/* -------------------------------------------------------------------------- */
std::string MeshIODiana::readElements(std::ifstream & infile, Mesh & mesh,
- UInt first_node_number) {
+ Idx first_node_number) {
AKANTU_DEBUG_IN();
std::string line;
my_getline(infile, line);
if ("CONNECTIVITY" == line) {
line = readConnectivity(infile, mesh, first_node_number);
}
/// read the line corresponding to the materials
if ("MATERIALS" == line) {
line = readMaterialElement(infile, mesh);
}
AKANTU_DEBUG_OUT();
return line;
}
/* -------------------------------------------------------------------------- */
std::string MeshIODiana::readConnectivity(std::ifstream & infile, Mesh & mesh,
- UInt first_node_number) {
+ Idx first_node_number) {
AKANTU_DEBUG_IN();
MeshAccessor mesh_accessor(mesh);
Int index;
std::string lline;
std::string diana_type;
- ElementType akantu_type;
- ElementType akantu_type_old = _not_defined;
- Array<UInt> * connectivity = nullptr;
- UInt node_per_element = 0;
+ ElementType akantu_type, akantu_type_old = _not_defined;
+ Array<Idx> * connectivity = nullptr;
+ Idx node_per_element = 0;
Element elem;
- UInt * read_order = nullptr;
+ Idx * read_order = nullptr;
while (true) {
my_getline(infile, lline);
// std::cerr << lline << std::endl;
std::stringstream sstr_elem(lline);
if (lline == "MATERIALS") {
break;
}
/// traiter les coordonnees
sstr_elem >> index;
sstr_elem >> diana_type;
akantu_type = _diana_to_akantu_element_types[diana_type];
if (akantu_type == _not_defined) {
continue;
}
if (akantu_type != akantu_type_old) {
connectivity = &(mesh_accessor.getConnectivity(akantu_type));
node_per_element = connectivity->getNbComponent();
akantu_type_old = akantu_type;
read_order = _read_order[akantu_type];
}
- Vector<UInt> local_connect(node_per_element);
+ Vector<Idx> local_connect(node_per_element);
// used if element is written on two lines
- UInt j_last = 0;
+ Int j_last = 0;
- for (UInt j = 0; j < node_per_element; ++j) {
- UInt node_index;
+ for (Int j = 0; j < node_per_element; ++j) {
+ Int node_index;
sstr_elem >> node_index;
// check s'il y a pas plus rien après un certain point
if (sstr_elem.fail()) {
sstr_elem.clear();
sstr_elem.ignore();
break;
}
node_index -= first_node_number;
local_connect(read_order[j]) = node_index;
j_last = j;
}
// check if element is written in two lines
if (j_last != (node_per_element - 1)) {
// if this is the case, read on more line
my_getline(infile, lline);
std::stringstream sstr_elem(lline);
- for (UInt j = (j_last + 1); j < node_per_element; ++j) {
+ for (auto j = (j_last + 1); j < node_per_element; ++j) {
- UInt node_index;
+ Int node_index;
sstr_elem >> node_index;
node_index -= first_node_number;
local_connect(read_order[j]) = node_index;
}
}
connectivity->push_back(local_connect);
elem.type = akantu_type;
elem.element = connectivity->size() - 1;
diana_element_number_to_elements[index] = elem;
akantu_number_to_diana_number[elem] = index;
}
AKANTU_DEBUG_OUT();
return lline;
}
/* -------------------------------------------------------------------------- */
std::string MeshIODiana::readMaterialElement(std::ifstream & infile,
Mesh & mesh) {
- AKANTU_DEBUG_IN();
-
std::string line;
for (auto type : mesh.elementTypes()) {
- UInt nb_element = mesh.getNbElement(type);
- mesh.getDataPointer<UInt>("material", type, _not_ghost, 1)
+ auto nb_element = mesh.getNbElement(type);
+ mesh.getDataPointer<Int>("material", type, _not_ghost, 1)
.resize(nb_element);
}
my_getline(infile, line);
while (line != "'MATERIALS'") {
line =
line.substr(line.find('/') + 1,
std::string::npos); // erase the first slash / of the line
char tutu[250] = {'\0'};
strncpy(tutu, line.c_str(), 249);
AKANTU_DEBUG_WARNING("reading line " << line);
- Array<UInt> temp_id(0, 2);
- UInt mat;
+ Array<Int> temp_id(0, 2);
+ Int mat;
while (true) {
std::stringstream sstr_intervals_elements(line);
- Vector<UInt> id(2);
+ Vector<Int> id(2);
char temp;
while (sstr_intervals_elements.good()) {
sstr_intervals_elements >> id(0) >> temp >> id(1); // >> "/" >> mat;
if (!sstr_intervals_elements.fail()) {
temp_id.push_back(id);
}
}
if (sstr_intervals_elements.fail()) {
sstr_intervals_elements.clear();
sstr_intervals_elements.ignore();
sstr_intervals_elements >> mat;
break;
}
my_getline(infile, line);
}
// loop over elements
- // UInt * temp_id_val = temp_id.storage();
- for (UInt i = 0; i < temp_id.size(); ++i) {
- for (UInt j = temp_id(i, 0); j <= temp_id(i, 1); ++j) {
- Element & element = diana_element_number_to_elements[j];
+ // Idx * temp_id_val = temp_id.data();
+ for (Int i = 0; i < temp_id.size(); ++i) {
+ for (Int j = temp_id(i, 0); j <= temp_id(i, 1); ++j) {
+ auto & element = diana_element_number_to_elements[j];
if (element.type == _not_defined) {
continue;
}
- UInt elem = element.element;
- ElementType type = element.type;
- Array<UInt> & data =
- mesh.getDataPointer<UInt>("material", type, _not_ghost);
+ auto elem = element.element;
+ auto type = element.type;
+ auto & data = mesh.getDataPointer<Int>("material", type, _not_ghost);
data(elem) = mat;
}
}
my_getline(infile, line);
}
- AKANTU_DEBUG_OUT();
return line;
}
/* -------------------------------------------------------------------------- */
std::string MeshIODiana::readMaterial(std::ifstream & infile,
const std::string & filename) {
AKANTU_DEBUG_IN();
std::stringstream mat_file_name;
mat_file_name << "material_" << filename;
std::ofstream material_file;
material_file.open(mat_file_name.str().c_str()); // mat_file_name.str());
- UInt mat_index;
+ Idx mat_index;
std::string line;
- bool first_mat = true;
- bool end = false;
+ auto first_mat = true;
+ auto end = false;
- UInt mat_id = 0;
+ Idx mat_id = 0;
using MatProp = std::map<std::string, Real>;
MatProp mat_prop;
do {
my_getline(infile, line);
std::stringstream sstr_material(line);
if (("'GROUPS'" == line) || ("'END'" == line)) {
if (!mat_prop.empty()) {
material_file << "material elastic [" << std::endl;
material_file << "\tname = material" << ++mat_id << std::endl;
for (auto it = mat_prop.begin(); it != mat_prop.end(); ++it) {
material_file << "\t" << it->first << " = " << it->second
<< std::endl;
}
material_file << "]" << std::endl;
mat_prop.clear();
}
end = true;
} else {
/// traiter les caractéristiques des matériaux
sstr_material >> mat_index;
if (!sstr_material.fail()) {
if (!first_mat) {
if (!mat_prop.empty()) {
material_file << "material elastic [" << std::endl;
material_file << "\tname = material" << ++mat_id << std::endl;
for (auto it = mat_prop.begin(); it != mat_prop.end(); ++it) {
material_file << "\t" << it->first << " = " << it->second
<< std::endl;
}
material_file << "]" << std::endl;
mat_prop.clear();
}
}
first_mat = false;
} else {
sstr_material.clear();
}
std::string prop_name;
sstr_material >> prop_name;
- std::map<std::string, std::string>::iterator it;
- it = _diana_to_akantu_mat_prop.find(prop_name);
+ auto it = _diana_to_akantu_mat_prop.find(prop_name);
if (it != _diana_to_akantu_mat_prop.end()) {
Real value;
sstr_material >> value;
mat_prop[it->second] = value;
} else {
AKANTU_DEBUG_INFO("In material reader, property " << prop_name
<< "not recognized");
}
}
} while (!end);
AKANTU_DEBUG_OUT();
return line;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/io/mesh_io/mesh_io_diana.hh b/src/io/mesh_io/mesh_io_diana.hh
index 0d4d06442..f775da891 100644
--- a/src/io/mesh_io/mesh_io_diana.hh
+++ b/src/io/mesh_io/mesh_io_diana.hh
@@ -1,109 +1,109 @@
/**
* @file mesh_io_diana.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Alodie Schneuwly <alodie.schneuwly@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Nov 08 2017
*
* @brief diana mesh reader description
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_IO_DIANA_HH_
#define AKANTU_MESH_IO_DIANA_HH_
/* -------------------------------------------------------------------------- */
#include "mesh_io.hh"
/* -------------------------------------------------------------------------- */
#include <vector>
/* -------------------------------------------------------------------------- */
namespace akantu {
class MeshIODiana : public MeshIO {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MeshIODiana();
~MeshIODiana() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// read a mesh from the file
void read(const std::string & filename, Mesh & mesh) override;
/// write a mesh to a file
void write(const std::string & filename, const Mesh & mesh) override;
private:
std::string readCoordinates(std::ifstream & infile, Mesh & mesh,
- UInt & first_node_number);
+ Idx & first_node_number);
std::string readElements(std::ifstream & infile, Mesh & mesh,
- UInt first_node_number);
+ Idx first_node_number);
std::string readGroups(std::ifstream & infile, Mesh & mesh,
- UInt first_node_number);
+ Idx first_node_number);
std::string readConnectivity(std::ifstream & infile, Mesh & mesh,
- UInt first_node_number);
+ Idx first_node_number);
std::string readMaterialElement(std::ifstream & infile, Mesh & mesh);
std::string readMaterial(std::ifstream & infile,
const std::string & filename);
- UInt readInterval(std::stringstream & line, std::set<UInt> & interval);
+ Idx readInterval(std::stringstream & line, std::set<Idx> & interval);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
std::map<std::string, ElementType> _diana_to_akantu_element_types;
std::map<std::string, std::string> _diana_to_akantu_mat_prop;
/// order in witch element as to be read, akantu_node_order =
/// _read_order[diana_node_order]
- std::map<ElementType, UInt *> _read_order;
+ std::map<ElementType, Int *> _read_order;
std::map<UInt, Element> diana_element_number_to_elements;
- std::map<Element, UInt> akantu_number_to_diana_number;
+ std::map<Element, Int> akantu_number_to_diana_number;
};
} // namespace akantu
#endif /* AKANTU_MESH_IO_DIANA_HH_ */
diff --git a/src/io/mesh_io/mesh_io_msh.cc b/src/io/mesh_io/mesh_io_msh.cc
index 2681903be..36a8a9b1d 100644
--- a/src/io/mesh_io/mesh_io_msh.cc
+++ b/src/io/mesh_io/mesh_io_msh.cc
@@ -1,1133 +1,1126 @@
/**
* @file mesh_io_msh.cc
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Oct 29 2020
*
* @brief Read/Write for MSH files generated by gmsh
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -----------------------------------------------------------------------------
Version (Legacy) 1.0
$NOD
number-of-nodes
node-number x-coord y-coord z-coord
...
$ENDNOD
$ELM
number-of-elements
elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list
...
$ENDELM
-----------------------------------------------------------------------------
Version 2.1
$MeshFormat
version-number file-type data-size
$EndMeshFormat
$Nodes
number-of-nodes
node-number x-coord y-coord z-coord
...
$EndNodes
$Elements
number-of-elements
elm-number elm-type number-of-tags < tag > ... node-number-list
...
$EndElements
$PhysicalNames
number-of-names
physical-dimension physical-number "physical-name"
...
$EndPhysicalNames
$NodeData
number-of-string-tags
< "string-tag" >
...
number-of-real-tags
< real-tag >
...
number-of-integer-tags
< integer-tag >
...
node-number value ...
...
$EndNodeData
$ElementData
number-of-string-tags
< "string-tag" >
...
number-of-real-tags
< real-tag >
...
number-of-integer-tags
< integer-tag >
...
elm-number value ...
...
$EndElementData
$ElementNodeData
number-of-string-tags
< "string-tag" >
...
number-of-real-tags
< real-tag >
...
number-of-integer-tags
< integer-tag >
...
elm-number number-of-nodes-per-element value ...
...
$ElementEndNodeData
-----------------------------------------------------------------------------
elem-type
1: 2-node line.
2: 3-node triangle.
3: 4-node quadrangle.
4: 4-node tetrahedron.
5: 8-node hexahedron.
6: 6-node prism.
7: 5-node pyramid.
8: 3-node second order line
9: 6-node second order triangle
10: 9-node second order quadrangle
11: 10-node second order tetrahedron
12: 27-node second order hexahedron
13: 18-node second order prism
14: 14-node second order pyramid
15: 1-node point.
16: 8-node second order quadrangle
17: 20-node second order hexahedron
18: 15-node second order prism
19: 13-node second order pyramid
20: 9-node third order incomplete triangle
21: 10-node third order triangle
22: 12-node fourth order incomplete triangle
23: 15-node fourth order triangle
24: 15-node fifth order incomplete triangle
25: 21-node fifth order complete triangle
26: 4-node third order edge
27: 5-node fourth order edge
28: 6-node fifth order edge
29: 20-node third order tetrahedron
30: 35-node fourth order tetrahedron
31: 56-node fifth order tetrahedron
-------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "mesh_io.hh"
#include "mesh_utils.hh"
#include "node_group.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Methods Implentations */
/* -------------------------------------------------------------------------- */
MeshIOMSH::MeshIOMSH() {
canReadSurface = true;
canReadExtendedData = true;
_msh_nodes_per_elem[_msh_not_defined] = 0;
_msh_nodes_per_elem[_msh_segment_2] = 2;
_msh_nodes_per_elem[_msh_triangle_3] = 3;
_msh_nodes_per_elem[_msh_quadrangle_4] = 4;
_msh_nodes_per_elem[_msh_tetrahedron_4] = 4;
_msh_nodes_per_elem[_msh_hexahedron_8] = 8;
_msh_nodes_per_elem[_msh_prism_1] = 6;
_msh_nodes_per_elem[_msh_pyramid_1] = 1;
_msh_nodes_per_elem[_msh_segment_3] = 3;
_msh_nodes_per_elem[_msh_triangle_6] = 6;
_msh_nodes_per_elem[_msh_quadrangle_9] = 9;
_msh_nodes_per_elem[_msh_tetrahedron_10] = 10;
_msh_nodes_per_elem[_msh_hexahedron_27] = 27;
_msh_nodes_per_elem[_msh_hexahedron_20] = 20;
_msh_nodes_per_elem[_msh_prism_18] = 18;
_msh_nodes_per_elem[_msh_prism_15] = 15;
_msh_nodes_per_elem[_msh_pyramid_14] = 14;
_msh_nodes_per_elem[_msh_point] = 1;
_msh_nodes_per_elem[_msh_quadrangle_8] = 8;
_msh_to_akantu_element_types[_msh_not_defined] = _not_defined;
_msh_to_akantu_element_types[_msh_segment_2] = _segment_2;
_msh_to_akantu_element_types[_msh_triangle_3] = _triangle_3;
_msh_to_akantu_element_types[_msh_quadrangle_4] = _quadrangle_4;
_msh_to_akantu_element_types[_msh_tetrahedron_4] = _tetrahedron_4;
_msh_to_akantu_element_types[_msh_hexahedron_8] = _hexahedron_8;
_msh_to_akantu_element_types[_msh_prism_1] = _pentahedron_6;
_msh_to_akantu_element_types[_msh_pyramid_1] = _not_defined;
_msh_to_akantu_element_types[_msh_segment_3] = _segment_3;
_msh_to_akantu_element_types[_msh_triangle_6] = _triangle_6;
_msh_to_akantu_element_types[_msh_quadrangle_9] = _not_defined;
_msh_to_akantu_element_types[_msh_tetrahedron_10] = _tetrahedron_10;
_msh_to_akantu_element_types[_msh_hexahedron_27] = _not_defined;
_msh_to_akantu_element_types[_msh_hexahedron_20] = _hexahedron_20;
_msh_to_akantu_element_types[_msh_prism_18] = _not_defined;
_msh_to_akantu_element_types[_msh_prism_15] = _pentahedron_15;
_msh_to_akantu_element_types[_msh_pyramid_14] = _not_defined;
_msh_to_akantu_element_types[_msh_point] = _point_1;
_msh_to_akantu_element_types[_msh_quadrangle_8] = _quadrangle_8;
_akantu_to_msh_element_types[_not_defined] = _msh_not_defined;
_akantu_to_msh_element_types[_segment_2] = _msh_segment_2;
_akantu_to_msh_element_types[_segment_3] = _msh_segment_3;
_akantu_to_msh_element_types[_triangle_3] = _msh_triangle_3;
_akantu_to_msh_element_types[_triangle_6] = _msh_triangle_6;
_akantu_to_msh_element_types[_tetrahedron_4] = _msh_tetrahedron_4;
_akantu_to_msh_element_types[_tetrahedron_10] = _msh_tetrahedron_10;
_akantu_to_msh_element_types[_quadrangle_4] = _msh_quadrangle_4;
_akantu_to_msh_element_types[_quadrangle_8] = _msh_quadrangle_8;
_akantu_to_msh_element_types[_hexahedron_8] = _msh_hexahedron_8;
_akantu_to_msh_element_types[_hexahedron_20] = _msh_hexahedron_20;
_akantu_to_msh_element_types[_pentahedron_6] = _msh_prism_1;
_akantu_to_msh_element_types[_pentahedron_15] = _msh_prism_15;
_akantu_to_msh_element_types[_point_1] = _msh_point;
#if defined(AKANTU_STRUCTURAL_MECHANICS)
_akantu_to_msh_element_types[_bernoulli_beam_2] = _msh_segment_2;
_akantu_to_msh_element_types[_bernoulli_beam_3] = _msh_segment_2;
_akantu_to_msh_element_types[_discrete_kirchhoff_triangle_18] =
_msh_triangle_3;
#endif
std::map<ElementType, MSHElementType>::iterator it;
for (it = _akantu_to_msh_element_types.begin();
it != _akantu_to_msh_element_types.end(); ++it) {
- UInt nb_nodes = _msh_nodes_per_elem[it->second];
+ Int nb_nodes = _msh_nodes_per_elem[it->second];
- std::vector<UInt> tmp(nb_nodes);
- for (UInt i = 0; i < nb_nodes; ++i) {
+ std::vector<Idx> tmp(nb_nodes);
+ for (Int i = 0; i < nb_nodes; ++i) {
tmp[i] = i;
}
switch (it->first) {
case _tetrahedron_10:
tmp[8] = 9;
tmp[9] = 8;
break;
case _pentahedron_6:
tmp[0] = 2;
tmp[1] = 0;
tmp[2] = 1;
tmp[3] = 5;
tmp[4] = 3;
tmp[5] = 4;
break;
case _pentahedron_15:
tmp[0] = 2;
tmp[1] = 0;
tmp[2] = 1;
tmp[3] = 5;
tmp[4] = 3;
tmp[5] = 4;
tmp[6] = 8;
tmp[8] = 11;
tmp[9] = 6;
tmp[10] = 9;
tmp[11] = 10;
tmp[12] = 14;
tmp[14] = 12;
break;
case _hexahedron_20:
tmp[9] = 11;
tmp[10] = 12;
tmp[11] = 9;
tmp[12] = 13;
tmp[13] = 10;
tmp[17] = 19;
tmp[18] = 17;
tmp[19] = 18;
break;
default:
// nothing to change
break;
}
_read_order[it->first] = tmp;
}
}
/* -------------------------------------------------------------------------- */
MeshIOMSH::~MeshIOMSH() = default;
/* -------------------------------------------------------------------------- */
namespace {
struct File {
std::string filename;
std::ifstream infile;
std::string line;
- size_t current_line{0};
+ std::size_t current_line{0};
- size_t first_node_number{std::numeric_limits<UInt>::max()},
+ std::size_t first_node_number{std::numeric_limits<std::size_t>::max()},
last_node_number{0};
bool has_physical_names{false};
std::unordered_map<size_t, size_t> node_tags;
std::unordered_map<size_t, Element> element_tags;
int version{0};
int size_of_size_t{0};
Mesh & mesh;
MeshAccessor mesh_accessor;
std::multimap<std::pair<int, int>, int> entity_tag_to_physical_tags;
File(const std::string & filename, Mesh & mesh)
: filename(filename), mesh(mesh), mesh_accessor(mesh) {
infile.open(filename.c_str());
if (not infile.good()) {
AKANTU_EXCEPTION("Cannot open file " << filename);
}
}
~File() { infile.close(); }
auto good() { return infile.good(); }
std::stringstream get_line() {
std::string tmp_str;
if (infile.eof()) {
AKANTU_EXCEPTION("Reached the end of the file " << filename);
}
std::getline(infile, tmp_str);
line = trim(tmp_str);
++current_line;
return std::stringstream(line);
}
template <typename... Ts> void read_line(Ts &&... ts) {
auto && sstr = get_line();
(void)std::initializer_list<int>{
(sstr >> std::forward<decltype(ts)>(ts), 0)...};
}
};
} // namespace
/* -------------------------------------------------------------------------- */
template <typename File, typename Readers>
void MeshIOMSH::populateReaders2(File & file, Readers & readers) {
readers["$NOD"] = readers["$Nodes"] = [&](const std::string & /*unused*/) {
UInt nb_nodes;
file.read_line(nb_nodes);
Array<Real> & nodes = file.mesh_accessor.getNodes();
nodes.resize(nb_nodes);
file.mesh_accessor.setNbGlobalNodes(nb_nodes);
size_t index;
Vector<double> coord(3);
/// for each node, read the coordinates
for (auto && data : enumerate(make_view(nodes, nodes.getNbComponent()))) {
file.read_line(index, coord(0), coord(1), coord(2));
if (index > std::numeric_limits<UInt>::max()) {
AKANTU_EXCEPTION(
"There are more nodes in this files than the index type of akantu "
"can handle, consider recompiling with a bigger index type");
}
file.first_node_number = std::min(file.first_node_number, index);
file.last_node_number = std::max(file.last_node_number, index);
for (auto && coord_data : zip(std::get<1>(data), coord)) {
std::get<0>(coord_data) = std::get<1>(coord_data);
}
file.node_tags[index] = std::get<0>(data);
}
};
readers["$ELM"] = readers["$Elements"] = [&](const std::string & /*unused*/) {
- UInt nb_elements;
+ Int nb_elements;
file.read_line(nb_elements);
Int index;
UInt msh_type;
ElementType akantu_type;
- for (UInt i = 0; i < nb_elements; ++i) {
+ for (Int i = 0; i < nb_elements; ++i) {
auto && sstr_elem = file.get_line();
sstr_elem >> index;
sstr_elem >> msh_type;
/// get the connectivity vector depending on the element type
akantu_type =
this->_msh_to_akantu_element_types[MSHElementType(msh_type)];
if (akantu_type == _not_defined) {
AKANTU_DEBUG_WARNING("Unsuported element kind "
<< msh_type << " at line " << file.current_line);
continue;
}
Element elem{akantu_type, 0, _not_ghost};
auto & connectivity = file.mesh_accessor.getConnectivity(akantu_type);
auto node_per_element = connectivity.getNbComponent();
auto & read_order = this->_read_order[akantu_type];
/// read tags informations
if (file.version < 2000) {
Int tag0;
Int tag1;
Int nb_nodes; // reg-phys, reg-elem, number-of-nodes
sstr_elem >> tag0 >> tag1 >> nb_nodes;
auto & data0 =
- file.mesh_accessor.template getData<UInt>("tag_0", akantu_type);
+ file.mesh_accessor.template getData<Int>("tag_0", akantu_type);
data0.push_back(tag0);
auto & data1 =
- file.mesh_accessor.template getData<UInt>("tag_1", akantu_type);
+ file.mesh_accessor.template getData<Int>("tag_1", akantu_type);
data1.push_back(tag1);
} else if (file.version < 4000) {
- UInt nb_tags;
+ Int nb_tags;
sstr_elem >> nb_tags;
- for (UInt j = 0; j < nb_tags; ++j) {
+ for (Int j = 0; j < nb_tags; ++j) {
Int tag;
sstr_elem >> tag;
- auto & data = file.mesh_accessor.template getData<UInt>(
+ auto & data = file.mesh_accessor.template getData<Int>(
"tag_" + std::to_string(j), akantu_type);
data.push_back(tag);
}
}
- Vector<UInt> local_connect(node_per_element);
- for (UInt j = 0; j < node_per_element; ++j) {
- UInt node_index;
+ Vector<Idx> local_connect(node_per_element);
+ for (Int j = 0; j < node_per_element; ++j) {
+ Int node_index;
sstr_elem >> node_index;
- AKANTU_DEBUG_ASSERT(node_index <= file.last_node_number,
+ AKANTU_DEBUG_ASSERT(node_index <= Int(file.last_node_number),
"Node number not in range : line "
<< file.current_line);
local_connect(read_order[j]) = file.node_tags[node_index];
}
connectivity.push_back(local_connect);
elem.element = connectivity.size() - 1;
file.element_tags[index] = elem;
}
};
- readers["$Periodic"] = [&](const std::string & /*unused*/) {
- UInt nb_periodic_entities;
+ readers["$Periodic"] = [&](const std::string &) {
+ Int nb_periodic_entities;
file.read_line(nb_periodic_entities);
file.mesh_accessor.getNodesFlags().resize(file.mesh.getNbNodes(),
NodeFlag::_normal);
- for (UInt p = 0; p < nb_periodic_entities; ++p) {
+ for (Int p = 0; p < nb_periodic_entities; ++p) {
// dimension slave-tag master-tag
- UInt dimension;
+ Int dimension;
file.read_line(dimension);
// transformation
file.get_line();
// nb nodes
- UInt nb_nodes;
+ Int nb_nodes;
file.read_line(nb_nodes);
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
// slave master
auto && sstr = file.get_line();
// The info in the mesh seem inconsistent so they are ignored for now.
continue;
if (dimension == file.mesh.getSpatialDimension() - 1) {
- UInt slave;
- UInt master;
+ Idx slave, master;
sstr >> slave;
sstr >> master;
file.mesh_accessor.addPeriodicSlave(file.node_tags[slave],
file.node_tags[master]);
}
}
}
// mesh_accessor.markMeshPeriodic();
};
}
/* -------------------------------------------------------------------------- */
template <typename File, typename Readers>
void MeshIOMSH::populateReaders4(File & file, Readers & readers) {
static std::map<int, std::string> entity_type{
{0, "points"},
{1, "curve"},
{2, "surface"},
{3, "volume"},
};
readers["$Entities"] = [&](const std::string & /*unused*/) {
size_t num_entity[4];
file.read_line(num_entity[0], num_entity[1], num_entity[2], num_entity[3]);
for (auto entity_dim : arange(4)) {
for (auto _ [[gnu::unused]] : arange(num_entity[entity_dim])) {
auto && sstr = file.get_line();
int tag;
double min_x;
double min_y;
double min_z;
double max_x;
double max_y;
double max_z;
size_t num_physical_tags;
sstr >> tag >> min_x >> min_y >> min_z;
if (entity_dim > 0 or file.version < 4001) {
sstr >> max_x >> max_y >> max_z;
}
sstr >> num_physical_tags;
for (auto _ [[gnu::unused]] : arange(num_physical_tags)) {
int phys_tag;
sstr >> phys_tag;
std::string physical_name;
if (this->physical_names.find(phys_tag) ==
this->physical_names.end()) {
physical_name = "msh_block_" + std::to_string(phys_tag);
} else {
physical_name = this->physical_names[phys_tag];
}
if (not file.mesh.elementGroupExists(physical_name)) {
file.mesh.createElementGroup(physical_name, entity_dim);
} else {
file.mesh.getElementGroup(physical_name).addDimension(entity_dim);
}
file.entity_tag_to_physical_tags.insert(
std::make_pair(std::make_pair(tag, entity_dim), phys_tag));
}
}
}
};
readers["$Nodes"] = [&](const std::string & /*unused*/) {
size_t num_blocks;
size_t num_nodes;
if (file.version >= 4001) {
file.read_line(num_blocks, num_nodes, file.first_node_number,
file.last_node_number);
} else {
file.read_line(num_blocks, num_nodes);
}
auto & nodes = file.mesh_accessor.getNodes();
nodes.reserve(num_nodes);
file.mesh_accessor.setNbGlobalNodes(num_nodes);
if (num_nodes > std::numeric_limits<UInt>::max()) {
AKANTU_EXCEPTION(
"There are more nodes in this files than the index type of akantu "
"can handle, consider recompiling with a bigger index type");
}
size_t node_id{0};
+ auto dim = nodes.getNbComponent();
+
for (auto block [[gnu::unused]] : arange(num_blocks)) {
int entity_dim;
int entity_tag;
int parametric;
size_t num_nodes_in_block;
Vector<double> pos(3);
- Vector<double> real_pos(nodes.getNbComponent());
if (file.version >= 4001) {
file.read_line(entity_dim, entity_tag, parametric, num_nodes_in_block);
if (parametric) {
AKANTU_EXCEPTION(
"Akantu does not support parametric nodes in msh files");
}
for (auto _ [[gnu::unused]] : arange(num_nodes_in_block)) {
size_t tag;
file.read_line(tag);
file.node_tags[tag] = node_id;
++node_id;
}
for (auto _ [[gnu::unused]] : arange(num_nodes_in_block)) {
file.read_line(pos(_x), pos(_y), pos(_z));
- for (auto && data : zip(real_pos, pos)) {
- std::get<0>(data) = std::get<1>(data);
- }
-
- nodes.push_back(real_pos);
+ nodes.push_back(pos.block(0, 0, dim, 1));
}
} else {
file.read_line(entity_tag, entity_dim, parametric, num_nodes_in_block);
for (auto _ [[gnu::unused]] : arange(num_nodes_in_block)) {
size_t tag;
file.read_line(tag, pos(_x), pos(_y), pos(_z));
file.first_node_number = std::min(file.first_node_number, tag);
file.last_node_number = std::max(file.last_node_number, tag);
- for (auto && data : zip(real_pos, pos)) {
- std::get<0>(data) = std::get<1>(data);
- }
+ nodes.push_back(pos.block(0, 0, dim, 1));
- nodes.push_back(real_pos);
file.node_tags[tag] = node_id;
++node_id;
}
}
}
};
readers["$Elements"] = [&](const std::string & /*unused*/) {
size_t num_blocks;
size_t num_elements;
file.read_line(num_blocks, num_elements);
for (auto block [[gnu::unused]] : arange(num_blocks)) {
int entity_dim;
int entity_tag;
int element_type;
size_t num_elements_in_block;
if (file.version >= 4001) {
file.read_line(entity_dim, entity_tag, element_type,
num_elements_in_block);
} else {
file.read_line(entity_tag, entity_dim, element_type,
num_elements_in_block);
}
/// get the connectivity vector depending on the element type
auto && akantu_type =
this->_msh_to_akantu_element_types[(MSHElementType)element_type];
if (akantu_type == _not_defined) {
AKANTU_DEBUG_WARNING("Unsuported element kind " << element_type
<< " at line "
<< file.current_line);
continue;
}
Element elem{akantu_type, 0, _not_ghost};
auto & connectivity = file.mesh_accessor.getConnectivity(akantu_type);
- Vector<UInt> local_connect(connectivity.getNbComponent());
+ Vector<Idx> local_connect(connectivity.getNbComponent());
auto && read_order = this->_read_order[akantu_type];
auto & data0 =
- file.mesh_accessor.template getData<UInt>("tag_0", akantu_type);
+ file.mesh_accessor.template getData<Idx>("tag_0", akantu_type);
data0.resize(data0.size() + num_elements_in_block, 0);
auto range = file.entity_tag_to_physical_tags.equal_range(
std::make_pair(entity_tag, entity_dim));
auto & physical_data = file.mesh_accessor.template getData<std::string>(
"physical_names", akantu_type);
physical_data.resize(physical_data.size() + num_elements_in_block, "");
for (auto _ [[gnu::unused]] : arange(num_elements_in_block)) {
auto && sstr_elem = file.get_line();
- size_t elem_tag;
+ std::size_t elem_tag;
sstr_elem >> elem_tag;
for (auto && c : arange(connectivity.getNbComponent())) {
- size_t node_tag;
+ std::size_t node_tag;
sstr_elem >> node_tag;
AKANTU_DEBUG_ASSERT(node_tag >= file.first_node_number,
"Node number not in range : line "
<< file.current_line);
AKANTU_DEBUG_ASSERT(node_tag <= file.last_node_number,
"Node number not in range : line "
<< file.current_line);
node_tag = file.node_tags[node_tag];
local_connect(read_order[c]) = node_tag;
}
connectivity.push_back(local_connect);
elem.element = connectivity.size() - 1;
file.element_tags[elem_tag] = elem;
bool first = true;
for (auto it = range.first; it != range.second; ++it) {
auto phys_it = this->physical_names.find(it->second);
if (first) {
data0(elem.element) =
it->second; // for compatibility with version 2
if (phys_it != this->physical_names.end()) {
physical_data(elem.element) = phys_it->second;
}
first = false;
}
if (phys_it != this->physical_names.end()) {
file.mesh.getElementGroup(phys_it->second).add(elem, true, false);
}
}
}
}
for (auto && element_group : file.mesh.iterateElementGroups()) {
element_group.getNodeGroup().optimize();
}
};
}
/* -------------------------------------------------------------------------- */
void MeshIOMSH::read(const std::string & filename, Mesh & mesh) {
File file(filename, mesh);
std::map<std::string, std::function<void(const std::string &)>> readers;
readers["$MeshFormat"] = [&](const std::string & /*unused*/) {
auto && sstr = file.get_line();
double version;
int format;
sstr >> version >> format;
int major = std::trunc(version);
int minor = std::round(10 * (version - major));
file.version = major * 1000 + minor;
if (format != 0) {
AKANTU_ERROR("This reader can only read ASCII files.");
}
if (file.version > 2000) {
sstr >> file.size_of_size_t;
if (file.size_of_size_t > int(sizeof(UInt))) {
AKANTU_DEBUG_INFO("The size of the indexes in akantu might be to small "
"to read this file (akantu "
<< sizeof(UInt) << " vs. msh file "
<< file.size_of_size_t << ")");
}
}
if (file.version < 4000) {
this->populateReaders2(file, readers);
} else {
this->populateReaders4(file, readers);
}
};
auto && read_data = [&](auto && entity_tags, auto && get_data,
auto && read_data) {
auto read_data_tags = [&](auto x) {
UInt number_of_tags{0};
file.read_line(number_of_tags);
std::vector<decltype(x)> tags(number_of_tags);
for (auto && tag : tags) {
file.read_line(tag);
}
return tags;
};
auto && string_tags = read_data_tags(std::string{});
auto && real_tags [[gnu::unused]] = read_data_tags(double{});
auto && int_tags = read_data_tags(int{});
for (auto & s : string_tags) {
s = trim(s, '"');
}
auto id = string_tags[0];
auto size = int_tags[2];
auto nb_component = int_tags[1];
auto & data = get_data(id, size, nb_component);
for (auto n [[gnu::unused]] : arange(size)) {
auto && sstr = file.get_line();
size_t tag;
sstr >> tag;
const auto & entity = entity_tags[tag];
read_data(entity, sstr, data, nb_component);
}
};
readers["$NodeData"] = [&](const std::string & /*unused*/) {
/* $NodeData
numStringTags(ASCII int)
stringTag(string) ...
numRealTags(ASCII int)
realTag(ASCII double) ...
numIntegerTags(ASCII int)
integerTag(ASCII int) ...
nodeTag(size_t) value(double) ...
...
$EndNodeData */
read_data(
file.node_tags,
[&](auto && id, auto && size [[gnu::unused]],
auto && nb_component [[gnu::unused]]) -> Array<double> & {
auto & data =
file.mesh.template getNodalData<double>(id, nb_component);
data.resize(size);
return data;
},
[&](auto && node, auto && sstr, auto && data,
auto && nb_component [[gnu::unused]]) {
for (auto c : arange(nb_component)) {
sstr >> data(node, c);
}
});
};
readers["$ElementData"] = [&](const std::string & /*unused*/) {
/* $ElementData
numStringTags(ASCII int)
stringTag(string) ...
numRealTags(ASCII int)
realTag(ASCII double) ...
numIntegerTags(ASCII int)
integerTag(ASCII int) ...
elementTag(size_t) value(double) ...
...
$EndElementData
*/
read_data(
file.element_tags,
[&](auto && id, auto && size [[gnu::unused]],
auto && nb_component
[[gnu::unused]]) -> ElementTypeMapArray<double> & {
file.mesh.template getElementalData<double>(id);
return file.mesh.template getElementalData<double>(id);
},
[&](auto && element, auto && sstr, auto && data, auto && nb_component) {
if (not data.exists(element.type)) {
data.alloc(mesh.getNbElement(element.type), nb_component,
element.type, element.ghost_type);
}
auto & data_array = data(element.type);
for (auto c : arange(nb_component)) {
sstr >> data_array(element.element, c);
}
});
};
readers["$ElementNodeData"] = [&](const std::string & /*unused*/) {
/* $ElementNodeData
numStringTags(ASCII int)
stringTag(string) ...
numRealTags(ASCII int)
realTag(ASCII double) ...
numIntegerTags(ASCII int)
integerTag(ASCII int) ...
elementTag(size_t) value(double) ...
...
$EndElementNodeData
*/
read_data(
file.element_tags,
[&](auto && id, auto && size [[gnu::unused]],
auto && nb_component
[[gnu::unused]]) -> ElementTypeMapArray<double> & {
file.mesh.template getElementalData<double>(id);
auto & data = file.mesh.template getElementalData<double>(id);
data.isNodal(true);
return data;
},
[&](auto && element, auto && sstr, auto && data, auto && nb_component) {
int nb_nodes_per_element;
sstr >> nb_nodes_per_element;
if (not data.exists(element.type)) {
data.alloc(mesh.getNbElement(element.type),
nb_component * nb_nodes_per_element, element.type,
element.ghost_type);
}
auto & data_array = data(element.type);
for (auto c : arange(nb_component)) {
sstr >> data_array(element.element, c);
}
});
};
readers["$PhysicalNames"] = [&](const std::string & /*unused*/) {
file.has_physical_names = true;
int num_of_phys_names;
file.read_line(num_of_phys_names); /// the format line
for (auto k [[gnu::unused]] : arange(num_of_phys_names)) {
int phys_name_id;
int phys_dim;
std::string phys_name;
file.read_line(phys_dim, phys_name_id, std::quoted(phys_name));
this->physical_names[phys_name_id] = phys_name;
}
};
readers["Unsupported"] = [&](const std::string & _block) {
std::string block = _block.substr(1);
AKANTU_DEBUG_WARNING("Unsupported block_kind " << block << " at line "
<< file.current_line);
auto && end_block = "$End" + block;
while (file.line != end_block) {
file.get_line();
}
};
while (file.good()) {
std::string block;
file.read_line(block);
auto && it = readers.find(block);
if (it != readers.end()) {
it->second(block);
std::string end_block;
file.read_line(end_block);
block = block.substr(1);
if (end_block != "$End" + block) {
AKANTU_EXCEPTION("The reader failed to properly read the block "
<< block << ". Expected a $End" << block << " at line "
<< file.current_line);
}
} else if (not block.empty()) {
readers["Unsupported"](block);
}
}
// mesh.updateTypesOffsets(_not_ghost);
if (file.version < 4000) {
this->constructPhysicalNames("tag_0", mesh);
if (file.has_physical_names) {
mesh.createGroupsFromMeshData<std::string>("physical_names");
}
}
MeshUtils::fillElementToSubElementsData(mesh);
}
/* -------------------------------------------------------------------------- */
void MeshIOMSH::write(const std::string & filename, const Mesh & mesh) {
std::ofstream outfile;
const Array<Real> & nodes = mesh.getNodes();
outfile.open(filename.c_str());
outfile << "$MeshFormat"
<< "\n";
outfile << "2.2 0 8"
<< "\n";
outfile << "$EndMeshFormat"
<< "\n";
outfile << std::setprecision(std::numeric_limits<Real>::digits10);
outfile << "$Nodes"
<< "\n";
outfile << nodes.size() << "\n";
outfile << std::uppercase;
- for (UInt i = 0; i < nodes.size(); ++i) {
- Int offset = i * nodes.getNbComponent();
+ for (Int i = 0; i < nodes.size(); ++i) {
+ auto offset = i * nodes.getNbComponent();
outfile << i + 1;
- for (UInt j = 0; j < nodes.getNbComponent(); ++j) {
- outfile << " " << nodes.storage()[offset + j];
+ for (Int j = 0; j < nodes.getNbComponent(); ++j) {
+ outfile << " " << nodes.data()[offset + j];
}
- for (UInt p = nodes.getNbComponent(); p < 3; ++p) {
+ for (Int p = nodes.getNbComponent(); p < 3; ++p) {
outfile << " " << 0.;
}
outfile << "\n";
;
}
outfile << std::nouppercase;
outfile << "$EndNodes"
<< "\n";
outfile << "$Elements"
<< "\n";
Int nb_elements = 0;
for (auto && type :
mesh.elementTypes(_all_dimensions, _not_ghost, _ek_not_defined)) {
- const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost);
+ const auto & connectivity = mesh.getConnectivity(type, _not_ghost);
nb_elements += connectivity.size();
}
outfile << nb_elements << "\n";
std::map<Element, size_t> element_to_msh_element;
- UInt element_idx = 1;
+ Idx element_idx = 1;
auto element = ElementNull;
for (auto && type :
mesh.elementTypes(_all_dimensions, _not_ghost, _ek_not_defined)) {
const auto & connectivity = mesh.getConnectivity(type, _not_ghost);
element.type = type;
- UInt * tag[2] = {nullptr, nullptr};
- if (mesh.hasData<UInt>("tag_0", type, _not_ghost)) {
- const auto & data_tag_0 = mesh.getData<UInt>("tag_0", type, _not_ghost);
- tag[0] = data_tag_0.storage();
+ Int * tag[2] = {nullptr, nullptr};
+ if (mesh.hasData<Int>("tag_0", type, _not_ghost)) {
+ const auto & data_tag_0 = mesh.getData<Int>("tag_0", type, _not_ghost);
+ tag[0] = data_tag_0.data();
}
- if (mesh.hasData<UInt>("tag_1", type, _not_ghost)) {
- const auto & data_tag_1 = mesh.getData<UInt>("tag_1", type, _not_ghost);
- tag[1] = data_tag_1.storage();
+ if (mesh.hasData<Int>("tag_1", type, _not_ghost)) {
+ const auto & data_tag_1 = mesh.getData<Int>("tag_1", type, _not_ghost);
+ tag[1] = data_tag_1.data();
}
for (auto && data :
enumerate(make_view(connectivity, connectivity.getNbComponent()))) {
element.element = std::get<0>(data);
const auto & conn = std::get<1>(data);
element_to_msh_element.insert(std::make_pair(element, element_idx));
outfile << element_idx << " " << _akantu_to_msh_element_types[type]
<< " 2";
/// \todo write the real data in the file
- for (UInt t = 0; t < 2; ++t) {
+ for (Int t = 0; t < 2; ++t) {
if (tag[t] != nullptr) {
outfile << " " << tag[t][element.element];
} else {
outfile << " 0";
}
}
for (auto && c : conn) {
outfile << " " << c + 1;
}
outfile << "\n";
element_idx++;
}
}
outfile << "$EndElements"
<< "\n";
if (mesh.hasData(MeshDataType::_nodal)) {
auto && tags = mesh.getTagNames();
for (auto && tag : tags) {
auto type = mesh.getTypeCode(tag, MeshDataType::_nodal);
if (type != MeshDataTypeCode::_real) {
AKANTU_DEBUG_WARNING(
"The field "
<< tag << " is ignored by the MSH writer, msh files do not support "
<< type << " data");
continue;
}
auto && data = mesh.getNodalData<double>(tag);
outfile << "$NodeData"
<< "\n";
outfile << "1"
<< "\n";
outfile << "\"" << tag << "\"\n";
outfile << "1\n0.0"
<< "\n";
outfile << "3\n0"
<< "\n";
outfile << data.getNbComponent() << "\n";
outfile << data.size() << "\n";
for (auto && d : enumerate(make_view(data, data.getNbComponent()))) {
outfile << std::get<0>(d) + 1;
for (auto && v : std::get<1>(d)) {
outfile << " " << v;
}
outfile << "\n";
}
outfile << "$EndNodeData"
<< "\n";
}
}
if (mesh.hasData(MeshDataType::_elemental)) {
auto && tags = mesh.getTagNames();
for (auto && tag : tags) {
auto && data = mesh.getElementalData<double>(tag);
auto type = mesh.getTypeCode(tag, MeshDataType::_elemental);
if (type != MeshDataTypeCode::_real) {
AKANTU_DEBUG_WARNING(
"The field "
<< tag << " is ignored by the MSH writer, msh files do not support "
<< type << " data");
continue;
}
if (data.isNodal()) {
continue;
}
auto size = data.size();
if (size == 0) {
continue;
}
auto && nb_components = data.getNbComponents();
auto nb_component = nb_components(*(data.elementTypes().begin()));
outfile << "$ElementData"
<< "\n";
outfile << "1"
<< "\n";
outfile << "\"" << tag << "\"\n";
outfile << "1\n0.0"
<< "\n";
outfile << "3\n0"
<< "\n";
outfile << nb_component << "\n";
outfile << size << "\n";
Element element;
for (auto type : data.elementTypes()) {
element.type = type;
for (auto && _ :
enumerate(make_view(data(type), nb_components(type)))) {
element.element = std::get<0>(_);
outfile << element_to_msh_element[element];
for (auto && v : std::get<1>(_)) {
outfile << " " << v;
}
outfile << "\n";
}
}
outfile << "$EndElementData"
<< "\n";
}
}
outfile.close();
}
/* --------------------------------------------------------------------------
*/
} // namespace akantu
diff --git a/src/io/mesh_io/mesh_io_msh.hh b/src/io/mesh_io/mesh_io_msh.hh
index acfae74fc..4e8278ec0 100644
--- a/src/io/mesh_io/mesh_io_msh.hh
+++ b/src/io/mesh_io/mesh_io_msh.hh
@@ -1,117 +1,117 @@
/**
* @file mesh_io_msh.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue May 21 2019
*
* @brief Read/Write for MSH files
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_IO_MSH_HH_
#define AKANTU_MESH_IO_MSH_HH_
/* -------------------------------------------------------------------------- */
#include "mesh_io.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class MeshIOMSH : public MeshIO {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MeshIOMSH();
~MeshIOMSH() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// read a mesh from the file
void read(const std::string & filename, Mesh & mesh) override;
/// write a mesh to a file
void write(const std::string & filename, const Mesh & mesh) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// MSH element types
enum MSHElementType {
_msh_not_defined = 0,
_msh_segment_2 = 1, // 2-node line.
_msh_triangle_3 = 2, // 3-node triangle.
_msh_quadrangle_4 = 3, // 4-node quadrangle.
_msh_tetrahedron_4 = 4, // 4-node tetrahedron.
_msh_hexahedron_8 = 5, // 8-node hexahedron.
_msh_prism_1 = 6, // 6-node prism.
_msh_pyramid_1 = 7, // 5-node pyramid.
_msh_segment_3 = 8, // 3-node second order line
_msh_triangle_6 = 9, // 6-node second order triangle
_msh_quadrangle_9 = 10, // 9-node second order quadrangle
_msh_tetrahedron_10 = 11, // 10-node second order tetrahedron
_msh_hexahedron_27 = 12, // 27-node second order hexahedron
_msh_prism_18 = 13, // 18-node second order prism
_msh_pyramid_14 = 14, // 14-node second order pyramid
_msh_point = 15, // 1-node point.
_msh_quadrangle_8 = 16, // 8-node second order quadrangle
_msh_hexahedron_20 = 17, // 20-node second order hexahedron
_msh_prism_15 = 18 // 15-node second order prism
};
#define MAX_NUMBER_OF_NODE_PER_ELEMENT 10 // tetrahedron of second order
/// order in witch element as to be read
- std::map<ElementType, std::vector<UInt>> _read_order;
+ std::map<ElementType, std::vector<Int>> _read_order;
/// number of nodes per msh element
- std::map<MSHElementType, UInt> _msh_nodes_per_elem;
+ std::map<MSHElementType, Int> _msh_nodes_per_elem;
/// correspondence between msh element types and akantu element types
std::map<MSHElementType, ElementType> _msh_to_akantu_element_types;
/// correspondence between akantu element types and msh element types
std::map<ElementType, MSHElementType> _akantu_to_msh_element_types;
protected:
template <typename File, typename Readers>
void populateReaders2(File & file, Readers & readers);
template <typename File, typename Readers>
void populateReaders4(File & file, Readers & readers);
};
} // namespace akantu
#endif /* AKANTU_MESH_IO_MSH_HH_ */
diff --git a/src/io/mesh_io/mesh_io_msh_struct.cc b/src/io/mesh_io/mesh_io_msh_struct.cc
index 6c3bdd3fd..8f1dc38f2 100644
--- a/src/io/mesh_io/mesh_io_msh_struct.cc
+++ b/src/io/mesh_io/mesh_io_msh_struct.cc
@@ -1,81 +1,81 @@
/**
* @file mesh_io_msh_struct.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jan 26 2018
*
* @brief Read/Write for MSH files generated by gmsh
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_io_msh_struct.hh"
/* -------------------------------------------------------------------------- */
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
MeshIOMSHStruct::MeshIOMSHStruct() {
canReadSurface = true;
canReadExtendedData = true;
_msh_to_akantu_element_types.clear();
_msh_to_akantu_element_types[_msh_not_defined] = _not_defined;
_msh_to_akantu_element_types[_msh_segment_2] = _bernoulli_beam_2;
_msh_to_akantu_element_types[_msh_triangle_3] =
_discrete_kirchhoff_triangle_18;
_akantu_to_msh_element_types.clear();
_akantu_to_msh_element_types[_not_defined] = _msh_not_defined;
_akantu_to_msh_element_types[_bernoulli_beam_2] = _msh_segment_2;
_akantu_to_msh_element_types[_bernoulli_beam_3] = _msh_segment_2;
_akantu_to_msh_element_types[_discrete_kirchhoff_triangle_18] =
_msh_triangle_3;
for (auto & kv_pair : _akantu_to_msh_element_types) {
- UInt nb_nodes = _msh_nodes_per_elem[kv_pair.second];
- std::vector<UInt> tmp(nb_nodes);
+ Int nb_nodes = _msh_nodes_per_elem[kv_pair.second];
+ std::vector<Idx> tmp(nb_nodes);
std::iota(tmp.begin(), tmp.end(), 0);
_read_order[kv_pair.first] = tmp;
}
}
/* -------------------------------------------------------------------------- */
void MeshIOMSHStruct::read(const std::string & filename, Mesh & mesh) {
if (mesh.getSpatialDimension() == 2) {
_msh_to_akantu_element_types[_msh_segment_2] = _bernoulli_beam_2;
} else if (mesh.getSpatialDimension() == 3) {
_msh_to_akantu_element_types[_msh_segment_2] = _bernoulli_beam_3;
AKANTU_DEBUG_WARNING("The MeshIOMSHStruct is reading bernoulli beam 3D be "
"sure to provide the missing normals with the element "
"data \"extra_normal\"");
}
MeshIOMSH::read(filename, mesh);
}
} // namespace akantu
diff --git a/src/io/parser/algebraic_parser.hh b/src/io/parser/algebraic_parser.hh
index 7197ca16d..bafe0c124 100644
--- a/src/io/parser/algebraic_parser.hh
+++ b/src/io/parser/algebraic_parser.hh
@@ -1,518 +1,519 @@
/**
* @file algebraic_parser.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Tue Mar 03 2020
*
* @brief algebraic_parser definition of the grammar
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
// Boost
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ALGEBRAIC_PARSER_HH_
#define AKANTU_ALGEBRAIC_PARSER_HH_
namespace spirit = boost::spirit;
namespace qi = boost::spirit::qi;
namespace lbs = boost::spirit::qi::labels;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
namespace akantu {
namespace parser {
struct algebraic_error_handler_ {
template <typename, typename, typename> struct result {
using type = void;
};
template <typename Iterator>
void operator()(qi::info const & what, Iterator err_pos,
Iterator last) const {
AKANTU_EXCEPTION(
"Error! Expecting "
<< what // what failed?
<< " here: \""
<< std::string(err_pos, last) // iterators to error-pos, end
<< "\"");
}
};
static Real my_min(Real a, Real b) { return std::min(a, b); }
static Real my_max(Real a, Real b) { return std::max(a, b); }
static Real my_pow(Real a, Real b) { return std::pow(a, b); }
static Real eval_param(const ID & a, const ParserSection & section) {
return section.getParameter(a, _ppsc_current_and_parent_scope);
}
static Real unary_func(Real (*func)(Real), Real a) { return func(a); }
static Real binary_func(Real (*func)(Real, Real), Real a, Real b) {
return func(a, b);
}
template <class Iterator, typename Skipper = spirit::unused_type>
struct AlgebraicGrammar : qi::grammar<Iterator, Real(), Skipper> {
AlgebraicGrammar(const ParserSection & section)
: AlgebraicGrammar::base_type(start, "algebraic_grammar"),
section(section) {
// phx::function<lazy_pow_> lazy_pow;
// phx::function<lazy_unary_func_> lazy_unary_func;
// phx::function<lazy_binary_func_> lazy_binary_func;
// phx::function<lazy_eval_param_> lazy_eval_param;
/* clang-format off */
start
= expr.alias()
;
expr
= term [ lbs::_val = lbs::_1 ]
>> *( ('+' > term [ lbs::_val += lbs::_1 ])
| ('-' > term [ lbs::_val -= lbs::_1 ])
)
;
term
= factor [ lbs::_val = lbs::_1 ]
>> *( ('*' > factor [ lbs::_val *= lbs::_1 ])
| ('/' > factor [ lbs::_val /= lbs::_1 ])
)
;
factor
= number [ lbs::_val = lbs::_1 ]
>> *("**" > number [ lbs::_val = phx::bind(&my_pow, lbs::_val, lbs::_1) ])
;
number
= real [ lbs::_val = lbs::_1 ]
| ('-' > number [ lbs::_val = -lbs::_1 ])
| ('+' > number [ lbs::_val = lbs::_1 ])
| constant [ lbs::_val = lbs::_1 ]
| function [ lbs::_val = lbs::_1 ]
| ('(' > expr > ')') [ lbs::_val = lbs::_1 ]
| variable [ lbs::_val = lbs::_1 ]
;
function
= (qi::no_case[unary_function]
> '('
> expr
> ')') [ lbs::_val = phx::bind(&unary_func, lbs::_1, lbs::_2) ]
| (qi::no_case[binary_function]
> '(' >> expr
> ',' >> expr
> ')') [ lbs::_val = phx::bind(&binary_func ,lbs::_1, lbs::_2, lbs::_3) ]
;
variable
= key [ lbs::_val = phx::bind(&eval_param, lbs::_1, section) ]
;
key
= qi::no_skip[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9")] // coming from the InputFileGrammar
;
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
#ifndef M_E
# define M_E 2.7182818284590452354
#endif
constant.add
("pi", M_PI)
("e", M_E);
unary_function.add
("abs" , &std::abs )
("acos" , &std::acos )
("asin" , &std::asin )
("atan" , &std::atan )
("ceil" , &std::ceil )
("cos" , &std::cos )
("cosh" , &std::cosh )
("exp" , &std::exp )
("floor" , &std::floor )
("log10" , &std::log10 )
("log" , &std::log )
("sin" , &std::sin )
("sinh" , &std::sinh )
("sqrt" , &std::sqrt )
("tan" , &std::tan )
("tanh" , &std::tanh )
("acosh" , &std::acosh )
("asinh" , &std::asinh )
("atanh" , &std::atanh )
("exp2" , &std::exp2 )
("expm1" , &std::expm1 )
("log1p" , &std::log1p )
("log2" , &std::log2 )
("erf" , &std::erf )
("erfc" , &std::erfc )
("lgamma", &std::lgamma)
("tgamma", &std::tgamma)
("trunc" , &std::trunc )
("round" , &std::round )
// ("crbt" , &std::crbt )
;
binary_function.add
("pow" , &std::pow )
("min" , &parser::my_min)
("max" , &parser::my_max)
("atan2", &std::atan2 )
("fmod" , &std::fmod )
("hypot", &std::hypot )
;
#if !defined(AKANTU_NDEBUG)
phx::function<algebraic_error_handler_> const error_handler = algebraic_error_handler_();
qi::on_error<qi::fail>(start, error_handler(lbs::_4, lbs::_3, lbs::_2));
#endif
expr .name("expression");
term .name("term");
factor .name("factor");
number .name("numerical-value");
variable.name("variable");
function.name("function");
constant.name("constants-list");
unary_function.name("unary-functions-list");
binary_function.name("binary-functions-list");
#if !defined AKANTU_NDEBUG
if(AKANTU_DEBUG_TEST(dblDebug)) {
qi::debug(expr);
qi::debug(term);
qi::debug(factor);
qi::debug(number);
qi::debug(variable);
qi::debug(function);
}
#endif
}
/* clang-format on */
private:
qi::rule<Iterator, Real(), Skipper> start;
qi::rule<Iterator, Real(), Skipper> expr;
qi::rule<Iterator, Real(), Skipper> term;
qi::rule<Iterator, Real(), Skipper> factor;
qi::rule<Iterator, Real(), Skipper> number;
qi::rule<Iterator, Real(), Skipper> variable;
qi::rule<Iterator, Real(), Skipper> function;
qi::rule<Iterator, std::string(), Skipper> key;
qi::real_parser<Real, qi::real_policies<Real>> real;
qi::symbols<char, Real> constant;
qi::symbols<char, Real (*)(Real)> unary_function;
qi::symbols<char, Real (*)(Real, Real)> binary_function;
const ParserSection & section;
};
/* ---------------------------------------------------------------------- */
/* Vector Parser */
/* ---------------------------------------------------------------------- */
struct parsable_vector {
operator Vector<Real>() {
Vector<Real> tmp(_cells.size());
auto it = _cells.begin();
- for (UInt i = 0; it != _cells.end(); ++it, ++i) {
+ for (Int i = 0; it != _cells.end(); ++it, ++i) {
tmp(i) = *it;
}
return tmp;
}
std::vector<Real> _cells;
};
inline std::ostream & operator<<(std::ostream & stream,
const parsable_vector & pv) {
stream << "pv[";
auto it = pv._cells.begin();
if (it != pv._cells.end()) {
stream << *it;
for (++it; it != pv._cells.end(); ++it) {
stream << ", " << *it;
}
}
stream << "]";
return stream;
}
struct parsable_matrix {
operator Matrix<Real>() {
size_t cols = 0;
auto it_rows = _cells.begin();
for (; it_rows != _cells.end(); ++it_rows) {
cols = std::max(cols, it_rows->_cells.size());
}
- Matrix<Real> tmp(_cells.size(), _cells[0]._cells.size(), 0.);
+ Matrix<Real> tmp(_cells.size(), cols);
+ tmp.fill(0.);
it_rows = _cells.begin();
- for (UInt i = 0; it_rows != _cells.end(); ++it_rows, ++i) {
+ for (Int i = 0; it_rows != _cells.end(); ++it_rows, ++i) {
auto it_cols = it_rows->_cells.begin();
- for (UInt j = 0; it_cols != it_rows->_cells.end(); ++it_cols, ++j) {
+ for (Int j = 0; it_cols != it_rows->_cells.end(); ++it_cols, ++j) {
tmp(i, j) = *it_cols;
}
}
return tmp;
}
std::vector<parsable_vector> _cells;
};
inline std::ostream & operator<<(std::ostream & stream,
const parsable_matrix & pm) {
stream << "pm[";
auto it = pm._cells.begin();
if (it != pm._cells.end()) {
stream << *it;
for (++it; it != pm._cells.end(); ++it) {
stream << ", " << *it;
}
}
stream << "]";
return stream;
}
/* ---------------------------------------------------------------------- */
template <typename T1, typename T2>
static void cont_add(T1 & cont, T2 & value) {
cont._cells.push_back(value);
}
/* ---------------------------------------------------------------------- */
template <class Iterator, typename Skipper = spirit::unused_type>
struct VectorGrammar : qi::grammar<Iterator, parsable_vector(), Skipper> {
VectorGrammar(const ParserSection & section)
: VectorGrammar::base_type(start, "vector_algebraic_grammar"),
number(section) {
start = '[' > vector > ']';
vector =
(number[phx::bind(&cont_add<parsable_vector, Real>, lbs::_a,
lbs::_1)] >>
*(',' >> number[phx::bind(&cont_add<parsable_vector, Real>, lbs::_a,
lbs::_1)]))[lbs::_val = lbs::_a];
#if !defined(AKANTU_NDEBUG)
phx::function<algebraic_error_handler_> const error_handler =
algebraic_error_handler_();
qi::on_error<qi::fail>(start, error_handler(lbs::_4, lbs::_3, lbs::_2));
#endif
start.name("start");
vector.name("vector");
number.name("value");
#if !defined AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDebug)) {
qi::debug(start);
qi::debug(vector);
}
#endif
}
private:
qi::rule<Iterator, parsable_vector(), Skipper> start;
qi::rule<Iterator, parsable_vector(), qi::locals<parsable_vector>, Skipper>
vector;
qi::rule<Iterator, Real(), Skipper> value;
AlgebraicGrammar<Iterator, Skipper> number;
};
/* ---------------------------------------------------------------------- */
static inline bool vector_eval(const ID & a, const ParserSection & section,
parsable_vector & result) {
std::string value = section.getParameter(a, _ppsc_current_and_parent_scope);
std::string::const_iterator b = value.begin();
std::string::const_iterator e = value.end();
parser::VectorGrammar<std::string::const_iterator, qi::space_type> grammar(
section);
return qi::phrase_parse(b, e, grammar, qi::space, result);
}
/* ---------------------------------------------------------------------- */
template <class Iterator, typename Skipper = spirit::unused_type>
struct MatrixGrammar : qi::grammar<Iterator, parsable_matrix(), Skipper> {
MatrixGrammar(const ParserSection & section)
: MatrixGrammar::base_type(start, "matrix_algebraic_grammar"),
vector(section) {
start = '[' >> matrix >> ']';
matrix =
(rows[phx::bind(&cont_add<parsable_matrix, parsable_vector>, lbs::_a,
lbs::_1)] >>
*(',' >> rows[phx::bind(&cont_add<parsable_matrix, parsable_vector>,
lbs::_a, lbs::_1)]))[lbs::_val = lbs::_a];
rows = eval_vector | vector;
eval_vector = (key[lbs::_pass = phx::bind(&vector_eval, lbs::_1, section,
lbs::_a)])[lbs::_val = lbs::_a];
key = qi::char_("a-zA-Z_") >>
*qi::char_("a-zA-Z_0-9") // coming from the InputFileGrammar
;
#if !defined(AKANTU_NDEBUG)
phx::function<algebraic_error_handler_> const error_handler =
algebraic_error_handler_();
qi::on_error<qi::fail>(start, error_handler(lbs::_4, lbs::_3, lbs::_2));
#endif
start.name("matrix");
matrix.name("all_rows");
rows.name("rows");
vector.name("vector");
eval_vector.name("eval_vector");
#ifndef AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDebug)) {
qi::debug(start);
qi::debug(matrix);
qi::debug(rows);
qi::debug(eval_vector);
qi::debug(key);
}
#endif
}
private:
qi::rule<Iterator, parsable_matrix(), Skipper> start;
qi::rule<Iterator, parsable_matrix(), qi::locals<parsable_matrix>, Skipper>
matrix;
qi::rule<Iterator, parsable_vector(), Skipper> rows;
qi::rule<Iterator, parsable_vector(), qi::locals<parsable_vector>, Skipper>
eval_vector;
qi::rule<Iterator, std::string(), Skipper> key;
VectorGrammar<Iterator, Skipper> vector;
};
/* ---------------------------------------------------------------------- */
/* Randon Generator */
/* ---------------------------------------------------------------------- */
struct ParsableRandomGenerator {
ParsableRandomGenerator(
Real base = Real(),
const RandomDistributionType & type = _rdt_not_defined,
const parsable_vector & parameters = parsable_vector())
: base(base), type(type), parameters(parameters) {}
Real base;
RandomDistributionType type;
parsable_vector parameters;
};
inline std::ostream & operator<<(std::ostream & stream,
const ParsableRandomGenerator & prg) {
- stream << "prg[" << prg.base << " " << UInt(prg.type) << " "
+ stream << "prg[" << prg.base << " " << Int(prg.type) << " "
<< prg.parameters << "]";
return stream;
}
/* ---------------------------------------------------------------------- */
template <class Iterator, typename Skipper = spirit::unused_type>
struct RandomGeneratorGrammar
: qi::grammar<Iterator, ParsableRandomGenerator(), Skipper> {
RandomGeneratorGrammar(const ParserSection & section)
: RandomGeneratorGrammar::base_type(start, "random_generator_grammar"),
number(section) {
start = generator.alias();
generator =
qi::hold[distribution[lbs::_val = lbs::_1]] |
number[lbs::_val = phx::construct<ParsableRandomGenerator>(lbs::_1)];
distribution = (number >> generator_type >> '[' >> generator_params >>
']')[lbs::_val = phx::construct<ParsableRandomGenerator>(
lbs::_1, lbs::_2, lbs::_3)];
generator_params =
(number[phx::bind(&cont_add<parsable_vector, Real>, lbs::_a,
lbs::_1)] >>
*(',' > number[phx::bind(&cont_add<parsable_vector, Real>, lbs::_a,
lbs::_1)]))[lbs::_val = lbs::_a];
#define AKANTU_RANDOM_DISTRIBUTION_TYPE_ADD(r, data, elem) \
(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem)), \
AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \
BOOST_PP_TUPLE_ELEM(2, 0, elem)))
generator_type.add BOOST_PP_SEQ_FOR_EACH(
AKANTU_RANDOM_DISTRIBUTION_TYPE_ADD, _,
AKANTU_RANDOM_DISTRIBUTION_TYPES);
#undef AKANTU_RANDOM_DISTRIBUTION_TYPE_ADD
#if !defined(AKANTU_NDEBUG)
phx::function<algebraic_error_handler_> const error_handler =
algebraic_error_handler_();
qi::on_error<qi::fail>(start, error_handler(lbs::_4, lbs::_3, lbs::_2));
#endif
start.name("random-generator");
generator.name("random-generator");
distribution.name("random-distribution");
generator_type.name("generator-type");
generator_params.name("generator-parameters");
number.name("number");
#ifndef AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDebug)) {
qi::debug(generator);
qi::debug(distribution);
qi::debug(generator_params);
}
#endif
}
private:
qi::rule<Iterator, ParsableRandomGenerator(), Skipper> start;
qi::rule<Iterator, ParsableRandomGenerator(), Skipper> generator;
qi::rule<Iterator, ParsableRandomGenerator(), Skipper> distribution;
qi::rule<Iterator, parsable_vector(), qi::locals<parsable_vector>, Skipper>
generator_params;
AlgebraicGrammar<Iterator, Skipper> number;
qi::symbols<char, RandomDistributionType> generator_type;
};
} // namespace parser
} // namespace akantu
#endif /* AKANTU_ALGEBRAIC_PARSER_HH_ */
diff --git a/src/io/parser/parameter_registry.cc b/src/io/parser/parameter_registry.cc
index ef6c7aefb..08a644195 100644
--- a/src/io/parser/parameter_registry.cc
+++ b/src/io/parser/parameter_registry.cc
@@ -1,156 +1,147 @@
/**
* @file parameter_registry.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed May 04 2016
* @date last modification: Thu Feb 01 2018
*
* @brief Parameter Registry and derived classes implementation
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <utility>
#include "parameter_registry.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
Parameter::Parameter() = default;
/* -------------------------------------------------------------------------- */
Parameter::Parameter(std::string name, std::string description,
ParameterAccessType param_type)
: name(std::move(name)), description(std::move(description)),
param_type(param_type) {}
/* -------------------------------------------------------------------------- */
bool Parameter::isWritable() const { return (param_type & _pat_writable) != 0; }
/* -------------------------------------------------------------------------- */
bool Parameter::isReadable() const { return (param_type & _pat_readable) != 0; }
/* -------------------------------------------------------------------------- */
bool Parameter::isInternal() const { return (param_type & _pat_internal) != 0; }
/* -------------------------------------------------------------------------- */
bool Parameter::isParsable() const { return (param_type & _pat_parsable) != 0; }
/* -------------------------------------------------------------------------- */
void Parameter::setAccessType(ParameterAccessType ptype) {
this->param_type = ptype;
}
/* -------------------------------------------------------------------------- */
void Parameter::printself(std::ostream & stream) const {
stream << " ";
if (isInternal()) {
stream << "iii";
} else {
if (isReadable()) {
stream << "r";
} else {
stream << "-";
}
if (isWritable()) {
stream << "w";
} else {
stream << "-";
}
if (isParsable()) {
stream << "p";
} else {
stream << "-";
}
}
stream << " ";
std::stringstream sstr;
sstr << name;
UInt width = std::max(int(10 - sstr.str().length()), 0);
sstr.width(width);
if (not description.empty()) {
sstr << " [" << description << "]";
}
stream << sstr.str();
width = std::max(int(50 - sstr.str().length()), 0);
stream.width(width);
stream << " : ";
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ParameterRegistry::ParameterRegistry() = default;
/* -------------------------------------------------------------------------- */
-ParameterRegistry::~ParameterRegistry() {
- for (auto && data : params) {
- delete data.second;
- data.second = NULL;
- }
- this->params.clear();
-}
+ParameterRegistry::~ParameterRegistry() = default;
/* -------------------------------------------------------------------------- */
void ParameterRegistry::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
- Parameters::const_iterator it;
- for (it = params.begin(); it != params.end(); ++it) {
+ for (auto && [_, param] : params) {
stream << space;
- it->second->printself(stream);
+ param->printself(stream);
}
- SubRegisteries::const_iterator sub_it;
- for (sub_it = sub_registries.begin(); sub_it != sub_registries.end();
- ++sub_it) {
+ for (auto && [_, registry] : sub_registries) {
stream << space << "Registry [" << std::endl;
- sub_it->second->printself(stream, indent + 1);
+ registry.get().printself(stream, indent + 1);
stream << space << "]";
}
}
/* -------------------------------------------------------------------------- */
void ParameterRegistry::registerSubRegistry(const ID & id,
ParameterRegistry & registry) {
- sub_registries[id] = &registry;
+ sub_registries.insert_or_assign(id, std::ref(registry));
}
/* -------------------------------------------------------------------------- */
void ParameterRegistry::setParameterAccessType(const std::string & name,
ParameterAccessType ptype) {
auto it = params.find(name);
if (it == params.end()) {
AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this));
}
Parameter & param = *(it->second);
param.setAccessType(ptype);
}
} // namespace akantu
diff --git a/src/io/parser/parameter_registry.hh b/src/io/parser/parameter_registry.hh
index 5395c8729..962a60e5a 100644
--- a/src/io/parser/parameter_registry.hh
+++ b/src/io/parser/parameter_registry.hh
@@ -1,228 +1,228 @@
/**
* @file parameter_registry.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Aug 09 2012
* @date last modification: Wed Oct 17 2018
*
* @brief Interface of the parameter registry
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "parser.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PARAMETER_REGISTRY_HH_
#define AKANTU_PARAMETER_REGISTRY_HH_
namespace akantu {
class ParserParameter;
}
namespace akantu {
/* -------------------------------------------------------------------------- */
/// Defines the access modes of parsable parameters
enum ParameterAccessType {
_pat_internal = 0x0001,
_pat_writable = 0x0010,
_pat_readable = 0x0100,
_pat_modifiable = 0x0110, //<_pat_readable | _pat_writable,
_pat_parsable = 0x1000,
_pat_parsmod = 0x1110 //< _pat_parsable | _pat_modifiable
};
/// Bit-wise operator between access modes
inline ParameterAccessType operator|(const ParameterAccessType & a,
const ParameterAccessType & b) {
auto tmp = ParameterAccessType(UInt(a) | UInt(b));
return tmp;
}
/* -------------------------------------------------------------------------- */
template <typename T> class ParameterTyped;
/**
* Interface for the Parameter
*/
class Parameter {
public:
Parameter();
Parameter(std::string name, std::string description,
ParameterAccessType param_type);
virtual ~Parameter() = default;
/* ------------------------------------------------------------------------ */
bool isInternal() const;
bool isWritable() const;
bool isReadable() const;
bool isParsable() const;
void setAccessType(ParameterAccessType ptype);
/* ------------------------------------------------------------------------ */
template <typename T, typename V> void set(const V & value);
virtual void setAuto(const ParserParameter & param);
template <typename T> T & get();
template <typename T> const T & get() const;
virtual inline operator Real() const { throw std::bad_cast(); };
template <typename T> inline operator T() const;
/* ------------------------------------------------------------------------ */
virtual void printself(std::ostream & stream) const;
virtual const std::type_info & type() const = 0;
protected:
/// Returns const instance of templated sub-class ParameterTyped
template <typename T> const ParameterTyped<T> & getParameterTyped() const;
/// Returns instance of templated sub-class ParameterTyped
template <typename T> ParameterTyped<T> & getParameterTyped();
protected:
/// Name of parameter
std::string name;
private:
/// Description of parameter
std::string description;
/// Type of access
ParameterAccessType param_type{_pat_internal};
};
/* -------------------------------------------------------------------------- */
/* Typed Parameter */
/* -------------------------------------------------------------------------- */
/**
* Type parameter transfering a ParserParameter (string: string) to a typed
* parameter in the memory of the p
*/
template <typename T> class ParameterTyped : public Parameter {
public:
ParameterTyped(const std::string & name, const std::string & description,
ParameterAccessType param_type, T & param);
/* ------------------------------------------------------------------------ */
template <typename V> void setTyped(const V & value);
void setAuto(const ParserParameter & value) override;
T & getTyped();
const T & getTyped() const;
void printself(std::ostream & stream) const override;
inline operator Real() const override;
inline const std::type_info & type() const override { return typeid(T); }
private:
/// Value of parameter
T & param;
};
/* -------------------------------------------------------------------------- */
/* Parsable Interface */
/* -------------------------------------------------------------------------- */
/// Defines interface for classes to manipulate parsable parameters
class ParameterRegistry {
public:
ParameterRegistry();
virtual ~ParameterRegistry();
/* ------------------------------------------------------------------------ */
/// Add parameter to the params map
template <typename T>
void registerParam(const std::string & name, T & variable,
ParameterAccessType type,
const std::string & description = "");
/// Add parameter to the params map (with default value)
template <typename T>
void registerParam(const std::string & name, T & variable,
const T & default_value, ParameterAccessType type,
const std::string & description = "");
/*------------------------------------------------------------------------- */
protected:
void registerSubRegistry(const ID & id, ParameterRegistry & registry);
/* ------------------------------------------------------------------------ */
public:
/// Set value to a parameter (with possible different type)
template <typename T, typename V>
void setMixed(const std::string & name, const V & value);
/// Set value to a parameter
template <typename T> void set(const std::string & name, const T & value);
/// Get value of a parameter
inline const Parameter & get(const std::string & name) const;
/// Get value of a parameter
inline Parameter & get(const std::string & name);
std::vector<ID> listParameters() const {
std::vector<ID> params;
for (const auto & pair : this->params) {
params.push_back(pair.first);
}
return params;
}
std::vector<ID> listSubRegisteries() const {
std::vector<ID> subs;
for (const auto & pair : this->sub_registries) {
subs.push_back(pair.first);
}
return subs;
}
protected:
template <typename T> T & get_(const std::string & name);
protected:
void setParameterAccessType(const std::string & name,
ParameterAccessType ptype);
/* ------------------------------------------------------------------------ */
virtual void printself(std::ostream & stream, int indent) const;
protected:
- /// Parameters map
- using Parameters = std::map<std::string, Parameter *>;
- Parameters params;
+ /// list of registered parameters, shared_ptr instead of unique_ptr is only
+ /// for py11 interface to compile propoerly
+ std::map<std::string, std::shared_ptr<Parameter>> params;
/// list of sub-registries
- using SubRegisteries = std::map<std::string, ParameterRegistry *>;
- SubRegisteries sub_registries;
+ std::map<std::string, std::reference_wrapper<ParameterRegistry>>
+ sub_registries;
/// should accessor check in sub registries
bool consisder_sub{true};
};
} // namespace akantu
#include "parameter_registry_tmpl.hh"
#endif /* AKANTU_PARAMETER_REGISTRY_HH_ */
diff --git a/src/io/parser/parameter_registry_tmpl.hh b/src/io/parser/parameter_registry_tmpl.hh
index 47c742c7c..9e3d051bb 100644
--- a/src/io/parser/parameter_registry_tmpl.hh
+++ b/src/io/parser/parameter_registry_tmpl.hh
@@ -1,459 +1,484 @@
/**
* @file parameter_registry_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed May 04 2016
* @date last modification: Thu Mar 19 2020
*
* @brief implementation of the templated part of ParameterRegistry class and
* the derivated ones
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_error.hh"
#include "aka_iterators.hh"
-//#include "parameter_registry.hh"
+#include "aka_types.hh"
#include "parser.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <set>
#include <string>
#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PARAMETER_REGISTRY_TMPL_HH_
#define AKANTU_PARAMETER_REGISTRY_TMPL_HH_
namespace akantu {
namespace debug {
class ParameterException : public Exception {
public:
ParameterException(const std::string & name, const std::string & message)
: Exception(message), name(name) {}
const std::string & name;
};
class ParameterUnexistingException : public ParameterException {
public:
ParameterUnexistingException(const std::string & name,
const ParameterRegistry & registery)
: ParameterException(name, "Parameter " + name +
" does not exists in this scope") {
auto && params = registery.listParameters();
this->_info =
std::accumulate(params.begin(), params.end(),
this->_info + "\n Possible parameters are: ",
[](auto && str, auto && param) {
static auto first = true;
auto ret = str + (first ? " " : ", ") + param;
first = false;
return ret;
});
}
};
class ParameterAccessRightException : public ParameterException {
public:
ParameterAccessRightException(const std::string & name,
const std::string & perm)
: ParameterException(name, "Parameter " + name + " is not " + perm) {}
};
class ParameterWrongTypeException : public ParameterException {
public:
ParameterWrongTypeException(const std::string & name,
const std::type_info & wrong_type,
const std::type_info & type)
: ParameterException(name, "Parameter " + name +
" type error, cannot convert " +
debug::demangle(type.name()) + " to " +
debug::demangle(wrong_type.name())) {}
};
} // namespace debug
/* -------------------------------------------------------------------------- */
template <typename T>
const ParameterTyped<T> & Parameter::getParameterTyped() const {
try {
const auto & tmp = aka::as_type<ParameterTyped<T>>(*this);
return tmp;
} catch (std::bad_cast &) {
AKANTU_CUSTOM_EXCEPTION(
debug::ParameterWrongTypeException(name, typeid(T), this->type()));
}
}
/* -------------------------------------------------------------------------- */
template <typename T> ParameterTyped<T> & Parameter::getParameterTyped() {
try {
auto & tmp = aka::as_type<ParameterTyped<T>>(*this);
return tmp;
} catch (std::bad_cast &) {
AKANTU_CUSTOM_EXCEPTION(
debug::ParameterWrongTypeException(name, typeid(T), this->type()));
}
}
/* ------------------------------------------------------------------------ */
template <typename T, typename V> void Parameter::set(const V & value) {
if (not isWritable()) {
AKANTU_CUSTOM_EXCEPTION(
debug::ParameterAccessRightException(name, "writable"));
}
ParameterTyped<T> & typed_param = getParameterTyped<T>();
typed_param.setTyped(value);
}
/* ------------------------------------------------------------------------ */
inline void Parameter::setAuto(const ParserParameter & /*value*/) {
if (not isParsable()) {
AKANTU_CUSTOM_EXCEPTION(
debug::ParameterAccessRightException(name, "parsable"));
}
}
/* -------------------------------------------------------------------------- */
template <typename T> const T & Parameter::get() const {
if (not isReadable()) {
AKANTU_CUSTOM_EXCEPTION(
debug::ParameterAccessRightException(name, "readable"));
}
const ParameterTyped<T> & typed_param = getParameterTyped<T>();
return typed_param.getTyped();
}
/* -------------------------------------------------------------------------- */
template <typename T> T & Parameter::get() {
ParameterTyped<T> & typed_param = getParameterTyped<T>();
if (not isReadable() or not this->isWritable()) {
AKANTU_CUSTOM_EXCEPTION(
debug::ParameterAccessRightException(name, "accessible"));
}
return typed_param.getTyped();
}
/* -------------------------------------------------------------------------- */
template <typename T> inline Parameter::operator T() const {
return this->get<T>();
}
/* -------------------------------------------------------------------------- */
template <typename T>
ParameterTyped<T>::ParameterTyped(const std::string & name,
const std::string & description,
ParameterAccessType param_type, T & param)
: Parameter(name, description, param_type), param(param) {}
/* -------------------------------------------------------------------------- */
template <typename T>
template <typename V>
void ParameterTyped<T>::setTyped(const V & value) {
param = value;
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void ParameterTyped<T>::setAuto(const ParserParameter & value) {
Parameter::setAuto(value);
param = static_cast<T>(value);
}
/* -------------------------------------------------------------------------- */
template <>
inline void
ParameterTyped<std::string>::setAuto(const ParserParameter & value) {
Parameter::setAuto(value);
param = value.getValue();
}
-/* -------------------------------------------------------------------------- */
-template <>
-inline void
-ParameterTyped<Vector<Real>>::setAuto(const ParserParameter & in_param) {
- Parameter::setAuto(in_param);
- Vector<Real> tmp = in_param;
- if (param.size() == 0) {
- param = tmp;
- } else {
- for (UInt i = 0; i < param.size(); ++i) {
- param(i) = tmp(i);
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void
-ParameterTyped<Matrix<Real>>::setAuto(const ParserParameter & in_param) {
- Parameter::setAuto(in_param);
- Matrix<Real> tmp = in_param;
- if (param.size() == 0) {
- param = tmp;
- } else {
- for (UInt i = 0; i < param.rows(); ++i) {
- for (UInt j = 0; j < param.cols(); ++j) {
- param(i, j) = tmp(i, j);
- }
- }
- }
-}
-
/* -------------------------------------------------------------------------- */
template <typename T> const T & ParameterTyped<T>::getTyped() const {
return param;
}
/* -------------------------------------------------------------------------- */
template <typename T> T & ParameterTyped<T>::getTyped() { return param; }
/* -------------------------------------------------------------------------- */
template <typename T>
inline void ParameterTyped<T>::printself(std::ostream & stream) const {
Parameter::printself(stream);
stream << param << "\n";
}
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+template <typename T, Int m, Int n>
+class ParameterTyped<Eigen::Matrix<T, m, n>> : public Parameter {
+public:
+ ParameterTyped(const std::string & name, const std::string & description,
+ ParameterAccessType param_type, Eigen::Matrix<T, m, n> & param)
+ : Parameter(name, description, param_type), param(param) {}
+
+ template <typename V> void setTyped(const V & value) { param = value; }
+ void setAuto(const ParserParameter & value) override {
+ Parameter::setAuto(value);
+ if constexpr (n == 1) {
+ Vector<Real> tmp = value;
+ if (param.rows() != 0) {
+ param = tmp.block(0, 0, param.rows(), 1);
+ } else {
+ param = tmp;
+ }
+ } else {
+ Matrix<Real> tmp = value;
+ if (param.rows() != 0 and param.cols() != 0) {
+ param = tmp.block(0, 0, param.rows(), param.cols());
+ } else {
+ param = tmp;
+ }
+ }
+ }
+
+ Eigen::Matrix<T, m, n> & getTyped() { return param; }
+ const Eigen::Matrix<T, m, n> & getTyped() const { return param; }
+
+ void printself(std::ostream & stream) const override {
+ Parameter::printself(stream);
+
+ stream << "[ ";
+ for (int i : arange(param.rows())) {
+ if (param.cols() != 1) {
+ stream << "[ ";
+ }
+ for (int j : arange(param.cols())) {
+ stream << param(i, j) << " ";
+ }
+ if (param.cols() != 1) {
+ stream << "] ";
+ }
+ }
+ stream << "]\n";
+ }
+
+ inline const std::type_info & type() const override {
+ return typeid(Eigen::Matrix<T, m, n>);
+ }
+
+private:
+ /// Value of parameter
+ Eigen::Matrix<T, m, n> & param;
+};
+
+/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <typename T> class ParameterTyped<std::vector<T>> : public Parameter {
public:
ParameterTyped(const std::string & name, const std::string & description,
ParameterAccessType param_type, std::vector<T> & param)
: Parameter(name, description, param_type), param(param) {}
/* ------------------------------------------------------------------------
*/
template <typename V> void setTyped(const V & value) { param = value; }
void setAuto(const ParserParameter & value) override {
Parameter::setAuto(value);
param.zero();
const std::vector<T> & tmp = value;
for (auto && z : tmp) {
param.emplace_back(z);
}
}
std::vector<T> & getTyped() { return param; }
const std::vector<T> & getTyped() const { return param; }
void printself(std::ostream & stream) const override {
Parameter::printself(stream);
stream << "[ ";
for (auto && v : param) {
stream << v << " ";
}
stream << "]\n";
}
inline const std::type_info & type() const override {
return typeid(std::vector<T>);
}
private:
/// Value of parameter
std::vector<T> & param;
};
+/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <typename T> class ParameterTyped<std::set<T>> : public Parameter {
public:
ParameterTyped(const std::string & name, const std::string & description,
ParameterAccessType param_type, std::set<T> & param)
: Parameter(name, description, param_type), param(param) {}
/* ------------------------------------------------------------------------
*/
template <typename V> void setTyped(const V & value) { param = value; }
- void setAuto(const ParserParameter & value) override {
+ void setAuto(const ParserParameter & value) {
Parameter::setAuto(value);
param.clear();
const std::set<T> & tmp = value;
for (auto && z : tmp) {
param.emplace(z);
}
}
std::set<T> & getTyped() { return param; }
const std::set<T> & getTyped() const { return param; }
- void printself(std::ostream & stream) const override {
+ void printself(std::ostream & stream) const {
Parameter::printself(stream);
stream << "[ ";
for (auto && v : param) {
stream << v << " ";
}
stream << "]\n";
}
- inline const std::type_info & type() const override {
- return typeid(std::set<T>);
- }
+ inline const std::type_info & type() const { return typeid(std::set<T>); }
private:
/// Value of parameter
std::set<T> & param;
};
/* -------------------------------------------------------------------------- */
template <>
inline void ParameterTyped<bool>::printself(std::ostream & stream) const {
Parameter::printself(stream);
stream << std::boolalpha << param << "\n";
}
/* -------------------------------------------------------------------------- */
template <typename T>
void ParameterRegistry::registerParam(const std::string & name, T & variable,
ParameterAccessType type,
const std::string & description) {
auto it = params.find(name);
if (it != params.end()) {
AKANTU_CUSTOM_EXCEPTION(debug::ParameterException(
name, "Parameter named " + name + " already registered."));
}
- auto * param = new ParameterTyped<T>(name, description, type, variable);
- params[name] = param;
+ auto && param =
+ std::make_shared<ParameterTyped<T>>(name, description, type, variable);
+ params[name] = std::move(param);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void ParameterRegistry::registerParam(const std::string & name, T & variable,
const T & default_value,
ParameterAccessType type,
const std::string & description) {
variable = default_value;
registerParam(name, variable, type, description);
}
/* -------------------------------------------------------------------------- */
template <typename T, typename V>
void ParameterRegistry::setMixed(const std::string & name, const V & value) {
auto it = params.find(name);
if (it == params.end()) {
if (consisder_sub) {
- for (auto it = sub_registries.begin(); it != sub_registries.end(); ++it) {
- it->second->setMixed<T>(name, value);
+ for (auto && [_, registery] : sub_registries) {
+ registery.get().template setMixed<T>(name, value);
}
} else {
AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this));
}
} else {
Parameter & param = *(it->second);
param.set<T>(value);
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
void ParameterRegistry::set(const std::string & name, const T & value) {
this->template setMixed<T>(name, value);
}
/* -------------------------------------------------------------------------- */
template <typename T> T & ParameterRegistry::get_(const std::string & name) {
auto it = params.find(name);
if (it == params.end()) {
if (consisder_sub) {
- for (auto it = sub_registries.begin(); it != sub_registries.end(); ++it) {
+ for (auto && [_, registery] : sub_registries) {
try {
- return it->second->get_<T>(name);
+ return registery.get().template get_<T>(name);
} catch (...) {
}
}
}
// nothing was found not even in sub registries
AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this));
}
Parameter & param = *(it->second);
return param.get<T>();
}
/* -------------------------------------------------------------------------- */
const Parameter & ParameterRegistry::get(const std::string & name) const {
auto it = params.find(name);
if (it == params.end()) {
if (consisder_sub) {
- for (auto it = sub_registries.begin(); it != sub_registries.end(); ++it) {
+ for (auto && [_, registery] : sub_registries) {
try {
- return it->second->get(name);
+ return registery.get().get(name);
} catch (...) {
}
}
}
// nothing was found not even in sub registries
AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this));
}
Parameter & param = *(it->second);
return param;
}
/* -------------------------------------------------------------------------- */
Parameter & ParameterRegistry::get(const std::string & name) {
auto it = params.find(name);
if (it == params.end()) {
if (consisder_sub) {
- for (auto it = sub_registries.begin(); it != sub_registries.end(); ++it) {
+ for (auto && [_, registery] : sub_registries) {
try {
- return it->second->get(name);
+ return registery.get().get(name);
} catch (...) {
}
}
}
// nothing was found not even in sub registries
AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this));
}
Parameter & param = *(it->second);
return param;
}
/* -------------------------------------------------------------------------- */
-namespace {
- namespace details {
- template <class T, class R, class Enable = void> struct CastHelper {
- static R convert(const T & /*unused*/) { throw std::bad_cast(); }
- };
-
- template <class T, class R>
- struct CastHelper<T, R,
- std::enable_if_t<std::is_convertible<T, R>::value>> {
- static R convert(const T & val) { return val; }
- };
- } // namespace details
-} // namespace
+namespace details {
+ template <class T, class R, class Enable = void> struct CastHelper {
+ static R convert(const T & /*unused*/) { throw std::bad_cast(); }
+ };
+
+ template <class T, class R>
+ struct CastHelper<T, R, std::enable_if_t<std::is_convertible<T, R>::value>> {
+ static R convert(const T & val) { return val; }
+ };
+} // namespace details
template <typename T> inline ParameterTyped<T>::operator Real() const {
if (not isReadable()) {
AKANTU_CUSTOM_EXCEPTION(
debug::ParameterAccessRightException(name, "accessible"));
}
return details::CastHelper<T, Real>::convert(param);
}
} // namespace akantu
#endif /* AKANTU_PARAMETER_REGISTRY_TMPL_HH_ */
diff --git a/src/io/parser/parsable.cc b/src/io/parser/parsable.cc
index 140e26e65..a4baca18b 100644
--- a/src/io/parser/parsable.cc
+++ b/src/io/parser/parsable.cc
@@ -1,112 +1,113 @@
/**
* @file parsable.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Thu Feb 08 2018
*
* @brief Parsable implementation
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "parsable.hh"
#include "aka_random_generator.hh"
+#include <memory>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
Parsable::Parsable(const ParserType & section_type, const ID & id)
: section_type(section_type), pid(id) {
this->consisder_sub = false;
}
/* -------------------------------------------------------------------------- */
Parsable::~Parsable() = default;
/* -------------------------------------------------------------------------- */
void Parsable::registerSubSection(const ParserType & type,
const std::string & name,
Parsable & sub_section) {
SubSectionKey key(type, name);
- sub_sections[key] = &sub_section;
+ sub_sections.insert_or_assign(key, std::ref(sub_section));
this->registerSubRegistry(name, sub_section);
}
/* -------------------------------------------------------------------------- */
void Parsable::parseParam(const ParserParameter & in_param) {
auto it = params.find(in_param.getName());
if (it == params.end()) {
if (Parser::isPermissive()) {
AKANTU_DEBUG_WARNING("No parameter named " << in_param.getName()
<< " registered in " << pid
<< ".");
return;
}
AKANTU_EXCEPTION("No parameter named " << in_param.getName()
<< " registered in " << pid << ".");
}
Parameter & param = *(it->second);
param.setAuto(in_param);
}
/* -------------------------------------------------------------------------- */
void Parsable::parseSection(const ParserSection & section) {
if (section_type != section.getType()) {
AKANTU_EXCEPTION("The object "
<< pid << " is meant to parse section of type "
<< section_type << ", so it cannot parse section of type "
<< section.getType());
}
auto params = section.getParameters();
auto it = params.first;
for (; it != params.second; ++it) {
parseParam(*it);
}
auto sit = section.getSubSections().first;
for (; sit != section.getSubSections().second; ++sit) {
parseSubSection(*sit);
}
}
/* -------------------------------------------------------------------------- */
void Parsable::parseSubSection(const ParserSection & section) {
SubSectionKey key(section.getType(), section.getName());
auto it = sub_sections.find(key);
if (it != sub_sections.end()) {
- it->second->parseSection(section);
+ it->second.get().parseSection(section);
} else if (!Parser::isPermissive()) {
AKANTU_EXCEPTION("No parsable defined for sub sections of type <"
<< key.first << "," << key.second << "> in " << pid);
} else {
AKANTU_DEBUG_WARNING("No parsable defined for sub sections of type <"
<< key.first << "," << key.second << "> in " << pid);
}
}
} // namespace akantu
diff --git a/src/io/parser/parsable.hh b/src/io/parser/parsable.hh
index e64e85bdd..0e991f3a3 100644
--- a/src/io/parser/parsable.hh
+++ b/src/io/parser/parsable.hh
@@ -1,74 +1,73 @@
/**
* @file parsable.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Aug 09 2012
* @date last modification: Fri Dec 08 2017
*
* @brief Interface of the parameter registry
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "parameter_registry.hh"
#include "parser.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PARSABLE_HH_
#define AKANTU_PARSABLE_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Parsable Interface */
/* -------------------------------------------------------------------------- */
/// Defines interface for classes to manipulate parsable parameters
class Parsable : public ParameterRegistry {
public:
Parsable(const ParserType & section_type, const ID & id = std::string());
~Parsable() override;
/// Add subsection to the sub_sections map
void registerSubSection(const ParserType & type, const std::string & name,
Parsable & sub_section);
/* ------------------------------------------------------------------------ */
public:
virtual void parseSection(const ParserSection & section);
virtual void parseSubSection(const ParserSection & section);
virtual void parseParam(const ParserParameter & in_param);
private:
ParserType section_type;
/// ID of parsable object
ID pid;
using SubSectionKey = std::pair<ParserType, std::string>;
- using SubSections = std::map<SubSectionKey, Parsable *>;
/// Subsections map
- SubSections sub_sections;
+ std::map<SubSectionKey, std::reference_wrapper<Parsable>> sub_sections;
};
} // namespace akantu
#endif /* AKANTU_PARSABLE_HH_ */
diff --git a/src/io/parser/parser.hh b/src/io/parser/parser.hh
index fa1966f8f..f73440a2f 100644
--- a/src/io/parser/parser.hh
+++ b/src/io/parser/parser.hh
@@ -1,543 +1,545 @@
/**
* @file parser.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri Apr 02 2021
*
* @brief File parser interface
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_random_generator.hh"
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PARSER_HH_
#define AKANTU_PARSER_HH_
namespace akantu {
#if !defined(DOXYGEN)
// clang-format off
#define AKANTU_SECTION_TYPES \
(cohesive_inserter) \
(contact) \
(embedded_interface) \
(friction) \
(global) \
(heat) \
(integration_scheme) \
(material) \
- (phasefield) \
+ (phasefield) \
(mesh) \
(model) \
(model_solver) \
(neighborhood) \
(neighborhoods) \
(non_linear_solver) \
(non_local) \
(rules) \
(solver) \
(time_step_solver) \
(user) \
(weight_function) \
- (contact_detector) \
- (contact_resolution) \
+ (contact_detector) \
+ (contact_resolution) \
(not_defined)
// clang-format on
/// Defines the possible section types
AKANTU_CLASS_ENUM_DECLARE(ParserType, AKANTU_SECTION_TYPES)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(ParserType, AKANTU_SECTION_TYPES)
AKANTU_CLASS_ENUM_INPUT_STREAM(ParserType, AKANTU_SECTION_TYPES)
#else
enum class ParserType {
cohesive_inserter,
contact,
embedded_interface,
friction,
global,
heat,
integration_scheme,
material,
phasefield,
mesh,
model,
model_solver,
neighborhood,
neighborhoods,
non_linear_solver,
non_local,
rules,
solver,
time_step_solver,
user,
weight_function,
not_defined
};
#endif
/// Defines the possible search contexts/scopes (for parameter search)
enum ParserParameterSearchCxt {
_ppsc_current_scope = 0x1,
_ppsc_parent_scope = 0x2,
_ppsc_current_and_parent_scope = 0x3
};
/* ------------------------------------------------------------------------ */
/* Parameters Class */
/* ------------------------------------------------------------------------ */
class ParserSection;
/// @brief The ParserParameter objects represent the end of tree branches as
/// they
/// are the different informations contained in the input file.
class ParserParameter {
public:
ParserParameter()
: name(std::string()), value(std::string()), dbg_filename(std::string()) {
}
ParserParameter(const std::string & name, const std::string & value,
const ParserSection & parent_section)
: parent_section(&parent_section), name(name), value(value),
dbg_filename(std::string()) {}
ParserParameter(const ParserParameter & param) = default;
virtual ~ParserParameter() = default;
/// Get parameter name
const std::string & getName() const { return name; }
/// Get parameter value
const std::string & getValue() const { return value; }
/// Set info for debug output
- void setDebugInfo(const std::string & filename, UInt line, UInt column) {
+ void setDebugInfo(const std::string & filename, Int line, Int column) {
dbg_filename = filename;
dbg_line = line;
dbg_column = column;
}
template <typename T> inline operator T() const;
- // template <typename T> inline operator Vector<T>() const;
- // template <typename T> inline operator Matrix<T>() const;
+ template <typename T, Int m, Int n, std::enable_if_t<n == 1> * = nullptr>
+ inline operator Matrix<T, m, n>() const;
+ template <typename T, Int m, Int n, std::enable_if_t<n != 1> * = nullptr>
+ inline operator Matrix<T, m, n>() const;
/// Print parameter info in stream
void printself(std::ostream & stream,
__attribute__((unused)) unsigned int indent = 0) const {
stream << name << ": " << value << " (" << dbg_filename << ":" << dbg_line
<< ":" << dbg_column << ")";
}
private:
void setParent(const ParserSection & sect) { parent_section = &sect; }
friend class ParserSection;
private:
/// Pointer to the parent section
const ParserSection * parent_section{nullptr};
/// Name of the parameter
std::string name;
/// Value of the parameter
std::string value;
/// File for debug output
std::string dbg_filename;
/// Position of parameter in parsed file
- UInt dbg_line, dbg_column;
+ Int dbg_line, dbg_column;
};
/* ------------------------------------------------------------------------ */
/* Sections Class */
/* ------------------------------------------------------------------------ */
/// ParserSection represents a branch of the parsing tree.
class ParserSection {
public:
using SubSections = std::multimap<ParserType, ParserSection>;
using Parameters = std::map<std::string, ParserParameter>;
private:
using const_section_iterator_ = SubSections::const_iterator;
public:
/* ------------------------------------------------------------------------ */
/* SubSection iterator */
/* ------------------------------------------------------------------------ */
/// Iterator on sections
class const_section_iterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = ParserSection;
using pointer = ParserSection *;
using reference = ParserSection &;
const_section_iterator() = default;
const_section_iterator(const const_section_iterator_ & it) : it(it) {}
const_section_iterator(const const_section_iterator & other) = default;
const_section_iterator &
operator=(const const_section_iterator & other) = default;
const ParserSection & operator*() const { return it->second; }
const ParserSection * operator->() const { return &(it->second); }
bool operator==(const const_section_iterator & other) const {
return it == other.it;
}
bool operator!=(const const_section_iterator & other) const {
return it != other.it;
}
const_section_iterator & operator++() {
++it;
return *this;
}
const_section_iterator operator++(int) {
const_section_iterator tmp = *this;
operator++();
return tmp;
}
private:
const_section_iterator_ it;
};
/* ------------------------------------------------------------------------ */
/* Parameters iterator */
/* ------------------------------------------------------------------------ */
/// Iterator on parameters
class const_parameter_iterator {
public:
const_parameter_iterator(const const_parameter_iterator & other) = default;
const_parameter_iterator(const Parameters::const_iterator & it) : it(it) {}
const_parameter_iterator &
operator=(const const_parameter_iterator & other) {
if (this != &other) {
it = other.it;
}
return *this;
}
const ParserParameter & operator*() const { return it->second; }
const ParserParameter * operator->() { return &(it->second); };
bool operator==(const const_parameter_iterator & other) const {
return it == other.it;
}
bool operator!=(const const_parameter_iterator & other) const {
return it != other.it;
}
const_parameter_iterator & operator++() {
++it;
return *this;
}
const_parameter_iterator operator++(int) {
const_parameter_iterator tmp = *this;
operator++();
return tmp;
}
private:
Parameters::const_iterator it;
};
/* ---------------------------------------------------------------------- */
ParserSection() : name(std::string()) {}
ParserSection(const std::string & name, ParserType type)
: name(name), type(type) {}
ParserSection(const std::string & name, ParserType type,
const std::string & option,
const ParserSection & parent_section)
: parent_section(&parent_section), name(name), type(type),
option(option) {}
ParserSection(const ParserSection & section)
: parent_section(section.parent_section), name(section.name),
type(section.type), option(section.option),
parameters(section.parameters),
sub_sections_by_type(section.sub_sections_by_type) {
setChldrenPointers();
}
ParserSection & operator=(const ParserSection & other) {
if (&other != this) {
parent_section = other.parent_section;
name = other.name;
type = other.type;
option = other.option;
parameters = other.parameters;
sub_sections_by_type = other.sub_sections_by_type;
setChldrenPointers();
}
return *this;
}
virtual ~ParserSection();
virtual void printself(std::ostream & stream, unsigned int indent = 0) const;
/* ---------------------------------------------------------------------- */
/* Creation functions */
/* ---------------------------------------------------------------------- */
public:
ParserParameter & addParameter(const ParserParameter & param);
ParserSection & addSubSection(const ParserSection & section);
protected:
/// Clean ParserSection content
void clean() {
parameters.clear();
sub_sections_by_type.clear();
}
private:
void setChldrenPointers() {
for (auto && param_pair : this->parameters) {
param_pair.second.setParent(*this);
}
for (auto && sub_sect_pair : this->sub_sections_by_type) {
sub_sect_pair.second.setParent(*this);
}
}
/* ---------------------------------------------------------------------- */
/* Accessors */
/* ---------------------------------------------------------------------- */
public:
class SubSectionsRange
: public std::pair<const_section_iterator, const_section_iterator> {
public:
SubSectionsRange(const const_section_iterator & first,
const const_section_iterator & second)
: std::pair<const_section_iterator, const_section_iterator>(first,
second) {}
auto begin() { return this->first; }
auto end() { return this->second; }
};
/// Get begin and end iterators on subsections of certain type
auto getSubSections(ParserType type = ParserType::_not_defined) const {
if (type != ParserType::_not_defined) {
auto range = sub_sections_by_type.equal_range(type);
return SubSectionsRange(range.first, range.second);
}
return SubSectionsRange(sub_sections_by_type.begin(),
sub_sections_by_type.end());
}
/// Get number of subsections of certain type
- UInt getNbSubSections(ParserType type = ParserType::_not_defined) const {
+ Int getNbSubSections(ParserType type = ParserType::_not_defined) const {
if (type != ParserType::_not_defined) {
return this->sub_sections_by_type.count(type);
}
return this->sub_sections_by_type.size();
}
/// Get begin and end iterators on parameters
auto getParameters() const {
return std::pair<const_parameter_iterator, const_parameter_iterator>(
parameters.begin(), parameters.end());
}
/* ---------------------------------------------------------------------- */
/// Get parameter within specified context
const ParserParameter & getParameter(
const std::string & name,
ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const {
Parameters::const_iterator it;
if ((search_ctx & _ppsc_current_scope) != 0) {
it = parameters.find(name);
}
if (it == parameters.end()) {
if ((search_ctx & _ppsc_parent_scope) != 0 and
parent_section != nullptr) {
return parent_section->getParameter(name, search_ctx);
}
AKANTU_SILENT_EXCEPTION(
"The parameter " << name
<< " has not been found in the specified context");
}
return it->second;
}
/* ------------------------------------------------------------------------ */
/// Get parameter within specified context, with a default value in case the
/// parameter does not exists
template <class T>
T getParameter(
const std::string & name, const T & default_value,
ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const {
try {
T tmp = this->getParameter(name, search_ctx);
return tmp;
} catch (debug::Exception &) {
return default_value;
}
}
/* ------------------------------------------------------------------------ */
/// Check if parameter exists within specified context
bool hasParameter(
const std::string & name,
ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const {
Parameters::const_iterator it;
if ((search_ctx & _ppsc_current_scope) != 0) {
it = parameters.find(name);
}
if (it == parameters.end()) {
if ((search_ctx & _ppsc_parent_scope) != 0 and
parent_section != nullptr) {
return parent_section->hasParameter(name, search_ctx);
}
return false;
}
return true;
}
/* --------------------------------------------------------------------------
*/
/// Get value of given parameter in context
template <class T>
T getParameterValue(
const std::string & name,
ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const {
const ParserParameter & tmp_param = getParameter(name, search_ctx);
T t = tmp_param;
return t;
}
/* --------------------------------------------------------------------------
*/
/// Get section name
std::string getName() const { return name; }
/// Get section type
ParserType getType() const { return type; }
/// Get section option
std::string getOption(const std::string & def = "") const {
return (not option.empty()) ? option : def;
}
protected:
void setParent(const ParserSection & sect) { parent_section = &sect; }
/* ---------------------------------------------------------------------- */
/* Members */
/* ---------------------------------------------------------------------- */
private:
/// Pointer to the parent section
const ParserSection * parent_section{nullptr};
/// Name of section
std::string name;
/// Type of section, see AKANTU_SECTION_TYPES
ParserType type{ParserType::_not_defined};
/// Section option
std::string option;
/// Map of parameters in section
Parameters parameters;
/// Multi-map of subsections
SubSections sub_sections_by_type;
};
/* ------------------------------------------------------------------------ */
/* Parser Class */
/* ------------------------------------------------------------------------ */
/// Root of parsing tree, represents the global ParserSection
class Parser : public ParserSection {
public:
Parser() : ParserSection("global", ParserType::_global) {}
void parse(const std::string & filename);
std::string getLastParsedFile() const;
static bool isPermissive() { return permissive_parser; }
public:
/// Parse real scalar
static Real parseReal(const std::string & value,
const ParserSection & section);
/// Parse real vector
static Vector<Real> parseVector(const std::string & value,
const ParserSection & section);
/// Parse real matrix
static Matrix<Real> parseMatrix(const std::string & value,
const ParserSection & section);
/// Parse real random parameter
static RandomParameter<Real>
parseRandomParameter(const std::string & value,
const ParserSection & section);
protected:
/// General parse function
template <class T, class Grammar>
static T parseType(const std::string & value, Grammar & grammar);
protected:
// friend class Parsable;
static bool permissive_parser;
std::string last_parsed_file;
};
inline std::ostream & operator<<(std::ostream & stream,
const ParserParameter & _this) {
_this.printself(stream);
return stream;
}
inline std::ostream & operator<<(std::ostream & stream,
const ParserSection & section) {
section.printself(stream);
return stream;
}
} // namespace akantu
namespace std {
template <> struct iterator_traits<::akantu::Parser::const_section_iterator> {
using iterator_category = input_iterator_tag;
using value_type = ::akantu::ParserParameter;
using difference_type = ptrdiff_t;
using pointer = const ::akantu::ParserParameter *;
using reference = const ::akantu::ParserParameter &;
};
} // namespace std
#include "parser_tmpl.hh"
#endif /* AKANTU_PARSER_HH_ */
diff --git a/src/io/parser/parser_grammar_tmpl.hh b/src/io/parser/parser_grammar_tmpl.hh
index ddff996d8..2074679a3 100644
--- a/src/io/parser/parser_grammar_tmpl.hh
+++ b/src/io/parser/parser_grammar_tmpl.hh
@@ -1,83 +1,83 @@
/**
* @file parser_grammar_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 11 2015
* @date last modification: Sun Dec 03 2017
*
* @brief implementation of the templated part of ParsableParam Parsable and
* ParsableParamTyped
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-//#include <boost/config/warning_disable.hpp>
+#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PARSER_GRAMMAR_TMPL_HH
#define AKANTU_PARSER_GRAMMAR_TMPL_HH
namespace akantu {
namespace qi = boost::spirit::qi;
/* -------------------------------------------------------------------------- */
template <class T, class Grammar>
T Parser::parseType(const std::string & value, Grammar & grammar) {
using boost::spirit::ascii::space;
std::string::const_iterator b = value.begin();
std::string::const_iterator e = value.end();
T resultat = T();
bool res = false;
try {
res = qi::phrase_parse(b, e, grammar, space, resultat);
} catch (debug::Exception & ex) {
AKANTU_EXCEPTION("Could not parse '"
<< value << "' as a " << debug::demangle(typeid(T).name())
<< ", an unknown error append '" << ex.what());
}
if (!res || (b != e)) {
AKANTU_EXCEPTION("Could not parse '"
<< value << "' as a " << debug::demangle(typeid(T).name())
<< ", an unknown error append '"
<< std::string(value.begin(), b) << "<HERE>"
<< std::string(b, e) << "'");
}
return resultat;
}
namespace parser {
template <class Iterator> struct Skipper {
using type = qi::rule<Iterator, void()>;
};
} // namespace parser
} // namespace akantu
#endif // AKANTU_PARSER_GRAMMAR_TMPL_HH
diff --git a/src/io/parser/parser_tmpl.hh b/src/io/parser/parser_tmpl.hh
index d8c0ed56d..e8e10ac6a 100644
--- a/src/io/parser/parser_tmpl.hh
+++ b/src/io/parser/parser_tmpl.hh
@@ -1,125 +1,128 @@
/**
* @file parser_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Thu Mar 19 2020
*
* @brief Implementation of the parser templated methods
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <regex>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename T> inline ParserParameter::operator T() const {
T t;
std::stringstream sstr(value);
sstr >> t;
if (sstr.bad()) {
AKANTU_EXCEPTION("No known conversion of a ParserParameter \""
<< name << "\" to the type " << typeid(T).name());
}
return t;
}
#if !defined(DOXYGEN)
/* -------------------------------------------------------------------------- */
template <> inline ParserParameter::operator const char *() const {
return value.c_str();
}
/* -------------------------------------------------------------------------- */
template <> inline ParserParameter::operator Real() const {
return Parser::parseReal(value, *parent_section);
}
/* --------------------------------------------------------- -----------------
*/
template <> inline ParserParameter::operator bool() const {
bool b;
std::stringstream sstr(value);
sstr >> std::boolalpha >> b;
if (sstr.fail()) {
sstr.clear();
sstr >> std::noboolalpha >> b;
}
return b;
}
/* -------------------------------------------------------------------------- */
template <> inline ParserParameter::operator std::vector<std::string>() const {
std::vector<std::string> tmp;
auto string =
std::regex_replace(value, std::regex("[[:space:]]|\\[|\\]"), "");
std::smatch sm;
while (std::regex_search(string, sm, std::regex("[^,]+"))) {
tmp.push_back(sm.str());
string = sm.suffix();
}
return tmp;
}
/* -------------------------------------------------------------------------- */
template <> inline ParserParameter::operator std::set<std::string>() const {
std::set<std::string> tmp;
auto string =
std::regex_replace(value, std::regex("[[:space:]]|\\[|\\]"), "");
std::smatch sm;
while (std::regex_search(string, sm, std::regex("[^,]+"))) {
tmp.emplace(sm.str());
string = sm.suffix();
}
return tmp;
}
/* -------------------------------------------------------------------------- */
-template <> inline ParserParameter::operator Vector<Real>() const {
+template <typename T, Int m, Int n, std::enable_if_t<n == 1> *>
+inline ParserParameter::operator Matrix<T, m, n>() const {
return Parser::parseVector(value, *parent_section);
}
-/* --------------------------------------------------------- ---------------- */
-template <> inline ParserParameter::operator Vector<UInt>() const {
- Vector<Real> tmp = Parser::parseVector(value, *parent_section);
- Vector<UInt> tmp_uint(tmp.size());
- for (UInt i = 0; i < tmp.size(); ++i) {
- tmp_uint(i) = UInt(tmp(i));
- }
- return tmp_uint;
-}
+// /* --------------------------------------------------------- ----------------
+// */ template <Int m, Int n, std::enable_if_t<n == 1> * = nullptr> inline
+// ParserParameter::operator Matrix<Int, m, n>() const {
+// Vector<Real> tmp = Parser::parseVector(value, *parent_section);
+// Vector<Int> tmp_int(tmp.size());
+// for (Int i = 0; i < tmp.size(); ++i) {
+// tmp_int(i) = Int(tmp(i));
+// }
+// return tmp_int;
+// }
/* --------------------------------------------------------- ---------------- */
-template <> inline ParserParameter::operator Matrix<Real>() const {
+template <typename T, Int m, Int n, std::enable_if_t<n != 1> *>
+inline ParserParameter::operator Matrix<T, m, n>() const {
return Parser::parseMatrix(value, *parent_section);
}
/* -------------------------------------------------------------------------- */
template <> inline ParserParameter::operator RandomParameter<Real>() const {
return Parser::parseRandomParameter(value, *parent_section);
}
#endif
} // namespace akantu
diff --git a/src/mesh/element_group.cc b/src/mesh/element_group.cc
index 972c53c16..2bfdff72e 100644
--- a/src/mesh/element_group.cc
+++ b/src/mesh/element_group.cc
@@ -1,246 +1,235 @@
/**
* @file element_group.cc
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Wed Dec 09 2020
*
* @brief Stores information relevent to the notion of domain boundary and
* surfaces.
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "aka_csr.hh"
#include "dumpable.hh"
#include "dumpable_inline_impl.hh"
#include "group_manager.hh"
#include "group_manager_inline_impl.hh"
#include "mesh.hh"
#include "mesh_utils.hh"
#if defined(AKANTU_COHESIVE_ELEMENT)
#include "cohesive_element_inserter.hh"
#endif
#include <algorithm>
#include <iterator>
#include <sstream>
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper_paraview.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
ElementGroup::ElementGroup(const std::string & group_name, const Mesh & mesh,
- NodeGroup & node_group, UInt dimension,
+ NodeGroup & node_group, Int dimension,
const std::string & id)
: mesh(mesh), name(group_name), elements("elements", id),
node_group(node_group), dimension(dimension) {
AKANTU_DEBUG_IN();
this->registerDumper<DumperParaview>("paraview_" + group_name, group_name,
true);
this->addDumpFilteredMesh(mesh, elements, node_group.getNodes(),
_all_dimensions);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
ElementGroup::ElementGroup(const ElementGroup & /*other*/) = default;
/* -------------------------------------------------------------------------- */
void ElementGroup::clear() { elements.free(); }
/* -------------------------------------------------------------------------- */
void ElementGroup::clear(ElementType type, GhostType ghost_type) {
if (elements.exists(type, ghost_type)) {
elements(type, ghost_type).clear();
}
}
/* -------------------------------------------------------------------------- */
bool ElementGroup::empty() const { return elements.empty(); }
/* -------------------------------------------------------------------------- */
void ElementGroup::append(const ElementGroup & other_group) {
AKANTU_DEBUG_IN();
node_group.append(other_group.node_group);
/// loop on all element types in all dimensions
for (auto ghost_type : ghost_types) {
for (auto type : other_group.elementTypes(_ghost_type = ghost_type,
_element_kind = _ek_not_defined)) {
- const Array<UInt> & other_elem_list =
- other_group.elements(type, ghost_type);
- UInt nb_other_elem = other_elem_list.size();
-
- Array<UInt> * elem_list;
- UInt nb_elem = 0;
-
- /// create current type if doesn't exists, otherwise get information
- if (elements.exists(type, ghost_type)) {
- elem_list = &elements(type, ghost_type);
- nb_elem = elem_list->size();
- } else {
- elem_list = &(elements.alloc(0, 1, type, ghost_type));
- }
+ const auto & other_elem_list = other_group.elements(type, ghost_type);
+ auto nb_other_elem = other_elem_list.size();
+
+ auto & elem_list = elements.alloc(0, 1, type, ghost_type);
+ auto nb_elem = elem_list.size();
/// append new elements to current list
- elem_list->resize(nb_elem + nb_other_elem);
+ elem_list.resize(nb_elem + nb_other_elem);
std::copy(other_elem_list.begin(), other_elem_list.end(),
- elem_list->begin() + nb_elem);
+ elem_list.begin() + nb_elem);
}
}
this->optimize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ElementGroup::printself(std::ostream & stream, int indent) const {
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
;
}
stream << space << "ElementGroup [" << std::endl;
stream << space << " + name: " << name << std::endl;
stream << space << " + dimension: " << dimension << std::endl;
elements.printself(stream, indent + 1);
node_group.printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
void ElementGroup::optimize() {
// increasing the locality of data when iterating on the element of a group
for (auto ghost_type : ghost_types) {
for (auto type : elements.elementTypes(_ghost_type = ghost_type)) {
auto & els = elements(type, ghost_type);
std::sort(els.begin(), els.end());
auto end = std::unique(els.begin(), els.end());
els.resize(end - els.begin());
}
}
node_group.optimize();
}
/* -------------------------------------------------------------------------- */
void ElementGroup::fillFromNodeGroup() {
CSR<Element> node_to_elem;
MeshUtils::buildNode2Elements(this->mesh, node_to_elem, this->dimension);
std::set<Element> seen;
- for (auto node : node_group) {
- auto ite = node_to_elem.begin(node);
- auto ende = node_to_elem.end(node);
- for (auto && element : node_to_elem.getRow(node)) {
+ for (const auto & node : this->node_group) {
+ for (const auto & element : node_to_elem.getRow(node)) {
if (this->dimension != _all_dimensions &&
this->dimension != Mesh::getSpatialDimension(element.type)) {
continue;
}
if (seen.find(element) != seen.end()) {
continue;
}
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
auto conn = mesh.getConnectivity(element);
- UInt count = 0;
- for (auto && n : conn) {
- count += (this->node_group.getNodes().find(n) != UInt(-1) ? 1 : 0);
+ Int count = 0;
+ for (auto n : conn) {
+ count += (this->node_group.getNodes().find(n) != Idx(-1) ? 1 : 0);
}
if (count == nb_nodes_per_element) {
this->add(element);
}
seen.insert(element);
}
}
this->optimize();
}
/* -------------------------------------------------------------------------- */
-void ElementGroup::addDimension(UInt dimension) {
+void ElementGroup::addDimension(Int dimension) {
this->dimension = std::max(dimension, this->dimension);
}
/* -------------------------------------------------------------------------- */
-void ElementGroup::onNodesAdded(const Array<UInt> & new_nodes,
- const NewNodesEvent & event) {
+void ElementGroup::onNodesAdded(const Array<Idx> & /*new_nodes*/,
+ const NewNodesEvent & event [[gnu::unused]]) {
#if defined(AKANTU_COHESIVE_ELEMENT)
if (aka::is_of_type<CohesiveNewNodesEvent>(event)) {
// nodes might have changed in the connectivity
node_group.clear();
const auto & mesh_to_mesh_facet =
mesh.getData<Element>("mesh_to_mesh_facet");
for (auto ghost_type : ghost_types) {
for (auto type : elements.elementTypes(_ghost_type = ghost_type)) {
auto & els = elements(type, ghost_type);
if (not mesh_to_mesh_facet.exists(type, ghost_type)) {
continue;
}
const auto & mesh_to_mesh_facet_type =
mesh_to_mesh_facet(type, ghost_type);
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto && conn_it = make_view(mesh.getConnectivity(type, ghost_type),
nb_nodes_per_element)
.begin();
auto && mesh_facet_conn_it =
make_view(mesh.getMeshFacets().getConnectivity(type, ghost_type),
nb_nodes_per_element)
.begin();
for (auto element : els) {
auto && mesh_facet_conn =
mesh_facet_conn_it[mesh_to_mesh_facet_type(element).element];
auto && conn = conn_it[element];
conn = mesh_facet_conn;
for (auto && n : conn) {
node_group.add(n, false);
}
}
}
}
node_group.optimize();
}
#endif
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/mesh/element_group.hh b/src/mesh/element_group.hh
index 9824916b6..aef2014cb 100644
--- a/src/mesh/element_group.hh
+++ b/src/mesh/element_group.hh
@@ -1,208 +1,203 @@
/**
* @file element_group.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri May 03 2013
* @date last modification: Mon Mar 08 2021
*
* @brief Stores information relevent to the notion of domain boundary and
* surfaces.
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dumpable.hh"
#include "element_type_map.hh"
#include "node_group.hh"
/* -------------------------------------------------------------------------- */
#include <set>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_GROUP_HH_
#define AKANTU_ELEMENT_GROUP_HH_
namespace akantu {
class Mesh;
class Element;
class NewNodesEvent;
} // namespace akantu
namespace akantu {
/* -------------------------------------------------------------------------- */
class ElementGroup : public Dumpable {
-
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
ElementGroup(const std::string & name, const Mesh & mesh,
- NodeGroup & node_group, UInt dimension = _all_dimensions,
+ NodeGroup & node_group, Int dimension = _all_dimensions,
const std::string & id = "element_group");
ElementGroup(const ElementGroup & /*unused*/);
/* ------------------------------------------------------------------------ */
/* Type definitions */
/* ------------------------------------------------------------------------ */
public:
- using ElementList = ElementTypeMapArray<UInt>;
- using NodeList = Array<UInt>;
+ using ElementList = ElementTypeMapArray<Idx>;
/* ------------------------------------------------------------------------ */
/* Element iterator */
/* ------------------------------------------------------------------------ */
-
using type_iterator = ElementList::type_iterator;
- [[deprecated("Use elementTypes instead")]] inline type_iterator
- firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost,
+
+ [[deprecated("Use elementTypes instead")]] inline auto
+ firstType(Int dim = _all_dimensions, GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_regular) const;
- [[deprecated("Use elementTypes instead")]] inline type_iterator
- lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost,
+ [[deprecated("Use elementTypes instead")]] inline auto
+ lastType(Int dim = _all_dimensions, GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_regular) const;
template <typename... pack>
inline decltype(auto) elementTypes(pack &&... _pack) const {
return elements.elementTypes(_pack...);
}
- using const_element_iterator = Array<UInt>::const_iterator<UInt>;
-
- inline const_element_iterator begin(ElementType type,
- GhostType ghost_type = _not_ghost) const;
- inline const_element_iterator end(ElementType type,
- GhostType ghost_type = _not_ghost) const;
+ inline auto begin(ElementType type, GhostType ghost_type = _not_ghost) const;
+ inline auto end(ElementType type, GhostType ghost_type = _not_ghost) const;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// empty the element group
void clear();
void clear(ElementType type, GhostType ghost_type = _not_ghost);
bool empty() const __attribute__((warn_unused_result));
/// append another group to this group
/// BE CAREFUL: it doesn't conserve the element order
void append(const ElementGroup & other_group);
/// add an element to the group. By default the it does not add the nodes to
/// the group
inline void add(const Element & el, bool add_nodes = false,
bool check_for_duplicate = true);
/// \todo fix the default for add_nodes : make it coherent with the other
/// method
- inline void add(ElementType type, UInt element,
+ inline void add(ElementType type, Idx element,
GhostType ghost_type = _not_ghost, bool add_nodes = true,
bool check_for_duplicate = true);
- inline void addNode(UInt node_id, bool check_for_duplicate = true);
+ inline void addNode(Idx node_id, bool check_for_duplicate = true);
- inline void removeNode(UInt node_id);
+ inline void removeNode(Idx node_id);
/// function to print the contain of the class
virtual void printself(std::ostream & stream, int indent = 0) const;
/// fill the elements based on the underlying node group.
virtual void fillFromNodeGroup();
// sort and remove duplicated values
void optimize();
/// change the dimension if needed
- void addDimension(UInt dimension);
+ void addDimension(Int dimension);
- void onNodesAdded(const Array<UInt> & new_nodes, const NewNodesEvent & event);
+ void onNodesAdded(const Array<Idx> & new_nodes, const NewNodesEvent & event);
private:
- inline void addElement(ElementType elem_type, UInt elem_id,
+ inline void addElement(ElementType elem_type, Idx elem_id,
GhostType ghost_type);
friend class GroupManager;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- const Array<UInt> & getElements(ElementType type,
- GhostType ghost_type = _not_ghost) const;
- AKANTU_GET_MACRO(Elements, elements, const ElementTypeMapArray<UInt> &);
- AKANTU_GET_MACRO_NOT_CONST(Elements, elements, ElementTypeMapArray<UInt> &);
+ const Array<Idx> & getElements(ElementType type,
+ GhostType ghost_type = _not_ghost) const;
+ AKANTU_GET_MACRO_AUTO(Elements, elements);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Elements, elements);
template <class... Args> auto size(Args &&... pack) const {
return elements.size(std::forward<Args>(pack)...);
}
decltype(auto) getElementsIterable(ElementType type,
GhostType ghost_type = _not_ghost) const;
// AKANTU_GET_MACRO(Nodes, node_group.getNodes(), const Array<UInt> &);
- AKANTU_GET_MACRO(NodeGroup, node_group, const NodeGroup &);
- AKANTU_GET_MACRO_NOT_CONST(NodeGroup, node_group, NodeGroup &);
+ AKANTU_GET_MACRO_AUTO(NodeGroup, node_group);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(NodeGroup, node_group);
+
+ AKANTU_GET_MACRO_AUTO(Dimension, dimension);
+ AKANTU_GET_MACRO_AUTO(Name, name);
- AKANTU_GET_MACRO(Dimension, dimension, UInt);
- AKANTU_GET_MACRO(Name, name, std::string);
- inline UInt getNbNodes() const;
+ inline Int getNbNodes() const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// Mesh to which this group belongs
const Mesh & mesh;
/// name of the group
std::string name;
/// list of elements composing the group
ElementList elements;
/// sub list of nodes which are composing the elements
NodeGroup & node_group;
/// group dimension
- UInt dimension{_all_dimensions};
+ Int dimension{_all_dimensions};
/// empty arry for the iterator to work when an element type not present
- Array<UInt> empty_elements;
+ Array<Idx> empty_elements;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const ElementGroup & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "element.hh"
#include "element_group_inline_impl.hh"
#endif /* AKANTU_ELEMENT_GROUP_HH_ */
diff --git a/src/mesh/element_group_inline_impl.hh b/src/mesh/element_group_inline_impl.hh
index 80e3fb84d..d1b1d04d2 100644
--- a/src/mesh/element_group_inline_impl.hh
+++ b/src/mesh/element_group_inline_impl.hh
@@ -1,148 +1,143 @@
/**
* @file element_group_inline_impl.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Tue Mar 09 2021
*
* @brief Stores information relevent to the notion of domain boundary and
* surfaces.
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "element_group.hh"
+#include "element_type_map.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_ELEMENT_GROUP_INLINE_IMPL_HH_
-#define AKANTU_ELEMENT_GROUP_INLINE_IMPL_HH_
+//#ifndef AKANTU_ELEMENT_GROUP_INLINE_IMPL_HH_
+//#define AKANTU_ELEMENT_GROUP_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline void ElementGroup::add(const Element & el, bool add_nodes,
bool check_for_duplicate) {
this->add(el.type, el.element, el.ghost_type, add_nodes, check_for_duplicate);
}
/* -------------------------------------------------------------------------- */
-
-inline void ElementGroup::add(ElementType type, UInt element,
+inline void ElementGroup::add(ElementType type, Idx element,
GhostType ghost_type, bool add_nodes,
bool check_for_duplicate) {
-
addElement(type, element, ghost_type);
if (add_nodes) {
- Array<UInt>::const_vector_iterator it =
- mesh.getConnectivity(type, ghost_type)
- .begin(mesh.getNbNodesPerElement(type)) +
- element;
- const Vector<UInt> & conn = *it;
- for (UInt i = 0; i < conn.size(); ++i) {
+ auto it = mesh.getConnectivity(type, ghost_type)
+ .begin(mesh.getNbNodesPerElement(type)) +
+ element;
+ auto && conn = *it;
+ for (Idx i = 0; i < conn.size(); ++i) {
addNode(conn[i], check_for_duplicate);
}
}
}
/* -------------------------------------------------------------------------- */
-inline void ElementGroup::addNode(UInt node_id, bool check_for_duplicate) {
+inline void ElementGroup::addNode(Idx node_id, bool check_for_duplicate) {
node_group.add(node_id, check_for_duplicate);
}
/* -------------------------------------------------------------------------- */
-inline void ElementGroup::removeNode(UInt node_id) {
+inline void ElementGroup::removeNode(Idx node_id) {
node_group.remove(node_id);
}
/* -------------------------------------------------------------------------- */
-inline void ElementGroup::addElement(ElementType elem_type, UInt elem_id,
+inline void ElementGroup::addElement(ElementType elem_type, Idx elem_id,
GhostType ghost_type) {
if (!(elements.exists(elem_type, ghost_type))) {
elements.alloc(0, 1, elem_type, ghost_type);
}
elements(elem_type, ghost_type).push_back(elem_id);
- this->dimension = UInt(
+ this->dimension = Int(
std::max(Int(this->dimension), Int(mesh.getSpatialDimension(elem_type))));
}
/* -------------------------------------------------------------------------- */
-inline UInt ElementGroup::getNbNodes() const { return node_group.size(); }
+inline Int ElementGroup::getNbNodes() const { return node_group.size(); }
/* -------------------------------------------------------------------------- */
-inline ElementGroup::type_iterator
-ElementGroup::firstType(UInt dim, GhostType ghost_type,
- ElementKind kind) const {
+inline auto ElementGroup::firstType(Int dim, GhostType ghost_type,
+ ElementKind kind) const {
return elements.elementTypes(dim, ghost_type, kind).begin();
}
/* -------------------------------------------------------------------------- */
-inline ElementGroup::type_iterator
-ElementGroup::lastType(UInt dim, GhostType ghost_type, ElementKind kind) const {
+inline auto ElementGroup::lastType(Int dim, GhostType ghost_type,
+ ElementKind kind) const {
return elements.elementTypes(dim, ghost_type, kind).end();
}
/* -------------------------------------------------------------------------- */
-inline ElementGroup::const_element_iterator
-ElementGroup::begin(ElementType type, GhostType ghost_type) const {
+inline auto ElementGroup::begin(ElementType type, GhostType ghost_type) const {
if (elements.exists(type, ghost_type)) {
return elements(type, ghost_type).begin();
}
return empty_elements.begin();
}
/* -------------------------------------------------------------------------- */
-inline ElementGroup::const_element_iterator
-ElementGroup::end(ElementType type, GhostType ghost_type) const {
+inline auto ElementGroup::end(ElementType type, GhostType ghost_type) const {
if (elements.exists(type, ghost_type)) {
return elements(type, ghost_type).end();
}
return empty_elements.end();
}
/* -------------------------------------------------------------------------- */
-inline const Array<UInt> &
+inline const Array<Idx> &
ElementGroup::getElements(ElementType type, GhostType ghost_type) const {
if (elements.exists(type, ghost_type)) {
return elements(type, ghost_type);
}
return empty_elements;
}
/* -------------------------------------------------------------------------- */
inline decltype(auto)
ElementGroup::getElementsIterable(ElementType type,
GhostType ghost_type) const {
return make_transform_adaptor(this->elements(type, ghost_type),
[type, ghost_type](auto && el) {
return Element{type, el, ghost_type};
});
}
} // namespace akantu
-#endif /* AKANTU_ELEMENT_GROUP_INLINE_IMPL_HH_ */
+//#endif /* AKANTU_ELEMENT_GROUP_INLINE_IMPL_HH_ */
diff --git a/src/mesh/element_type_map.cc b/src/mesh/element_type_map.cc
index 0a72b2940..f0de9dfec 100644
--- a/src/mesh/element_type_map.cc
+++ b/src/mesh/element_type_map.cc
@@ -1,73 +1,71 @@
/**
* @file element_type_map.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Mar 04 2020
*
* @brief storage class by element type
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
FEEngineElementTypeMapArrayInitializer::FEEngineElementTypeMapArrayInitializer(
- const FEEngine & fe_engine, UInt nb_component, UInt spatial_dimension,
+ const FEEngine & fe_engine, Int nb_component, Int spatial_dimension,
GhostType ghost_type, ElementKind element_kind)
: MeshElementTypeMapArrayInitializer(
fe_engine.getMesh(), nb_component,
- spatial_dimension == UInt(-2)
- ? fe_engine.getMesh().getSpatialDimension()
- : spatial_dimension,
+ spatial_dimension == -2 ? fe_engine.getMesh().getSpatialDimension()
+ : spatial_dimension,
ghost_type, element_kind, true, false),
fe_engine(fe_engine) {}
FEEngineElementTypeMapArrayInitializer::FEEngineElementTypeMapArrayInitializer(
const FEEngine & fe_engine,
const ElementTypeMapArrayInitializer::CompFunc & nb_component,
- UInt spatial_dimension, GhostType ghost_type, ElementKind element_kind)
+ Int spatial_dimension, GhostType ghost_type, ElementKind element_kind)
: MeshElementTypeMapArrayInitializer(
fe_engine.getMesh(), nb_component,
- spatial_dimension == UInt(-2)
- ? fe_engine.getMesh().getSpatialDimension()
- : spatial_dimension,
+ spatial_dimension == -2 ? fe_engine.getMesh().getSpatialDimension()
+ : spatial_dimension,
ghost_type, element_kind, true, false),
fe_engine(fe_engine) {}
-UInt FEEngineElementTypeMapArrayInitializer::size(ElementType type) const {
+Int FEEngineElementTypeMapArrayInitializer::size(ElementType type) const {
return MeshElementTypeMapArrayInitializer::size(type) *
fe_engine.getNbIntegrationPoints(type, this->ghost_type);
}
FEEngineElementTypeMapArrayInitializer::ElementTypesIteratorHelper
FEEngineElementTypeMapArrayInitializer::elementTypes() const {
return this->fe_engine.elementTypes(spatial_dimension, ghost_type,
element_kind);
}
} // namespace akantu
diff --git a/src/mesh/element_type_map.hh b/src/mesh/element_type_map.hh
index 187f901c4..e12875f9e 100644
--- a/src/mesh/element_type_map.hh
+++ b/src/mesh/element_type_map.hh
@@ -1,491 +1,535 @@
/**
* @file element_type_map.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 31 2011
* @date last modification: Thu Mar 11 2021
*
* @brief storage class by element type
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_named_argument.hh"
#include "element.hh"
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_TYPE_MAP_HH_
#define AKANTU_ELEMENT_TYPE_MAP_HH_
namespace akantu {
class FEEngine;
+class IntegrationPoint;
} // namespace akantu
namespace akantu {
namespace {
DECLARE_NAMED_ARGUMENT(all_ghost_types);
DECLARE_NAMED_ARGUMENT(default_value);
DECLARE_NAMED_ARGUMENT(element_kind);
DECLARE_NAMED_ARGUMENT(ghost_type);
DECLARE_NAMED_ARGUMENT(nb_component);
DECLARE_NAMED_ARGUMENT(nb_component_functor);
DECLARE_NAMED_ARGUMENT(with_nb_element);
DECLARE_NAMED_ARGUMENT(with_nb_nodes_per_element);
DECLARE_NAMED_ARGUMENT(spatial_dimension);
DECLARE_NAMED_ARGUMENT(do_not_default);
DECLARE_NAMED_ARGUMENT(element_filter);
} // namespace
template <class Stored, typename SupportType = ElementType>
class ElementTypeMap;
/* -------------------------------------------------------------------------- */
/* ElementTypeMapBase */
/* -------------------------------------------------------------------------- */
/// Common non templated base class for the ElementTypeMap class
class ElementTypeMapBase {
public:
virtual ~ElementTypeMapBase() = default;
};
/* -------------------------------------------------------------------------- */
/* ElementTypeMap */
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
class ElementTypeMap : public ElementTypeMapBase {
-
public:
+ using value_type = Stored;
+
ElementTypeMap();
~ElementTypeMap() override;
- inline static std::string printType(const SupportType & type,
- GhostType ghost_type);
+ inline static auto printType(SupportType type, GhostType ghost_type)
+ -> std::string;
/*! Tests whether a type is present in the object
* @param type the type to check for
* @param ghost_type optional: by default, the data map for non-ghost
* elements is searched
* @return true if the type is present. */
- inline bool exists(const SupportType & type,
- GhostType ghost_type = _not_ghost) const;
+ inline auto exists(SupportType type, GhostType ghost_type = _not_ghost) const
+ -> bool;
/*! get the stored data corresponding to a type
* @param type the type to check for
* @param ghost_type optional: by default, the data map for non-ghost
* elements is searched
* @return stored data corresponding to type. */
- inline const Stored & operator()(const SupportType & type,
- GhostType ghost_type = _not_ghost) const;
+ inline auto operator()(SupportType type,
+ GhostType ghost_type = _not_ghost) const
+ -> const Stored &;
/*! get the stored data corresponding to a type
* @param type the type to check for
* @param ghost_type optional: by default, the data map for non-ghost
* elements is searched
* @return stored data corresponding to type. */
- inline Stored & operator()(const SupportType & type,
- GhostType ghost_type = _not_ghost);
+ inline auto operator()(SupportType type, GhostType ghost_type = _not_ghost)
+ -> Stored &;
/*! insert data of a new type (not yet present) into the map. THIS METHOD IS
* NOT ARRAY SAFE, when using ElementTypeMapArray, use setArray instead
* @param data to insert
* @param type type of data (if this type is already present in the map,
* an exception is thrown).
* @param ghost_type optional: by default, the data map for non-ghost
* elements is searched
* @return stored data corresponding to type. */
template <typename U>
- inline Stored & operator()(U && insertee, const SupportType & type,
- GhostType ghost_type = _not_ghost);
+ inline auto operator()(U && insertee, SupportType type,
+ GhostType ghost_type = _not_ghost) -> Stored &;
public:
/// print helper
virtual void printself(std::ostream & stream, int indent = 0) const;
/* ------------------------------------------------------------------------ */
/* Element type Iterator */
/* ------------------------------------------------------------------------ */
/*! iterator allows to iterate over type-data pairs of the map. The interface
* expects the SupportType to be ElementType. */
using DataMap = std::map<SupportType, Stored>;
/// helper class to use in range for constructions
class type_iterator {
public:
using value_type = const SupportType;
using pointer = const SupportType *;
- using reference = const SupportType &;
+ using reference = SupportType;
+ using iterator_category = std::input_iterator_tag;
+ using difference_type = Int;
protected:
using DataMapIterator =
typename ElementTypeMap<Stored>::DataMap::const_iterator;
public:
type_iterator(DataMapIterator & list_begin, DataMapIterator & list_end,
- UInt dim, ElementKind ek);
+ Int dim, ElementKind ek);
type_iterator(const type_iterator & it);
type_iterator() = default;
- inline reference operator*();
- inline reference operator*() const;
- inline type_iterator & operator++();
- type_iterator operator++(int);
- inline bool operator==(const type_iterator & other) const;
- inline bool operator!=(const type_iterator & other) const;
- type_iterator & operator=(const type_iterator & it);
+ inline auto operator*() -> reference;
+ inline auto operator*() const -> reference;
+ inline auto operator++() -> type_iterator &;
+ auto operator++(int) -> type_iterator;
+ inline auto operator==(const type_iterator & other) const -> bool;
+ inline auto operator!=(const type_iterator & other) const -> bool;
+ auto operator=(const type_iterator & other) -> type_iterator &;
private:
DataMapIterator list_begin;
DataMapIterator list_end;
- UInt dim;
+ Int dim;
ElementKind kind;
};
/// helper class to use in range for constructions
class ElementTypesIteratorHelper {
public:
using Container = ElementTypeMap<Stored, SupportType>;
using iterator = typename Container::type_iterator;
- ElementTypesIteratorHelper(const Container & container, UInt dim,
+ ElementTypesIteratorHelper(const Container & container, Int dim,
GhostType ghost_type, ElementKind kind)
: container(std::cref(container)), dim(dim), ghost_type(ghost_type),
kind(kind) {}
template <typename... pack>
ElementTypesIteratorHelper(const Container & container,
use_named_args_t /*unused*/, pack &&... _pack)
: ElementTypesIteratorHelper(
container, OPTIONAL_NAMED_ARG(spatial_dimension, _all_dimensions),
OPTIONAL_NAMED_ARG(ghost_type, _not_ghost),
OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined)) {}
ElementTypesIteratorHelper(const ElementTypesIteratorHelper &) = default;
- ElementTypesIteratorHelper &
- operator=(const ElementTypesIteratorHelper &) = default;
- ElementTypesIteratorHelper &
- operator=(ElementTypesIteratorHelper &&) noexcept = default;
+ auto operator=(const ElementTypesIteratorHelper &)
+ -> ElementTypesIteratorHelper & = default;
+ auto operator=(ElementTypesIteratorHelper &&) noexcept
+ -> ElementTypesIteratorHelper & = default;
- iterator begin();
- iterator end();
+ auto begin() -> iterator;
+ auto end() -> iterator;
private:
std::reference_wrapper<const Container> container;
- UInt dim;
+ Int dim;
GhostType ghost_type;
ElementKind kind;
};
private:
- ElementTypesIteratorHelper
- elementTypesImpl(UInt dim = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind kind = _ek_not_defined) const;
+ auto elementTypesImpl(Int dim = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind kind = _ek_not_defined) const
+ -> ElementTypesIteratorHelper;
template <typename... pack>
- ElementTypesIteratorHelper
- elementTypesImpl(const use_named_args_t & /*unused*/, pack &&... _pack) const;
+ auto elementTypesImpl(const use_named_args_t & /*unused*/,
+ pack &&... _pack) const -> ElementTypesIteratorHelper;
public:
/*!
* \param _pack
* \parblock
* represent optional parameters:
* \li \c _spatial_dimension filter for elements of given spatial
* dimension
* \li \c _ghost_type filter for a certain ghost_type
* \li \c _element_kind filter for elements of given kind
* \endparblock
*/
template <typename... pack>
- std::enable_if_t<are_named_argument<pack...>::value,
- ElementTypesIteratorHelper>
- elementTypes(pack &&... _pack) const {
+ auto elementTypes(pack &&... _pack) const
+ -> std::enable_if_t<are_named_argument<pack...>::value,
+ ElementTypesIteratorHelper> {
return elementTypesImpl(use_named_args,
std::forward<decltype(_pack)>(_pack)...);
}
template <typename... pack>
- std::enable_if_t<not are_named_argument<pack...>::value,
- ElementTypesIteratorHelper>
- elementTypes(pack &&... _pack) const {
+ auto elementTypes(pack &&... _pack) const
+ -> std::enable_if_t<not are_named_argument<pack...>::value,
+ ElementTypesIteratorHelper> {
return elementTypesImpl(std::forward<decltype(_pack)>(_pack)...);
}
/*! Get an iterator to the beginning of a subset datamap. This method expects
* the SupportType to be ElementType.
* @param dim optional: iterate over data of dimension dim (e.g. when
* iterating over (surface) facets of a 3D mesh, dim would be 2).
* by default, all dimensions are considered.
* @param ghost_type optional: by default, the data map for non-ghost
* elements is iterated over.
* @param kind optional: the kind of element to search for (see
* aka_common.hh), by default all kinds are considered
* @return an iterator to the first stored data matching the filters
* or an iterator to the end of the map if none match*/
- [[deprecated("Use elementTypes instead")]] inline type_iterator
- firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost,
- ElementKind kind = _ek_not_defined) const;
+ [[deprecated("Use elementTypes instead")]] inline auto
+ firstType(Int dim = _all_dimensions, GhostType ghost_type = _not_ghost,
+ ElementKind kind = _ek_not_defined) const -> type_iterator;
/*! Get an iterator to the end of a subset datamap. This method expects
* the SupportType to be ElementType.
* @param dim optional: iterate over data of dimension dim (e.g. when
* iterating over (surface) facets of a 3D mesh, dim would be 2).
* by default, all dimensions are considered.
* @param ghost_type optional: by default, the data map for non-ghost
* elements is iterated over.
* @param kind optional: the kind of element to search for (see
* aka_common.hh), by default all kinds are considered
* @return an iterator to the last stored data matching the filters
* or an iterator to the end of the map if none match */
- [[deprecated("Use elementTypes instead")]] inline type_iterator
- lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost,
- ElementKind kind = _ek_not_defined) const;
+ [[deprecated("Use elementTypes instead")]] inline auto
+ lastType(Int dim = _all_dimensions, GhostType ghost_type = _not_ghost,
+ ElementKind kind = _ek_not_defined) const -> type_iterator;
/*! Direct access to the underlying data map. for internal use by daughter
* classes only
* @param ghost_type whether to return the data map or the ghost_data map
* @return the raw map */
- inline DataMap & getData(GhostType ghost_type);
+ inline auto getData(GhostType ghost_type) -> DataMap &;
/*! Direct access to the underlying data map. for internal use by daughter
* classes only
* @param ghost_type whether to return the data map or the ghost_data map
* @return the raw map */
- inline const DataMap & getData(GhostType ghost_type) const;
+ inline auto getData(GhostType ghost_type) const -> const DataMap &;
/* ------------------------------------------------------------------------ */
protected:
DataMap data;
DataMap ghost_data;
};
/* -------------------------------------------------------------------------- */
/* Some typedefs */
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
class ElementTypeMapArray
: public ElementTypeMap<std::unique_ptr<Array<T>>, SupportType> {
public:
using value_type = T;
using array_type = Array<T>;
protected:
using parent = ElementTypeMap<std::unique_ptr<Array<T>>, SupportType>;
using DataMap = typename parent::DataMap;
public:
using type_iterator = typename parent::type_iterator;
/// standard assigment (copy) operator
auto operator=(const ElementTypeMapArray & other) -> ElementTypeMapArray &;
ElementTypeMapArray(const ElementTypeMapArray & other);
/// explicit copy
void copy(const ElementTypeMapArray & other);
/*! Constructor
* @param id optional: identifier (string)
* @param parent_id optional: parent identifier. for organizational purposes
* only
*/
ElementTypeMapArray(const ID & id = "by_element_type_array",
const ID & parent_id = "no_parent")
: parent(), id(parent_id + ":" + id), name(id){};
/*! allocate memory for a new array
* @param size number of tuples of the new array
* @param nb_component tuple size
* @param type the type under which the array is indexed in the map
* @param ghost_type whether to add the field to the data map or the
* ghost_data map
* @param default_value the default value to use to fill the array
* @return a reference to the allocated array */
- inline Array<T> & alloc(UInt size, UInt nb_component,
- const SupportType & type, GhostType ghost_type,
- const T & default_value = T());
+ inline auto alloc(Int size, Int nb_component, SupportType type,
+ GhostType ghost_type, const T & default_value = T())
+ -> Array<T> &;
/*! allocate memory for a new array in both the data and the ghost_data map
* @param size number of tuples of the new array
* @param nb_component tuple size
- * @param type the type under which the array is indexed in the map
- * @param default_value the default value to use to fill the array
- */
- inline void alloc(UInt size, UInt nb_component, const SupportType & type,
+ * @param type the type under which the array is indexed in the map*/
+ inline void alloc(Int size, Int nb_component, SupportType type,
const T & default_value = T());
/* get a reference to the array of certain type
* @param type data filed under type is returned
* @param ghost_type optional: by default the non-ghost map is searched
* @return a reference to the array */
- inline const Array<T> & operator()(const SupportType & type,
- GhostType ghost_type = _not_ghost) const;
+ inline auto operator()(SupportType type,
+ GhostType ghost_type = _not_ghost) const
+ -> const Array<T> &;
+
+ /// access the data of an element, this combine the map and array accessor
+ inline auto operator()(const Element & element, Int component = 0) const
+ -> const T &;
+
+ /// access the data of an element, this combine the map and array accessor
+ inline auto operator()(const Element & element, Int component = 0) -> T &;
/// access the data of an element, this combine the map and array accessor
- inline const T & operator()(const Element & element,
- UInt component = 0) const;
+ inline auto operator()(const IntegrationPoint & point,
+ Int component = 0) const -> const T &;
/// access the data of an element, this combine the map and array accessor
- inline T & operator()(const Element & element, UInt component = 0);
+ inline auto operator()(const IntegrationPoint & point, Int component = 0)
+ -> T &;
/// access the data of an element, this combine the map and array accessor
inline decltype(auto) get(const Element & element);
inline decltype(auto) get(const Element & element) const;
+ inline decltype(auto) get(const IntegrationPoint & point);
+ inline decltype(auto) get(const IntegrationPoint & point) const;
+
+ template <typename... Ns,
+ std::enable_if_t<
+ std::conjunction_v<std::is_integral<std::decay_t<Ns>>...> and
+ sizeof...(Ns) >= 1> * = nullptr>
+ inline decltype(auto) get(const Element & element, Ns &&... ns);
+ template <typename... Ns,
+ std::enable_if_t<
+ std::conjunction_v<std::is_integral<std::decay_t<Ns>>...> and
+ sizeof...(Ns) >= 1> * = nullptr>
+ inline decltype(auto) get(const Element & element, Ns &&... ns) const;
+
/* get a reference to the array of certain type
* @param type data filed under type is returned
* @param ghost_type optional: by default the non-ghost map is searched
* @return a const reference to the array */
- inline Array<T> & operator()(const SupportType & type,
- GhostType ghost_type = _not_ghost);
+ inline auto operator()(SupportType type, GhostType ghost_type = _not_ghost)
+ -> Array<T> &;
/*! insert data of a new type (not yet present) into the map.
* @param type type of data (if this type is already present in the map,
* an exception is thrown).
* @param ghost_type optional: by default, the data map for non-ghost
* elements is searched
* @param vect the vector to include into the map
* @return stored data corresponding to type. */
- inline void setArray(const SupportType & type, GhostType ghost_type,
+ inline void setArray(SupportType type, GhostType ghost_type,
const Array<T> & vect);
/*! frees all memory related to the data*/
inline void free();
inline void clear();
inline bool empty() const __attribute__((warn_unused_result));
/*! set all values in the ElementTypeMap to zero*/
inline void zero() { this->set(T()); }
/*! set all values in the ElementTypeMap to value */
template <typename ST> inline void set(const ST & value);
/*! deletes and reorders entries in the stored arrays
* @param new_numbering a ElementTypeMapArray of new indices. UInt(-1)
* indicates
* deleted entries. */
- inline void
- onElementsRemoved(const ElementTypeMapArray<UInt> & new_numbering);
+ inline void onElementsRemoved(const ElementTypeMapArray<Int> & new_numbering);
/// text output helper
void printself(std::ostream & stream, int indent = 0) const override;
/*! set the id
* @param id the new name
*/
inline void setID(const ID & id) { this->id = id; }
/// return the id
inline auto getID() const -> ID { return this->id; }
- ElementTypeMap<UInt>
- getNbComponents(UInt dim = _all_dimensions,
- GhostType requested_ghost_type = _not_ghost,
- ElementKind kind = _ek_not_defined) const {
- ElementTypeMap<UInt> nb_components;
- bool all_ghost_types = requested_ghost_type == _casper;
+ auto getNbComponents(Int dim = _all_dimensions,
+ GhostType requested_ghost_type = _not_ghost,
+ ElementKind kind = _ek_not_defined) const
+ -> ElementTypeMap<Int> {
+ ElementTypeMap<Int> nb_components;
+ auto all_ghost_types = requested_ghost_type == _casper;
for (auto ghost_type : ghost_types) {
if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types)) {
continue;
}
- for (auto & type : this->elementTypes(dim, ghost_type, kind)) {
- UInt nb_comp = (*this)(type, ghost_type).getNbComponent();
+ for (const auto & type : this->elementTypes(dim, ghost_type, kind)) {
+ auto nb_comp = (*this)(type, ghost_type).getNbComponent();
nb_components(type, ghost_type) = nb_comp;
}
}
return nb_components;
}
/* ------------------------------------------------------------------------ */
/* more evolved allocators */
/* ------------------------------------------------------------------------ */
public:
/// initialize the arrays in accordance to a functor
template <class Func>
void initialize(const Func & f, const T & default_value, bool do_not_default);
/// initialize with sizes and number of components in accordance of a mesh
/// content
template <typename... pack>
void initialize(const Mesh & mesh, pack &&... _pack);
/// initialize with sizes and number of components in accordance of a fe
/// engine content (aka integration points)
template <typename... pack>
void initialize(const FEEngine & fe_engine, pack &&... _pack);
/* ------------------------------------------------------------------------ */
/* Accesssors */
/* ------------------------------------------------------------------------ */
public:
/// get the name of the internal field
AKANTU_GET_MACRO(Name, name, ID);
/**
* get the size of the ElementTypeMapArray<T>
* @param[in] _pack
* \parblock
* optional arguments can be any of:
* \li \c _spatial_dimension the dimension to consider (default:
* _all_dimensions)
* \li \c _ghost_type (default: _not_ghost)
* \li \c _element_kind (default: _ek_not_defined)
* \li \c _all_ghost_types (default: false)
* \endparblock
**/
- template <typename... pack> UInt size(pack &&... _pack) const;
+ template <typename... pack> auto size(pack &&... _pack) const -> Int;
- bool isNodal() const { return is_nodal; }
+ auto isNodal() const -> bool { return is_nodal; }
void isNodal(bool is_nodal) { this->is_nodal = is_nodal; }
private:
- UInt sizeImpl(UInt spatial_dimension, GhostType ghost_type,
- ElementKind kind) const;
+ auto sizeImpl(Int spatial_dimension, GhostType ghost_type,
+ ElementKind kind) const -> Int;
private:
ID id;
protected:
/// name of the element type map: e.g. connectivity, grad_u
ID name;
/// Is the data stored by node of the element
bool is_nodal{false};
};
/// to store data Array<Real> by element type
using ElementTypeMapReal = ElementTypeMapArray<Real>;
/// to store data Array<Int> by element type
using ElementTypeMapInt = ElementTypeMapArray<Int>;
/// to store data Array<UInt> by element type
-using ElementTypeMapUInt = ElementTypeMapArray<UInt, ElementType>;
+using ElementTypeMapUInt = ElementTypeMapArray<UInt>;
+/// to store data Array<Idx> by element type
+using ElementTypeMapIdx = ElementTypeMapArray<Idx>;
} // namespace akantu
+// namespace std {
+// template <class Stored, typename SupportType>
+// struct iterator_traits<
+// ::akantu::template ElementTypeMap<Stored, SupportType>::type_iterator> {
+// private:
+// using iterator_type =
+// typename ::akantu::ElementTypeMap<Stored, SupportType>::type_iterator;
+
+// public:
+// using iterator_category = typename iterator_type::iterator_category;
+// using value_type = typename iterator_type::value_type;
+// using difference_type = typename iterator_type::difference_type;
+// using pointer = typename iterator_type::pointer;
+// using reference = typename iterator_type::reference;
+// };
+// } // namespace std
+
#endif /* AKANTU_ELEMENT_TYPE_MAP_HH_ */
diff --git a/src/mesh/element_type_map_filter.hh b/src/mesh/element_type_map_filter.hh
index 2ad599dc2..513e83ff8 100644
--- a/src/mesh/element_type_map_filter.hh
+++ b/src/mesh/element_type_map_filter.hh
@@ -1,130 +1,126 @@
/**
* @file element_type_map_filter.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 02 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Filtered version based on a an akantu::ElementGroup of a
* akantu::ElementTypeMap
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_array_filter.hh"
+//#include "aka_array_filter.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_BY_ELEMENT_TYPE_FILTER_HH_
#define AKANTU_BY_ELEMENT_TYPE_FILTER_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/* ElementTypeMapFilter */
/* -------------------------------------------------------------------------- */
-
template <class T, typename SupportType = ElementType>
class ElementTypeMapArrayFilter {
-
/* ------------------------------------------------------------------------ */
/* Typedefs */
/* ------------------------------------------------------------------------ */
-
public:
using array_type = ArrayFilter<T>;
using value_type = typename array_type::value_type;
using type_iterator =
- typename ElementTypeMapArray<UInt, SupportType>::type_iterator;
+ typename ElementTypeMapArray<Idx, SupportType>::type_iterator;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
ElementTypeMapArrayFilter(
const ElementTypeMapArray<T, SupportType> & array,
- const ElementTypeMapArray<UInt, SupportType> & filter,
- const ElementTypeMap<UInt, SupportType> & nb_data_per_elem)
+ const ElementTypeMapArray<Idx, SupportType> & filter,
+ const ElementTypeMap<Int, SupportType> & nb_data_per_elem)
: array(array), filter(filter), nb_data_per_elem(nb_data_per_elem) {}
ElementTypeMapArrayFilter(
const ElementTypeMapArray<T, SupportType> & array,
- const ElementTypeMapArray<UInt, SupportType> & filter)
+ const ElementTypeMapArray<Idx, SupportType> & filter)
: array(array), filter(filter) {}
~ElementTypeMapArrayFilter() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
-
- inline ArrayFilter<T> operator()(const SupportType & type,
- GhostType ghost_type = _not_ghost) const {
+public:
+ inline const ArrayFilter<T>
+ operator()(SupportType type, GhostType ghost_type = _not_ghost) const {
if (filter.exists(type, ghost_type)) {
+ Int nb_comp = 1;
+ auto && array_v = array(type, ghost_type);
if (nb_data_per_elem.exists(type, ghost_type)) {
- return ArrayFilter<T>(array(type, ghost_type), filter(type, ghost_type),
- nb_data_per_elem(type, ghost_type) /
- array(type, ghost_type).getNbComponent());
+ nb_comp = nb_data_per_elem(type, ghost_type) / array_v.getNbComponent();
}
- return ArrayFilter<T>(array(type, ghost_type), filter(type, ghost_type),
- 1);
+ return ArrayFilter<T>(array_v, filter(type, ghost_type), nb_comp);
}
return ArrayFilter<T>(empty_array, empty_filter, 1);
};
template <typename... Args>
decltype(auto) elementTypes(Args &&... args) const {
return filter.elementTypes(std::forward<decltype(args)>(args)...);
}
- decltype(auto) getNbComponents(UInt dim = _all_dimensions,
+ decltype(auto) getNbComponents(Int dim = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_not_defined) const {
return this->array.getNbComponents(dim, ghost_type, kind);
};
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
std::string getID() {
return std::string("filtered:" + this->array().getID());
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
const ElementTypeMapArray<T, SupportType> & array;
- const ElementTypeMapArray<UInt, SupportType> & filter;
- ElementTypeMap<UInt> nb_data_per_elem;
+ const ElementTypeMapArray<Idx, SupportType> & filter;
+ ElementTypeMap<Int> nb_data_per_elem;
/// Empty array to be able to return consistent filtered arrays
Array<T> empty_array;
- Array<UInt> empty_filter;
+ Array<Idx> empty_filter;
};
} // namespace akantu
#endif /* AKANTU_BY_ELEMENT_TYPE_FILTER_HH_ */
diff --git a/src/mesh/element_type_map_tmpl.hh b/src/mesh/element_type_map_tmpl.hh
index eb6ac82c5..edad7251f 100644
--- a/src/mesh/element_type_map_tmpl.hh
+++ b/src/mesh/element_type_map_tmpl.hh
@@ -1,867 +1,935 @@
/**
* @file element_type_map_tmpl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 31 2011
* @date last modification: Thu Mar 11 2021
*
* @brief implementation of template functions of the ElementTypeMap and
* ElementTypeMapArray classes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_static_if.hh"
-#include "element_type_map.hh"
-#include "mesh.hh"
+#include "integration_point.hh"
+//#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include "element_type_conversion.hh"
/* -------------------------------------------------------------------------- */
#include <functional>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_TYPE_MAP_TMPL_HH_
#define AKANTU_ELEMENT_TYPE_MAP_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* ElementTypeMap */
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline std::string
-ElementTypeMap<Stored, SupportType>::printType(const SupportType & type,
+ElementTypeMap<Stored, SupportType>::printType(SupportType type,
GhostType ghost_type) {
std::stringstream sstr;
sstr << "(" << ghost_type << ":" << type << ")";
return sstr.str();
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline bool
-ElementTypeMap<Stored, SupportType>::exists(const SupportType & type,
+ElementTypeMap<Stored, SupportType>::exists(SupportType type,
GhostType ghost_type) const {
return this->getData(ghost_type).find(type) !=
this->getData(ghost_type).end();
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline const Stored &
-ElementTypeMap<Stored, SupportType>::operator()(const SupportType & type,
+ElementTypeMap<Stored, SupportType>::operator()(SupportType type,
GhostType ghost_type) const {
auto it = this->getData(ghost_type).find(type);
if (it == this->getData(ghost_type).end()) {
AKANTU_SILENT_EXCEPTION("No element of type "
<< ElementTypeMap::printType(type, ghost_type)
<< " in this ElementTypeMap<"
<< debug::demangle(typeid(Stored).name())
<< "> class");
}
return it->second;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline Stored &
-ElementTypeMap<Stored, SupportType>::operator()(const SupportType & type,
+ElementTypeMap<Stored, SupportType>::operator()(SupportType type,
GhostType ghost_type) {
return this->getData(ghost_type)[type];
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
template <typename U>
-inline Stored & ElementTypeMap<Stored, SupportType>::operator()(
- U && insertee, const SupportType & type, GhostType ghost_type) {
+inline Stored &
+ElementTypeMap<Stored, SupportType>::operator()(U && insertee, SupportType type,
+ GhostType ghost_type) {
auto it = this->getData(ghost_type).find(type);
if (it != this->getData(ghost_type).end()) {
AKANTU_SILENT_EXCEPTION("Element of type "
<< ElementTypeMap::printType(type, ghost_type)
<< " already in this ElementTypeMap<"
<< debug::demangle(typeid(Stored).name())
<< "> class");
} else {
auto & data = this->getData(ghost_type);
const auto & res =
data.insert(std::make_pair(type, std::forward<U>(insertee)));
it = res.first;
}
return it->second;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline typename ElementTypeMap<Stored, SupportType>::DataMap &
ElementTypeMap<Stored, SupportType>::getData(GhostType ghost_type) {
if (ghost_type == _not_ghost) {
return data;
}
return ghost_data;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline const typename ElementTypeMap<Stored, SupportType>::DataMap &
ElementTypeMap<Stored, SupportType>::getData(GhostType ghost_type) const {
if (ghost_type == _not_ghost) {
return data;
}
return ghost_data;
}
/* -------------------------------------------------------------------------- */
/// Works only if stored is a pointer to a class with a printself method
template <class Stored, typename SupportType>
void ElementTypeMap<Stored, SupportType>::printself(std::ostream & stream,
int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "ElementTypeMap<" << debug::demangle(typeid(Stored).name())
<< "> [" << std::endl;
for (auto && gt : ghost_types) {
const DataMap & data = getData(gt);
for (auto & pair : data) {
stream << space << space << ElementTypeMap::printType(pair.first, gt)
<< std::endl;
}
}
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
ElementTypeMap<Stored, SupportType>::ElementTypeMap() = default;
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
ElementTypeMap<Stored, SupportType>::~ElementTypeMap() = default;
/* -------------------------------------------------------------------------- */
/* ElementTypeMapArray */
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
void ElementTypeMapArray<T, SupportType>::copy(
const ElementTypeMapArray & other) {
for (auto ghost_type : ghost_types) {
for (auto type :
this->elementTypes(_all_dimensions, ghost_type, _ek_not_defined)) {
const auto & array_to_copy = other(type, ghost_type);
auto & array =
this->alloc(0, array_to_copy.getNbComponent(), type, ghost_type);
array.copy(array_to_copy);
}
}
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
ElementTypeMapArray<T, SupportType>::ElementTypeMapArray(
const ElementTypeMapArray & other)
: parent(), id(other.id + "_copy"), name(other.name + "_copy") {
this->copy(other);
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
auto ElementTypeMapArray<T, SupportType>::operator=(
const ElementTypeMapArray & other) -> ElementTypeMapArray & {
if (this != &other) {
AKANTU_DEBUG_WARNING("You are copying the ElementTypeMapArray "
<< this->id << " are you sure it is on purpose");
this->id = other.id + "_copy";
this->name = other.name + "_copy";
this->copy(other);
}
return *this;
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline Array<T> & ElementTypeMapArray<T, SupportType>::alloc(
- UInt size, UInt nb_component, const SupportType & type,
- GhostType ghost_type, const T & default_value) {
+ Int size, Int nb_component, SupportType type, GhostType ghost_type,
+ const T & default_value) {
std::string ghost_id;
if (ghost_type == _ghost) {
ghost_id = ":ghost";
}
auto it = this->getData(ghost_type).find(type);
if (it == this->getData(ghost_type).end()) {
auto id = this->id + ":" + std::to_string(type) + ghost_id;
this->getData(ghost_type)[type] =
std::make_unique<Array<T>>(size, nb_component, default_value, id);
return *(this->getData(ghost_type)[type]);
}
AKANTU_DEBUG_INFO("The vector "
<< this->id << this->printType(type, ghost_type)
<< " already exists, it is resized instead of allocated.");
auto && array = *(it->second);
array.resize(size);
return array;
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
-inline void
-ElementTypeMapArray<T, SupportType>::alloc(UInt size, UInt nb_component,
- const SupportType & type,
- const T & default_value) {
+inline void ElementTypeMapArray<T, SupportType>::alloc(
+ Int size, Int nb_component, SupportType type, const T & default_value) {
this->alloc(size, nb_component, type, _not_ghost, default_value);
this->alloc(size, nb_component, type, _ghost, default_value);
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline void ElementTypeMapArray<T, SupportType>::free() {
AKANTU_DEBUG_IN();
for (auto gt : ghost_types) {
auto & data = this->getData(gt);
data.clear();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline void ElementTypeMapArray<T, SupportType>::clear() {
for (auto gt : ghost_types) {
auto & data = this->getData(gt);
for (auto & vect : data) {
vect.second->clear();
}
}
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline bool ElementTypeMapArray<T, SupportType>::empty() const {
bool is_empty = true;
for (auto gt : ghost_types) {
auto & data = this->getData(gt);
for (auto & vect : data) {
is_empty &= vect.second->empty();
if (not is_empty) {
return false;
}
}
}
return is_empty;
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
template <typename ST>
inline void ElementTypeMapArray<T, SupportType>::set(const ST & value) {
for (auto gt : ghost_types) {
auto & data = this->getData(gt);
for (auto & vect : data) {
vect.second->set(value);
}
}
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline const Array<T> &
-ElementTypeMapArray<T, SupportType>::operator()(const SupportType & type,
+ElementTypeMapArray<T, SupportType>::operator()(SupportType type,
GhostType ghost_type) const {
auto it = this->getData(ghost_type).find(type);
if (it == this->getData(ghost_type).end()) {
AKANTU_SILENT_EXCEPTION("No element of type "
<< ElementTypeMapArray::printType(type, ghost_type)
<< " in this const ElementTypeMapArray<"
<< debug::demangle(typeid(T).name()) << "> class(\""
<< this->id << "\")");
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline Array<T> &
-ElementTypeMapArray<T, SupportType>::operator()(const SupportType & type,
+ElementTypeMapArray<T, SupportType>::operator()(SupportType type,
GhostType ghost_type) {
auto it = this->getData(ghost_type).find(type);
if (it == this->getData(ghost_type).end()) {
AKANTU_SILENT_EXCEPTION("No element of type "
<< ElementTypeMapArray::printType(type, ghost_type)
<< " in this ElementTypeMapArray<"
<< debug::demangle(typeid(T).name())
<< "> class (\"" << this->id << "\")");
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline void ElementTypeMapArray<T, SupportType>::setArray(
- const SupportType & type, GhostType ghost_type, const Array<T> & vect) {
+ SupportType type, GhostType ghost_type, const Array<T> & vect) {
auto it = this->getData(ghost_type).find(type);
if (AKANTU_DEBUG_TEST(dblWarning) && it != this->getData(ghost_type).end() &&
it->second != &vect) {
AKANTU_DEBUG_WARNING(
"The Array "
<< this->printType(type, ghost_type)
<< " is already registred, this call can lead to a memory leak.");
}
this->getData(ghost_type)[type] = &(const_cast<Array<T> &>(vect));
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline void ElementTypeMapArray<T, SupportType>::onElementsRemoved(
- const ElementTypeMapArray<UInt> & new_numbering) {
+ const ElementTypeMapArray<Idx> & new_numbering) {
for (auto gt : ghost_types) {
for (auto && type :
new_numbering.elementTypes(_all_dimensions, gt, _ek_not_defined)) {
auto support_type = convertType<ElementType, SupportType>(type);
if (this->exists(support_type, gt)) {
const auto & renumbering = new_numbering(type, gt);
if (renumbering.empty()) {
continue;
}
auto & vect = this->operator()(support_type, gt);
+ auto nb_entry_per_element = vect.size() / renumbering.size();
auto nb_component = vect.getNbComponent();
- Array<T> tmp(renumbering.size(), nb_component);
- UInt new_size = 0;
-
- for (UInt i = 0; i < vect.size(); ++i) {
- UInt new_i = renumbering(i);
- if (new_i != UInt(-1)) {
- std::copy_n(vect.storage() + i * nb_component, nb_component,
- tmp.storage() + new_i * nb_component);
+
+ Array<T> tmp(renumbering.size() * nb_entry_per_element, nb_component);
+ auto tmp_it =
+ make_view(tmp, nb_entry_per_element * nb_component).begin();
+ Int new_size = 0;
+
+ for (auto && data :
+ zip(renumbering,
+ make_view(vect, nb_entry_per_element * nb_component))) {
+ auto new_i = std::get<0>(data);
+ if (new_i != -1) {
+ tmp_it[new_i] = std::get<1>(data);
++new_size;
}
}
tmp.resize(new_size);
vect.copy(tmp);
}
}
}
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
void ElementTypeMapArray<T, SupportType>::printself(std::ostream & stream,
int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "ElementTypeMapArray<" << debug::demangle(typeid(T).name())
<< "> [" << std::endl;
for (UInt g = _not_ghost; g <= _ghost; ++g) {
auto gt = (GhostType)g;
const DataMap & data = this->getData(gt);
typename DataMap::const_iterator it;
for (it = data.begin(); it != data.end(); ++it) {
stream << space << space << ElementTypeMapArray::printType(it->first, gt)
<< " [" << std::endl;
it->second->printself(stream, indent + 3);
stream << space << space << " ]" << std::endl;
}
}
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
/* SupportType Iterator */
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
ElementTypeMap<Stored, SupportType>::type_iterator::type_iterator(
- DataMapIterator & list_begin, DataMapIterator & list_end, UInt dim,
+ DataMapIterator & list_begin, DataMapIterator & list_end, Int dim,
ElementKind ek)
: list_begin(list_begin), list_end(list_end), dim(dim), kind(ek) {}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
ElementTypeMap<Stored, SupportType>::type_iterator::type_iterator(
const type_iterator & it)
: list_begin(it.list_begin), list_end(it.list_end), dim(it.dim),
kind(it.kind) {}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
typename ElementTypeMap<Stored, SupportType>::type_iterator &
ElementTypeMap<Stored, SupportType>::type_iterator::operator=(
const type_iterator & it) {
if (this != &it) {
list_begin = it.list_begin;
list_end = it.list_end;
dim = it.dim;
kind = it.kind;
}
return *this;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline typename ElementTypeMap<Stored, SupportType>::type_iterator::reference
ElementTypeMap<Stored, SupportType>::type_iterator::operator*() {
return list_begin->first;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline typename ElementTypeMap<Stored, SupportType>::type_iterator::reference
ElementTypeMap<Stored, SupportType>::type_iterator::operator*() const {
return list_begin->first;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline typename ElementTypeMap<Stored, SupportType>::type_iterator &
ElementTypeMap<Stored, SupportType>::type_iterator::operator++() {
++list_begin;
while ((list_begin != list_end) &&
(((dim != _all_dimensions) &&
(dim != Mesh::getSpatialDimension(list_begin->first))) ||
((kind != _ek_not_defined) &&
(kind != Mesh::getKind(list_begin->first))))) {
++list_begin;
}
return *this;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
typename ElementTypeMap<Stored, SupportType>::type_iterator
ElementTypeMap<Stored, SupportType>::type_iterator::operator++(int) {
type_iterator tmp(*this);
operator++();
return tmp;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline bool ElementTypeMap<Stored, SupportType>::type_iterator::operator==(
const type_iterator & other) const {
return this->list_begin == other.list_begin;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline bool ElementTypeMap<Stored, SupportType>::type_iterator::operator!=(
const type_iterator & other) const {
return this->list_begin != other.list_begin;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
auto ElementTypeMap<Stored, SupportType>::ElementTypesIteratorHelper::begin()
-> iterator {
auto b = container.get().getData(ghost_type).begin();
auto e = container.get().getData(ghost_type).end();
// loop until the first valid type
while ((b != e) &&
(((dim != _all_dimensions) &&
(dim != Mesh::getSpatialDimension(b->first))) ||
((kind != _ek_not_defined) && (kind != Mesh::getKind(b->first))))) {
++b;
}
return iterator(b, e, dim, kind);
}
template <class Stored, typename SupportType>
auto ElementTypeMap<Stored, SupportType>::ElementTypesIteratorHelper::end()
-> iterator {
auto e = container.get().getData(ghost_type).end();
return iterator(e, e, dim, kind);
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
auto ElementTypeMap<Stored, SupportType>::elementTypesImpl(
- UInt dim, GhostType ghost_type, ElementKind kind) const
+ Int dim, GhostType ghost_type, ElementKind kind) const
-> ElementTypesIteratorHelper {
return ElementTypesIteratorHelper(*this, dim, ghost_type, kind);
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
template <typename... pack>
auto ElementTypeMap<Stored, SupportType>::elementTypesImpl(
const use_named_args_t & unused, pack &&... _pack) const
-> ElementTypesIteratorHelper {
return ElementTypesIteratorHelper(*this, unused, _pack...);
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline auto ElementTypeMap<Stored, SupportType>::firstType(
- UInt dim, GhostType ghost_type, ElementKind kind) const -> type_iterator {
+ Int dim, GhostType ghost_type, ElementKind kind) const -> type_iterator {
return elementTypes(dim, ghost_type, kind).begin();
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
inline auto ElementTypeMap<Stored, SupportType>::lastType(
- UInt dim, GhostType ghost_type, ElementKind kind) const -> type_iterator {
+ Int dim, GhostType ghost_type, ElementKind kind) const -> type_iterator {
typename DataMap::const_iterator e;
e = getData(ghost_type).end();
return typename ElementTypeMap<Stored, SupportType>::type_iterator(e, e, dim,
kind);
}
/* -------------------------------------------------------------------------- */
/// standard output stream operator
template <class Stored, typename SupportType>
inline std::ostream &
operator<<(std::ostream & stream,
const ElementTypeMap<Stored, SupportType> & _this) {
_this.printself(stream);
return stream;
}
/* -------------------------------------------------------------------------- */
class ElementTypeMapArrayInitializer {
protected:
- using CompFunc = std::function<UInt(ElementType, GhostType)>;
+ using CompFunc = std::function<Int(ElementType, GhostType)>;
public:
ElementTypeMapArrayInitializer(const CompFunc & comp_func,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined)
: comp_func(comp_func), spatial_dimension(spatial_dimension),
ghost_type(ghost_type), element_kind(element_kind) {}
GhostType ghostType() const { return ghost_type; }
- virtual UInt nbComponent(ElementType type) const {
+ virtual Int nbComponent(ElementType type) const {
return comp_func(type, ghostType());
}
virtual bool isNodal() const { return false; }
protected:
CompFunc comp_func;
- UInt spatial_dimension;
+ Int spatial_dimension;
GhostType ghost_type;
ElementKind element_kind;
};
/* -------------------------------------------------------------------------- */
class MeshElementTypeMapArrayInitializer
: public ElementTypeMapArrayInitializer {
using CompFunc = ElementTypeMapArrayInitializer::CompFunc;
public:
MeshElementTypeMapArrayInitializer(
- const Mesh & mesh, UInt nb_component = 1,
- UInt spatial_dimension = _all_dimensions,
+ const Mesh & mesh, Int nb_component = 1,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined, bool with_nb_element = false,
bool with_nb_nodes_per_element = false,
- const ElementTypeMapArray<UInt> * filter = nullptr)
+ const ElementTypeMapArray<Idx> * filter = nullptr)
: MeshElementTypeMapArrayInitializer(
mesh,
- [nb_component](ElementType /*unused*/, GhostType /*unused*/)
- -> UInt { return nb_component; },
+ [nb_component](ElementType, GhostType) -> Int {
+ return nb_component;
+ },
spatial_dimension, ghost_type, element_kind, with_nb_element,
with_nb_nodes_per_element, filter) {}
MeshElementTypeMapArrayInitializer(
const Mesh & mesh, const CompFunc & comp_func,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined, bool with_nb_element = false,
bool with_nb_nodes_per_element = false,
- const ElementTypeMapArray<UInt> * filter = nullptr)
+ const ElementTypeMapArray<Idx> * filter = nullptr)
: ElementTypeMapArrayInitializer(comp_func, spatial_dimension, ghost_type,
element_kind),
mesh(mesh), with_nb_element(with_nb_element),
with_nb_nodes_per_element(with_nb_nodes_per_element), filter(filter) {}
decltype(auto) elementTypes() const {
if (filter != nullptr) {
return filter->elementTypes(this->spatial_dimension, this->ghost_type,
this->element_kind);
}
return mesh.elementTypes(this->spatial_dimension, this->ghost_type,
this->element_kind);
}
- virtual UInt size(ElementType type) const {
+ virtual Idx size(ElementType type) const {
if (with_nb_element) {
if (filter != nullptr) {
return (*filter)(type, this->ghost_type).size();
}
return mesh.getNbElement(type, this->ghost_type);
}
return 0;
}
- UInt nbComponent(ElementType type) const override {
- UInt res = ElementTypeMapArrayInitializer::nbComponent(type);
+ Int nbComponent(ElementType type) const override {
+ auto res = ElementTypeMapArrayInitializer::nbComponent(type);
if (with_nb_nodes_per_element) {
return (res * Mesh::getNbNodesPerElement(type));
}
return res;
}
bool isNodal() const override { return with_nb_nodes_per_element; }
protected:
const Mesh & mesh;
bool with_nb_element{false};
bool with_nb_nodes_per_element{false};
- const ElementTypeMapArray<UInt> * filter{nullptr};
+ const ElementTypeMapArray<Idx> * filter{nullptr};
};
/* -------------------------------------------------------------------------- */
class FEEngineElementTypeMapArrayInitializer
: public MeshElementTypeMapArrayInitializer {
public:
FEEngineElementTypeMapArrayInitializer(
- const FEEngine & fe_engine, UInt nb_component = 1,
- UInt spatial_dimension = _all_dimensions,
+ const FEEngine & fe_engine, Int nb_component = 1,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined);
FEEngineElementTypeMapArrayInitializer(
const FEEngine & fe_engine,
const ElementTypeMapArrayInitializer::CompFunc & nb_component,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined);
- UInt size(ElementType type) const override;
+ Int size(ElementType type) const override;
using ElementTypesIteratorHelper =
ElementTypeMapArray<Real, ElementType>::ElementTypesIteratorHelper;
ElementTypesIteratorHelper elementTypes() const;
protected:
const FEEngine & fe_engine;
};
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
template <class Func>
void ElementTypeMapArray<T, SupportType>::initialize(const Func & f,
const T & default_value,
bool do_not_default) {
this->is_nodal = f.isNodal();
auto ghost_type = f.ghostType();
- for (auto & type : f.elementTypes()) {
+ for (const auto & type : f.elementTypes()) {
if (not this->exists(type, ghost_type)) {
if (do_not_default) {
auto & array = this->alloc(0, f.nbComponent(type), type, ghost_type);
array.resize(f.size(type));
} else {
this->alloc(f.size(type), f.nbComponent(type), type, ghost_type,
default_value);
}
} else {
auto & array = this->operator()(type, ghost_type);
if (not do_not_default) {
array.resize(f.size(type), default_value);
} else {
array.resize(f.size(type));
}
}
}
}
/* -------------------------------------------------------------------------- */
/**
* All parameters are named optionals
* \param _nb_component a functor giving the number of components per
* (ElementType, GhostType) pair or a scalar giving a unique number of
* components
* regardless of type
* \param _spatial_dimension a filter for the elements of a specific dimension
* \param _element_kind filter with element kind (_ek_regular, _ek_structural,
* ...)
* \param _with_nb_element allocate the arrays with the number of elements for
* each
* type in the mesh
* \param _with_nb_nodes_per_element multiply the number of components by the
* number of nodes per element
* \param _default_value default inital value
* \param _do_not_default do not initialize the allocated arrays
* \param _ghost_type filter a type of ghost
*/
template <typename T, typename SupportType>
template <typename... pack>
void ElementTypeMapArray<T, SupportType>::initialize(const Mesh & mesh,
pack &&... _pack) {
GhostType requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _casper);
bool all_ghost_types =
OPTIONAL_NAMED_ARG(all_ghost_types, requested_ghost_type == _casper);
for (GhostType ghost_type : ghost_types) {
if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types)) {
continue;
}
auto functor = MeshElementTypeMapArrayInitializer(
mesh, OPTIONAL_NAMED_ARG(nb_component, 1),
OPTIONAL_NAMED_ARG(spatial_dimension, mesh.getSpatialDimension()),
ghost_type, OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined),
OPTIONAL_NAMED_ARG(with_nb_element, false),
OPTIONAL_NAMED_ARG(with_nb_nodes_per_element, false),
OPTIONAL_NAMED_ARG(element_filter, nullptr));
this->initialize(functor, OPTIONAL_NAMED_ARG(default_value, T()),
OPTIONAL_NAMED_ARG(do_not_default, false));
}
}
/* -------------------------------------------------------------------------- */
/**
* All parameters are named optionals
* \param _nb_component a functor giving the number of components per
* (ElementType, GhostType) pair or a scalar giving a unique number of
* components
* regardless of type
* \param _spatial_dimension a filter for the elements of a specific dimension
* \param _element_kind filter with element kind (_ek_regular, _ek_structural,
* ...)
* \param _default_value default inital value
* \param _do_not_default do not initialize the allocated arrays
* \param _ghost_type filter a specific ghost type
* \param _all_ghost_types get all ghost types
*/
template <typename T, typename SupportType>
template <typename... pack>
void ElementTypeMapArray<T, SupportType>::initialize(const FEEngine & fe_engine,
pack &&... _pack) {
GhostType requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _casper);
bool all_ghost_types =
OPTIONAL_NAMED_ARG(all_ghost_types, requested_ghost_type == _casper);
for (auto ghost_type : ghost_types) {
if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types)) {
continue;
}
auto functor = FEEngineElementTypeMapArrayInitializer(
fe_engine, OPTIONAL_NAMED_ARG(nb_component, 1),
- OPTIONAL_NAMED_ARG(spatial_dimension, UInt(-2)), ghost_type,
+ OPTIONAL_NAMED_ARG(spatial_dimension, Int(-2)), ghost_type,
OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined));
this->initialize(functor, OPTIONAL_NAMED_ARG(default_value, T()),
OPTIONAL_NAMED_ARG(do_not_default, false));
}
}
/* -------------------------------------------------------------------------- */
template <class T, typename SupportType>
inline T &
ElementTypeMapArray<T, SupportType>::operator()(const Element & element,
- UInt component) {
+ Int component) {
return this->operator()(element.type, element.ghost_type)(element.element,
component);
}
/* -------------------------------------------------------------------------- */
template <class T, typename SupportType>
inline const T &
ElementTypeMapArray<T, SupportType>::operator()(const Element & element,
- UInt component) const {
+ Int component) const {
return this->operator()(element.type, element.ghost_type)(element.element,
component);
}
+/* -------------------------------------------------------------------------- */
+template <class T, typename SupportType>
+inline T &
+ElementTypeMapArray<T, SupportType>::operator()(const IntegrationPoint & point,
+ Int component) {
+ return this->operator()(point.type, point.ghost_type)(point.global_num,
+ component);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class T, typename SupportType>
+inline const T &
+ElementTypeMapArray<T, SupportType>::operator()(const IntegrationPoint & point,
+ Int component) const {
+ return this->operator()(point.type, point.ghost_type)(point.global_num,
+ component);
+}
+
/* -------------------------------------------------------------------------- */
template <class T, typename SupportType>
inline decltype(auto)
ElementTypeMapArray<T, SupportType>::get(const Element & element) {
auto & array = operator()(element.type, element.ghost_type);
auto it = array.begin(array.getNbComponent());
return it[element.element];
}
/* -------------------------------------------------------------------------- */
template <class T, typename SupportType>
inline decltype(auto)
ElementTypeMapArray<T, SupportType>::get(const Element & element) const {
- auto & array = operator()(element.type, element.ghost_type);
+ const auto & array = operator()(element.type, element.ghost_type);
+ auto it = array.begin(array.getNbComponent());
+ return it[element.element];
+}
+
+/* -------------------------------------------------------------------------- */
+template <class T, typename SupportType>
+inline decltype(auto)
+ElementTypeMapArray<T, SupportType>::get(const IntegrationPoint & point) {
+ auto & array = operator()(point.type, point.ghost_type);
+ auto it = array.begin(array.getNbComponent());
+ return it[point.global_num];
+}
+
+/* -------------------------------------------------------------------------- */
+template <class T, typename SupportType>
+inline decltype(auto)
+ElementTypeMapArray<T, SupportType>::get(const IntegrationPoint & point) const {
+ const auto & array = operator()(point.type, point.ghost_type);
auto it = array.begin(array.getNbComponent());
+ return it[point.global_num];
+}
+
+/* -------------------------------------------------------------------------- */
+template <class T, typename SupportType>
+template <typename... Ns,
+ std::enable_if_t<
+ std::conjunction_v<std::is_integral<std::decay_t<Ns>>...> and
+ sizeof...(Ns) >= 1> *>
+inline decltype(auto)
+ElementTypeMapArray<T, SupportType>::get(const Element & element, Ns &&... ns) {
+ auto & array = this->operator()(element.type, element.ghost_type);
+ auto it = make_view(array, std::forward<Ns>(ns)...).begin();
+ return it[element.element];
+}
+
+/* -------------------------------------------------------------------------- */
+template <class T, typename SupportType>
+template <typename... Ns,
+ std::enable_if_t<
+ std::conjunction_v<std::is_integral<std::decay_t<Ns>>...> and
+ sizeof...(Ns) >= 1> *>
+inline decltype(auto)
+ElementTypeMapArray<T, SupportType>::get(const Element & element,
+ Ns &&... ns) const {
+ const auto & array = this->operator()(element.type, element.ghost_type);
+ auto it = make_view(array, std::forward<Ns>(ns)...).begin();
return it[element.element];
}
/* -------------------------------------------------------------------------- */
template <class T, typename SupportType>
-UInt ElementTypeMapArray<T, SupportType>::sizeImpl(UInt spatial_dimension,
- GhostType ghost_type,
- ElementKind kind) const {
- UInt size = 0;
+Int ElementTypeMapArray<T, SupportType>::sizeImpl(Int spatial_dimension,
+ GhostType ghost_type,
+ ElementKind kind) const {
+ Int size = 0;
for (auto && type : this->elementTypes(spatial_dimension, ghost_type, kind)) {
size += this->operator()(type, ghost_type).size();
}
return size;
}
/* -------------------------------------------------------------------------- */
template <class T, typename SupportType>
template <typename... pack>
-UInt ElementTypeMapArray<T, SupportType>::size(pack &&... _pack) const {
- UInt size = 0;
+Int ElementTypeMapArray<T, SupportType>::size(pack &&... _pack) const {
+ Int size = 0;
GhostType requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _casper);
bool all_ghost_types =
OPTIONAL_NAMED_ARG(all_ghost_types, requested_ghost_type == _casper);
for (auto ghost_type : ghost_types) {
if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types)) {
continue;
}
size +=
sizeImpl(OPTIONAL_NAMED_ARG(spatial_dimension, _all_dimensions),
ghost_type, OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined));
}
return size;
}
} // namespace akantu
#endif /* AKANTU_ELEMENT_TYPE_MAP_TMPL_HH_ */
diff --git a/src/mesh/group_manager.cc b/src/mesh/group_manager.cc
index 1c127862c..7f022bc1c 100644
--- a/src/mesh/group_manager.cc
+++ b/src/mesh/group_manager.cc
@@ -1,1043 +1,976 @@
/**
* @file group_manager.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@gmail.com>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Thu Nov 12 2020
*
* @brief Stores information about ElementGroup and NodeGroup
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "group_manager.hh"
#include "aka_csr.hh"
#include "data_accessor.hh"
#include "element_group.hh"
#include "element_synchronizer.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
+#include "mesh_global_data_updater.hh"
+#include "mesh_iterators.hh"
#include "mesh_utils.hh"
#include "node_group.hh"
+#include "node_synchronizer.hh"
+#include "periodic_node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <iterator>
#include <list>
#include <numeric>
#include <queue>
#include <sstream>
#include <utility>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
GroupManager::GroupManager(Mesh & mesh, const ID & id) : id(id), mesh(mesh) {
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
GroupManager::~GroupManager() = default;
/* -------------------------------------------------------------------------- */
NodeGroup & GroupManager::createNodeGroup(const std::string & group_name,
bool replace_group) {
AKANTU_DEBUG_IN();
auto it = node_groups.find(group_name);
if (it != node_groups.end()) {
if (replace_group) {
it->second.reset();
} else {
AKANTU_EXCEPTION(
"Trying to create a node group that already exists:" << group_name);
}
}
std::stringstream sstr;
sstr << this->id << ":" << group_name << "_node_group";
auto && ptr = std::make_unique<NodeGroup>(group_name, mesh, sstr.str());
auto & node_group = *ptr;
// \todo insert_or_assign in c++17
if (it != node_groups.end()) {
it->second = std::move(ptr);
} else {
node_groups[group_name] = std::move(ptr);
}
AKANTU_DEBUG_OUT();
return node_group;
}
/* -------------------------------------------------------------------------- */
template <typename T>
NodeGroup &
GroupManager::createFilteredNodeGroup(const std::string & group_name,
const NodeGroup & source_node_group,
T & filter) {
AKANTU_DEBUG_IN();
NodeGroup & node_group = this->createNodeGroup(group_name);
node_group.append(source_node_group);
if (T::type == FilterFunctor::_node_filter_functor) {
node_group.applyNodeFilter(filter);
} else {
AKANTU_ERROR("ElementFilter cannot be applied to NodeGroup yet."
<< " Needs to be implemented.");
}
AKANTU_DEBUG_OUT();
return node_group;
}
/* -------------------------------------------------------------------------- */
ElementGroup & GroupManager::createElementGroup(const std::string & group_name,
- UInt dimension,
+ Int dimension,
bool replace_group) {
AKANTU_DEBUG_IN();
auto it = element_groups.find(group_name);
if (it != element_groups.end()) {
if (replace_group) {
it->second.reset();
} else {
AKANTU_EXCEPTION("Trying to create a element group that already exists:"
<< group_name);
}
}
- NodeGroup & new_node_group =
- createNodeGroup(group_name + "_nodes", replace_group);
+ auto & new_node_group = createNodeGroup(group_name + "_nodes", replace_group);
auto && ptr = std::make_unique<ElementGroup>(
group_name, mesh, new_node_group, dimension,
this->id + ":" + group_name + "_element_group");
auto & element_group = *ptr;
if (it != element_groups.end()) {
it->second = std::move(ptr);
} else {
element_groups[group_name] = std::move(ptr);
}
AKANTU_DEBUG_OUT();
return element_group;
}
/* -------------------------------------------------------------------------- */
void GroupManager::destroyElementGroup(const std::string & group_name,
bool destroy_node_group) {
AKANTU_DEBUG_IN();
auto eit = element_groups.find(group_name);
if (eit != element_groups.end()) {
if (destroy_node_group) {
destroyNodeGroup(eit->second->getNodeGroup().getName());
}
element_groups.erase(eit);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void GroupManager::destroyNodeGroup(const std::string & group_name) {
AKANTU_DEBUG_IN();
auto nit = node_groups.find(group_name);
if (nit != node_groups.end()) {
node_groups.erase(nit);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
ElementGroup & GroupManager::createElementGroup(const std::string & group_name,
- UInt dimension,
+ Int dimension,
NodeGroup & node_group) {
AKANTU_DEBUG_IN();
if (element_groups.find(group_name) != element_groups.end()) {
AKANTU_EXCEPTION(
"Trying to create a element group that already exists:" << group_name);
}
auto && ptr =
std::make_unique<ElementGroup>(group_name, mesh, node_group, dimension,
id + ":" + group_name + "_element_group");
auto & element_group = *ptr;
element_groups[group_name] = std::move(ptr);
AKANTU_DEBUG_OUT();
return element_group;
}
/* -------------------------------------------------------------------------- */
template <typename T>
ElementGroup & GroupManager::createFilteredElementGroup(
- const std::string & group_name, UInt dimension,
- const NodeGroup & node_group, T & filter) {
+ const std::string & group_name, Int dimension, const NodeGroup & node_group,
+ T & filter) {
AKANTU_DEBUG_IN();
if (T::type == FilterFunctor::_node_filter_functor) {
auto & filtered_node_group = this->createFilteredNodeGroup(
group_name + "_nodes", node_group, filter);
AKANTU_DEBUG_OUT();
return this->createElementGroup(group_name, dimension, filtered_node_group);
}
if (T::type == FilterFunctor::_element_filter_functor) {
AKANTU_ERROR(
"Cannot handle an ElementFilter yet. Needs to be implemented.");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
class ClusterSynchronizer : public DataAccessor<Element> {
- using DistantIDs = std::set<std::pair<UInt, UInt>>;
+ using DistantIDs = std::set<std::pair<Idx, Idx>>;
public:
- ClusterSynchronizer(GroupManager & group_manager, UInt element_dimension,
+ ClusterSynchronizer(GroupManager & group_manager, Int element_dimension,
std::string cluster_name_prefix,
- ElementTypeMapArray<UInt> & element_to_fragment,
+ ElementTypeMapArray<Idx> & element_to_fragment,
const ElementSynchronizer & element_synchronizer,
- UInt nb_cluster)
+ Int nb_cluster)
: group_manager(group_manager), element_dimension(element_dimension),
cluster_name_prefix(std::move(cluster_name_prefix)),
element_to_fragment(element_to_fragment),
element_synchronizer(element_synchronizer), nb_cluster(nb_cluster) {}
- UInt synchronize() {
- Communicator & comm = Communicator::getStaticCommunicator();
- UInt rank = comm.whoAmI();
- UInt nb_proc = comm.getNbProc();
+ auto synchronize() {
+ auto & comm = Communicator::getStaticCommunicator();
+ auto rank = comm.whoAmI();
+ auto nb_proc = comm.getNbProc();
/// find starting index to renumber local clusters
- Array<UInt> nb_cluster_per_proc(nb_proc);
+ Array<Int> nb_cluster_per_proc(nb_proc);
nb_cluster_per_proc(rank) = nb_cluster;
comm.allGather(nb_cluster_per_proc);
starting_index = std::accumulate(nb_cluster_per_proc.begin(),
- nb_cluster_per_proc.begin() + rank, 0U);
+ nb_cluster_per_proc.begin() + rank, 0);
- UInt global_nb_fragment =
+ auto global_nb_fragment =
std::accumulate(nb_cluster_per_proc.begin() + rank,
nb_cluster_per_proc.end(), starting_index);
/// create the local to distant cluster pairs with neighbors
element_synchronizer.synchronizeOnce(*this,
SynchronizationTag::_gm_clusters);
/// count total number of pairs
- Array<int> nb_pairs(nb_proc); // This is potentially a bug for more than
+ Array<Int> nb_pairs(nb_proc); // This is potentially a bug for more than
// 2**31 pairs, but due to a all gatherv after
// it must be int to match MPI interfaces
- nb_pairs(rank) = distant_ids.size();
+ nb_pairs(rank) = Int(distant_ids.size());
comm.allGather(nb_pairs);
- UInt total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0);
+ auto total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0);
/// generate pairs global array
- UInt local_pair_index =
- std::accumulate(nb_pairs.storage(), nb_pairs.storage() + rank, 0);
+ auto local_pair_index =
+ std::accumulate(nb_pairs.begin(), nb_pairs.end() + rank, 0);
- Array<UInt> total_pairs(total_nb_pairs, 2);
+ Array<Int> total_pairs(total_nb_pairs, 2);
for (const auto & ids : distant_ids) {
total_pairs(local_pair_index, 0) = ids.first;
total_pairs(local_pair_index, 1) = ids.second;
++local_pair_index;
}
/// communicate pairs to all processors
nb_pairs *= 2;
comm.allGatherV(total_pairs, nb_pairs);
/// renumber clusters
/// generate fragment list
- std::vector<std::set<UInt>> global_clusters;
- UInt total_nb_cluster = 0;
+ std::vector<std::set<Int>> global_clusters;
+ Int total_nb_cluster = 0;
Array<bool> is_fragment_in_cluster(global_nb_fragment, 1, false);
- std::queue<UInt> fragment_check_list;
+ std::queue<Int> fragment_check_list;
while (not total_pairs.empty()) {
/// create a new cluster
++total_nb_cluster;
global_clusters.resize(total_nb_cluster);
- std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1];
+ std::set<Int> & current_cluster = global_clusters[total_nb_cluster - 1];
- UInt first_fragment = total_pairs(0, 0);
- UInt second_fragment = total_pairs(0, 1);
+ auto first_fragment = total_pairs(0, 0);
+ auto second_fragment = total_pairs(0, 1);
total_pairs.erase(0);
fragment_check_list.push(first_fragment);
fragment_check_list.push(second_fragment);
while (!fragment_check_list.empty()) {
- UInt current_fragment = fragment_check_list.front();
-
- UInt * total_pairs_end = total_pairs.storage() + total_pairs.size() * 2;
-
- UInt * fragment_found =
- std::find(total_pairs.storage(), total_pairs_end, current_fragment);
+ auto current_fragment = fragment_check_list.front();
+ auto * total_pairs_end = total_pairs.data() + total_pairs.size() * 2;
+ auto * fragment_found =
+ std::find(total_pairs.data(), total_pairs_end, current_fragment);
if (fragment_found != total_pairs_end) {
- UInt position = fragment_found - total_pairs.storage();
- UInt pair = position / 2;
- UInt other_index = (position + 1) % 2;
+ auto position = fragment_found - total_pairs.data();
+ auto pair = position / 2;
+ auto other_index = (position + 1) % 2;
fragment_check_list.push(total_pairs(pair, other_index));
total_pairs.erase(pair);
} else {
fragment_check_list.pop();
current_cluster.insert(current_fragment);
is_fragment_in_cluster(current_fragment) = true;
}
}
}
/// add to FragmentToCluster all local fragments
- for (UInt c = 0; c < global_nb_fragment; ++c) {
+ for (auto c : arange(global_nb_fragment)) {
if (!is_fragment_in_cluster(c)) {
++total_nb_cluster;
global_clusters.resize(total_nb_cluster);
- std::set<UInt> & current_cluster =
- global_clusters[total_nb_cluster - 1];
+ auto & current_cluster = global_clusters[total_nb_cluster - 1];
current_cluster.insert(c);
}
}
/// reorganize element groups to match global clusters
- for (UInt c = 0; c < global_clusters.size(); ++c) {
+ for (auto c : arange(global_clusters.size())) {
/// create new element group corresponding to current cluster
- std::stringstream sstr;
- sstr << cluster_name_prefix << "_" << c;
- ElementGroup & cluster =
- group_manager.createElementGroup(sstr.str(), element_dimension, true);
-
- auto it = global_clusters[c].begin();
- auto end = global_clusters[c].end();
+ auto & cluster = group_manager.createElementGroup(
+ cluster_name_prefix + "_" + std::to_string(c), element_dimension,
+ true);
/// append to current element group all fragments that belong to
/// the same cluster if they exist
- for (; it != end; ++it) {
- Int local_index = *it - starting_index;
+ for (auto gc : global_clusters[c]) {
+ Int local_index = gc - starting_index;
if (local_index < 0 || local_index >= Int(nb_cluster)) {
continue;
}
- std::stringstream tmp_sstr;
- tmp_sstr << "tmp_" << cluster_name_prefix << "_" << local_index;
+ auto id =
+ "tmp_" + cluster_name_prefix + "_" + std::to_string(local_index);
+ AKANTU_DEBUG_ASSERT(group_manager.elementGroupExists(id),
+ "Temporary fragment \"" << id << "\" not found");
- AKANTU_DEBUG_ASSERT(group_manager.elementGroupExists(tmp_sstr.str()),
- "Temporary fragment \"" << tmp_sstr.str()
- << "\" not found");
-
- cluster.append(group_manager.getElementGroup(tmp_sstr.str()));
- group_manager.destroyElementGroup(tmp_sstr.str(), true);
+ cluster.append(group_manager.getElementGroup(id));
+ group_manager.destroyElementGroup(id, true);
}
}
return total_nb_cluster;
}
private:
/// functions for parallel communications
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override {
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override {
if (tag == SynchronizationTag::_gm_clusters) {
return elements.size() * sizeof(UInt);
}
return 0;
}
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override {
if (tag != SynchronizationTag::_gm_clusters) {
return;
}
- Array<Element>::const_iterator<> el_it = elements.begin();
- Array<Element>::const_iterator<> el_end = elements.end();
-
- for (; el_it != el_end; ++el_it) {
-
- const Element & el = *el_it;
-
+ for (const auto & el : elements) {
/// for each element pack its global cluster index
- buffer << element_to_fragment(el.type, el.ghost_type)(el.element) +
- starting_index;
+ buffer << element_to_fragment(el) + starting_index;
}
}
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override {
if (tag != SynchronizationTag::_gm_clusters) {
return;
}
- Array<Element>::const_iterator<> el_it = elements.begin();
- Array<Element>::const_iterator<> el_end = elements.end();
-
- for (; el_it != el_end; ++el_it) {
- UInt distant_cluster;
-
+ for (const auto & el : elements) {
+ Idx distant_cluster;
buffer >> distant_cluster;
- const Element & el = *el_it;
- UInt local_cluster =
- element_to_fragment(el.type, el.ghost_type)(el.element) +
- starting_index;
+ auto local_cluster = element_to_fragment(el) + starting_index;
distant_ids.insert(std::make_pair(local_cluster, distant_cluster));
}
- }
+ } // namespace akantu
private:
GroupManager & group_manager;
- UInt element_dimension;
+ Int element_dimension{-1};
std::string cluster_name_prefix;
- ElementTypeMapArray<UInt> & element_to_fragment;
+ ElementTypeMapArray<Idx> & element_to_fragment;
const ElementSynchronizer & element_synchronizer;
- UInt nb_cluster;
+ Int nb_cluster{0};
DistantIDs distant_ids;
- UInt starting_index;
-};
+ Idx starting_index{0};
+}; // namespace akantu
/* -------------------------------------------------------------------------- */
/// \todo this function doesn't work in 1D
-UInt GroupManager::createBoundaryGroupFromGeometry() {
- UInt spatial_dimension = mesh.getSpatialDimension();
+Int GroupManager::createBoundaryGroupFromGeometry() {
+ auto spatial_dimension = mesh.getSpatialDimension();
return createClusters(spatial_dimension - 1, "boundary");
}
/* -------------------------------------------------------------------------- */
-UInt GroupManager::createClusters(
- UInt element_dimension, Mesh & mesh_facets,
- const std::string & cluster_name_prefix,
+Int GroupManager::createClusters(
+ Int element_dimension, Mesh & mesh_facets, std::string cluster_name_prefix,
const GroupManager::ClusteringFilter & filter) {
return createClusters(element_dimension, cluster_name_prefix, filter,
mesh_facets);
}
/* -------------------------------------------------------------------------- */
-UInt GroupManager::createClusters(
- UInt element_dimension, const std::string & cluster_name_prefix,
+Int GroupManager::createClusters(
+ Int element_dimension, std::string cluster_name_prefix,
const GroupManager::ClusteringFilter & filter) {
MeshAccessor mesh_accessor(mesh);
auto mesh_facets = std::make_unique<Mesh>(mesh.getSpatialDimension(),
mesh_accessor.getNodesSharedPtr(),
"mesh_facets_for_clusters");
mesh_facets->defineMeshParent(mesh);
MeshUtils::buildAllFacets(mesh, *mesh_facets, element_dimension,
element_dimension - 1);
return createClusters(element_dimension, cluster_name_prefix, filter,
*mesh_facets);
}
/* -------------------------------------------------------------------------- */
//// \todo if needed element list construction can be optimized by
//// templating the filter class
-UInt GroupManager::createClusters(UInt element_dimension,
- const std::string & cluster_name_prefix,
- const GroupManager::ClusteringFilter & filter,
- Mesh & mesh_facets) {
+Int GroupManager::createClusters(Int element_dimension,
+ const std::string & cluster_name_prefix,
+ const GroupManager::ClusteringFilter & filter,
+ Mesh & mesh_facets) {
AKANTU_DEBUG_IN();
- UInt nb_proc = mesh.getCommunicator().getNbProc();
+ auto nb_proc = mesh.getCommunicator().getNbProc();
std::string tmp_cluster_name_prefix = cluster_name_prefix;
- ElementTypeMapArray<UInt> * element_to_fragment = nullptr;
+ std::unique_ptr<ElementTypeMapArray<Idx>> element_to_fragment;
if (nb_proc > 1 && mesh.isDistributed()) {
element_to_fragment =
- new ElementTypeMapArray<UInt>("element_to_fragment", id);
+ std::make_unique<ElementTypeMapArray<Idx>>("element_to_fragment", id);
element_to_fragment->initialize(
mesh, _nb_component = 1, _spatial_dimension = element_dimension,
_element_kind = _ek_not_defined, _with_nb_element = true);
- // mesh.initElementTypeMapArray(*element_to_fragment, 1, element_dimension,
- // false, _ek_not_defined, true);
tmp_cluster_name_prefix = "tmp_" + tmp_cluster_name_prefix;
}
ElementTypeMapArray<bool> seen_elements("seen_elements", id);
seen_elements.initialize(mesh, _spatial_dimension = element_dimension,
_element_kind = _ek_not_defined,
- _with_nb_element = true);
- // mesh.initElementTypeMapArray(seen_elements, 1, element_dimension, false,
- // _ek_not_defined, true);
+ _with_nb_element = true, _default_value = false);
- for (auto ghost_type : ghost_types) {
- Element el;
- el.ghost_type = ghost_type;
- for (auto type :
- mesh.elementTypes(_spatial_dimension = element_dimension,
- _ghost_type = ghost_type, _element_kind = _ek_not_defined)) {
- el.type = type;
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- Array<bool> & seen_elements_array = seen_elements(type, ghost_type);
+ for_each_element(
+ mesh,
+ [&filter, &seen_elements](auto && el) {
+ seen_elements(el) = not filter(el);
+ },
+ _spatial_dimension = element_dimension);
- for (UInt e = 0; e < nb_element; ++e) {
- el.element = e;
- if (!filter(el)) {
- seen_elements_array(e) = true;
- }
- }
- }
- }
+ Int nb_cluster = 0;
- Array<bool> checked_node(mesh.getNbNodes(), 1, false);
-
- UInt nb_cluster = 0;
+ std::vector<std::string> created_groups;
for (auto ghost_type : ghost_types) {
Element uns_el;
uns_el.ghost_type = ghost_type;
for (auto type :
mesh.elementTypes(_spatial_dimension = element_dimension,
_ghost_type = ghost_type, _element_kind = _ek_not_defined)) {
uns_el.type = type;
- Array<bool> & seen_elements_vec =
- seen_elements(uns_el.type, uns_el.ghost_type);
+ auto & seen_elements_vec = seen_elements(uns_el.type, uns_el.ghost_type);
- for (UInt e = 0; e < seen_elements_vec.size(); ++e) {
+ for (Int e = 0; e < seen_elements_vec.size(); ++e) {
// skip elements that have been already seen
if (seen_elements_vec(e)) {
continue;
}
// set current element
uns_el.element = e;
seen_elements_vec(e) = true;
+ auto group_name =
+ tmp_cluster_name_prefix + "_" + std::to_string(nb_cluster);
+
+ created_groups.push_back(group_name);
+
/// create a new cluster
- std::stringstream sstr;
- sstr << tmp_cluster_name_prefix << "_" << nb_cluster;
- ElementGroup & cluster =
- createElementGroup(sstr.str(), element_dimension, true);
+ auto & cluster =
+ createElementGroup(group_name, element_dimension, true);
++nb_cluster;
// point element are cluster by themself
if (element_dimension == 0) {
- cluster.add(uns_el);
-
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(uns_el.type);
- Vector<UInt> connect =
- mesh.getConnectivity(uns_el.type, uns_el.ghost_type)
- .begin(nb_nodes_per_element)[uns_el.element];
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- /// add element's nodes to the cluster
- UInt node = connect[n];
- if (!checked_node(node)) {
- cluster.addNode(node);
- checked_node(node) = true;
- }
- }
-
+ cluster.add(uns_el, true, false);
continue;
}
std::queue<Element> element_to_add;
element_to_add.push(uns_el);
/// keep looping until current cluster is complete (no more
/// connected elements)
- while (!element_to_add.empty()) {
+ while (not element_to_add.empty()) {
/// take first element and erase it in the queue
- Element el = element_to_add.front();
+ auto el = element_to_add.front();
element_to_add.pop();
/// if parallel, store cluster index per element
if (nb_proc > 1 && mesh.isDistributed()) {
- (*element_to_fragment)(el.type, el.ghost_type)(el.element) =
- nb_cluster - 1;
+ (*element_to_fragment)(el) = nb_cluster - 1;
}
/// add current element to the cluster
- cluster.add(el);
-
- const Array<Element> & element_to_facet =
- mesh_facets.getSubelementToElement(el.type, el.ghost_type);
-
- UInt nb_facet_per_element = element_to_facet.getNbComponent();
+ cluster.add(el, true, false);
- for (UInt f = 0; f < nb_facet_per_element; ++f) {
- const Element & facet = element_to_facet(el.element, f);
+ const auto & element_to_facets =
+ mesh_facets.getSubelementToElement().get(el);
+ for (auto && facet : element_to_facets) {
if (facet == ElementNull) {
continue;
}
- const std::vector<Element> & connected_elements =
- mesh_facets.getElementToSubelement(
- facet.type, facet.ghost_type)(facet.element);
+ const auto & connected_elements =
+ const_cast<const Mesh &>(mesh_facets)
+ .getElementToSubelement(facet);
- for (UInt elem = 0; elem < connected_elements.size(); ++elem) {
- const Element & check_el = connected_elements[elem];
+ for (const auto & check_el : connected_elements) {
// check if this element has to be skipped
if (check_el == ElementNull || check_el == el) {
continue;
}
- Array<bool> & seen_elements_vec_current =
- seen_elements(check_el.type, check_el.ghost_type);
+ auto & seen_elements_current = seen_elements(check_el);
- if (not seen_elements_vec_current(check_el.element)) {
- seen_elements_vec_current(check_el.element) = true;
+ if (not seen_elements_current) {
+ seen_elements_current = true;
element_to_add.push(check_el);
}
}
}
-
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type);
- Vector<UInt> connect = mesh.getConnectivity(el.type, el.ghost_type)
- .begin(nb_nodes_per_element)[el.element];
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- /// add element's nodes to the cluster
- UInt node = connect[n];
- if (!checked_node(node)) {
- cluster.addNode(node, false);
- checked_node(node) = true;
- }
- }
}
}
}
}
+ for (auto && gid : created_groups) {
+ this->getElementGroup(gid).getNodeGroup().optimize();
+ }
+
if (nb_proc > 1 && mesh.isDistributed()) {
ClusterSynchronizer cluster_synchronizer(
*this, element_dimension, cluster_name_prefix, *element_to_fragment,
this->mesh.getElementSynchronizer(), nb_cluster);
nb_cluster = cluster_synchronizer.synchronize();
- delete element_to_fragment;
}
if (mesh.isDistributed()) {
this->synchronizeGroupNames();
}
AKANTU_DEBUG_OUT();
return nb_cluster;
}
/* -------------------------------------------------------------------------- */
template <typename T>
void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) {
std::set<std::string> group_names;
const auto & datas = mesh.getData<T>(dataset_name);
- std::map<std::string, UInt> group_dim;
+ std::map<std::string, Int> group_dim;
for (auto ghost_type : ghost_types) {
for (auto type : datas.elementTypes(_ghost_type = ghost_type)) {
- const Array<T> & dataset = datas(type, ghost_type);
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ const auto & dataset = datas(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
AKANTU_DEBUG_ASSERT(dataset.size() == nb_element,
"Not the same number of elements ("
<< type << ":" << ghost_type
<< ") in the map from MeshData ("
<< dataset.size() << ") " << dataset_name
<< " and in the mesh (" << nb_element << ")!");
- for (UInt e(0); e < nb_element; ++e) {
+ for (Int e(0); e < nb_element; ++e) {
std::stringstream sstr;
sstr << dataset(e);
std::string gname = sstr.str();
group_names.insert(gname);
auto it = group_dim.find(gname);
if (it == group_dim.end()) {
group_dim[gname] = mesh.getSpatialDimension(type);
} else {
it->second = std::max(it->second, mesh.getSpatialDimension(type));
}
}
}
}
for (auto && name : group_names) {
createElementGroup(name, group_dim[name]);
}
if (mesh.isDistributed()) {
this->synchronizeGroupNames();
}
Element el;
for (auto ghost_type : ghost_types) {
el.ghost_type = ghost_type;
for (auto type : datas.elementTypes(_ghost_type = ghost_type)) {
el.type = type;
- const Array<T> & dataset = datas(type, ghost_type);
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ const auto & dataset = datas(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
AKANTU_DEBUG_ASSERT(dataset.size() == nb_element,
"Not the same number of elements in the map from "
"MeshData and in the mesh!");
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(el.type);
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(el.type);
- Array<UInt>::const_iterator<Vector<UInt>> cit =
+ auto cit =
mesh.getConnectivity(type, ghost_type).begin(nb_nodes_per_element);
- for (UInt e(0); e < nb_element; ++e, ++cit) {
+ for (Int e(0); e < nb_element; ++e, ++cit) {
el.element = e;
std::stringstream sstr;
sstr << dataset(e);
- ElementGroup & group = getElementGroup(sstr.str());
+ auto & group = getElementGroup(sstr.str());
group.add(el, false, false);
- const Vector<UInt> & connect = *cit;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- UInt node = connect[n];
+ const auto & connect = *cit;
+ for (auto node : connect) {
group.addNode(node, false);
}
}
}
}
for (auto && name : group_names) {
getElementGroup(name).optimize();
}
}
template void GroupManager::createGroupsFromMeshData<std::string>(
const std::string & dataset_name);
template void
GroupManager::createGroupsFromMeshData<UInt>(const std::string & dataset_name);
/* -------------------------------------------------------------------------- */
void GroupManager::createElementGroupFromNodeGroup(
const std::string & name, const std::string & node_group_name,
- UInt dimension) {
+ Int dimension) {
NodeGroup & node_group = getNodeGroup(node_group_name);
ElementGroup & group = createElementGroup(name, dimension, node_group);
group.fillFromNodeGroup();
}
/* -------------------------------------------------------------------------- */
void GroupManager::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "GroupManager [" << std::endl;
std::set<std::string> node_group_seen;
for (auto & group : iterateElementGroups()) {
group.printself(stream, indent + 1);
node_group_seen.insert(group.getNodeGroup().getName());
}
for (auto & group : iterateNodeGroups()) {
if (node_group_seen.find(group.getName()) == node_group_seen.end()) {
group.printself(stream, indent + 1);
}
}
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
-UInt GroupManager::getNbElementGroups(UInt dimension) const {
+Int GroupManager::getNbElementGroups(Int dimension) const {
if (dimension == _all_dimensions) {
return element_groups.size();
}
return std::count_if(element_groups.begin(), element_groups.end(),
[dimension](auto && eg) {
return eg.second->getDimension() == dimension;
});
}
/* -------------------------------------------------------------------------- */
void GroupManager::checkAndAddGroups(DynamicCommunicationBuffer & buffer) {
AKANTU_DEBUG_IN();
- UInt nb_node_group;
+ Int nb_node_group;
buffer >> nb_node_group;
AKANTU_DEBUG_INFO("Received " << nb_node_group << " node group names");
- for (UInt ng = 0; ng < nb_node_group; ++ng) {
+ for (Int ng = 0; ng < nb_node_group; ++ng) {
std::string node_group_name;
buffer >> node_group_name;
if (node_groups.find(node_group_name) == node_groups.end()) {
this->createNodeGroup(node_group_name);
}
AKANTU_DEBUG_INFO("Received node goup name: " << node_group_name);
}
- UInt nb_element_group;
+ Int nb_element_group;
buffer >> nb_element_group;
AKANTU_DEBUG_INFO("Received " << nb_element_group << " element group names");
- for (UInt eg = 0; eg < nb_element_group; ++eg) {
+ for (Int eg = 0; eg < nb_element_group; ++eg) {
std::string element_group_name;
buffer >> element_group_name;
std::string node_group_name;
buffer >> node_group_name;
- UInt dim;
+ Int dim;
buffer >> dim;
AKANTU_DEBUG_INFO("Received element group name: "
<< element_group_name << " corresponding to a "
<< Int(dim) << "D group with node group "
<< node_group_name);
- NodeGroup & node_group = *node_groups[node_group_name];
+ auto & node_group = *node_groups[node_group_name];
if (element_groups.find(element_group_name) == element_groups.end()) {
this->createElementGroup(element_group_name, dim, node_group);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void GroupManager::fillBufferWithGroupNames(
DynamicCommunicationBuffer & comm_buffer) const {
AKANTU_DEBUG_IN();
// packing node group names;
- UInt nb_groups = this->node_groups.size();
+ Int nb_groups = this->node_groups.size();
comm_buffer << nb_groups;
AKANTU_DEBUG_INFO("Sending " << nb_groups << " node group names");
auto nnames_it = node_groups.begin();
auto nnames_end = node_groups.end();
for (; nnames_it != nnames_end; ++nnames_it) {
std::string node_group_name = nnames_it->first;
comm_buffer << node_group_name;
AKANTU_DEBUG_INFO("Sending node goupe name: " << node_group_name);
}
// packing element group names with there associated node group name
nb_groups = this->element_groups.size();
comm_buffer << nb_groups;
AKANTU_DEBUG_INFO("Sending " << nb_groups << " element group names");
- auto gnames_it = this->element_groups.begin();
- auto gnames_end = this->element_groups.end();
- for (; gnames_it != gnames_end; ++gnames_it) {
- ElementGroup & element_group = *(gnames_it->second);
- std::string element_group_name = gnames_it->first;
+
+ for (auto && pair : this->element_groups) {
+ auto & element_group = *(pair.second);
+ std::string element_group_name = pair.first;
std::string node_group_name = element_group.getNodeGroup().getName();
- UInt dim = element_group.getDimension();
+ Int dim = element_group.getDimension();
comm_buffer << element_group_name;
comm_buffer << node_group_name;
comm_buffer << dim;
AKANTU_DEBUG_INFO("Sending element group name: "
<< element_group_name << " corresponding to a "
<< Int(dim) << "D group with the node group "
<< node_group_name);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void GroupManager::synchronizeGroupNames() {
AKANTU_DEBUG_IN();
- const Communicator & comm = mesh.getCommunicator();
- Int nb_proc = comm.getNbProc();
- Int my_rank = comm.whoAmI();
+ const auto & comm = mesh.getCommunicator();
+ auto nb_proc = comm.getNbProc();
+ auto my_rank = comm.whoAmI();
if (nb_proc == 1) {
return;
}
if (my_rank == 0) {
for (Int p = 1; p < nb_proc; ++p) {
DynamicCommunicationBuffer recv_buffer;
auto tag = Tag::genTag(p, 0, Tag::_element_group);
comm.receive(recv_buffer, p, tag);
AKANTU_DEBUG_INFO("Got " << printMemorySize<char>(recv_buffer.size())
<< " from proc " << p << " " << tag);
this->checkAndAddGroups(recv_buffer);
}
DynamicCommunicationBuffer comm_buffer;
this->fillBufferWithGroupNames(comm_buffer);
AKANTU_DEBUG_INFO("Initiating broadcast with "
<< printMemorySize<char>(comm_buffer.size()));
comm.broadcast(comm_buffer);
} else {
DynamicCommunicationBuffer comm_buffer;
this->fillBufferWithGroupNames(comm_buffer);
auto tag = Tag::genTag(my_rank, 0, Tag::_element_group);
AKANTU_DEBUG_INFO("Sending " << printMemorySize<char>(comm_buffer.size())
<< " to proc " << 0 << " " << tag);
comm.send(comm_buffer, 0, tag);
DynamicCommunicationBuffer recv_buffer;
comm.broadcast(recv_buffer);
AKANTU_DEBUG_INFO("Receiving broadcast with "
<< printMemorySize<char>(recv_buffer.size()));
this->checkAndAddGroups(recv_buffer);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
const ElementGroup &
GroupManager::getElementGroup(const std::string & name) const {
auto it = element_groups.find(name);
if (it == element_groups.end()) {
AKANTU_EXCEPTION("There are no element groups named "
<< name << " associated to the group manager: " << id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
ElementGroup & GroupManager::getElementGroup(const std::string & name) {
auto it = element_groups.find(name);
if (it == element_groups.end()) {
AKANTU_EXCEPTION("There are no element groups named "
<< name << " associated to the group manager: " << id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
const NodeGroup & GroupManager::getNodeGroup(const std::string & name) const {
auto it = node_groups.find(name);
if (it == node_groups.end()) {
AKANTU_EXCEPTION("There are no node groups named "
<< name << " associated to the group manager: " << id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
NodeGroup & GroupManager::getNodeGroup(const std::string & name) {
auto it = node_groups.find(name);
if (it == node_groups.end()) {
AKANTU_EXCEPTION("There are no node groups named "
<< name << " associated to the group manager: " << id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
template <typename GroupsType>
void GroupManager::renameGroup(GroupsType & groups, const std::string & name,
const std::string & new_name) {
auto it = groups.find(name);
if (it == groups.end()) {
AKANTU_EXCEPTION("There are no group named "
<< name << " associated to the group manager: " << id);
}
auto && group_ptr = std::move(it->second);
group_ptr->name = new_name;
groups.erase(it);
groups[new_name] = std::move(group_ptr);
}
/* -------------------------------------------------------------------------- */
void GroupManager::renameElementGroup(const std::string & name,
const std::string & new_name) {
renameGroup(element_groups, name, new_name);
}
/* -------------------------------------------------------------------------- */
void GroupManager::renameNodeGroup(const std::string & name,
const std::string & new_name) {
renameGroup(node_groups, name, new_name);
}
/* -------------------------------------------------------------------------- */
void GroupManager::copyElementGroup(const std::string & name,
const std::string & new_name) {
const auto & grp = getElementGroup(name);
auto & new_grp = createElementGroup(new_name, grp.getDimension());
new_grp.getElements().copy(grp.getElements());
}
/* -------------------------------------------------------------------------- */
void GroupManager::copyNodeGroup(const std::string & name,
const std::string & new_name) {
const auto & grp = getNodeGroup(name);
auto & new_grp = createNodeGroup(new_name);
new_grp.getNodes().copy(grp.getNodes());
}
/* -------------------------------------------------------------------------- */
-void GroupManager::onNodesAdded(const Array<UInt> & new_nodes,
+void GroupManager::onNodesAdded(const Array<Idx> & new_nodes,
const NewNodesEvent & event) {
for (auto && group : make_values_adaptor(element_groups)) {
group->onNodesAdded(new_nodes, event);
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/mesh/group_manager.hh b/src/mesh/group_manager.hh
index f19a7d966..124482bd8 100644
--- a/src/mesh/group_manager.hh
+++ b/src/mesh/group_manager.hh
@@ -1,352 +1,353 @@
/**
* @file group_manager.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@gmail.com>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri Jul 24 2020
*
* @brief Stores information relevent to the notion of element and nodes
* groups.
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_GROUP_MANAGER_HH_
#define AKANTU_GROUP_MANAGER_HH_
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_iterators.hh"
#include "element_type_map.hh"
/* -------------------------------------------------------------------------- */
#include <set>
/* -------------------------------------------------------------------------- */
namespace akantu {
class Element;
class ElementGroup;
class ElementSynchronizer;
class Mesh;
class NewNodesEvent;
class NodeGroup;
template <bool> class CommunicationBufferTemplated;
namespace dumpers {
class Field;
}
} // namespace akantu
namespace akantu {
/* -------------------------------------------------------------------------- */
class GroupManager {
/* ------------------------------------------------------------------------ */
/* Typedefs */
/* ------------------------------------------------------------------------ */
private:
using ElementGroups = std::map<std::string, std::unique_ptr<ElementGroup>>;
using NodeGroups = std::map<std::string, std::unique_ptr<NodeGroup>>;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
GroupManager(Mesh & mesh, const ID & id = "group_manager");
virtual ~GroupManager();
/* ------------------------------------------------------------------------ */
/* Groups iterators */
/* ------------------------------------------------------------------------ */
public:
using node_group_iterator = NodeGroups::iterator;
using element_group_iterator = ElementGroups::iterator;
using const_node_group_iterator = NodeGroups::const_iterator;
using const_element_group_iterator = ElementGroups::const_iterator;
#define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, function, \
param_in, param_out) \
[[deprecated( \
"use iterate(Element|Node)Groups or " \
"(element|node)GroupExists")]] inline BOOST_PP_CAT(BOOST_PP_CAT(const_, \
group_type), \
_iterator) \
BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) const { \
return BOOST_PP_CAT(group_type, s).function(param_out); \
}; \
\
[[deprecated("use iterate(Element|Node)Groups or " \
"(element|node)GroupExists")]] inline BOOST_PP_CAT(group_type, \
_iterator) \
BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) { \
return BOOST_PP_CAT(group_type, s).function(param_out); \
}
#define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(group_type, function) \
AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION( \
group_type, function, BOOST_PP_EMPTY(), BOOST_PP_EMPTY())
AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, begin);
AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, end);
AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, begin);
AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, end);
AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(element_group, find,
const std::string & name, name);
AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(node_group, find,
const std::string & name, name);
public:
decltype(auto) iterateNodeGroups() {
return make_dereference_adaptor(make_values_adaptor(node_groups));
}
decltype(auto) iterateNodeGroups() const {
return make_dereference_adaptor(make_values_adaptor(node_groups));
}
decltype(auto) iterateElementGroups() {
return make_dereference_adaptor(make_values_adaptor(element_groups));
}
decltype(auto) iterateElementGroups() const {
return make_dereference_adaptor(make_values_adaptor(element_groups));
}
/* ------------------------------------------------------------------------ */
/* Clustering filter */
/* ------------------------------------------------------------------------ */
public:
class ClusteringFilter {
public:
virtual bool operator()(const Element & /*unused*/) const { return true; }
};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// create an empty node group
NodeGroup & createNodeGroup(const std::string & group_name,
bool replace_group = false);
/// create an element group and the associated node group
ElementGroup & createElementGroup(const std::string & group_name,
- UInt dimension = _all_dimensions,
+ Int dimension = _all_dimensions,
bool replace_group = false);
/* ------------------------------------------------------------------------ */
/// renames an element group
void renameElementGroup(const std::string & name,
const std::string & new_name);
/// renames a node group
void renameNodeGroup(const std::string & name, const std::string & new_name);
/// copy an existing element group
void copyElementGroup(const std::string & name, const std::string & new_name);
/// copy an existing node group
void copyNodeGroup(const std::string & name, const std::string & new_name);
/* ------------------------------------------------------------------------ */
/// create a node group from another node group but filtered
template <typename T>
NodeGroup & createFilteredNodeGroup(const std::string & group_name,
const NodeGroup & node_group, T & filter);
/// create an element group from another element group but filtered
template <typename T>
ElementGroup &
- createFilteredElementGroup(const std::string & group_name, UInt dimension,
+ createFilteredElementGroup(const std::string & group_name, Int dimension,
const NodeGroup & node_group, T & filter);
/// destroy a node group
void destroyNodeGroup(const std::string & group_name);
/// destroy an element group and the associated node group
void destroyElementGroup(const std::string & group_name,
bool destroy_node_group = false);
// /// destroy all element groups and the associated node groups
// void destroyAllElementGroups(bool destroy_node_groups = false);
/// create a element group using an existing node group
ElementGroup & createElementGroup(const std::string & group_name,
- UInt dimension, NodeGroup & node_group);
+ Int dimension, NodeGroup & node_group);
/// create groups based on values stored in a given mesh data
template <typename T>
void createGroupsFromMeshData(const std::string & dataset_name);
/// create boundaries group by a clustering algorithm \todo extend to parallel
- UInt createBoundaryGroupFromGeometry();
+ Int createBoundaryGroupFromGeometry();
/// create element clusters for a given dimension
- UInt createClusters(UInt element_dimension, Mesh & mesh_facets,
- const std::string & cluster_name_prefix = "cluster",
- const ClusteringFilter & filter = ClusteringFilter());
+ Int createClusters(Int element_dimension, Mesh & mesh_facets,
+ std::string cluster_name_prefix = "cluster",
+ const ClusteringFilter & filter = ClusteringFilter());
/// create element clusters for a given dimension
- UInt createClusters(UInt element_dimension,
- const std::string & cluster_name_prefix = "cluster",
- const ClusteringFilter & filter = ClusteringFilter());
+ Int createClusters(Int element_dimension,
+ std::string cluster_name_prefix = "cluster",
+ const ClusteringFilter & filter = ClusteringFilter());
private:
/// create element clusters for a given dimension
- UInt createClusters(UInt element_dimension,
- const std::string & cluster_name_prefix,
- const ClusteringFilter & filter, Mesh & mesh_facets);
+ Int createClusters(Int element_dimension,
+ const std::string & cluster_name_prefix,
+ const ClusteringFilter & filter, Mesh & mesh_facets);
public:
/// Create an ElementGroup based on a NodeGroup
void createElementGroupFromNodeGroup(const std::string & name,
const std::string & node_group,
- UInt dimension = _all_dimensions);
+ Int dimension = _all_dimensions);
virtual void printself(std::ostream & stream, int indent = 0) const;
/// this function insure that the group names are present on all processors
/// /!\ it is a SMP call
void synchronizeGroupNames();
/// register an elemental field to the given group name (overloading for
/// ElementalPartionField)
template <typename T, template <bool> class dump_type>
std::shared_ptr<dumpers::Field> createElementalField(
const ElementTypeMapArray<T> & field, const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>());
+ Int spatial_dimension, ElementKind kind,
+ ElementTypeMap<Int> nb_data_per_elem = ElementTypeMap<Int>());
/// register an elemental field to the given group name (overloading for
/// ElementalField)
- template <typename T, template <class> class ret_type,
- template <class, template <class> class, bool> class dump_type>
+ template <typename T, class ret_type,
+ template <class, class, bool> class dump_type>
std::shared_ptr<dumpers::Field> createElementalField(
const ElementTypeMapArray<T> & field, const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>());
+ Int spatial_dimension, ElementKind kind,
+ ElementTypeMap<Int> nb_data_per_elem = ElementTypeMap<Int>());
/// register an elemental field to the given group name (overloading for
/// MaterialInternalField)
template <typename T,
/// type of InternalMaterialField
template <typename, bool filtered> class dump_type>
std::shared_ptr<dumpers::Field>
createElementalField(const ElementTypeMapArray<T> & field,
- const std::string & group_name, UInt spatial_dimension,
- ElementKind kind, ElementTypeMap<UInt> nb_data_per_elem);
+ const std::string & group_name, Int spatial_dimension,
+ ElementKind kind, ElementTypeMap<Int> nb_data_per_elem);
template <typename type, bool flag, template <class, bool> class ftype>
std::shared_ptr<dumpers::Field>
createNodalField(const ftype<type, flag> * field,
- const std::string & group_name, UInt padding_size = 0);
+ const std::string & group_name, Int padding_size = 0);
template <typename type, bool flag, template <class, bool> class ftype>
std::shared_ptr<dumpers::Field>
createStridedNodalField(const ftype<type, flag> * field,
- const std::string & group_name, UInt size,
- UInt stride, UInt padding_size);
+ const std::string & group_name, Int size, Int stride,
+ Int padding_size);
- void onNodesAdded(const Array<UInt> & new_nodes, const NewNodesEvent & event);
+ void onNodesAdded(const Array<Idx> & new_nodes, const NewNodesEvent & event);
protected:
/// fill a buffer with all the group names
void fillBufferWithGroupNames(
CommunicationBufferTemplated<false> & comm_buffer) const;
/// take a buffer and create the missing groups localy
void checkAndAddGroups(CommunicationBufferTemplated<false> & buffer);
/// register an elemental field to the given group name
template <class dump_type, typename field_type>
inline std::shared_ptr<dumpers::Field>
createElementalField(const field_type & field, const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- const ElementTypeMap<UInt> & nb_data_per_elem);
+ Int spatial_dimension, ElementKind kind,
+ const ElementTypeMap<Int> & nb_data_per_elem);
/// register an elemental field to the given group name
template <class dump_type, typename field_type>
inline std::shared_ptr<dumpers::Field>
createElementalFilteredField(const field_type & field,
const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- ElementTypeMap<UInt> nb_data_per_elem);
+ Int spatial_dimension, ElementKind kind,
+ ElementTypeMap<Int> nb_data_per_elem);
/* ------------------------------------------------------------------------ */
/* Accessor */
/* ------------------------------------------------------------------------ */
public:
// AKANTU_GET_MACRO(ElementGroups, element_groups, const ElementGroups &);
- const ElementGroup & getElementGroup(const std::string & name) const;
- const NodeGroup & getNodeGroup(const std::string & name) const;
+ [[nodiscard]] const ElementGroup &
+ getElementGroup(const std::string & name) const;
+ [[nodiscard]] const NodeGroup & getNodeGroup(const std::string & name) const;
ElementGroup & getElementGroup(const std::string & name);
NodeGroup & getNodeGroup(const std::string & name);
- UInt getNbElementGroups(UInt dimension = _all_dimensions) const;
- UInt getNbNodeGroups() { return node_groups.size(); };
+ [[nodiscard]] Int getNbElementGroups(Int dimension = _all_dimensions) const;
+ Int getNbNodeGroups() { return node_groups.size(); };
- bool elementGroupExists(const std::string & name) {
+ [[nodiscard]] bool elementGroupExists(const std::string & name) const {
return element_groups.find(name) != element_groups.end();
}
- bool nodeGroupExists(const std::string & name) {
+ [[nodiscard]] bool nodeGroupExists(const std::string & name) const {
return node_groups.find(name) != node_groups.end();
}
private:
template <typename GroupsType>
void renameGroup(GroupsType & groups, const std::string & name,
const std::string & new_name);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// id to create element and node groups
ID id;
/// list of the node groups managed
NodeGroups node_groups;
/// list of the element groups managed
ElementGroups element_groups;
/// Mesh to which the element belongs
Mesh & mesh;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const GroupManager & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#endif /* AKANTU_GROUP_MANAGER_HH_ */
diff --git a/src/mesh/group_manager_inline_impl.hh b/src/mesh/group_manager_inline_impl.hh
index 583281cc8..d925605cd 100644
--- a/src/mesh/group_manager_inline_impl.hh
+++ b/src/mesh/group_manager_inline_impl.hh
@@ -1,196 +1,196 @@
/**
* @file group_manager_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Tue Mar 03 2020
*
* @brief Stores information relevent to the notion of domain boundary and
* surfaces.
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_field.hh"
#include "element_group.hh"
#include "element_type_map_filter.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_nodal_field.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename T, template <bool> class dump_type>
std::shared_ptr<dumpers::Field>
GroupManager::createElementalField(const ElementTypeMapArray<T> & field,
const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- ElementTypeMap<UInt> nb_data_per_elem) {
+ Int spatial_dimension, ElementKind kind,
+ ElementTypeMap<Int> nb_data_per_elem) {
- const ElementTypeMapArray<T> * field_ptr = &field;
+ const auto * field_ptr = &field;
if (field_ptr == nullptr) {
return nullptr;
}
if (group_name == "all") {
return this->createElementalField<dump_type<false>>(
field, group_name, spatial_dimension, kind, nb_data_per_elem);
}
return this->createElementalFilteredField<dump_type<true>>(
field, group_name, spatial_dimension, kind, nb_data_per_elem);
}
/* -------------------------------------------------------------------------- */
-template <typename T, template <class> class T2,
- template <class, template <class> class, bool> class dump_type>
+template <typename T, class ret_type,
+ template <class, class, bool> class dump_type>
std::shared_ptr<dumpers::Field>
GroupManager::createElementalField(const ElementTypeMapArray<T> & field,
const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- ElementTypeMap<UInt> nb_data_per_elem) {
+ Int spatial_dimension, ElementKind kind,
+ ElementTypeMap<Int> nb_data_per_elem) {
- const ElementTypeMapArray<T> * field_ptr = &field;
+ const auto * field_ptr = &field;
if (field_ptr == nullptr) {
return nullptr;
}
if (group_name == "all") {
- return this->createElementalField<dump_type<T, T2, false>>(
+ return this->createElementalField<dump_type<T, ret_type, false>>(
field, group_name, spatial_dimension, kind, nb_data_per_elem);
}
- return this->createElementalFilteredField<dump_type<T, T2, true>>(
+ return this->createElementalFilteredField<dump_type<T, ret_type, true>>(
field, group_name, spatial_dimension, kind, nb_data_per_elem);
}
/* -------------------------------------------------------------------------- */
template <typename T, template <typename T2, bool filtered>
class dump_type> ///< type of InternalMaterialField
std::shared_ptr<dumpers::Field>
GroupManager::createElementalField(const ElementTypeMapArray<T> & field,
const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- ElementTypeMap<UInt> nb_data_per_elem) {
- const ElementTypeMapArray<T> * field_ptr = &field;
+ Int spatial_dimension, ElementKind kind,
+ ElementTypeMap<Int> nb_data_per_elem) {
+ const auto * field_ptr = &field;
if (field_ptr == nullptr) {
return nullptr;
}
if (group_name == "all") {
return this->createElementalField<dump_type<T, false>>(
field, group_name, spatial_dimension, kind, nb_data_per_elem);
}
return this->createElementalFilteredField<dump_type<T, true>>(
field, group_name, spatial_dimension, kind, nb_data_per_elem);
}
/* -------------------------------------------------------------------------- */
template <typename dump_type, typename field_type>
std::shared_ptr<dumpers::Field> GroupManager::createElementalField(
const field_type & field, const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- const ElementTypeMap<UInt> & nb_data_per_elem) {
+ Int spatial_dimension, ElementKind kind,
+ const ElementTypeMap<Int> & nb_data_per_elem) {
const field_type * field_ptr = &field;
if (field_ptr == nullptr) {
return nullptr;
}
if (group_name != "all") {
throw;
}
auto dumper =
std::make_shared<dump_type>(field, spatial_dimension, _not_ghost, kind);
dumper->setNbDataPerElem(nb_data_per_elem);
return dumper;
}
/* -------------------------------------------------------------------------- */
template <typename dump_type, typename field_type>
std::shared_ptr<dumpers::Field> GroupManager::createElementalFilteredField(
const field_type & field, const std::string & group_name,
- UInt spatial_dimension, ElementKind kind,
- ElementTypeMap<UInt> nb_data_per_elem) {
+ Int spatial_dimension, ElementKind kind,
+ ElementTypeMap<Int> nb_data_per_elem) {
- const field_type * field_ptr = &field;
+ const auto * field_ptr = &field;
if (field_ptr == nullptr) {
return nullptr;
}
if (group_name == "all") {
throw;
}
using T = typename field_type::value_type;
- ElementGroup & group = this->getElementGroup(group_name);
- UInt dim = group.getDimension();
+ auto & group = this->getElementGroup(group_name);
+ auto dim = group.getDimension();
if (dim != spatial_dimension) {
throw;
}
- const ElementTypeMapArray<UInt> & elemental_filter = group.getElements();
+ const auto & elemental_filter = group.getElements();
auto * filtered = new ElementTypeMapArrayFilter<T>(field, elemental_filter,
nb_data_per_elem);
auto dumper = std::make_shared<dump_type>(*filtered, dim, _not_ghost, kind);
dumper->setNbDataPerElem(nb_data_per_elem);
return dumper;
}
/* -------------------------------------------------------------------------- */
template <typename type, bool flag, template <class, bool> class ftype>
std::shared_ptr<dumpers::Field>
GroupManager::createNodalField(const ftype<type, flag> * field,
const std::string & group_name,
- UInt padding_size) {
+ Int padding_size) {
return createStridedNodalField(field, group_name, 0, 0, padding_size);
}
/* -------------------------------------------------------------------------- */
template <typename type, bool flag, template <class, bool> class ftype>
std::shared_ptr<dumpers::Field>
GroupManager::createStridedNodalField(const ftype<type, flag> * field,
- const std::string & group_name, UInt size,
- UInt stride, UInt padding_size) {
+ const std::string & group_name, Int size,
+ Int stride, Int padding_size) {
if (not field) {
return nullptr;
}
if (group_name == "all") {
using DumpType = typename dumpers::NodalField<type, false>;
auto dumper = std::make_shared<DumpType>(*field, size, stride);
dumper->setPadding(padding_size);
return dumper;
}
ElementGroup & group = this->getElementGroup(group_name);
- const Array<UInt> * nodal_filter = &(group.getNodeGroup().getNodes());
+ const auto & nodal_filter = group.getNodeGroup().getNodes();
using DumpType = typename dumpers::NodalField<type, true>;
- auto dumper = std::make_shared<DumpType>(*field, size, stride, nodal_filter);
+ auto dumper = std::make_shared<DumpType>(*field, size, stride, &nodal_filter);
dumper->setPadding(padding_size);
return dumper;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/mesh/mesh.cc b/src/mesh/mesh.cc
index 1f34f3a85..bedde06a8 100644
--- a/src/mesh/mesh.cc
+++ b/src/mesh/mesh.cc
@@ -1,665 +1,674 @@
/**
* @file mesh.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Feb 09 2021
*
* @brief class handling meshes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
/* -------------------------------------------------------------------------- */
#include "aka_config.hh"
/* -------------------------------------------------------------------------- */
#include "element_class.hh"
#include "group_manager_inline_impl.hh"
#include "mesh.hh"
#include "mesh_global_data_updater.hh"
#include "mesh_io.hh"
#include "mesh_iterators.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "element_synchronizer.hh"
#include "facet_synchronizer.hh"
#include "mesh_utils_distribution.hh"
#include "node_synchronizer.hh"
#include "periodic_node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
#include "dumper_field.hh"
#include "dumper_internal_material_field.hh"
/* -------------------------------------------------------------------------- */
#include <limits>
#include <sstream>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-Mesh::Mesh(UInt spatial_dimension, const ID & id, Communicator & communicator)
+Mesh::Mesh(Int spatial_dimension, const ID & id, Communicator & communicator)
: GroupManager(*this, id + ":group_manager"), MeshData("mesh_data", id),
id(id), connectivities("connectivities", id),
- ghosts_counters("ghosts_counters", id), normals("normals", id),
- spatial_dimension(spatial_dimension), size(spatial_dimension, 0.),
- bbox(spatial_dimension), bbox_local(spatial_dimension),
- communicator(&communicator) {
+ ghosts_counters("ghosts_counters", id),
+ spatial_dimension(spatial_dimension),
+ size(Vector<double>::Zero(spatial_dimension)), bbox(spatial_dimension),
+ bbox_local(spatial_dimension), communicator(&communicator) {
AKANTU_DEBUG_IN();
-
+ size.fill(0.);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Mesh::Mesh(UInt spatial_dimension, Communicator & communicator, const ID & id)
+Mesh::Mesh(Int spatial_dimension, Communicator & communicator, const ID & id)
: Mesh(spatial_dimension, id, communicator) {
AKANTU_DEBUG_IN();
this->nodes =
std::make_shared<Array<Real>>(0, spatial_dimension, id + ":coordinates");
this->nodes_flags = std::make_shared<Array<NodeFlag>>(0, 1, NodeFlag::_normal,
id + ":nodes_flags");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Mesh::Mesh(UInt spatial_dimension, const ID & id)
+Mesh::Mesh(Int spatial_dimension, const ID & id)
: Mesh(spatial_dimension, Communicator::getStaticCommunicator(), id) {}
/* -------------------------------------------------------------------------- */
-Mesh::Mesh(UInt spatial_dimension, const std::shared_ptr<Array<Real>> & nodes,
+Mesh::Mesh(Int spatial_dimension, const std::shared_ptr<Array<Real>> & nodes,
const ID & id)
: Mesh(spatial_dimension, id, Communicator::getStaticCommunicator()) {
+ // NOLINTBEGIN(cppcoreguidelines-prefer-member-initializer)
this->nodes = nodes;
-
this->nb_global_nodes = this->nodes->size();
-
+ // NOLINTEND(cppcoreguidelines-prefer-member-initializer)
+ //
this->nodes_to_elements.resize(nodes->size());
for (auto & node_set : nodes_to_elements) {
node_set = std::make_unique<std::set<Element>>();
}
this->computeBoundingBox();
}
+/* -------------------------------------------------------------------------- */
+Mesh::~Mesh() = default;
+
/* -------------------------------------------------------------------------- */
void Mesh::getBarycenters(Array<Real> & barycenter, ElementType type,
GhostType ghost_type) const {
barycenter.resize(getNbElement(type, ghost_type));
for (auto && data : enumerate(make_view(barycenter, spatial_dimension))) {
- getBarycenter(Element{type, UInt(std::get<0>(data)), ghost_type},
+ getBarycenter(Element{type, Idx(std::get<0>(data)), ghost_type},
std::get<1>(data));
}
}
class FacetGlobalConnectivityAccessor : public DataAccessor<Element> {
public:
FacetGlobalConnectivityAccessor(Mesh & mesh)
: global_connectivity("global_connectivity",
"facet_connectivity_synchronizer") {
global_connectivity.initialize(
mesh, _spatial_dimension = _all_dimensions, _with_nb_element = true,
_with_nb_nodes_per_element = true, _element_kind = _ek_regular);
mesh.getGlobalConnectivity(global_connectivity);
}
- UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override {
- UInt size = 0;
+ [[nodiscard]] Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override {
+ Int size = 0;
if (tag == SynchronizationTag::_smmc_facets_conn) {
- UInt nb_nodes = Mesh::getNbNodesPerElementList(elements);
- size += nb_nodes * sizeof(UInt);
+ Int nb_nodes = Mesh::getNbNodesPerElementList(elements);
+ size += nb_nodes * sizeof(Idx);
}
return size;
}
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const override {
if (tag == SynchronizationTag::_smmc_facets_conn) {
for (const auto & element : elements) {
const auto & conns =
global_connectivity(element.type, element.ghost_type);
for (auto n : arange(conns.getNbComponent())) {
buffer << conns(element.element, n);
}
}
}
}
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) override {
if (tag == SynchronizationTag::_smmc_facets_conn) {
for (const auto & element : elements) {
auto & conns = global_connectivity(element.type, element.ghost_type);
for (auto n : arange(conns.getNbComponent())) {
buffer >> conns(element.element, n);
}
}
}
}
AKANTU_GET_MACRO(GlobalConnectivity, (global_connectivity), decltype(auto));
-protected:
- ElementTypeMapArray<UInt> global_connectivity;
+private:
+ ElementTypeMapArray<Idx> global_connectivity;
};
+/* -------------------------------------------------------------------------- */
+// const Array<Real> & Mesh::getNormals(ElementType element_type,
+// GhostType ghost_type) {
+// if (this->hasData<Real>("normals", element_type, ghost_type)) {
+// return this->getData<Real>("normals", element_type, ghost_type);
+// }
+
+// auto & normals = getDataPointer<Real>("normals", element_type, ghost_type,
+// spatial_dimension, true);
+// for (auto && data [[gnu::unused]] :
+// enumerate(make_view(normals, spatial_dimension))) {
+// AKANTU_TO_IMPLEMENT();
+// }
+
+// AKANTU_TO_IMPLEMENT();
+// }
+
/* -------------------------------------------------------------------------- */
Mesh & Mesh::initMeshFacets(const ID & id) {
AKANTU_DEBUG_IN();
if (mesh_facets) {
AKANTU_DEBUG_OUT();
return *mesh_facets;
}
mesh_facets = std::make_unique<Mesh>(spatial_dimension, this->nodes,
getID() + ":" + id);
-
mesh_facets->mesh_parent = this;
mesh_facets->is_mesh_facets = true;
mesh_facets->nodes_flags = this->nodes_flags;
mesh_facets->nodes_global_ids = this->nodes_global_ids;
MeshUtils::buildAllFacets(*this, *mesh_facets, 0);
if (mesh.isDistributed()) {
mesh_facets->is_distributed = true;
mesh_facets->element_synchronizer = std::make_unique<FacetSynchronizer>(
*mesh_facets, mesh.getElementSynchronizer());
FacetGlobalConnectivityAccessor data_accessor(*mesh_facets);
/// communicate
mesh_facets->element_synchronizer->synchronizeOnce(
data_accessor, SynchronizationTag::_smmc_facets_conn);
/// flip facets
MeshUtils::flipFacets(*mesh_facets, data_accessor.getGlobalConnectivity(),
_ghost);
}
/// transfers the the mesh physical names to the mesh facets
if (not this->hasData("physical_names")) {
AKANTU_DEBUG_OUT();
return *mesh_facets;
}
auto & mesh_phys_data = this->getData<std::string>("physical_names");
auto & mesh_to_mesh_facet = this->getData<Element>("mesh_to_mesh_facet");
mesh_to_mesh_facet.initialize(*this,
_spatial_dimension = spatial_dimension - 1,
_with_nb_element = true);
auto & phys_data = mesh_facets->getData<std::string>("physical_names");
phys_data.initialize(*mesh_facets, _spatial_dimension = spatial_dimension - 1,
_with_nb_element = true);
ElementTypeMapArray<Real> barycenters(getID(), "temporary_barycenters");
barycenters.initialize(*mesh_facets, _nb_component = spatial_dimension,
_spatial_dimension = spatial_dimension - 1,
_with_nb_element = true);
for (auto && ghost_type : ghost_types) {
for (auto && type :
barycenters.elementTypes(spatial_dimension - 1, ghost_type)) {
mesh_facets->getBarycenters(barycenters(type, ghost_type), type,
ghost_type);
}
}
for_each_element(
mesh,
[&](auto && element) {
Vector<Real> barycenter(spatial_dimension);
mesh.getBarycenter(element, barycenter);
auto norm_barycenter = barycenter.norm();
auto tolerance = Math::getTolerance();
if (norm_barycenter > tolerance) {
tolerance *= norm_barycenter;
}
Vector<Real> barycenter_facet(spatial_dimension);
auto range = enumerate(make_view(
barycenters(element.type, element.ghost_type), spatial_dimension));
#ifndef AKANTU_NDEBUG
auto min_dist = std::numeric_limits<Real>::max();
#endif
// this is a spacial search coded the most inefficient way.
auto facet =
std::find_if(range.begin(), range.end(), [&](auto && data) {
auto norm_distance = barycenter.distance(std::get<1>(data));
#ifndef AKANTU_NDEBUG
min_dist = std::min(min_dist, norm_distance);
#endif
return (norm_distance < tolerance);
});
if (facet == range.end()) {
AKANTU_DEBUG_INFO("The element "
<< element
<< " did not find its associated facet in the "
"mesh_facets! Try to decrease math tolerance. "
"The closest element was at a distance of "
<< min_dist);
return;
}
// set physical name
- auto && facet_element = Element{element.type, UInt(std::get<0>(*facet)),
- element.ghost_type};
+ auto && facet_element =
+ Element{element.type, std::get<0>(*facet), element.ghost_type};
phys_data(facet_element) = mesh_phys_data(element);
mesh_to_mesh_facet(element) = facet_element;
},
_spatial_dimension = spatial_dimension - 1);
mesh_facets->createGroupsFromMeshData<std::string>("physical_names");
AKANTU_DEBUG_OUT();
return *mesh_facets;
}
/* -------------------------------------------------------------------------- */
void Mesh::defineMeshParent(const Mesh & mesh) {
AKANTU_DEBUG_IN();
this->mesh_parent = &mesh;
this->is_mesh_facets = true;
AKANTU_DEBUG_OUT();
}
-/* -------------------------------------------------------------------------- */
-Mesh::~Mesh() = default;
-
/* -------------------------------------------------------------------------- */
void Mesh::read(const std::string & filename, const MeshIOType & mesh_io_type) {
AKANTU_DEBUG_ASSERT(not is_distributed,
"You cannot read a mesh that is already distributed");
MeshIO::read(filename, *this, mesh_io_type);
auto types =
this->elementTypes(spatial_dimension, _not_ghost, _ek_not_defined);
auto it = types.begin();
auto last = types.end();
if (it == last) {
AKANTU_DEBUG_WARNING(
"The mesh contained in the file "
<< filename << " does not seem to be of the good dimension."
<< " No element of dimension " << spatial_dimension << " were read.");
}
this->makeReady();
}
/* -------------------------------------------------------------------------- */
void Mesh::write(const std::string & filename,
const MeshIOType & mesh_io_type) {
MeshIO::write(filename, *this, mesh_io_type);
}
/* -------------------------------------------------------------------------- */
void Mesh::makeReady() {
this->nb_global_nodes = this->nodes->size();
this->computeBoundingBox();
this->nodes_flags->resize(nodes->size(), NodeFlag::_normal);
this->nodes_to_elements.resize(nodes->size());
for (auto & node_set : nodes_to_elements) {
node_set = std::make_unique<std::set<Element>>();
}
}
/* -------------------------------------------------------------------------- */
void Mesh::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "Mesh [" << std::endl;
stream << space << " + id : " << getID() << std::endl;
stream << space << " + spatial dimension : " << this->spatial_dimension
<< std::endl;
stream << space << " + nodes [" << std::endl;
nodes->printself(stream, indent + 2);
stream << space << " + connectivities [" << std::endl;
connectivities.printself(stream, indent + 2);
stream << space << " ]" << std::endl;
GroupManager::printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
void Mesh::computeBoundingBox() {
AKANTU_DEBUG_IN();
bbox_local.reset();
for (auto & pos : make_view(*nodes, spatial_dimension)) {
// if(!isPureGhostNode(i))
bbox_local += pos;
}
if (this->is_distributed) {
bbox = bbox_local.allSum(*communicator);
} else {
bbox = bbox_local;
}
size = bbox.size();
AKANTU_DEBUG_OUT();
}
-/* -------------------------------------------------------------------------- */
-void Mesh::initNormals() {
- normals.initialize(*this, _nb_component = spatial_dimension,
- _spatial_dimension = spatial_dimension,
- _element_kind = _ek_not_defined);
-}
-
/* -------------------------------------------------------------------------- */
void Mesh::getGlobalConnectivity(
- ElementTypeMapArray<UInt> & global_connectivity) {
+ ElementTypeMapArray<Idx> & global_connectivity) {
AKANTU_DEBUG_IN();
for (auto && ghost_type : ghost_types) {
for (auto type :
global_connectivity.elementTypes(_spatial_dimension = _all_dimensions,
_element_kind = _ek_not_defined, _ghost_type = ghost_type)) {
if (not connectivities.exists(type, ghost_type)) {
continue;
}
- auto & local_conn = connectivities(type, ghost_type);
- auto & g_connectivity = global_connectivity(type, ghost_type);
-
- UInt nb_nodes = local_conn.size() * local_conn.getNbComponent();
+ auto local_conn_view = make_view(connectivities(type, ghost_type));
+ auto global_conn_view = make_view(global_connectivity(type, ghost_type));
- std::transform(local_conn.begin_reinterpret(nb_nodes),
- local_conn.end_reinterpret(nb_nodes),
- g_connectivity.begin_reinterpret(nb_nodes),
- [&](UInt l) -> UInt { return this->getNodeGlobalId(l); });
+ std::transform(local_conn_view.begin(), local_conn_view.end(),
+ global_conn_view.begin(),
+ [&](Idx l) -> Idx { return this->getNodeGlobalId(l); });
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
DumperIOHelper & Mesh::getGroupDumper(const std::string & dumper_name,
const std::string & group_name) {
if (group_name == "all") {
return this->getDumper(dumper_name);
}
return element_groups[group_name]->getDumper(dumper_name);
}
/* -------------------------------------------------------------------------- */
template <typename T>
-ElementTypeMap<UInt> Mesh::getNbDataPerElem(ElementTypeMapArray<T> & arrays) {
- ElementTypeMap<UInt> nb_data_per_elem;
+ElementTypeMap<Int> Mesh::getNbDataPerElem(ElementTypeMapArray<T> & arrays) {
+ ElementTypeMap<Int> nb_data_per_elem;
for (auto type : arrays.elementTypes(_element_kind = _ek_not_defined)) {
- UInt nb_elements = this->getNbElement(type);
+ auto nb_elements = this->getNbElement(type);
auto & array = arrays(type);
nb_data_per_elem(type) = array.getNbComponent() * array.size();
nb_data_per_elem(type) /= nb_elements;
}
return nb_data_per_elem;
}
/* -------------------------------------------------------------------------- */
-template ElementTypeMap<UInt>
+template ElementTypeMap<Int>
Mesh::getNbDataPerElem(ElementTypeMapArray<Real> & array);
-template ElementTypeMap<UInt>
-Mesh::getNbDataPerElem(ElementTypeMapArray<UInt> & array);
+template ElementTypeMap<Int>
+Mesh::getNbDataPerElem(ElementTypeMapArray<Int> & array);
/* -------------------------------------------------------------------------- */
template <typename T>
std::shared_ptr<dumpers::Field>
Mesh::createFieldFromAttachedData(const std::string & field_id,
const std::string & group_name,
ElementKind element_kind) {
std::shared_ptr<dumpers::Field> field;
ElementTypeMapArray<T> * internal = nullptr;
try {
internal = &(this->getData<T>(field_id));
} catch (...) {
return nullptr;
}
- ElementTypeMap<UInt> nb_data_per_elem = this->getNbDataPerElem(*internal);
+ auto && nb_data_per_elem = this->getNbDataPerElem(*internal);
field = this->createElementalField<T, dumpers::InternalMaterialField>(
*internal, group_name, this->spatial_dimension, element_kind,
nb_data_per_elem);
return field;
}
template std::shared_ptr<dumpers::Field>
Mesh::createFieldFromAttachedData<Real>(const std::string & field_id,
const std::string & group_name,
ElementKind element_kind);
template std::shared_ptr<dumpers::Field>
-Mesh::createFieldFromAttachedData<UInt>(const std::string & field_id,
- const std::string & group_name,
- ElementKind element_kind);
+Mesh::createFieldFromAttachedData<Int>(const std::string & field_id,
+ const std::string & group_name,
+ ElementKind element_kind);
/* -------------------------------------------------------------------------- */
void Mesh::distributeImpl(
Communicator & communicator,
const std::function<Int(const Element &, const Element &)> &
edge_weight_function [[gnu::unused]],
const std::function<Int(const Element &)> & vertex_weight_function
[[gnu::unused]]) {
AKANTU_DEBUG_ASSERT(is_distributed == false,
"This mesh is already distribute");
this->communicator = &communicator;
this->element_synchronizer = std::make_unique<ElementSynchronizer>(
*this, this->getID() + ":element_synchronizer", true);
this->node_synchronizer = std::make_unique<NodeSynchronizer>(
*this, this->getID() + ":node_synchronizer", true);
- Int psize = this->communicator->getNbProc();
+ auto psize = this->communicator->getNbProc();
if (psize > 1) {
#ifdef AKANTU_USE_SCOTCH
- Int prank = this->communicator->whoAmI();
+ auto prank = this->communicator->whoAmI();
if (prank == 0) {
MeshPartitionScotch partition(*this, spatial_dimension);
partition.partitionate(psize, edge_weight_function,
vertex_weight_function);
MeshUtilsDistribution::distributeMeshCentralized(*this, 0, partition);
} else {
MeshUtilsDistribution::distributeMeshCentralized(*this, 0);
}
#else
AKANTU_ERROR("Cannot distribute a mesh without a partitioning tool");
#endif
}
// if (psize > 1)
this->is_distributed = true;
this->computeBoundingBox();
- MeshIsDistributedEvent event(*this, AKANTU_CURRENT_FUNCTION);
+ MeshIsDistributedEvent event(AKANTU_CURRENT_FUNCTION);
this->sendEvent(event);
}
/* -------------------------------------------------------------------------- */
-void Mesh::getAssociatedElements(const Array<UInt> & node_list,
- Array<Element> & elements) const {
+void Mesh::getAssociatedElements(const Array<Idx> & node_list,
+ Array<Element> & elements) {
for (const auto & node : node_list) {
for (const auto & element : *nodes_to_elements[node]) {
elements.push_back(element);
}
}
}
/* -------------------------------------------------------------------------- */
-void Mesh::getAssociatedElements(const UInt & node,
+void Mesh::getAssociatedElements(const Idx & node,
Array<Element> & elements) const {
for (const auto & element : *nodes_to_elements[node]) {
elements.push_back(element);
}
}
/* -------------------------------------------------------------------------- */
-void Mesh::fillNodesToElements(UInt dimension) {
- Element e;
+void Mesh::fillNodesToElements(Int dimension) {
+ Element element{ElementNull};
- UInt nb_nodes = nodes->size();
+ auto nb_nodes = nodes->size();
this->nodes_to_elements.resize(nb_nodes);
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (this->nodes_to_elements[n]) {
this->nodes_to_elements[n]->clear();
} else {
this->nodes_to_elements[n] = std::make_unique<std::set<Element>>();
}
}
for (auto ghost_type : ghost_types) {
- e.ghost_type = ghost_type;
+ element.ghost_type = ghost_type;
for (const auto & type :
elementTypes(dimension, ghost_type, _ek_not_defined)) {
- e.type = type;
+ element.type = type;
- UInt nb_element = this->getNbElement(type, ghost_type);
+ auto nb_element = this->getNbElement(type, ghost_type);
auto connectivity = connectivities(type, ghost_type);
auto conn_it = connectivity.begin(connectivity.getNbComponent());
- for (UInt el = 0; el < nb_element; ++el, ++conn_it) {
- e.element = el;
- const Vector<UInt> & conn = *conn_it;
+ for (Int el = 0; el < nb_element; ++el, ++conn_it) {
+ element.element = el;
+ const auto & conn = *conn_it;
for (auto node : conn) {
- nodes_to_elements[node]->insert(e);
+ nodes_to_elements[node]->insert(element);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
-std::tuple<UInt, UInt>
-Mesh::updateGlobalData(NewNodesEvent & nodes_event,
- NewElementsEvent & elements_event) {
+std::tuple<Idx, Idx> Mesh::updateGlobalData(NewNodesEvent & nodes_event,
+ NewElementsEvent & elements_event) {
if (global_data_updater) {
return this->global_data_updater->updateData(nodes_event, elements_event);
}
return std::make_tuple(nodes_event.getList().size(),
elements_event.getList().size());
}
/* -------------------------------------------------------------------------- */
void Mesh::registerGlobalDataUpdater(
std::unique_ptr<MeshGlobalDataUpdater> && global_data_updater) {
this->global_data_updater = std::move(global_data_updater);
}
/* -------------------------------------------------------------------------- */
void Mesh::eraseElements(const Array<Element> & elements) {
- ElementTypeMap<UInt> last_element;
+ ElementTypeMap<Idx> last_element;
RemovedElementsEvent event(*this, "new_numbering", AKANTU_CURRENT_FUNCTION);
auto & remove_list = event.getList();
auto & new_numbering = event.getNewNumbering();
for (auto && el : elements) {
if (el.ghost_type != _not_ghost) {
auto & count = ghosts_counters(el);
--count;
+ AKANTU_DEBUG_ASSERT(count >= 0,
+ "Something went wrong in the ghost element counter");
+
if (count > 0) {
continue;
}
}
-
remove_list.push_back(el);
if (not new_numbering.exists(el.type, el.ghost_type)) {
auto nb_element = mesh.getNbElement(el.type, el.ghost_type);
auto & numbering =
new_numbering.alloc(nb_element, 1, el.type, el.ghost_type);
- for (auto && pair : enumerate(numbering)) {
- std::get<1>(pair) = std::get<0>(pair);
+ for (auto && [i, numb] : enumerate(numbering)) {
+ numb = i;
}
}
- new_numbering(el) = UInt(-1);
+ new_numbering(el) = -1;
}
auto find_last_not_deleted = [](auto && array, Int start) -> Int {
do {
--start;
- } while (start >= 0 and array[start] == UInt(-1));
+ } while (start >= 0 and array[start] == -1);
return start;
};
auto find_first_deleted = [](auto && array, Int start) -> Int {
auto begin = array.begin();
auto it = std::find_if(begin + start, array.end(),
- [](auto & el) { return el == UInt(-1); });
+ [](auto & el) { return el == -1; });
return Int(it - begin);
};
for (auto ghost_type : ghost_types) {
for (auto type : new_numbering.elementTypes(_ghost_type = ghost_type)) {
auto & numbering = new_numbering(type, ghost_type);
auto last_not_delete = find_last_not_deleted(numbering, numbering.size());
if (last_not_delete < 0) {
continue;
}
auto pos = find_first_deleted(numbering, 0);
while (pos < last_not_delete) {
std::swap(numbering[pos], numbering[last_not_delete]);
last_not_delete = find_last_not_deleted(numbering, last_not_delete);
pos = find_first_deleted(numbering, pos + 1);
}
}
}
+
+ this->ghosts_counters.onElementsRemoved(new_numbering);
this->sendEvent(event);
}
} // namespace akantu
diff --git a/src/mesh/mesh.hh b/src/mesh/mesh.hh
index 19f23d05e..4d0d1dbb2 100644
--- a/src/mesh/mesh.hh
+++ b/src/mesh/mesh.hh
@@ -1,699 +1,742 @@
/**
* @file mesh.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Nov 12 2020
*
* @brief the class representing the meshes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_HH_
#define AKANTU_MESH_HH_
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_bbox.hh"
#include "aka_event_handler_manager.hh"
#include "communicator.hh"
#include "dumpable.hh"
#include "element.hh"
#include "element_class.hh"
#include "element_type_map.hh"
#include "group_manager.hh"
#include "mesh_data.hh"
#include "mesh_events.hh"
/* -------------------------------------------------------------------------- */
#include <functional>
#include <set>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
namespace akantu {
class ElementSynchronizer;
class NodeSynchronizer;
class PeriodicNodeSynchronizer;
class MeshGlobalDataUpdater;
} // namespace akantu
namespace akantu {
namespace {
DECLARE_NAMED_ARGUMENT(communicator);
DECLARE_NAMED_ARGUMENT(edge_weight_function);
DECLARE_NAMED_ARGUMENT(vertex_weight_function);
} // namespace
/* -------------------------------------------------------------------------- */
/* Mesh */
/* -------------------------------------------------------------------------- */
/**
* @class Mesh mesh.hh
*
* This class contaisn the coordinates of the nodes in the Mesh.nodes
* akant::Array, and the connectivity. The connectivity are stored in by element
* types.
*
* In order to loop on all element you have to loop on all types like this :
* @code{.cpp}
for(auto & type : mesh.elementTypes()) {
- UInt nb_element = mesh.getNbElement(type);
- const Array<UInt> & conn = mesh.getConnectivity(type);
- for(UInt e = 0; e < nb_element; ++e) {
+ Int nb_element = mesh.getNbElement(type);
+ const auto & conn = mesh.getConnectivity(type);
+ for(Int e = 0; e < nb_element; ++e) {
...
}
}
or
for_each_element(mesh, [](Element & element) {
std::cout << element << std::endl
});
@endcode
*/
class Mesh : public EventHandlerManager<MeshEventHandler>,
public GroupManager,
public MeshData,
public Dumpable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
private:
/// default constructor used for chaining, the last parameter is just to
/// differentiate constructors
- Mesh(UInt spatial_dimension, const ID & id, Communicator & communicator);
+ Mesh(Int spatial_dimension, const ID & id, Communicator & communicator);
public:
/// constructor that create nodes coordinates array
- Mesh(UInt spatial_dimension, const ID & id = "mesh");
+ Mesh(Int spatial_dimension, const ID & id = "mesh");
/// mesh not distributed and not using the default communicator
- Mesh(UInt spatial_dimension, Communicator & communicator,
+ Mesh(Int spatial_dimension, Communicator & communicator,
const ID & id = "mesh");
/**
* constructor that use an existing nodes coordinates
* array, by getting the vector of coordinates
*/
- Mesh(UInt spatial_dimension, const std::shared_ptr<Array<Real>> & nodes,
+ Mesh(Int spatial_dimension, const std::shared_ptr<Array<Real>> & nodes,
const ID & id = "mesh");
~Mesh() override;
+ Mesh(const Mesh &) = delete;
+ Mesh(Mesh &&) = delete;
+ Mesh & operator=(const Mesh &) = delete;
+ Mesh & operator=(Mesh &&) = delete;
+
/// read the mesh from a file
void read(const std::string & filename,
const MeshIOType & mesh_io_type = _miot_auto);
/// write the mesh to a file
void write(const std::string & filename,
const MeshIOType & mesh_io_type = _miot_auto);
protected:
void makeReady();
private:
/// initialize the connectivity to NULL and other stuff
void init();
/// function that computes the bounding box (fills xmin, xmax)
void computeBoundingBox();
/* ------------------------------------------------------------------------ */
/* Distributed memory methods and accessors */
/* ------------------------------------------------------------------------ */
public:
protected:
/// patitionate the mesh among the processors involved in their computation
virtual void distributeImpl(
Communicator & communicator,
const std::function<Int(const Element &, const Element &)> &
edge_weight_function,
const std::function<Int(const Element &)> & vertex_weight_function);
public:
/// with the arguments to pass to the partitionner
template <typename... pack>
std::enable_if_t<are_named_argument<pack...>::value>
distribute(pack &&... _pack) {
distributeImpl(
OPTIONAL_NAMED_ARG(communicator, Communicator::getStaticCommunicator()),
OPTIONAL_NAMED_ARG(edge_weight_function,
[](auto &&, auto &&) { return 1; }),
OPTIONAL_NAMED_ARG(vertex_weight_function, [](auto &&) { return 1; }));
}
/// defines is the mesh is distributed or not
inline bool isDistributed() const { return this->is_distributed; }
/* ------------------------------------------------------------------------ */
/* Periodicity methods and accessors */
/* ------------------------------------------------------------------------ */
public:
/// set the periodicity in a given direction
void makePeriodic(const SpatialDirection & direction);
void makePeriodic(const SpatialDirection & direction, const ID & list_1,
const ID & list_2);
protected:
void makePeriodic(const SpatialDirection & direction,
- const Array<UInt> & list_left,
- const Array<UInt> & list_right);
+ const Array<Idx> & list_1, const Array<Idx> & list_2);
/// Removes the face that the mesh is periodic
void wipePeriodicInfo();
- inline void addPeriodicSlave(UInt slave, UInt master);
+ inline void addPeriodicSlave(Idx slave, Idx master);
template <typename T>
void synchronizePeriodicSlaveDataWithMaster(Array<T> & data);
// update the periodic synchronizer (creates it if it does not exists)
void updatePeriodicSynchronizer();
public:
/// defines if the mesh is periodic or not
inline bool isPeriodic() const { return this->is_periodic; }
inline bool isPeriodic(const SpatialDirection & /*direction*/) const {
return this->is_periodic;
}
class PeriodicSlaves;
/// get the master node for a given slave nodes, except if node not a slave
- inline UInt getPeriodicMaster(UInt slave) const;
+ inline Idx getPeriodicMaster(Idx slave) const;
/// get an iterable list of slaves for a given master node
- inline decltype(auto) getPeriodicSlaves(UInt master) const;
+ inline decltype(auto) getPeriodicSlaves(Idx master) const;
/* ------------------------------------------------------------------------ */
/* General Methods */
/* ------------------------------------------------------------------------ */
public:
/// function to print the containt of the class
void printself(std::ostream & stream, int indent = 0) const override;
/// extract coordinates of nodes from an element
- template <typename T>
- inline void
- extractNodalValuesFromElement(const Array<T> & nodal_values, T * local_coord,
- const UInt * connectivity, UInt n_nodes,
- UInt nb_degree_of_freedom) const;
+ template <typename T, class Derived1, class Derived2,
+ std::enable_if_t<aka::is_vector_v<Derived2>> * = nullptr>
+ inline void extractNodalValuesFromElement(
+ const Array<T> & nodal_values,
+ Eigen::MatrixBase<Derived1> & elemental_values,
+ const Eigen::MatrixBase<Derived2> & connectivity) const;
- // /// extract coordinates of nodes from a reversed element
- // inline void extractNodalCoordinatesFromPBCElement(Real * local_coords,
- // UInt * connectivity,
- // UInt n_nodes);
+ /// extract coordinates of nodes from an element
+ template <typename T>
+ inline decltype(auto)
+ extractNodalValuesFromElement(const Array<T> & nodal_values,
+ const Element & element) const;
/// add a Array of connectivity for the given ElementType and GhostType .
inline void addConnectivityType(ElementType type,
GhostType ghost_type = _not_ghost);
/* ------------------------------------------------------------------------ */
template <class Event> inline void sendEvent(Event & event) {
// if(event.getList().size() != 0)
EventHandlerManager<MeshEventHandler>::sendEvent<Event>(event);
}
/// prepare the event to remove the elements listed
void eraseElements(const Array<Element> & elements);
/* ------------------------------------------------------------------------ */
template <typename T>
inline void removeNodesFromArray(Array<T> & vect,
- const Array<UInt> & new_numbering);
-
- /// initialize normals
- void initNormals();
+ const Array<Int> & new_numbering);
/// init facets' mesh
Mesh & initMeshFacets(const ID & id = "mesh_facets");
/// define parent mesh
void defineMeshParent(const Mesh & mesh);
/// get global connectivity array
- void getGlobalConnectivity(ElementTypeMapArray<UInt> & global_connectivity);
+ void getGlobalConnectivity(ElementTypeMapArray<Int> & global_connectivity);
public:
- void getAssociatedElements(const Array<UInt> & node_list,
- Array<Element> & elements) const;
+ void getAssociatedElements(const Array<Int> & node_list,
+ Array<Element> & elements);
+
+ void getAssociatedElements(const Idx & node, Array<Element> & elements) const;
- void getAssociatedElements(const UInt & node,
- Array<Element> & elements) const;
+ inline decltype(auto) getAssociatedElements(const Idx & node) const;
public:
/// fills the nodes_to_elements for given dimension elements
- void fillNodesToElements(UInt dimension = _all_dimensions);
+ void fillNodesToElements(Int dimension = _all_dimensions);
private:
/// update the global ids, nodes type, ...
- std::tuple<UInt, UInt> updateGlobalData(NewNodesEvent & nodes_event,
- NewElementsEvent & elements_event);
+ std::tuple<Int, Int> updateGlobalData(NewNodesEvent & nodes_event,
+ NewElementsEvent & elements_event);
void registerGlobalDataUpdater(
std::unique_ptr<MeshGlobalDataUpdater> && global_data_updater);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the id of the mesh
AKANTU_GET_MACRO(ID, id, const ID &);
/// get the spatial dimension of the mesh = number of component of the
/// coordinates
- AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
+ AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, Int);
/// get the nodes Array aka coordinates
AKANTU_GET_MACRO(Nodes, *nodes, const Array<Real> &);
AKANTU_GET_MACRO_NOT_CONST(Nodes, *nodes, Array<Real> &);
- /// get the normals for the elements
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Normals, normals, Real);
-
/// get the number of nodes
- AKANTU_GET_MACRO(NbNodes, nodes->size(), UInt);
+ auto getNbNodes() const { return nodes->size(); }
/// get the Array of global ids of the nodes (only used in parallel)
- AKANTU_GET_MACRO(GlobalNodesIds, *nodes_global_ids, const Array<UInt> &);
+ AKANTU_GET_MACRO_AUTO(GlobalNodesIds, *nodes_global_ids);
// AKANTU_GET_MACRO_NOT_CONST(GlobalNodesIds, *nodes_global_ids, Array<UInt>
// &);
/// get the global id of a node
- inline UInt getNodeGlobalId(UInt local_id) const;
+ inline auto getNodeGlobalId(Idx local_id) const;
/// get the global id of a node
- inline UInt getNodeLocalId(UInt global_id) const;
+ inline auto getNodeLocalId(Idx global_id) const;
/// get the global number of nodes
- inline UInt getNbGlobalNodes() const;
+ inline auto getNbGlobalNodes() const;
/// get the nodes type Array
AKANTU_GET_MACRO(NodesFlags, *nodes_flags, const Array<NodeFlag> &);
protected:
AKANTU_GET_MACRO_NOT_CONST(NodesFlags, *nodes_flags, Array<NodeFlag> &);
public:
- inline NodeFlag getNodeFlag(UInt local_id) const;
- inline Int getNodePrank(UInt local_id) const;
+ inline NodeFlag getNodeFlag(Idx local_id) const;
+ inline auto getNodePrank(Idx local_id) const;
/// say if a node is a pure ghost node
- inline bool isPureGhostNode(UInt n) const;
+ inline bool isPureGhostNode(Idx n) const;
/// say if a node is pur local or master node
- inline bool isLocalOrMasterNode(UInt n) const;
+ inline bool isLocalOrMasterNode(Idx n) const;
- inline bool isLocalNode(UInt n) const;
- inline bool isMasterNode(UInt n) const;
- inline bool isSlaveNode(UInt n) const;
+ inline bool isLocalNode(Idx n) const;
+ inline bool isMasterNode(Idx n) const;
+ inline bool isSlaveNode(Idx n) const;
- inline bool isPeriodicSlave(UInt n) const;
- inline bool isPeriodicMaster(UInt n) const;
+ inline bool isPeriodicSlave(Idx n) const;
+ inline bool isPeriodicMaster(Idx n) const;
const Vector<Real> & getLowerBounds() const { return bbox.getLowerBounds(); }
const Vector<Real> & getUpperBounds() const { return bbox.getUpperBounds(); }
AKANTU_GET_MACRO(BBox, bbox, const BBox &);
const Vector<Real> & getLocalLowerBounds() const {
return bbox_local.getLowerBounds();
}
const Vector<Real> & getLocalUpperBounds() const {
return bbox_local.getUpperBounds();
}
AKANTU_GET_MACRO(LocalBBox, bbox_local, const BBox &);
/// get the connectivity Array for a given type
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Connectivity, connectivities, UInt);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Connectivity, connectivities, Idx);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, Idx);
AKANTU_GET_MACRO(Connectivities, connectivities,
- const ElementTypeMapArray<UInt> &);
+ const ElementTypeMapArray<Idx> &);
/// get the number of element of a type in the mesh
- inline UInt getNbElement(ElementType type,
+ inline auto getNbElement(ElementType type,
GhostType ghost_type = _not_ghost) const;
/// get the number of element for a given ghost_type and a given dimension
- inline UInt getNbElement(UInt spatial_dimension = _all_dimensions,
+ inline auto getNbElement(Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_not_defined) const;
/// compute the barycenter of a given element
+ template <class D, std::enable_if_t<aka::is_vector_v<D>> * = nullptr>
inline void getBarycenter(const Element & element,
- Vector<Real> & barycenter) const;
+ const Eigen::MatrixBase<D> & barycenter) const;
+
+ inline Vector<Real> getBarycenter(const Element & element) const;
void getBarycenters(Array<Real> & barycenter, ElementType type,
GhostType ghost_type) const;
/// get the element connected to a subelement (element of lower dimension)
- const auto & getElementToSubelement() const;
+ decltype(auto) getElementToSubelement() const;
/// get the element connected to a subelement
const auto & getElementToSubelement(ElementType el_type,
GhostType ghost_type = _not_ghost) const;
/// get the elements connected to a subelement
- const auto & getElementToSubelement(const Element & element) const;
+ decltype(auto) getElementToSubelement(const Element & element) const;
/// get the subelement (element of lower dimension) connected to a element
- const auto & getSubelementToElement() const;
+ decltype(auto) getSubelementToElement() const;
/// get the subelement connected to an element
const auto & getSubelementToElement(ElementType el_type,
GhostType ghost_type = _not_ghost) const;
/// get the subelement (element of lower dimension) connected to a element
- VectorProxy<Element> getSubelementToElement(const Element & element) const;
+ decltype(auto) getSubelementToElement(const Element & element) const;
/// get connectivity of a given element
- inline VectorProxy<UInt> getConnectivity(const Element & element) const;
- inline Vector<UInt>
+ inline decltype(auto) getConnectivity(const Element & element) const;
+ inline decltype(auto)
getConnectivityWithPeriodicity(const Element & element) const;
protected:
/// get the element connected to a subelement (element of lower dimension)
auto & getElementToSubelementNC();
auto & getSubelementToElementNC();
inline auto & getElementToSubelementNC(const Element & element);
- inline VectorProxy<Element>
- getSubelementToElementNC(const Element & element) const;
+ inline decltype(auto) getSubelementToElementNC(const Element & element) const;
/// get the element connected to a subelement
auto & getElementToSubelementNC(ElementType el_type,
GhostType ghost_type = _not_ghost);
/// get the subelement connected to an element
auto & getSubelementToElementNC(ElementType el_type,
GhostType ghost_type = _not_ghost);
- inline VectorProxy<UInt> getConnectivityNC(const Element & element);
+ inline decltype(auto) getConnectivityNC(const Element & element);
public:
/// get a name field associated to the mesh
template <typename T>
- inline const Array<T> & getData(const ID & data_name, ElementType el_type,
- GhostType ghost_type = _not_ghost) const;
+ inline decltype(auto) getData(const ID & data_name, ElementType el_type,
+ GhostType ghost_type = _not_ghost) const;
/// get a name field associated to the mesh
template <typename T>
- inline Array<T> & getData(const ID & data_name, ElementType el_type,
- GhostType ghost_type = _not_ghost);
+ inline decltype(auto) getData(const ID & data_name, ElementType el_type,
+ GhostType ghost_type = _not_ghost);
/// get a name field associated to the mesh
template <typename T>
- inline const ElementTypeMapArray<T> & getData(const ID & data_name) const;
+ inline decltype(auto) getData(const ID & data_name) const;
/// get a name field associated to the mesh
- template <typename T>
- inline ElementTypeMapArray<T> & getData(const ID & data_name);
+ template <typename T> inline decltype(auto) getData(const ID & data_name);
template <typename T>
- ElementTypeMap<UInt> getNbDataPerElem(ElementTypeMapArray<T> & array);
+ auto getNbDataPerElem(ElementTypeMapArray<T> & array) -> ElementTypeMap<Int>;
template <typename T>
std::shared_ptr<dumpers::Field>
createFieldFromAttachedData(const std::string & field_id,
const std::string & group_name,
ElementKind element_kind);
/// templated getter returning the pointer to data in MeshData (modifiable)
template <typename T>
- inline Array<T> &
+ inline decltype(auto)
getDataPointer(const std::string & data_name, ElementType el_type,
- GhostType ghost_type = _not_ghost, UInt nb_component = 1,
+ GhostType ghost_type = _not_ghost, Int nb_component = 1,
bool size_to_nb_element = true,
bool resize_with_parent = false);
template <typename T>
- inline Array<T> & getDataPointer(const ID & data_name, ElementType el_type,
- GhostType ghost_type, UInt nb_component,
- bool size_to_nb_element,
- bool resize_with_parent, const T & defaul_);
+ inline decltype(auto)
+ getDataPointer(const ID & data_name, ElementType el_type,
+ GhostType ghost_type, Int nb_component,
+ bool size_to_nb_element, bool resize_with_parent,
+ const T & defaul_);
/// Facets mesh accessor
- inline const Mesh & getMeshFacets() const;
- inline Mesh & getMeshFacets();
+ inline auto getMeshFacets() const -> const Mesh &;
+ inline auto getMeshFacets() -> Mesh &;
inline auto hasMeshFacets() const { return mesh_facets != nullptr; }
/// Parent mesh accessor
- inline const Mesh & getMeshParent() const;
+ inline auto getMeshParent() const -> const Mesh &;
- inline bool isMeshFacets() const { return this->is_mesh_facets; }
+ inline auto isMeshFacets() const { return this->is_mesh_facets; }
/// return the dumper from a group and and a dumper name
- DumperIOHelper & getGroupDumper(const std::string & dumper_name,
- const std::string & group_name);
+ auto getGroupDumper(const std::string & dumper_name,
+ const std::string & group_name) -> DumperIOHelper &;
/* ------------------------------------------------------------------------ */
/* Wrappers on ElementClass functions */
/* ------------------------------------------------------------------------ */
public:
/// get the number of nodes per element for a given element type
- static inline UInt getNbNodesPerElement(ElementType type);
+ static inline constexpr auto getNbNodesPerElement(ElementType type) -> Int;
/// get the number of nodes per element for a given element type considered as
/// a first order element
- static inline ElementType getP1ElementType(ElementType type);
+ static inline constexpr auto getP1ElementType(ElementType type)
+ -> ElementType;
/// get the kind of the element type
- static inline ElementKind getKind(ElementType type);
+ static inline constexpr auto getKind(ElementType type) -> ElementKind;
/// get spatial dimension of a type of element
- static inline UInt getSpatialDimension(ElementType type);
+ static inline constexpr auto getSpatialDimension(ElementType type) -> Int;
/// get the natural space dimension of a type of element
- static inline UInt getNaturalSpaceDimension(const ElementType & type);
+ static inline constexpr auto getNaturalSpaceDimension(ElementType type)
+ -> Int;
/// get number of facets of a given element type
- static inline UInt getNbFacetsPerElement(ElementType type);
+ static inline constexpr auto getNbFacetsPerElement(ElementType type) -> Int;
/// get number of facets of a given element type
- static inline UInt getNbFacetsPerElement(ElementType type, UInt t);
+ static inline constexpr auto getNbFacetsPerElement(ElementType type, Idx t)
+ -> Int;
/// get local connectivity of a facet for a given facet type
- static inline auto getFacetLocalConnectivity(ElementType type, UInt t = 0);
+ static inline decltype(auto) getFacetLocalConnectivity(ElementType type,
+ Idx t = 0);
/// get connectivity of facets for a given element
- inline auto getFacetConnectivity(const Element & element, UInt t = 0) const;
+ inline auto getFacetConnectivity(const Element & element, Idx t = 0) const
+ -> Matrix<Idx>;
/// get the number of type of the surface element associated to a given
/// element type
- static inline UInt getNbFacetTypes(ElementType type, UInt t = 0);
+ static inline constexpr auto getNbFacetTypes(ElementType type, Idx t = 0)
+ -> Int;
/// get the type of the surface element associated to a given element
- static inline constexpr auto getFacetType(ElementType type, UInt t = 0);
+ static inline constexpr auto getFacetType(ElementType type, Idx t = 0)
+ -> ElementType;
/// get all the type of the surface element associated to a given element
- static inline constexpr auto getAllFacetTypes(ElementType type);
+ static inline decltype(auto) getAllFacetTypes(ElementType type);
/// get the number of nodes in the given element list
- static inline UInt getNbNodesPerElementList(const Array<Element> & elements);
+ static inline auto getNbNodesPerElementList(const Array<Element> & elements)
+ -> Int;
/* ------------------------------------------------------------------------ */
/* Element type Iterator */
/* ------------------------------------------------------------------------ */
- using type_iterator = ElementTypeMapArray<UInt, ElementType>::type_iterator;
+ using type_iterator [[deprecated]] =
+ ElementTypeMapArray<Idx, ElementType>::type_iterator;
using ElementTypesIteratorHelper =
- ElementTypeMapArray<UInt, ElementType>::ElementTypesIteratorHelper;
+ ElementTypeMapArray<Idx, ElementType>::ElementTypesIteratorHelper;
template <typename... pack>
- ElementTypesIteratorHelper elementTypes(pack &&... _pack) const;
+ auto elementTypes(pack &&... _pack) const -> ElementTypesIteratorHelper;
[[deprecated("Use elementTypes instead")]] inline decltype(auto)
- firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost,
+ firstType(Int dim = _all_dimensions, GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_regular) const {
return connectivities.elementTypes(dim, ghost_type, kind).begin();
}
[[deprecated("Use elementTypes instead")]] inline decltype(auto)
- lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost,
+ lastType(Int dim = _all_dimensions, GhostType ghost_type = _not_ghost,
ElementKind kind = _ek_regular) const {
return connectivities.elementTypes(dim, ghost_type, kind).end();
}
- AKANTU_GET_MACRO(ElementSynchronizer, *element_synchronizer,
- const ElementSynchronizer &);
- AKANTU_GET_MACRO_NOT_CONST(ElementSynchronizer, *element_synchronizer,
- ElementSynchronizer &);
- AKANTU_GET_MACRO(NodeSynchronizer, *node_synchronizer,
- const NodeSynchronizer &);
- AKANTU_GET_MACRO_NOT_CONST(NodeSynchronizer, *node_synchronizer,
- NodeSynchronizer &);
- AKANTU_GET_MACRO(PeriodicNodeSynchronizer, *periodic_node_synchronizer,
- const PeriodicNodeSynchronizer &);
- AKANTU_GET_MACRO_NOT_CONST(PeriodicNodeSynchronizer,
- *periodic_node_synchronizer,
- PeriodicNodeSynchronizer &);
+ AKANTU_GET_MACRO_DEREF_PTR(ElementSynchronizer, element_synchronizer);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(ElementSynchronizer,
+ element_synchronizer);
+ AKANTU_GET_MACRO_DEREF_PTR(NodeSynchronizer, node_synchronizer);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(NodeSynchronizer, node_synchronizer);
+ AKANTU_GET_MACRO_DEREF_PTR(PeriodicNodeSynchronizer,
+ periodic_node_synchronizer);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(PeriodicNodeSynchronizer,
+ periodic_node_synchronizer);
// AKANTU_GET_MACRO_NOT_CONST(Communicator, *communicator, StaticCommunicator
// &);
- AKANTU_GET_MACRO(Communicator, *communicator, const auto &);
- AKANTU_GET_MACRO_NOT_CONST(Communicator, *communicator, auto &);
- AKANTU_GET_MACRO(PeriodicMasterSlaves, periodic_master_slave, const auto &);
+ AKANTU_GET_MACRO_DEREF_PTR(Communicator, communicator);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Communicator, communicator);
+ AKANTU_GET_MACRO_AUTO(PeriodicMasterSlaves, periodic_master_slave);
/* ------------------------------------------------------------------------ */
/* Private methods for friends */
/* ------------------------------------------------------------------------ */
private:
friend class MeshAccessor;
friend class MeshUtils;
- AKANTU_GET_MACRO(NodesPointer, *nodes, Array<Real> &);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(NodesPointer, nodes);
/// get a pointer to the nodes_global_ids Array<UInt> and create it if
/// necessary
- inline Array<UInt> & getNodesGlobalIdsPointer();
+ inline auto getNodesGlobalIdsPointer() -> Array<Idx> &;
/// get a pointer to the nodes_type Array<Int> and create it if necessary
- inline Array<NodeFlag> & getNodesFlagsPointer();
+ inline auto getNodesFlagsPointer() -> Array<NodeFlag> &;
/// get a pointer to the connectivity Array for the given type and create it
/// if necessary
- inline Array<UInt> &
- getConnectivityPointer(ElementType type, GhostType ghost_type = _not_ghost);
+ inline auto getConnectivityPointer(ElementType type,
+ GhostType ghost_type = _not_ghost)
+ -> Array<Idx> &;
/// get the ghost element counter
- inline Array<UInt> & getGhostsCounters(ElementType type,
- GhostType ghost_type = _ghost) {
+ inline auto getGhostsCounters(ElementType type, GhostType ghost_type = _ghost)
+ -> Array<Idx> & {
AKANTU_DEBUG_ASSERT(ghost_type != _not_ghost,
"No ghost counter for _not_ghost elements");
return ghosts_counters(type, ghost_type);
}
/// get a pointer to the element_to_subelement Array for the given type and
/// create it if necessary
- inline Array<std::vector<Element>> &
+ inline decltype(auto)
getElementToSubelementPointer(ElementType type,
GhostType ghost_type = _not_ghost);
/// get a pointer to the subelement_to_element Array for the given type and
/// create it if necessary
- inline Array<Element> &
+ inline decltype(auto)
getSubelementToElementPointer(ElementType type,
GhostType ghost_type = _not_ghost);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
ID id;
/// array of the nodes coordinates
std::shared_ptr<Array<Real>> nodes;
/// global node ids
- std::shared_ptr<Array<UInt>> nodes_global_ids;
+ std::shared_ptr<Array<Idx>> nodes_global_ids;
/// node flags (shared/periodic/...)
std::shared_ptr<Array<NodeFlag>> nodes_flags;
/// processor handling the node when not local or master
- std::unordered_map<UInt, Int> nodes_prank;
+ std::unordered_map<Idx, Int> nodes_prank;
/// global number of nodes;
- UInt nb_global_nodes{0};
+ Int nb_global_nodes{0};
/// all class of elements present in this mesh (for heterogenous meshes)
- ElementTypeMapArray<UInt> connectivities;
+ ElementTypeMapArray<Idx> connectivities;
/// count the references on ghost elements
- ElementTypeMapArray<UInt> ghosts_counters;
-
- /// map to normals for all class of elements present in this mesh
- ElementTypeMapArray<Real> normals;
+ ElementTypeMapArray<Idx> ghosts_counters;
/// the spatial dimension of this mesh
- UInt spatial_dimension{0};
+ Idx spatial_dimension{0};
/// size covered by the mesh on each direction
Vector<Real> size;
+
/// global bounding box
BBox bbox;
/// local bounding box
BBox bbox_local;
/// Extra data loaded from the mesh file
// MeshData mesh_data;
/// facets' mesh
std::unique_ptr<Mesh> mesh_facets;
/// parent mesh (this is set for mesh_facets meshes)
const Mesh * mesh_parent{nullptr};
/// defines if current mesh is mesh_facets or not
bool is_mesh_facets{false};
/// defines if the mesh is centralized or distributed
bool is_distributed{false};
/// defines if the mesh is periodic
bool is_periodic{false};
/// Communicator on which mesh is distributed
Communicator * communicator;
/// Element synchronizer
std::unique_ptr<ElementSynchronizer> element_synchronizer;
/// Node synchronizer
std::unique_ptr<NodeSynchronizer> node_synchronizer;
/// Node synchronizer for periodic nodes
std::unique_ptr<PeriodicNodeSynchronizer> periodic_node_synchronizer;
using NodesToElements = std::vector<std::unique_ptr<std::set<Element>>>;
/// class to update global data using external knowledge
std::unique_ptr<MeshGlobalDataUpdater> global_data_updater;
/// This info is stored to simplify the dynamic changes
NodesToElements nodes_to_elements;
/// periodicity local info
- std::unordered_map<UInt, UInt> periodic_slave_master;
- std::unordered_multimap<UInt, UInt> periodic_master_slave;
+ std::unordered_map<Idx, Idx> periodic_slave_master;
+ std::unordered_multimap<Idx, Idx> periodic_master_slave;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream, const Mesh & _this) {
_this.printself(stream);
return stream;
}
+/* -------------------------------------------------------------------------- */
+inline constexpr auto Mesh::getNbNodesPerElement(ElementType type) -> Int {
+ return tuple_dispatch_with_default<AllElementTypes>(
+ [](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getNbNodesPerElement();
+ },
+ type, [](auto && /*type*/) { return 0; });
+}
+
+/* -------------------------------------------------------------------------- */
+inline auto Mesh::getNbElement(ElementType type, GhostType ghost_type) const {
+ try {
+ const auto & conn = connectivities(type, ghost_type);
+ return conn.size();
+ } catch (...) {
+ return 0;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+inline auto Mesh::getNbElement(const Int spatial_dimension,
+ GhostType ghost_type, ElementKind kind) const {
+ AKANTU_DEBUG_ASSERT(spatial_dimension <= 3 || spatial_dimension == Int(-1),
+ "spatial_dimension is " << spatial_dimension
+ << " and is greater than 3 !");
+ Int nb_element = 0;
+
+ for (auto type : elementTypes(spatial_dimension, ghost_type, kind)) {
+ nb_element += getNbElement(type, ghost_type);
+ }
+
+ return nb_element;
+}
+/* -------------------------------------------------------------------------- */
+
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* Inline functions */
/* -------------------------------------------------------------------------- */
#include "element_type_map_tmpl.hh"
#include "mesh_inline_impl.hh"
#endif /* AKANTU_MESH_HH_ */
diff --git a/src/mesh/mesh_accessor.hh b/src/mesh/mesh_accessor.hh
index 6388c6ed2..13d2e4ae1 100644
--- a/src/mesh/mesh_accessor.hh
+++ b/src/mesh/mesh_accessor.hh
@@ -1,221 +1,221 @@
/**
* @file mesh_accessor.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jun 30 2015
* @date last modification: Tue Feb 09 2021
*
* @brief this class allow to access some private member of mesh it is used for
* IO for examples
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_ACCESSOR_HH_
#define AKANTU_MESH_ACCESSOR_HH_
namespace akantu {
class NodeSynchronizer;
class ElementSynchronizer;
class MeshGlobalDataUpdater;
} // namespace akantu
namespace akantu {
class MeshAccessor {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
explicit MeshAccessor(Mesh & mesh) : _mesh(mesh) {}
virtual ~MeshAccessor() = default;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the global number of nodes
inline UInt getNbGlobalNodes() const { return this->_mesh.nb_global_nodes; }
/// set the global number of nodes
- inline void setNbGlobalNodes(UInt nb_global_nodes) {
+ inline void setNbGlobalNodes(Int nb_global_nodes) {
this->_mesh.nb_global_nodes = nb_global_nodes;
}
/// set the mesh as being distributed
inline void setDistributed() { this->_mesh.is_distributed = true; }
/// get a pointer to the nodes_global_ids Array<UInt> and create it if
/// necessary
inline auto & getNodesGlobalIds() {
return this->_mesh.getNodesGlobalIdsPointer();
}
/// get a pointer to the nodes_type Array<Int> and create it if necessary
inline auto & getNodesFlags() { return this->_mesh.getNodesFlags(); }
/// get a pointer to the nodes_type Array<Int> and create it if necessary
inline void setNodePrank(UInt node, Int prank) {
this->_mesh.nodes_prank[node] = prank;
}
/// get a pointer to the coordinates Array
inline auto & getNodes() { return this->_mesh.getNodesPointer(); }
/// get a pointer to the coordinates Array
inline auto getNodesSharedPtr() { return this->_mesh.nodes; }
/// get the connectivities
inline auto & getConnectivities() { return this->_mesh.connectivities; }
/// get the connectivity Array for the given type and create it
/// if necessary
inline auto & getConnectivity(ElementType type,
GhostType ghost_type = _not_ghost) {
return this->_mesh.getConnectivityPointer(type, ghost_type);
}
/// resize the connectivity (use carefully)
- inline void resizeConnectivity(UInt new_size, ElementType type,
+ inline void resizeConnectivity(Int new_size, ElementType type,
GhostType ghost_type = _not_ghost) {
- this->getConnectivity(type, ghost_type).resize(new_size, UInt(-1));
+ this->getConnectivity(type, ghost_type).resize(new_size, Idx(-1));
}
/// resize the nodes (use carefully)
- inline void resizeNodes(UInt new_size) {
- this->getNodes().resize(new_size, UInt(-1));
+ inline void resizeNodes(Int new_size) {
+ this->getNodes().resize(new_size);
}
/// get the connectivity for the given element
inline decltype(auto) getConnectivity(const Element & element) {
return this->_mesh.getConnectivityNC(element);
}
/// get the ghost element counter
inline auto & getGhostsCounters(ElementType type,
GhostType ghost_type = _ghost) {
return this->_mesh.getGhostsCounters(type, ghost_type);
}
/// get the element_to_subelement Array for the given type and
/// create it if necessary
inline auto & getElementToSubelement(ElementType type,
GhostType ghost_type = _not_ghost) {
return this->_mesh.getElementToSubelementPointer(type, ghost_type);
}
inline decltype(auto)
- getElementToSubelementNC(const ElementType & type,
- const GhostType & ghost_type = _not_ghost) {
+ getElementToSubelementNC(ElementType type,
+ GhostType ghost_type = _not_ghost) {
return this->_mesh.getElementToSubelementNC(type, ghost_type);
}
/// get the subelement_to_element Array for the given type and
/// create it if necessary
inline auto & getSubelementToElement(ElementType type,
GhostType ghost_type = _not_ghost) {
return this->_mesh.getSubelementToElementPointer(type, ghost_type);
}
inline decltype(auto)
- getSubelementToElementNC(const ElementType & type,
- const GhostType & ghost_type = _not_ghost) {
+ getSubelementToElementNC(ElementType type,
+ GhostType ghost_type = _not_ghost) {
return this->_mesh.getSubelementToElementNC(type, ghost_type);
}
/// get the element_to_subelement, creates it if necessary
inline decltype(auto) getElementToSubelement() {
return this->_mesh.getElementToSubelementNC();
}
/// get subelement_to_element, creates it if necessary
inline decltype(auto) getSubelementToElement() {
return this->_mesh.getSubelementToElementNC();
}
/// get a pointer to the element_to_subelement Array for element and
/// create it if necessary
inline decltype(auto) getElementToSubelement(const Element & element) {
return this->_mesh.getElementToSubelementNC(element);
}
/// get a pointer to the subelement_to_element Array for the given element and
/// create it if necessary
inline decltype(auto) getSubelementToElement(const Element & element) {
return this->_mesh.getSubelementToElementNC(element);
}
template <typename T>
- inline auto & getData(const std::string & data_name, ElementType el_type,
- GhostType ghost_type = _not_ghost,
- UInt nb_component = 1, bool size_to_nb_element = true,
- bool resize_with_parent = false) {
+ inline auto &
+ getData(const std::string & data_name, ElementType el_type,
+ GhostType ghost_type = _not_ghost, Int nb_component = 1,
+ bool size_to_nb_element = true, bool resize_with_parent = false) {
return this->_mesh.getDataPointer<T>(data_name, el_type, ghost_type,
nb_component, size_to_nb_element,
resize_with_parent);
}
/// get the node synchonizer
auto & getNodeSynchronizer() { return *this->_mesh.node_synchronizer; }
/// get the element synchonizer
auto & getElementSynchronizer() { return *this->_mesh.element_synchronizer; }
decltype(auto) updateGlobalData(NewNodesEvent & nodes_event,
NewElementsEvent & elements_event) {
return this->_mesh.updateGlobalData(nodes_event, elements_event);
}
void registerGlobalDataUpdater(
std::unique_ptr<MeshGlobalDataUpdater> && global_data_updater) {
this->_mesh.registerGlobalDataUpdater(
std::forward<std::unique_ptr<MeshGlobalDataUpdater>>(
global_data_updater));
}
/* ------------------------------------------------------------------------ */
void makeReady() { this->_mesh.makeReady(); }
/* ------------------------------------------------------------------------ */
- void addPeriodicSlave(UInt slave, UInt master) {
+ void addPeriodicSlave(Idx slave, Idx master) {
this->_mesh.addPeriodicSlave(slave, master);
}
void markMeshPeriodic() {
- for (UInt s : arange(this->_mesh.spatial_dimension)) {
+ for (Idx s : arange(this->_mesh.spatial_dimension)) {
this->_mesh.is_periodic |= 1 << s;
}
}
void wipePeriodicInfo() { this->_mesh.wipePeriodicInfo(); }
private:
Mesh & _mesh;
};
} // namespace akantu
#endif /* AKANTU_MESH_ACCESSOR_HH_ */
diff --git a/src/mesh/mesh_data.hh b/src/mesh/mesh_data.hh
index b478bb69f..6c8d4dbe0 100644
--- a/src/mesh/mesh_data.hh
+++ b/src/mesh/mesh_data.hh
@@ -1,189 +1,189 @@
/**
* @file mesh_data.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri May 03 2013
* @date last modification: Fri Dec 28 2018
*
* @brief Stores generic data loaded from the mesh file
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_DATA_HH_
#define AKANTU_MESH_DATA_HH_
/* -------------------------------------------------------------------------- */
#include "element_type_map.hh"
#include <map>
#include <string>
/* -------------------------------------------------------------------------- */
namespace akantu {
#define AKANTU_MESH_DATA_TYPES \
((_int, Int))((_uint, UInt))((_real, Real))((_bool, bool))( \
(_element, Element))((_std_string, std::string))( \
(_std_vector_element, std::vector<Element>))
#define AKANTU_MESH_DATA_TUPLE_FIRST_ELEM(s, data, elem) \
BOOST_PP_TUPLE_ELEM(2, 0, elem)
enum class MeshDataTypeCode : int {
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_MESH_DATA_TUPLE_FIRST_ELEM, ,
AKANTU_MESH_DATA_TYPES)),
_unknown
};
enum class MeshDataType {
_nodal,
_elemental,
};
class MeshData {
/* ------------------------------------------------------------------------ */
/* Typedefs */
/* ------------------------------------------------------------------------ */
private:
using TypeCode = MeshDataTypeCode;
using ElementalDataMap =
std::map<std::string, std::unique_ptr<ElementTypeMapBase>>;
using NodalDataMap = std::map<std::string, std::unique_ptr<ArrayBase>>;
using TypeCodeMap = std::map<std::string, TypeCode>;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MeshData(const ID & id = "mesh_data", const ID & parent_id = "");
/* ------------------------------------------------------------------------ */
/* Methods and accessors */
/* ------------------------------------------------------------------------ */
public:
/// tells if the given array exists
template <typename T>
bool hasData(const ID & data_name, ElementType elem_type,
GhostType ghost_type = _not_ghost) const;
/// tells if the given data exists
bool hasData(const ID & data_name,
MeshDataType type = MeshDataType::_elemental) const;
bool hasData(MeshDataType type = MeshDataType::_elemental) const;
/// get the names of the data stored in elemental_data
inline auto getTagNames(ElementType type,
GhostType ghost_type = _not_ghost) const;
/// get the names of the data stored in elemental_data
inline auto getTagNames() const;
/// get the type of the data stored in elemental_data
template <typename T> TypeCode getTypeCode() const;
inline TypeCode
getTypeCode(const ID & name,
MeshDataType type = MeshDataType::_elemental) const;
/// Get an existing elemental data array
template <typename T>
const Array<T> &
getElementalDataArray(const ID & data_name, ElementType elem_type,
GhostType ghost_type = _not_ghost) const;
template <typename T>
Array<T> & getElementalDataArray(const ID & data_name, ElementType elem_type,
GhostType ghost_type = _not_ghost);
/// Get an elemental data array, if it does not exist: allocate it
template <typename T>
Array<T> & getElementalDataArrayAlloc(const ID & data_name,
ElementType elem_type,
GhostType ghost_type = _not_ghost,
- UInt nb_component = 1);
+ Int nb_component = 1);
template <typename T>
- inline UInt getNbComponentTemplated(const ID & name, ElementType el_type,
- GhostType ghost_type) const;
- inline UInt getNbComponent(const ID & name, ElementType el_type,
- GhostType ghost_type = _not_ghost) const;
+ inline Int getNbComponentTemplated(const ID & name, ElementType el_type,
+ GhostType ghost_type) const;
+ inline Int getNbComponent(const ID & name, ElementType el_type,
+ GhostType ghost_type = _not_ghost) const;
- inline UInt getNbComponent(const ID & name) const;
+ inline Int getNbComponent(const ID & name) const;
/// Get an existing elemental data
template <typename T>
const ElementTypeMapArray<T> & getElementalData(const ID & name) const;
template <typename T>
ElementTypeMapArray<T> & getElementalData(const ID & name);
template <typename T>
- Array<T> & getNodalData(const ID & name, UInt nb_components = 1);
+ Array<T> & getNodalData(const ID & name, Int nb_components = 1);
template <typename T> const Array<T> & getNodalData(const ID & name) const;
private:
/// Register new elemental data (and alloc data) with check if the name is
/// new
template <typename T>
ElementTypeMapArray<T> & registerElementalData(const ID & name);
inline void registerElementalData(const ID & name, TypeCode type);
/// Register new nodal data (and alloc data) with check if the name is
/// new
template <typename T>
- Array<T> & registerNodalData(const ID & name, UInt nb_components = 1);
- inline void registerNodalData(const ID & name, UInt nb_components,
+ Array<T> & registerNodalData(const ID & name, Int nb_components = 1);
+ inline void registerNodalData(const ID & name, Int nb_components,
TypeCode type);
/// Register new elemental data (add alloc data)
template <typename T>
ElementTypeMapArray<T> & allocElementalData(const ID & name);
/// Register new nodal data (add alloc data)
template <typename T>
- Array<T> & allocNodalData(const ID & name, UInt nb_components);
+ Array<T> & allocNodalData(const ID & name, Int nb_components);
friend class SlaveNodeInfoPerProc;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
ID _id;
/// Map when elemental data is stored as ElementTypeMap
ElementalDataMap elemental_data;
/// Map when elemental data is stored as ElementTypeMap
NodalDataMap nodal_data;
/// Map when elementalType of the data stored in elemental_data
std::map<MeshDataType, TypeCodeMap> typecode_map{
{MeshDataType::_elemental, {}}, {MeshDataType::_nodal, {}}};
};
} // namespace akantu
#include "mesh_data_tmpl.hh"
#undef AKANTU_MESH_DATA_TUPLE_FIRST_ELEM
#endif /* AKANTU_MESH_DATA_HH_ */
diff --git a/src/mesh/mesh_data_tmpl.hh b/src/mesh/mesh_data_tmpl.hh
index a8ea53f4d..76cbe6815 100644
--- a/src/mesh/mesh_data_tmpl.hh
+++ b/src/mesh/mesh_data_tmpl.hh
@@ -1,411 +1,411 @@
/**
* @file mesh_data_tmpl.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri May 03 2013
* @date last modification: Fri Dec 28 2018
*
* @brief Stores generic data loaded from the mesh file
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_data.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_DATA_TMPL_HH_
#define AKANTU_MESH_DATA_TMPL_HH_
namespace akantu {
#define AKANTU_MESH_DATA_OSTREAM(r, name, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
stream << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, elem)); \
break; \
}
inline std::ostream & operator<<(std::ostream & stream,
const MeshDataTypeCode & type_code) {
switch (type_code) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_DATA_OSTREAM, name,
AKANTU_MESH_DATA_TYPES)
default:
stream << "(unknown type)";
}
return stream;
}
#undef AKANTU_MESH_DATA_OSTREAM
#define MESH_DATA_GET_TYPE(r, data, type) \
template <> \
inline MeshDataTypeCode \
MeshData::getTypeCode<BOOST_PP_TUPLE_ELEM(2, 1, type)>() const { \
return MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, type); \
}
/* -------------------------------------------------------------------------- */
// get the type of the data stored in elemental_data
template <typename T> inline MeshDataTypeCode MeshData::getTypeCode() const {
AKANTU_ERROR("Type " << debug::demangle(typeid(T).name())
<< " not implemented by MeshData.");
}
/* -------------------------------------------------------------------------- */
BOOST_PP_SEQ_FOR_EACH(MESH_DATA_GET_TYPE, void, AKANTU_MESH_DATA_TYPES)
#undef MESH_DATA_GET_TYPE
inline MeshDataTypeCode MeshData::getTypeCode(const ID & name,
MeshDataType type) const {
auto it = typecode_map.at(type).find(name);
if (it == typecode_map.at(type).end()) {
AKANTU_EXCEPTION("No dataset named " << name << " found.");
}
return it->second;
}
/* -------------------------------------------------------------------------- */
// Register new elemental data templated (and alloc data) with check if the
// name is new
template <typename T>
ElementTypeMapArray<T> & MeshData::registerElementalData(const ID & name) {
auto it = elemental_data.find(name);
if (it == elemental_data.end()) {
return allocElementalData<T>(name);
}
AKANTU_DEBUG_INFO("Data named " << name << " already registered.");
return getElementalData<T>(name);
}
/* -------------------------------------------------------------------------- */
// Register new elemental data of a given MeshDataTypeCode with check if the
// name is new
#define AKANTU_MESH_DATA_CASE_MACRO(r, name, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
registerElementalData<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(name); \
break; \
}
inline void MeshData::registerElementalData(const ID & name,
MeshDataTypeCode type) {
switch (type) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_DATA_CASE_MACRO, name,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR("Type " << type << "not implemented by MeshData.");
}
}
#undef AKANTU_MESH_DATA_CASE_MACRO
/* -------------------------------------------------------------------------- */
/// Register new elemental data (and alloc data)
template <typename T>
ElementTypeMapArray<T> & MeshData::allocElementalData(const ID & name) {
auto dataset = std::make_unique<ElementTypeMapArray<T>>(name, _id);
auto * dataset_typed = dataset.get();
elemental_data[name] = std::move(dataset);
typecode_map[MeshDataType::_elemental][name] = getTypeCode<T>();
return *dataset_typed;
}
/* -------------------------------------------------------------------------- */
// Register new nodal data templated (and alloc data) with check if the
// name is new
template <typename T>
-Array<T> & MeshData::registerNodalData(const ID & name, UInt nb_components) {
+Array<T> & MeshData::registerNodalData(const ID & name, Int nb_components) {
auto it = nodal_data.find(name);
if (it == nodal_data.end()) {
return allocNodalData<T>(name, nb_components);
}
AKANTU_DEBUG_INFO("Data named " << name << " already registered.");
return getNodalData<T>(name);
}
/* -------------------------------------------------------------------------- */
// Register new elemental data of a given MeshDataTypeCode with check if the
// name is new
#define AKANTU_MESH_NODAL_DATA_CASE_MACRO(r, name, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
registerNodalData<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(name, nb_components); \
break; \
}
-inline void MeshData::registerNodalData(const ID & name, UInt nb_components,
+inline void MeshData::registerNodalData(const ID & name, Int nb_components,
MeshDataTypeCode type) {
switch (type) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_NODAL_DATA_CASE_MACRO, name,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR("Type " << type << "not implemented by MeshData.");
}
}
#undef AKANTU_MESH_NODAL_DATA_CASE_MACRO
/* -------------------------------------------------------------------------- */
/// Register new elemental data (and alloc data)
template <typename T>
-Array<T> & MeshData::allocNodalData(const ID & name, UInt nb_components) {
+Array<T> & MeshData::allocNodalData(const ID & name, Int nb_components) {
auto dataset =
std::make_unique<Array<T>>(0, nb_components, T(), _id + ":" + name);
auto * dataset_typed = dataset.get();
nodal_data[name] = std::move(dataset);
typecode_map[MeshDataType::_nodal][name] = getTypeCode<T>();
return *dataset_typed;
}
/* -------------------------------------------------------------------------- */
template <typename T>
const Array<T> & MeshData::getNodalData(const ID & name) const {
auto it = nodal_data.find(name);
if (it == nodal_data.end()) {
AKANTU_EXCEPTION("No nodal dataset named " << name << " found.");
}
return aka::as_type<Array<T>>(*(it->second.get()));
}
/* -------------------------------------------------------------------------- */
// Get an existing elemental data
template <typename T>
-Array<T> & MeshData::getNodalData(const ID & name, UInt nb_components) {
+Array<T> & MeshData::getNodalData(const ID & name, Int nb_components) {
auto it = nodal_data.find(name);
if (it == nodal_data.end()) {
return allocNodalData<T>(name, nb_components);
}
return aka::as_type<Array<T>>(*(it->second.get()));
}
/* -------------------------------------------------------------------------- */
template <typename T>
const ElementTypeMapArray<T> &
MeshData::getElementalData(const ID & name) const {
auto it = elemental_data.find(name);
if (it == elemental_data.end()) {
AKANTU_EXCEPTION("No dataset named " << name << " found.");
}
return aka::as_type<ElementTypeMapArray<T>>(*(it->second.get()));
}
/* -------------------------------------------------------------------------- */
// Get an existing elemental data
template <typename T>
ElementTypeMapArray<T> & MeshData::getElementalData(const ID & name) {
auto it = elemental_data.find(name);
if (it == elemental_data.end()) {
return allocElementalData<T>(name);
}
return aka::as_type<ElementTypeMapArray<T>>(*(it->second.get()));
}
/* -------------------------------------------------------------------------- */
template <typename T>
bool MeshData::hasData(const ID & name, ElementType elem_type,
GhostType ghost_type) const {
auto it = elemental_data.find(name);
if (it == elemental_data.end()) {
return false;
}
auto & elem_map = aka::as_type<ElementTypeMapArray<T>>(*(it->second));
return elem_map.exists(elem_type, ghost_type);
}
/* -------------------------------------------------------------------------- */
inline bool MeshData::hasData(const ID & name, MeshDataType type) const {
if (type == MeshDataType::_elemental) {
auto it = elemental_data.find(name);
return (it != elemental_data.end());
}
if (type == MeshDataType::_nodal) {
auto it = nodal_data.find(name);
return (it != nodal_data.end());
}
return false;
}
/* -------------------------------------------------------------------------- */
inline bool MeshData::hasData(MeshDataType type) const {
switch (type) {
case MeshDataType::_elemental:
return (not elemental_data.empty());
case MeshDataType::_nodal:
return (not nodal_data.empty());
}
return false;
}
/* -------------------------------------------------------------------------- */
template <typename T>
const Array<T> & MeshData::getElementalDataArray(const ID & name,
ElementType elem_type,
GhostType ghost_type) const {
auto it = elemental_data.find(name);
if (it == elemental_data.end()) {
AKANTU_EXCEPTION("Data named " << name
<< " not registered for type: " << elem_type
<< " - ghost_type:" << ghost_type << "!");
}
return aka::as_type<ElementTypeMapArray<T>>(*(it->second))(elem_type,
ghost_type);
}
template <typename T>
Array<T> & MeshData::getElementalDataArray(const ID & name,
ElementType elem_type,
GhostType ghost_type) {
auto it = elemental_data.find(name);
if (it == elemental_data.end()) {
AKANTU_EXCEPTION("Data named " << name
<< " not registered for type: " << elem_type
<< " - ghost_type:" << ghost_type << "!");
}
return aka::as_type<ElementTypeMapArray<T>>(*(it->second.get()))(elem_type,
ghost_type);
}
/* -------------------------------------------------------------------------- */
// Get an elemental data array, if it does not exist: allocate it
template <typename T>
Array<T> &
MeshData::getElementalDataArrayAlloc(const ID & name, ElementType elem_type,
- GhostType ghost_type, UInt nb_component) {
+ GhostType ghost_type, Int nb_component) {
auto it = elemental_data.find(name);
ElementTypeMapArray<T> * dataset;
if (it == elemental_data.end()) {
dataset = &allocElementalData<T>(name);
} else {
dataset = dynamic_cast<ElementTypeMapArray<T> *>(it->second.get());
}
AKANTU_DEBUG_ASSERT(
getTypeCode<T>() ==
typecode_map.at(MeshDataType::_elemental).find(name)->second,
"Function getElementalDataArrayAlloc called with the wrong type!");
if (!(dataset->exists(elem_type, ghost_type))) {
dataset->alloc(0, nb_component, elem_type, ghost_type);
}
return (*dataset)(elem_type, ghost_type);
}
/* -------------------------------------------------------------------------- */
#define AKANTU_MESH_DATA_CASE_MACRO(r, name, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
nb_comp = getNbComponentTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>( \
name, el_type, ghost_type); \
break; \
}
-inline UInt MeshData::getNbComponent(const ID & name, ElementType el_type,
- GhostType ghost_type) const {
+inline Int MeshData::getNbComponent(const ID & name, ElementType el_type,
+ GhostType ghost_type) const {
auto it = typecode_map.at(MeshDataType::_elemental).find(name);
- UInt nb_comp(0);
+ Int nb_comp(0);
if (it == typecode_map.at(MeshDataType::_elemental).end()) {
AKANTU_EXCEPTION("Could not determine the type held in dataset "
<< name << " for type: " << el_type
<< " - ghost_type:" << ghost_type << ".");
}
MeshDataTypeCode type = it->second;
switch (type) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_DATA_CASE_MACRO, name,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR(
"Could not call the correct instance of getNbComponentTemplated.");
break;
}
return nb_comp;
}
#undef AKANTU_MESH_DATA_CASE_MACRO
/* -------------------------------------------------------------------------- */
template <typename T>
-inline UInt MeshData::getNbComponentTemplated(const ID & name,
- ElementType el_type,
- GhostType ghost_type) const {
+inline Int MeshData::getNbComponentTemplated(const ID & name,
+ ElementType el_type,
+ GhostType ghost_type) const {
return getElementalDataArray<T>(name, el_type, ghost_type).getNbComponent();
}
/* -------------------------------------------------------------------------- */
-inline UInt MeshData::getNbComponent(const ID & name) const {
+inline Int MeshData::getNbComponent(const ID & name) const {
auto it = nodal_data.find(name);
if (it == nodal_data.end()) {
AKANTU_EXCEPTION("No nodal dataset registered with the name" << name
<< ".");
}
return it->second->getNbComponent();
}
/* -------------------------------------------------------------------------- */
// get the names of the data stored in elemental_data
#define AKANTU_MESH_DATA_CASE_MACRO(r, name, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
ElementTypeMapArray<BOOST_PP_TUPLE_ELEM(2, 1, elem)> * dataset; \
dataset = \
dynamic_cast<ElementTypeMapArray<BOOST_PP_TUPLE_ELEM(2, 1, elem)> *>( \
it->second.get()); \
exists = dataset->exists(el_type, ghost_type); \
break; \
}
inline auto MeshData::getTagNames(ElementType el_type,
GhostType ghost_type) const {
std::vector<std::string> tags;
bool exists(false);
auto it = elemental_data.begin();
auto it_end = elemental_data.end();
for (; it != it_end; ++it) {
MeshDataTypeCode type = getTypeCode(it->first);
switch (type) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_MESH_DATA_CASE_MACRO, ,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR("Could not determine the proper type to (dynamic-)cast.");
break;
}
if (exists) {
tags.push_back(it->first);
}
}
return tags;
}
#undef AKANTU_MESH_DATA_CASE_MACRO
/* -------------------------------------------------------------------------- */
inline auto MeshData::getTagNames() const {
std::vector<std::string> tags;
for (auto && data : nodal_data) {
tags.push_back(std::get<0>(data));
}
return tags;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_MESH_DATA_TMPL_HH_ */
diff --git a/src/mesh/mesh_events.hh b/src/mesh/mesh_events.hh
index 38422f7fc..cf4dd1708 100644
--- a/src/mesh/mesh_events.hh
+++ b/src/mesh/mesh_events.hh
@@ -1,228 +1,220 @@
/**
* @file mesh_events.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Feb 20 2015
* @date last modification: Thu Feb 20 2020
*
* @brief Classes corresponding to mesh events type
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <utility>
#include "aka_array.hh"
#include "element.hh"
#include "element_type_map.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_EVENTS_HH_
#define AKANTU_MESH_EVENTS_HH_
namespace akantu {
/// akantu::MeshEvent is the base event for meshes
template <class Entity> class MeshEvent {
public:
MeshEvent(const std::string & origin = "") : origin_(origin) {}
virtual ~MeshEvent() = default;
/// Get the list of entity modified by the event nodes or elements
const Array<Entity> & getList() const { return list; }
/// Get the list of entity modified by the event nodes or elements
Array<Entity> & getList() { return list; }
std::string origin() const { return origin_; }
protected:
Array<Entity> list;
private:
std::string origin_;
};
class Mesh;
/// akantu::MeshEvent related to new nodes in the mesh
-class NewNodesEvent : public MeshEvent<UInt> {
+class NewNodesEvent : public MeshEvent<Idx> {
public:
NewNodesEvent(const std::string & origin = "") : MeshEvent(origin) {}
~NewNodesEvent() override = default;
};
/// akantu::MeshEvent related to nodes removed from the mesh
-class RemovedNodesEvent : public MeshEvent<UInt> {
+class RemovedNodesEvent : public MeshEvent<Idx> {
public:
inline RemovedNodesEvent(const Mesh & mesh, const std::string & origin = "");
~RemovedNodesEvent() override = default;
/// Get the new numbering following suppression of nodes from nodes arrays
- AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, Array<UInt> &);
+ AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, auto &);
/// Get the new numbering following suppression of nodes from nodes arrays
- AKANTU_GET_MACRO(NewNumbering, new_numbering, const Array<UInt> &);
+ AKANTU_GET_MACRO(NewNumbering, new_numbering, const auto &);
private:
- Array<UInt> new_numbering;
+ Array<Idx> new_numbering;
};
/// akantu::MeshEvent related to new elements in the mesh
class NewElementsEvent : public MeshEvent<Element> {
public:
NewElementsEvent(const std::string & origin = "")
: MeshEvent<Element>(origin) {}
~NewElementsEvent() override = default;
};
/// akantu::MeshEvent related to the case the mesh is made distributed.
/// Note that the `list` has no meaning for this event.
class MeshIsDistributedEvent : public MeshEvent<UInt> {
public:
- MeshIsDistributedEvent(const Mesh & mesh, const std::string & origin = "")
- : MeshEvent<UInt>(origin), mesh(mesh) {}
+ MeshIsDistributedEvent(const std::string & origin = "")
+ : MeshEvent<UInt>(origin) {}
~MeshIsDistributedEvent() override = default;
-
- const Mesh & getMesh() const noexcept { return this->mesh; }
-
-private:
- const Mesh & mesh;
};
/// akantu::MeshEvent related to elements removed from the mesh
class RemovedElementsEvent : public MeshEvent<Element> {
public:
inline RemovedElementsEvent(const Mesh & mesh,
const ID & new_numbering_id = "new_numbering",
const std::string & origin = "");
~RemovedElementsEvent() override = default;
/// Get the new numbering following suppression of elements from elements
/// arrays
- AKANTU_GET_MACRO(NewNumbering, new_numbering,
- const ElementTypeMapArray<UInt> &);
+ AKANTU_GET_MACRO(NewNumbering, new_numbering, const auto &);
/// Get the new numbering following suppression of elements from elements
/// arrays
- AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering,
- ElementTypeMapArray<UInt> &);
+ AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, auto &);
/// Get the new numbering following suppression of elements from elements
/// arrays
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NewNumbering, new_numbering, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NewNumbering, new_numbering, Idx);
/// Get the new numbering following suppression of elements from elements
/// arrays
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NewNumbering, new_numbering, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NewNumbering, new_numbering, Idx);
protected:
- ElementTypeMapArray<UInt> new_numbering;
+ ElementTypeMapArray<Idx> new_numbering;
};
/// akantu::MeshEvent for element that changed in some sort, can be seen as a
/// combination of removed and added elements
class ChangedElementsEvent : public RemovedElementsEvent {
public:
inline ChangedElementsEvent(
const Mesh & mesh,
const ID & new_numbering_id = "changed_event:new_numbering",
const std::string & origin = "")
: RemovedElementsEvent(mesh, new_numbering_id, origin) {}
~ChangedElementsEvent() override = default;
AKANTU_GET_MACRO(ListOld, list, const Array<Element> &);
AKANTU_GET_MACRO_NOT_CONST(ListOld, list, Array<Element> &);
AKANTU_GET_MACRO(ListNew, new_list, const Array<Element> &);
AKANTU_GET_MACRO_NOT_CONST(ListNew, new_list, Array<Element> &);
protected:
Array<Element> new_list;
};
/* -------------------------------------------------------------------------- */
class MeshEventHandler {
public:
virtual ~MeshEventHandler() = default;
/* ------------------------------------------------------------------------ */
/* Internal code */
/* ------------------------------------------------------------------------ */
private:
/// send a akantu::NewNodesEvent
inline void sendEvent(const NewNodesEvent & event) {
onNodesAdded(event.getList(), event);
}
/// send a akantu::RemovedNodesEvent
inline void sendEvent(const RemovedNodesEvent & event) {
onNodesRemoved(event.getList(), event.getNewNumbering(), event);
}
/// send a akantu::NewElementsEvent
inline void sendEvent(const NewElementsEvent & event) {
onElementsAdded(event.getList(), event);
}
/// send a akantu::RemovedElementsEvent
inline void sendEvent(const RemovedElementsEvent & event) {
onElementsRemoved(event.getList(), event.getNewNumbering(), event);
}
/// send a akantu::ChangedElementsEvent
inline void sendEvent(const ChangedElementsEvent & event) {
onElementsChanged(event.getListOld(), event.getListNew(),
event.getNewNumbering(), event);
}
/// send a akantu::MeshIsDistributedEvent
inline void sendEvent(const MeshIsDistributedEvent & event) {
- onMeshIsDistributed(event.getMesh(), event);
+ onMeshIsDistributed(event);
}
template <class EventHandler> friend class EventHandlerManager;
/* ------------------------------------------------------------------------ */
/* Interface */
/* ------------------------------------------------------------------------ */
public:
/// function to implement to react on akantu::NewNodesEvent
- virtual void onNodesAdded(const Array<UInt> & /*nodes_list*/,
+ virtual void onNodesAdded(const Array<Idx> & /*nodes_list*/,
const NewNodesEvent & /*event*/) {}
/// function to implement to react on akantu::RemovedNodesEvent
- virtual void onNodesRemoved(const Array<UInt> & /*nodes_list*/,
- const Array<UInt> & /*new_numbering*/,
+ virtual void onNodesRemoved(const Array<Idx> & /*nodes_list*/,
+ const Array<Idx> & /*new_numbering*/,
const RemovedNodesEvent & /*event*/) {}
/// function to implement to react on akantu::NewElementsEvent
virtual void onElementsAdded(const Array<Element> & /*elements_list*/,
const NewElementsEvent & /*event*/) {}
/// function to implement to react on akantu::RemovedElementsEvent
virtual void
onElementsRemoved(const Array<Element> & /*elements_list*/,
- const ElementTypeMapArray<UInt> & /*new_numbering*/,
+ const ElementTypeMapArray<Idx> & /*new_numbering*/,
const RemovedElementsEvent & /*event*/) {}
/// function to implement to react on akantu::ChangedElementsEvent
virtual void
onElementsChanged(const Array<Element> & /*old_elements_list*/,
const Array<Element> & /*new_elements_list*/,
- const ElementTypeMapArray<UInt> & /*new_numbering*/,
+ const ElementTypeMapArray<Idx> & /*new_numbering*/,
const ChangedElementsEvent & /*event*/) {}
/// function to implement to react on akantu::MeshIsDistributedEvent
- virtual void onMeshIsDistributed(const Mesh & /*mesh*/,
- const MeshIsDistributedEvent & /*event*/) {}
+ virtual void onMeshIsDistributed(const MeshIsDistributedEvent & /*event*/) {}
};
} // namespace akantu
#endif /* AKANTU_MESH_EVENTS_HH_ */
diff --git a/src/mesh/mesh_inline_impl.hh b/src/mesh/mesh_inline_impl.hh
index 6d9160394..19b9b67e9 100644
--- a/src/mesh/mesh_inline_impl.hh
+++ b/src/mesh/mesh_inline_impl.hh
@@ -1,766 +1,743 @@
/**
* @file mesh_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Thu Jul 15 2010
* @date last modification: Fri Dec 11 2020
*
* @brief Implementation of the inline functions of the mesh class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "element_class.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_MESH_INLINE_IMPL_HH_
-#define AKANTU_MESH_INLINE_IMPL_HH_
-
namespace akantu {
/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-inline ElementKind Element::kind() const { return Mesh::getKind(type); }
+inline constexpr auto Mesh::getNbFacetsPerElement(ElementType type) -> Int {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) -> Int {
+ constexpr ElementType type = std::decay_t<decltype(enum_type)>::value;
+ return ElementClass<type>::getNbFacetsPerElement();
+ },
+ type);
+}
/* -------------------------------------------------------------------------- */
+inline constexpr auto Mesh::getNbFacetsPerElement(ElementType type, Idx t)
+ -> Int {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = std::decay_t<decltype(enum_type)>::value;
+ return ElementClass<type>::getNbFacetsPerElement(t);
+ },
+ type);
+}
+
/* -------------------------------------------------------------------------- */
template <typename... pack>
-Mesh::ElementTypesIteratorHelper Mesh::elementTypes(pack &&... _pack) const {
+auto Mesh::elementTypes(pack &&... _pack) const -> ElementTypesIteratorHelper {
return connectivities.elementTypes(_pack...);
}
+/* -------------------------------------------------------------------------- */
+inline decltype(auto) Mesh::getConnectivity(const Element & element) const {
+ return connectivities.get(element);
+}
+
/* -------------------------------------------------------------------------- */
inline RemovedNodesEvent::RemovedNodesEvent(const Mesh & mesh,
const std::string & origin)
- : MeshEvent<UInt>(origin),
+ : MeshEvent<Idx>(origin),
new_numbering(mesh.getNbNodes(), 1, "new_numbering") {}
/* -------------------------------------------------------------------------- */
inline RemovedElementsEvent::RemovedElementsEvent(const Mesh & mesh,
const ID & new_numbering_id,
const std::string & origin)
: MeshEvent<Element>(origin),
new_numbering(new_numbering_id, mesh.getID()) {}
/* -------------------------------------------------------------------------- */
template <>
inline void Mesh::sendEvent<NewElementsEvent>(NewElementsEvent & event) {
this->fillNodesToElements();
EventHandlerManager<MeshEventHandler>::sendEvent(event);
}
/* -------------------------------------------------------------------------- */
template <> inline void Mesh::sendEvent<NewNodesEvent>(NewNodesEvent & event) {
this->computeBoundingBox();
this->nodes_flags->resize(this->nodes->size(), NodeFlag::_normal);
GroupManager::onNodesAdded(event.getList(), event);
EventHandlerManager<MeshEventHandler>::sendEvent(event);
}
/* -------------------------------------------------------------------------- */
template <>
inline void
Mesh::sendEvent<RemovedElementsEvent>(RemovedElementsEvent & event) {
this->connectivities.onElementsRemoved(event.getNewNumbering());
this->fillNodesToElements();
this->computeBoundingBox();
EventHandlerManager<MeshEventHandler>::sendEvent(event);
}
/* -------------------------------------------------------------------------- */
template <>
inline void Mesh::sendEvent<RemovedNodesEvent>(RemovedNodesEvent & event) {
const auto & new_numbering = event.getNewNumbering();
this->removeNodesFromArray(*nodes, new_numbering);
if (nodes_global_ids and not is_mesh_facets) {
this->removeNodesFromArray(*nodes_global_ids, new_numbering);
}
if (not is_mesh_facets) {
this->removeNodesFromArray(*nodes_flags, new_numbering);
}
if (not nodes_to_elements.empty()) {
std::vector<std::unique_ptr<std::set<Element>>> tmp(
nodes_to_elements.size());
auto it = nodes_to_elements.begin();
- UInt new_nb_nodes = 0;
+ Int new_nb_nodes = 0;
for (auto new_i : new_numbering) {
- if (new_i != UInt(-1)) {
+ if (new_i != Int(-1)) {
tmp[new_i] = std::move(*it);
++new_nb_nodes;
}
++it;
}
tmp.resize(new_nb_nodes);
std::move(tmp.begin(), tmp.end(), nodes_to_elements.begin());
}
computeBoundingBox();
EventHandlerManager<MeshEventHandler>::sendEvent(event);
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void Mesh::removeNodesFromArray(Array<T> & vect,
- const Array<UInt> & new_numbering) {
+ const Array<Idx> & new_numbering) {
Array<T> tmp(vect.size(), vect.getNbComponent());
- UInt nb_component = vect.getNbComponent();
- UInt new_nb_nodes = 0;
- for (UInt i = 0; i < new_numbering.size(); ++i) {
- UInt new_i = new_numbering(i);
- if (new_i != UInt(-1)) {
- T * to_copy = vect.storage() + i * nb_component;
+ auto nb_component = vect.getNbComponent();
+ auto new_nb_nodes = 0;
+ for (Int i = 0; i < new_numbering.size(); ++i) {
+ auto new_i = new_numbering(i);
+ if (new_i != Int(-1)) {
+ T * to_copy = vect.data() + i * nb_component;
std::uninitialized_copy(to_copy, to_copy + nb_component,
- tmp.storage() + new_i * nb_component);
+ tmp.data() + new_i * nb_component);
++new_nb_nodes;
}
}
tmp.resize(new_nb_nodes);
vect.copy(tmp);
}
/* -------------------------------------------------------------------------- */
-inline Array<UInt> & Mesh::getNodesGlobalIdsPointer() {
+inline auto Mesh::getNodesGlobalIdsPointer() -> Array<Idx> & {
AKANTU_DEBUG_IN();
if (not nodes_global_ids) {
- nodes_global_ids = std::make_shared<Array<UInt>>(
+ nodes_global_ids = std::make_shared<Array<Idx>>(
nodes->size(), 1, getID() + ":nodes_global_ids");
for (auto && global_ids : enumerate(*nodes_global_ids)) {
std::get<1>(global_ids) = std::get<0>(global_ids);
}
}
AKANTU_DEBUG_OUT();
return *nodes_global_ids;
}
/* -------------------------------------------------------------------------- */
-inline Array<UInt> & Mesh::getConnectivityPointer(ElementType type,
- GhostType ghost_type) {
+template <typename T>
+inline decltype(auto)
+Mesh::getDataPointer(const ID & data_name, ElementType el_type,
+ GhostType ghost_type, Int nb_component,
+ bool size_to_nb_element, bool resize_with_parent) {
+ Array<T> & tmp = this->getElementalDataArrayAlloc<T>(
+ data_name, el_type, ghost_type, nb_component);
+
+ if (size_to_nb_element) {
+ if (resize_with_parent) {
+ tmp.resize(mesh_parent->getNbElement(el_type, ghost_type));
+ } else {
+ tmp.resize(this->getNbElement(el_type, ghost_type));
+ }
+ }
+
+ return tmp;
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline decltype(auto)
+Mesh::getDataPointer(const ID & data_name, ElementType el_type,
+ GhostType ghost_type, Int nb_component,
+ bool size_to_nb_element, bool resize_with_parent,
+ const T & defaul_) {
+ Array<T> & tmp = this->getElementalDataArrayAlloc<T>(
+ data_name, el_type, ghost_type, nb_component);
+
+ if (size_to_nb_element) {
+ if (resize_with_parent) {
+ tmp.resize(mesh_parent->getNbElement(el_type, ghost_type), defaul_);
+ } else {
+ tmp.resize(this->getNbElement(el_type, ghost_type), defaul_);
+ }
+ }
+
+ return tmp;
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline decltype(auto) Mesh::getData(const ID & data_name, ElementType el_type,
+ GhostType ghost_type) const {
+ return this->getElementalDataArray<T>(data_name, el_type, ghost_type);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline decltype(auto) Mesh::getData(const ID & data_name, ElementType el_type,
+ GhostType ghost_type) {
+ return this->getElementalDataArray<T>(data_name, el_type, ghost_type);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline decltype(auto) Mesh::getData(const ID & data_name) const {
+ return this->getElementalData<T>(data_name);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline decltype(auto) Mesh::getData(const ID & data_name) {
+ return this->getElementalData<T>(data_name);
+}
+
+/* -------------------------------------------------------------------------- */
+inline auto Mesh::getConnectivityPointer(ElementType type, GhostType ghost_type)
+ -> Array<Idx> & {
if (connectivities.exists(type, ghost_type)) {
return connectivities(type, ghost_type);
}
if (ghost_type != _not_ghost) {
ghosts_counters.alloc(0, 1, type, ghost_type, 1);
}
AKANTU_DEBUG_INFO("The connectivity vector for the type " << type
<< " created");
UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
return connectivities.alloc(0, nb_nodes_per_element, type, ghost_type);
}
/* -------------------------------------------------------------------------- */
-inline Array<std::vector<Element>> &
+inline decltype(auto)
Mesh::getElementToSubelementPointer(ElementType type, GhostType ghost_type) {
return getDataPointer<std::vector<Element>>("element_to_subelement", type,
ghost_type, 1, true);
}
/* -------------------------------------------------------------------------- */
-inline Array<Element> &
+inline decltype(auto)
Mesh::getSubelementToElementPointer(ElementType type, GhostType ghost_type) {
auto & array = getDataPointer<Element>(
"subelement_to_element", type, ghost_type, getNbFacetsPerElement(type),
false, is_mesh_facets, ElementNull);
return array;
}
/* -------------------------------------------------------------------------- */
-inline const auto & Mesh::getElementToSubelement() const {
+inline decltype(auto) Mesh::getElementToSubelement() const {
return getData<std::vector<Element>>("element_to_subelement");
}
/* -------------------------------------------------------------------------- */
inline auto & Mesh::getElementToSubelementNC() {
return getData<std::vector<Element>>("element_to_subelement");
}
/* -------------------------------------------------------------------------- */
inline const auto & Mesh::getElementToSubelement(ElementType type,
GhostType ghost_type) const {
return getData<std::vector<Element>>("element_to_subelement", type,
ghost_type);
}
/* -------------------------------------------------------------------------- */
inline auto & Mesh::getElementToSubelementNC(ElementType type,
GhostType ghost_type) {
return getData<std::vector<Element>>("element_to_subelement", type,
ghost_type);
}
/* -------------------------------------------------------------------------- */
-inline const auto &
+inline decltype(auto)
Mesh::getElementToSubelement(const Element & element) const {
return getData<std::vector<Element>>("element_to_subelement")(element, 0);
}
/* -------------------------------------------------------------------------- */
inline auto & Mesh::getElementToSubelementNC(const Element & element) {
return getData<std::vector<Element>>("element_to_subelement")(element, 0);
}
/* -------------------------------------------------------------------------- */
-inline const auto & Mesh::getSubelementToElement() const {
+inline decltype(auto) Mesh::getSubelementToElement() const {
return getData<Element>("subelement_to_element");
}
/* -------------------------------------------------------------------------- */
inline auto & Mesh::getSubelementToElementNC() {
return getData<Element>("subelement_to_element");
}
/* -------------------------------------------------------------------------- */
inline const auto & Mesh::getSubelementToElement(ElementType type,
GhostType ghost_type) const {
return getData<Element>("subelement_to_element", type, ghost_type);
}
/* -------------------------------------------------------------------------- */
inline auto & Mesh::getSubelementToElementNC(ElementType type,
GhostType ghost_type) {
return getData<Element>("subelement_to_element", type, ghost_type);
}
/* -------------------------------------------------------------------------- */
-inline VectorProxy<Element>
+inline decltype(auto)
Mesh::getSubelementToElement(const Element & element) const {
return this->getSubelementToElement().get(element);
}
/* -------------------------------------------------------------------------- */
-inline VectorProxy<Element>
+inline decltype(auto)
Mesh::getSubelementToElementNC(const Element & element) const {
return this->getSubelementToElement().get(element);
}
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline Array<T> &
-Mesh::getDataPointer(const ID & data_name, ElementType el_type,
- GhostType ghost_type, UInt nb_component,
- bool size_to_nb_element, bool resize_with_parent) {
- Array<T> & tmp = this->getElementalDataArrayAlloc<T>(
- data_name, el_type, ghost_type, nb_component);
-
- if (size_to_nb_element) {
- if (resize_with_parent) {
- tmp.resize(mesh_parent->getNbElement(el_type, ghost_type));
- } else {
- tmp.resize(this->getNbElement(el_type, ghost_type));
- }
- }
-
- return tmp;
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline Array<T> &
-Mesh::getDataPointer(const ID & data_name, ElementType el_type,
- GhostType ghost_type, UInt nb_component,
- bool size_to_nb_element, bool resize_with_parent,
- const T & defaul_) {
- Array<T> & tmp = this->getElementalDataArrayAlloc<T>(
- data_name, el_type, ghost_type, nb_component);
-
- if (size_to_nb_element) {
- if (resize_with_parent) {
- tmp.resize(mesh_parent->getNbElement(el_type, ghost_type), defaul_);
- } else {
- tmp.resize(this->getNbElement(el_type, ghost_type), defaul_);
- }
- }
-
- return tmp;
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline const Array<T> & Mesh::getData(const ID & data_name, ElementType el_type,
- GhostType ghost_type) const {
- return this->getElementalDataArray<T>(data_name, el_type, ghost_type);
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline Array<T> & Mesh::getData(const ID & data_name, ElementType el_type,
- GhostType ghost_type) {
- return this->getElementalDataArray<T>(data_name, el_type, ghost_type);
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline const ElementTypeMapArray<T> &
-Mesh::getData(const ID & data_name) const {
- return this->getElementalData<T>(data_name);
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline ElementTypeMapArray<T> & Mesh::getData(const ID & data_name) {
- return this->getElementalData<T>(data_name);
-}
-
-/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbElement(ElementType type, GhostType ghost_type) const {
- try {
-
- const Array<UInt> & conn = connectivities(type, ghost_type);
- return conn.size();
- } catch (...) {
- return 0;
- }
-}
-
-/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbElement(const UInt spatial_dimension,
- GhostType ghost_type, ElementKind kind) const {
- AKANTU_DEBUG_ASSERT(spatial_dimension <= 3 || spatial_dimension == UInt(-1),
- "spatial_dimension is " << spatial_dimension
- << " and is greater than 3 !");
- UInt nb_element = 0;
-
- for (auto type : elementTypes(spatial_dimension, ghost_type, kind)) {
- nb_element += getNbElement(type, ghost_type);
- }
-
- return nb_element;
-}
-
-/* -------------------------------------------------------------------------- */
-inline void Mesh::getBarycenter(const Element & element,
- Vector<Real> & barycenter) const {
- Vector<UInt> conn = getConnectivity(element);
+template <class D, std::enable_if_t<aka::is_vector_v<D>> *>
+inline void
+Mesh::getBarycenter(const Element & element,
+ const Eigen::MatrixBase<D> & barycenter_) const {
+ const auto && conn = getConnectivity(element);
Matrix<Real> local_coord(spatial_dimension, conn.size());
auto node_begin = make_view(*nodes, spatial_dimension).begin();
- for (auto && node : enumerate(conn)) {
- local_coord(std::get<0>(node)) =
- Vector<Real>(node_begin[std::get<1>(node)]);
+ for (auto && data : enumerate(conn)) {
+ local_coord(std::get<0>(data)) = node_begin[std::get<1>(data)];
}
- Math::barycenter(local_coord.storage(), conn.size(), spatial_dimension,
- barycenter.storage());
+ auto & barycenter = const_cast<Eigen::MatrixBase<D> &>(barycenter_);
+ Math::barycenter(local_coord, barycenter);
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbNodesPerElement(ElementType type) {
- UInt nb_nodes_per_element = 0;
-#define GET_NB_NODES_PER_ELEMENT(type) \
- nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement()
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_NODES_PER_ELEMENT);
-#undef GET_NB_NODES_PER_ELEMENT
- return nb_nodes_per_element;
+inline Vector<Real> Mesh::getBarycenter(const Element & element) const {
+ Vector<Real> tmp(spatial_dimension);
+ getBarycenter(element, tmp);
+ return tmp;
}
/* -------------------------------------------------------------------------- */
-inline ElementType Mesh::getP1ElementType(ElementType type) {
- ElementType p1_type = _not_defined;
-#define GET_P1_TYPE(type) p1_type = ElementClass<type>::getP1ElementType()
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_P1_TYPE);
-#undef GET_P1_TYPE
- return p1_type;
+inline constexpr auto Mesh::getKind(ElementType type) -> ElementKind {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getKind();
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
-inline ElementKind Mesh::getKind(ElementType type) {
- ElementKind kind = _ek_not_defined;
-#define GET_KIND(type) kind = ElementClass<type>::getKind()
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_KIND);
-#undef GET_KIND
- return kind;
+inline constexpr auto Element::kind() const -> ElementKind {
+ return Mesh::getKind(type);
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getSpatialDimension(ElementType type) {
- UInt spatial_dimension = 0;
-#define GET_SPATIAL_DIMENSION(type) \
- spatial_dimension = ElementClass<type>::getSpatialDimension()
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SPATIAL_DIMENSION);
-#undef GET_SPATIAL_DIMENSION
-
- return spatial_dimension;
+inline constexpr auto Mesh::getP1ElementType(ElementType type) -> ElementType {
+ return tuple_dispatch_with_default<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getP1ElementType();
+ },
+ type, [](auto && /*enum_type*/) { return _not_defined; });
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNaturalSpaceDimension(const ElementType & type) {
- UInt natural_dimension = 0;
-#define GET_NATURAL_DIMENSION(type) \
- natural_dimension = ElementClass<type>::getNaturalSpaceDimension()
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NATURAL_DIMENSION);
-#undef GET_NATURAL_DIMENSION
-
- return natural_dimension;
+inline constexpr auto Mesh::getSpatialDimension(ElementType type) -> Int {
+ return tuple_dispatch_with_default<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getSpatialDimension();
+ },
+ type, [](auto && /*enum_type*/) { return 0; });
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbFacetTypes(ElementType type, UInt /*t*/) {
- UInt nb = 0;
-#define GET_NB_FACET_TYPE(type) nb = ElementClass<type>::getNbFacetTypes()
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET_TYPE);
-#undef GET_NB_FACET_TYPE
- return nb;
-}
-
-/* -------------------------------------------------------------------------- */
-inline constexpr auto Mesh::getFacetType(ElementType type, UInt t) {
-#define GET_FACET_TYPE(type) return ElementClass<type>::getFacetType(t);
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH_NO_DEFAULT(GET_FACET_TYPE);
-
-#undef GET_FACET_TYPE
-
- return _not_defined;
+inline constexpr auto Mesh::getNaturalSpaceDimension(ElementType type) -> Int {
+ return tuple_dispatch_with_default<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getNaturalSpaceDimension();
+ },
+ type, [](auto && /*enum_type*/) { return 0; });
}
/* -------------------------------------------------------------------------- */
-inline constexpr auto Mesh::getAllFacetTypes(ElementType type) {
-#define GET_FACET_TYPE(type) return ElementClass<type>::getFacetTypes();
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH_NO_DEFAULT(GET_FACET_TYPE);
-#undef GET_FACET_TYPE
-
- return ElementClass<_not_defined>::getFacetTypes();
+inline constexpr auto Mesh::getNbFacetTypes(ElementType type, Idx /*t*/)
+ -> Int {
+ return tuple_dispatch_with_default<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getNbFacetTypes();
+ },
+ type, [](auto && /*enum_type*/) { return 0; });
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbFacetsPerElement(ElementType type) {
- AKANTU_DEBUG_IN();
-
- UInt n_facet = 0;
-#define GET_NB_FACET(type) n_facet = ElementClass<type>::getNbFacetsPerElement()
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET);
-#undef GET_NB_FACET
-
- AKANTU_DEBUG_OUT();
- return n_facet;
+inline constexpr auto Mesh::getFacetType(ElementType type, Idx t)
+ -> ElementType {
+ return tuple_dispatch_with_default<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getFacetType(t);
+ },
+ type, [](auto && /*enum_type*/) { return _not_defined; });
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbFacetsPerElement(ElementType type, UInt t) {
- AKANTU_DEBUG_IN();
-
- UInt n_facet = 0;
-#define GET_NB_FACET(type) \
- n_facet = ElementClass<type>::getNbFacetsPerElement(t)
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET);
-#undef GET_NB_FACET
-
- AKANTU_DEBUG_OUT();
- return n_facet;
+inline decltype(auto) Mesh::getAllFacetTypes(ElementType type) {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ auto && map = ElementClass<type>::getFacetTypes();
+ return Eigen::Map<const Eigen::Matrix<ElementType, Eigen::Dynamic, 1>>(
+ map.data(), map.rows(), map.cols());
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
-inline auto Mesh::getFacetLocalConnectivity(ElementType type, UInt t) {
- AKANTU_DEBUG_IN();
-
-#define GET_FACET_CON(type) \
- AKANTU_DEBUG_OUT(); \
- return ElementClass<type>::getFacetLocalConnectivityPerElement(t)
-
- AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_CON);
-#undef GET_FACET_CON
-
- AKANTU_DEBUG_OUT();
- return ElementClass<_not_defined>::getFacetLocalConnectivityPerElement(0);
- // This avoid a compilation warning but will certainly
- // also cause a segfault if reached
+inline decltype(auto) Mesh::getFacetLocalConnectivity(ElementType type, Idx t) {
+ return tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getFacetLocalConnectivityPerElement(t);
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
-inline auto Mesh::getFacetConnectivity(const Element & element, UInt t) const {
- AKANTU_DEBUG_IN();
-
- Matrix<const UInt> local_facets(getFacetLocalConnectivity(element.type, t));
- Matrix<UInt> facets(local_facets.rows(), local_facets.cols());
+inline auto Mesh::getFacetConnectivity(const Element & element, Idx t) const
+ -> Matrix<Idx> {
+ auto local_facets = getFacetLocalConnectivity(element.type, t);
+ Matrix<Idx> facets(local_facets.rows(), local_facets.cols());
- const Array<UInt> & conn = connectivities(element.type, element.ghost_type);
+ const auto & conn = connectivities(element.type, element.ghost_type);
- for (UInt f = 0; f < facets.rows(); ++f) {
- for (UInt n = 0; n < facets.cols(); ++n) {
+ for (Int f = 0; f < facets.rows(); ++f) {
+ for (Int n = 0; n < facets.cols(); ++n) {
facets(f, n) = conn(element.element, local_facets(f, n));
}
}
- AKANTU_DEBUG_OUT();
return facets;
}
/* -------------------------------------------------------------------------- */
-inline VectorProxy<UInt> Mesh::getConnectivity(const Element & element) const {
+inline decltype(auto) Mesh::getConnectivityNC(const Element & element) {
return connectivities.get(element);
}
/* -------------------------------------------------------------------------- */
-inline VectorProxy<UInt> Mesh::getConnectivityNC(const Element & element) {
- return connectivities.get(element);
+template <typename T, class Derived1, class Derived2,
+ std::enable_if_t<aka::is_vector_v<Derived2>> *>
+inline void Mesh::extractNodalValuesFromElement(
+ const Array<T> & nodal_values,
+ Eigen::MatrixBase<Derived1> & elemental_values,
+ const Eigen::MatrixBase<Derived2> & connectivity) const {
+ static_assert(std::is_convertible<T, typename Derived1::Scalar>::value,
+ "Cannot extract the array to the vector");
+ AKANTU_DEBUG_ASSERT(
+ nodal_values.getNbComponent() == elemental_values.rows(),
+ "Cannot extract nodal values to a vector of different size");
+ auto nodal_values_it =
+ make_view(nodal_values, elemental_values.rows()).begin();
+ for (auto && data : enumerate(connectivity)) {
+ elemental_values(std::get<0>(data)) = nodal_values_it[std::get<1>(data)];
+ }
}
/* -------------------------------------------------------------------------- */
template <typename T>
-inline void Mesh::extractNodalValuesFromElement(
- const Array<T> & nodal_values, T * local_coord, const UInt * connectivity,
- UInt n_nodes, UInt nb_degree_of_freedom) const {
- for (UInt n = 0; n < n_nodes; ++n) {
- memcpy(local_coord + n * nb_degree_of_freedom,
- nodal_values.storage() + connectivity[n] * nb_degree_of_freedom,
- nb_degree_of_freedom * sizeof(T));
- }
+inline decltype(auto)
+Mesh::extractNodalValuesFromElement(const Array<T> & nodal_values,
+ const Element & element) const {
+ auto && conn = mesh.getConnectivity(element);
+ Matrix<Real> elemental_values(nodal_values.getNbComponent(),
+ Mesh::getNbNodesPerElement(element.type));
+ extractNodalValuesFromElement(nodal_values, elemental_values, conn);
+ return elemental_values;
}
/* -------------------------------------------------------------------------- */
inline void Mesh::addConnectivityType(ElementType type, GhostType ghost_type) {
getConnectivityPointer(type, ghost_type);
}
/* -------------------------------------------------------------------------- */
-inline bool Mesh::isPureGhostNode(UInt n) const {
+inline auto Mesh::isPureGhostNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_pure_ghost;
}
/* -------------------------------------------------------------------------- */
-inline bool Mesh::isLocalOrMasterNode(UInt n) const {
+inline auto Mesh::isLocalOrMasterNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_local_master_mask) == NodeFlag::_normal;
}
/* -------------------------------------------------------------------------- */
-inline bool Mesh::isLocalNode(UInt n) const {
+inline auto Mesh::isLocalNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_normal;
}
/* -------------------------------------------------------------------------- */
-inline bool Mesh::isMasterNode(UInt n) const {
+inline auto Mesh::isMasterNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_master;
}
/* -------------------------------------------------------------------------- */
-inline bool Mesh::isSlaveNode(UInt n) const {
+inline auto Mesh::isSlaveNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_slave;
}
/* -------------------------------------------------------------------------- */
-inline bool Mesh::isPeriodicSlave(UInt n) const {
+inline auto Mesh::isPeriodicSlave(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_periodic_mask) ==
NodeFlag::_periodic_slave;
}
/* -------------------------------------------------------------------------- */
-inline bool Mesh::isPeriodicMaster(UInt n) const {
+inline auto Mesh::isPeriodicMaster(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_periodic_mask) ==
NodeFlag::_periodic_master;
}
/* -------------------------------------------------------------------------- */
-inline NodeFlag Mesh::getNodeFlag(UInt local_id) const {
+inline auto Mesh::getNodeFlag(Idx local_id) const -> NodeFlag {
return (*nodes_flags)(local_id);
}
/* -------------------------------------------------------------------------- */
-inline Int Mesh::getNodePrank(UInt local_id) const {
+inline auto Mesh::getNodePrank(Idx local_id) const {
auto it = nodes_prank.find(local_id);
return it == nodes_prank.end() ? -1 : it->second;
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNodeGlobalId(UInt local_id) const {
+inline auto Mesh::getNodeGlobalId(Idx local_id) const {
return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id;
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNodeLocalId(UInt global_id) const {
+inline auto Mesh::getNodeLocalId(Idx global_id) const {
if (nodes_global_ids == nullptr) {
return global_id;
}
return nodes_global_ids->find(global_id);
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbGlobalNodes() const {
+inline auto Mesh::getNbGlobalNodes() const {
return nodes_global_ids ? nb_global_nodes : nodes->size();
}
/* -------------------------------------------------------------------------- */
-inline UInt Mesh::getNbNodesPerElementList(const Array<Element> & elements) {
- UInt nb_nodes_per_element = 0;
- UInt nb_nodes = 0;
+inline auto Mesh::getNbNodesPerElementList(const Array<Element> & elements)
+ -> Int {
+ Int nb_nodes_per_element = 0;
+ Int nb_nodes = 0;
ElementType current_element_type = _not_defined;
for (const auto & el : elements) {
if (el.type != current_element_type) {
current_element_type = el.type;
nb_nodes_per_element = Mesh::getNbNodesPerElement(current_element_type);
}
nb_nodes += nb_nodes_per_element;
}
return nb_nodes;
}
/* -------------------------------------------------------------------------- */
inline Mesh & Mesh::getMeshFacets() {
if (this->mesh_facets == nullptr) {
AKANTU_SILENT_EXCEPTION(
"No facet mesh is defined yet! check the buildFacets functions");
}
return *this->mesh_facets;
}
/* -------------------------------------------------------------------------- */
inline const Mesh & Mesh::getMeshFacets() const {
if (this->mesh_facets == nullptr) {
AKANTU_SILENT_EXCEPTION(
"No facet mesh is defined yet! check the buildFacets functions");
}
return *this->mesh_facets;
}
+
/* -------------------------------------------------------------------------- */
inline const Mesh & Mesh::getMeshParent() const {
if (this->mesh_parent == nullptr) {
AKANTU_SILENT_EXCEPTION(
"No parent mesh is defined! This is only valid in a mesh_facets");
}
-
return *this->mesh_parent;
}
/* -------------------------------------------------------------------------- */
-void Mesh::addPeriodicSlave(UInt slave, UInt master) {
+void Mesh::addPeriodicSlave(Idx slave, Idx master) {
if (master == slave) {
return;
}
// if pair already registered
auto master_slaves = periodic_master_slave.equal_range(master);
auto slave_it =
std::find_if(master_slaves.first, master_slaves.second,
[&](auto & pair) { return pair.second == slave; });
if (slave_it == master_slaves.second) {
// no duplicates
periodic_master_slave.insert(std::make_pair(master, slave));
AKANTU_DEBUG_INFO("adding periodic slave, slave gid:"
<< getNodeGlobalId(slave) << " [lid: " << slave << "]"
<< ", master gid:" << getNodeGlobalId(master)
<< " [lid: " << master << "]");
// std::cout << "adding periodic slave, slave gid:" <<
// getNodeGlobalId(slave)
// << " [lid: " << slave << "]"
// << ", master gid:" << getNodeGlobalId(master)
// << " [lid: " << master << "]" << std::endl;
}
periodic_slave_master[slave] = master;
auto set_flag = [&](auto node, auto flag) {
(*nodes_flags)[node] &= ~NodeFlag::_periodic_mask; // clean periodic flags
(*nodes_flags)[node] |= flag;
};
set_flag(slave, NodeFlag::_periodic_slave);
set_flag(master, NodeFlag::_periodic_master);
}
-/* -------------------------------------------------------------------------- */
-UInt Mesh::getPeriodicMaster(UInt slave) const {
+/* --------------------------------------------------------------------------
+ */
+auto Mesh::getPeriodicMaster(Idx slave) const -> Idx {
return periodic_slave_master.at(slave);
}
/* -------------------------------------------------------------------------- */
class Mesh::PeriodicSlaves {
- using internal_iterator = std::unordered_multimap<UInt, UInt>::const_iterator;
+ using internal_iterator = std::unordered_multimap<Idx, Idx>::const_iterator;
std::pair<internal_iterator, internal_iterator> pair;
public:
- PeriodicSlaves(const Mesh & mesh, UInt master)
+ PeriodicSlaves(const Mesh & mesh, Idx master)
: pair(mesh.getPeriodicMasterSlaves().equal_range(master)) {}
PeriodicSlaves(const PeriodicSlaves & other) = default;
- PeriodicSlaves(PeriodicSlaves && other) = default;
- PeriodicSlaves & operator=(const PeriodicSlaves & other) = default;
+ PeriodicSlaves(PeriodicSlaves && other) noexcept = default;
+ auto operator=(const PeriodicSlaves & other) -> PeriodicSlaves & = default;
class const_iterator {
internal_iterator it;
public:
const_iterator(internal_iterator it) : it(it) {}
const_iterator operator++() {
++it;
return *this;
}
bool operator!=(const const_iterator & other) { return other.it != it; }
bool operator==(const const_iterator & other) { return other.it == it; }
auto operator*() { return it->second; }
};
auto begin() const { return const_iterator(pair.first); }
auto end() const { return const_iterator(pair.second); }
};
/* -------------------------------------------------------------------------- */
-inline decltype(auto) Mesh::getPeriodicSlaves(UInt master) const {
+inline decltype(auto) Mesh::getPeriodicSlaves(Idx master) const {
return PeriodicSlaves(*this, master);
}
/* -------------------------------------------------------------------------- */
-inline Vector<UInt>
+inline decltype(auto)
Mesh::getConnectivityWithPeriodicity(const Element & element) const {
- Vector<UInt> conn = getConnectivity(element);
+ auto conn = getConnectivity(element);
if (not isPeriodic()) {
return conn;
}
for (auto && node : conn) {
if (isPeriodicSlave(node)) {
node = getPeriodicMaster(node);
}
}
return conn;
}
-} // namespace akantu
+/* -------------------------------------------------------------------------- */
+inline decltype(auto) Mesh::getAssociatedElements(const Idx & node) const {
+ return (*nodes_to_elements[node]);
+}
-#endif /* AKANTU_MESH_INLINE_IMPL_HH_ */
+} // namespace akantu
diff --git a/src/mesh/mesh_iterators.hh b/src/mesh/mesh_iterators.hh
index f6652d182..3faa17508 100644
--- a/src/mesh/mesh_iterators.hh
+++ b/src/mesh/mesh_iterators.hh
@@ -1,226 +1,248 @@
/**
* @file mesh_iterators.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Jul 16 2015
* @date last modification: Thu Mar 11 2021
*
* @brief Set of helper classes to have fun with range based for
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_named_argument.hh"
-#include "aka_static_if.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_ITERATORS_HH_
#define AKANTU_MESH_ITERATORS_HH_
namespace akantu {
class MeshElementsByTypes {
- using elements_iterator = Array<Element>::scalar_iterator;
+ using elements_iterator = Array<Element>::const_scalar_iterator;
public:
explicit MeshElementsByTypes(const Array<Element> & elements) {
this->elements.copy(elements);
std::sort(this->elements.begin(), this->elements.end());
}
/* ------------------------------------------------------------------------ */
class MeshElementsRange {
public:
MeshElementsRange() = default;
- MeshElementsRange(const elements_iterator & begin,
- const elements_iterator & end)
- : type((*begin).type), ghost_type((*begin).ghost_type), begin(begin),
+ MeshElementsRange(elements_iterator & begin, elements_iterator & end)
+ : type(begin->type), ghost_type(begin->ghost_type), begin(begin),
end(end) {}
AKANTU_GET_MACRO(Type, type, ElementType);
AKANTU_GET_MACRO(GhostType, ghost_type, GhostType);
- const Array<UInt> & getElements() {
+ const Array<Int> & getElements() {
elements.resize(end - begin);
auto el_it = elements.begin();
for (auto it = begin; it != end; ++it, ++el_it) {
*el_it = it->element;
}
return elements;
}
private:
ElementType type{_not_defined};
GhostType ghost_type{_casper};
elements_iterator begin;
elements_iterator end;
- Array<UInt> elements;
+ Array<Int> elements;
};
/* ------------------------------------------------------------------------ */
class iterator {
struct element_comparator {
bool operator()(const Element & lhs, const Element & rhs) const {
return ((rhs == ElementNull) || std::tie(lhs.ghost_type, lhs.type) <
std::tie(rhs.ghost_type, rhs.type));
}
};
public:
iterator(const iterator &) = default;
- iterator(const elements_iterator & first, const elements_iterator & last)
+ iterator(elements_iterator first, elements_iterator last)
: range(std::equal_range(first, last, *first, element_comparator())),
- first(first), last(last) {}
+ first(std::move(first)), last(std::move(last)) {}
- decltype(auto) operator*() const {
+ decltype(auto) operator*() {
return MeshElementsRange(range.first, range.second);
}
iterator operator++() {
first = range.second;
range = std::equal_range(first, last, *first, element_comparator());
return *this;
}
bool operator==(const iterator & other) const {
return (first == other.first and last == other.last);
}
bool operator!=(const iterator & other) const {
return (not operator==(other));
}
private:
std::pair<elements_iterator, elements_iterator> range;
elements_iterator first;
elements_iterator last;
};
iterator begin() { return iterator(elements.begin(), elements.end()); }
iterator end() { return iterator(elements.end(), elements.end()); }
private:
Array<Element> elements;
};
/* -------------------------------------------------------------------------- */
namespace mesh_iterators {
namespace details {
template <class internal_iterator> class delegated_iterator {
public:
using value_type = std::remove_pointer_t<
typename internal_iterator::value_type::second_type>;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::input_iterator_tag;
explicit delegated_iterator(internal_iterator it) : it(std::move(it)) {}
decltype(auto) operator*() {
return std::forward<decltype(*(it->second))>(*(it->second));
}
delegated_iterator operator++() {
++it;
return *this;
}
bool operator==(const delegated_iterator & other) const {
return other.it == it;
}
bool operator!=(const delegated_iterator & other) const {
return other.it != it;
}
private:
internal_iterator it;
};
} // namespace details
} // namespace mesh_iterators
+/* -------------------------------------------------------------------------- */
+template <class T,
+ typename = std::enable_if_t<std::is_integral<std::decay_t<T>>::value>>
+inline constexpr decltype(auto)
+element_range(const T & stop, ElementType type,
+ GhostType ghost_type = _not_ghost) {
+ return make_transform_adaptor(arange(stop),
+ [type, ghost_type](auto && value) {
+ return Element{type, value, ghost_type};
+ });
+}
+
+template <class T1, class T2,
+ typename = std::enable_if_t<
+ std::is_integral<std::common_type_t<T1, T2>>::value>>
+inline constexpr decltype(auto)
+element_range(const T1 & start, const T2 & stop, ElementType type,
+ GhostType ghost_type = _not_ghost) {
+ return make_transform_adaptor(arange(start, stop),
+ [type, ghost_type](auto && value) {
+ return Element{type, value, ghost_type};
+ });
+}
+
/* -------------------------------------------------------------------------- */
template <class Func>
-void for_each_element(UInt nb_elements, const Array<UInt> & filter_elements,
+void for_each_element(Int nb_elements, const Array<Idx> & filter_elements,
Func && function) {
if (filter_elements != empty_filter) {
std::for_each(filter_elements.begin(), filter_elements.end(),
std::forward<Func>(function));
} else {
auto && range = arange(nb_elements);
std::for_each(range.begin(), range.end(), std::forward<Func>(function));
}
}
/* -------------------------------------------------------------------------- */
template <class Func, typename... pack>
void for_each_element(const Mesh & mesh, Func && function, pack &&... _pack) {
auto requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _casper);
- const ElementTypeMapArray<UInt> * filter =
+ const ElementTypeMapArray<Idx> * filter =
OPTIONAL_NAMED_ARG(element_filter, nullptr);
bool all_ghost_types = requested_ghost_type == _casper;
auto spatial_dimension =
OPTIONAL_NAMED_ARG(spatial_dimension, mesh.getSpatialDimension());
auto element_kind = OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined);
for (auto ghost_type : ghost_types) {
if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types)) {
continue;
}
auto element_types =
mesh.elementTypes(spatial_dimension, ghost_type, element_kind);
if (filter) {
element_types =
filter->elementTypes(spatial_dimension, ghost_type, element_kind);
}
for (auto type : element_types) {
- const Array<UInt> * filter_array;
+ const Array<Idx> * filter_array;
if (filter) {
filter_array = &((*filter)(type, ghost_type));
} else {
filter_array = &empty_filter;
}
auto nb_elements = mesh.getNbElement(type, ghost_type);
for_each_element(nb_elements, *filter_array, [&](auto && el) {
auto element = Element{type, el, ghost_type};
std::forward<Func>(function)(element);
});
}
}
}
} // namespace akantu
#endif /* AKANTU_MESH_ITERATORS_HH_ */
diff --git a/src/mesh/mesh_periodic.cc b/src/mesh/mesh_periodic.cc
index c585c548f..f636648da 100644
--- a/src/mesh/mesh_periodic.cc
+++ b/src/mesh/mesh_periodic.cc
@@ -1,466 +1,466 @@
/**
* @file mesh_periodic.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Feb 12 2018
* @date last modification: Sun Mar 15 2020
*
* @brief Implementation of the perdiodicity capabilities in the mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communication_tag.hh"
#include "communicator.hh"
#include "element_group.hh"
#include "mesh.hh"
#include "periodic_node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
void Mesh::makePeriodic(const SpatialDirection & direction) {
- Array<UInt> list_1;
- Array<UInt> list_2;
+ Array<Idx> list_1;
+ Array<Idx> list_2;
Real tolerance = 1e-10;
auto lower_bound = this->getLowerBounds();
auto upper_bound = this->getUpperBounds();
auto length = upper_bound(direction) - lower_bound(direction);
const auto & positions = *nodes;
for (auto && data : enumerate(make_view(positions, spatial_dimension))) {
- UInt node = std::get<0>(data);
+ auto node = std::get<0>(data);
const auto & pos = std::get<1>(data);
if (std::abs((pos(direction) - lower_bound(direction)) / length) <
tolerance) {
list_1.push_back(node);
}
if (std::abs((pos(direction) - upper_bound(direction)) / length) <
tolerance) {
list_2.push_back(node);
}
}
this->makePeriodic(direction, list_1, list_2);
}
/* -------------------------------------------------------------------------- */
void Mesh::makePeriodic(const SpatialDirection & direction, const ID & list_1,
const ID & list_2) {
const auto & list_nodes_1 =
mesh.getElementGroup(list_1).getNodeGroup().getNodes();
const auto & list_nodes_2 =
mesh.getElementGroup(list_2).getNodeGroup().getNodes();
this->makePeriodic(direction, list_nodes_1, list_nodes_2);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
namespace {
struct NodeInfo {
NodeInfo() = default;
- NodeInfo(UInt spatial_dimension) : position(spatial_dimension) {}
- NodeInfo(UInt node, const Vector<Real> & position,
+ NodeInfo(Int spatial_dimension) : position(spatial_dimension) {}
+ NodeInfo(Idx node, const Vector<Real> & position,
const SpatialDirection & direction)
: node(node), position(position) {
this->direction_position = position(direction);
this->position(direction) = 0.;
}
NodeInfo(const NodeInfo & other) = default;
NodeInfo(NodeInfo && other) noexcept = default;
NodeInfo & operator=(const NodeInfo & other) = default;
NodeInfo & operator=(NodeInfo && other) = default;
- UInt node{0};
+ Idx node{0};
Vector<Real> position;
Real direction_position{0.};
};
} // namespace
/* -------------------------------------------------------------------------- */
// left is for lower values on direction and right for highest values
void Mesh::makePeriodic(const SpatialDirection & direction,
- const Array<UInt> & list_left,
- const Array<UInt> & list_right) {
+ const Array<Idx> & list_left,
+ const Array<Idx> & list_right) {
Real tolerance = 1e-10;
const auto & positions = *nodes;
auto lower_bound = this->getLowerBounds();
auto upper_bound = this->getUpperBounds();
auto length = upper_bound(direction) - lower_bound(direction);
lower_bound(direction) = 0;
upper_bound(direction) = 0;
auto prank = communicator->whoAmI();
std::vector<NodeInfo> nodes_left(list_left.size());
std::vector<NodeInfo> nodes_right(list_right.size());
BBox bbox(spatial_dimension);
- auto to_position = [&](UInt node) {
+ auto to_position = [&](auto node) {
Vector<Real> pos(spatial_dimension);
- for (UInt s : arange(spatial_dimension)) {
+ for (auto s : arange(spatial_dimension)) {
pos(s) = positions(node, s);
}
auto && info = NodeInfo(node, pos, direction);
bbox += info.position;
return std::move(info);
};
std::transform(list_left.begin(), list_left.end(), nodes_left.begin(),
to_position);
BBox bbox_left = bbox;
bbox.reset();
std::transform(list_right.begin(), list_right.end(), nodes_right.begin(),
to_position);
BBox bbox_right = bbox;
- std::vector<UInt> new_nodes;
+ std::vector<Idx> new_nodes;
if (is_distributed) {
NewNodesEvent event(AKANTU_CURRENT_FUNCTION);
/* ---------------------------------------------------------------------- */
// function to send nodes in bboxes intersections
auto extract_and_send_nodes = [&](const auto & bbox, const auto & node_list,
auto & buffers, auto proc, auto cnt) {
// buffers.resize(buffers.size() + 1);
buffers.push_back(std::make_unique<DynamicCommunicationBuffer>());
auto & buffer = *buffers.back();
// std::cout << "Sending to " << proc << std::endl;
for (auto & info : node_list) {
if (bbox.contains(info.position) and isLocalOrMasterNode(info.node)) {
- Vector<Real> pos = info.position;
+ auto pos = info.position;
pos(direction) = info.direction_position;
- NodeFlag flag = (*nodes_flags)(info.node) & NodeFlag::_periodic_mask;
- UInt gnode = getNodeGlobalId(info.node);
+ auto flag = (*nodes_flags)(info.node) & NodeFlag::_periodic_mask;
+ auto gnode = getNodeGlobalId(info.node);
buffer << gnode;
buffer << pos;
buffer << flag;
// std::cout << " - node " << getNodeGlobalId(info.node);
// if is slave sends master info
if (flag == NodeFlag::_periodic_slave) {
- UInt master = getNodeGlobalId(periodic_slave_master[info.node]);
+ auto master = getNodeGlobalId(periodic_slave_master[info.node]);
// std::cout << " slave of " << master << std::endl;
buffer << master;
}
// if is master sends list of slaves
if (flag == NodeFlag::_periodic_master) {
- UInt nb_slaves = periodic_master_slave.count(info.node);
+ auto nb_slaves = periodic_master_slave.count(info.node);
buffer << nb_slaves;
// std::cout << " master of " << nb_slaves << " nodes : [";
auto slaves = periodic_master_slave.equal_range(info.node);
for (auto it = slaves.first; it != slaves.second; ++it) {
- UInt gslave = getNodeGlobalId(it->second);
+ auto gslave = getNodeGlobalId(it->second);
// std::cout << (it == slaves.first ? "" : ", ") << gslave;
buffer << gslave;
}
// std::cout << "]";
}
// std::cout << std::endl;
}
}
auto tag = Tag::genTag(prank, 10 * direction + cnt, Tag::_periodic_nodes);
// std::cout << "SBuffer size " << buffer.size() << " " << tag <<
// std::endl;
return communicator->asyncSend(buffer, proc, tag);
};
/* ---------------------------------------------------------------------- */
// function to receive nodes in bboxes intersections
auto recv_and_extract_nodes = [&](auto & node_list, const auto proc,
auto cnt) {
DynamicCommunicationBuffer buffer;
auto tag = Tag::genTag(proc, 10 * direction + cnt, Tag::_periodic_nodes);
communicator->receive(buffer, proc, tag);
// std::cout << "RBuffer size " << buffer.size() << " " << tag <<
// std::endl; std::cout << "Receiving from " << proc << std::endl;
while (not buffer.empty()) {
Vector<Real> pos(spatial_dimension);
- UInt global_node;
+ Idx global_node;
NodeFlag flag;
buffer >> global_node;
buffer >> pos;
buffer >> flag;
// std::cout << " - node " << global_node;
auto local_node = getNodeLocalId(global_node);
// get the master info of is slave
if (flag == NodeFlag::_periodic_slave) {
- UInt master_node;
+ Idx master_node;
buffer >> master_node;
// std::cout << " slave of " << master_node << std::endl;
// auto local_master_node = getNodeLocalId(master_node);
// AKANTU_DEBUG_ASSERT(local_master_node != UInt(-1),
//"Should I know the master node " << master_node);
}
// get the list of slaves if is master
if ((flag & NodeFlag::_periodic_mask) == NodeFlag::_periodic_master) {
- UInt nb_slaves;
+ Int nb_slaves;
buffer >> nb_slaves;
// std::cout << " master of " << nb_slaves << " nodes : [";
for (auto ns [[gnu::unused]] : arange(nb_slaves)) {
- UInt gslave_node;
+ Idx gslave_node;
buffer >> gslave_node;
// std::cout << (ns == 0 ? "" : ", ") << gslave_node;
// auto lslave_node = getNodeLocalId(gslave_node);
// AKANTU_DEBUG_ASSERT(lslave_node != UInt(-1),
// "Should I know the slave node " <<
// gslave_node);
}
// std::cout << "]";
}
// std::cout << std::endl;
- if (local_node != UInt(-1)) {
+ if (local_node != -1) {
continue;
}
local_node = nodes->size();
NodeInfo info(local_node, pos, direction);
nodes->push_back(pos);
nodes_global_ids->push_back(global_node);
nodes_flags->push_back(flag | NodeFlag::_pure_ghost);
new_nodes.push_back(info.node);
node_list.push_back(info);
nodes_prank[info.node] = proc;
event.getList().push_back(local_node);
}
};
/* ---------------------------------------------------------------------- */
auto && intersections_with_right =
bbox_left.intersection(bbox_right, *communicator);
auto && intersections_with_left =
bbox_right.intersection(bbox_left, *communicator);
std::vector<CommunicationRequest> send_requests;
std::vector<std::unique_ptr<DynamicCommunicationBuffer>> send_buffers;
// sending nodes in the common zones
auto send_intersections = [&](auto & intersections, auto send_count) {
for (auto && data : intersections) {
auto proc = std::get<0>(data);
// Send local nodes if intersects with remote
const auto & intersection_with_proc = std::get<1>(data);
if (intersection_with_proc) {
send_requests.push_back(
extract_and_send_nodes(intersection_with_proc, nodes_right,
send_buffers, proc, send_count));
}
send_count += 2;
}
};
auto recv_intersections = [&](auto & intersections, auto recv_count) {
for (auto && data : intersections) {
auto proc = std::get<0>(data);
// receive remote nodes if intersects with local
const auto & intersection_with_proc = std::get<1>(data);
if (intersection_with_proc) {
recv_and_extract_nodes(nodes_right, proc, recv_count);
}
recv_count += 2;
}
};
send_intersections(intersections_with_left, 0);
send_intersections(intersections_with_right, 1);
recv_intersections(intersections_with_right, 0);
recv_intersections(intersections_with_right, 1);
Communicator::waitAll(send_requests);
Communicator::freeCommunicationRequest(send_requests);
this->sendEvent(event);
} // end distributed work
auto to_sort = [&](auto && info1, auto && info2) -> bool {
return info1.position < info2.position;
};
// sort nodes based on their distance to lower corner
std::sort(nodes_left.begin(), nodes_left.end(), to_sort);
std::sort(nodes_right.begin(), nodes_right.end(), to_sort);
// function to change the master of nodes
auto updating_master = [&](auto & old_master, auto & new_master) {
if (old_master == new_master) {
return;
}
auto slaves = periodic_master_slave.equal_range(old_master);
AKANTU_DEBUG_ASSERT(
isPeriodicMaster(
old_master), // slaves.first != periodic_master_slave.end(),
"Cannot update master " << old_master << ", its not a master node!");
decltype(periodic_master_slave) tmp_master_slave;
for (auto it = slaves.first; it != slaves.second; ++it) {
auto slave = it->second;
tmp_master_slave.insert(std::make_pair(new_master, slave));
periodic_slave_master[slave] = new_master;
}
periodic_master_slave.erase(old_master);
(*nodes_flags)[old_master] &= ~NodeFlag::_periodic_master;
addPeriodicSlave(old_master, new_master);
for (auto && data : tmp_master_slave) {
addPeriodicSlave(data.second, data.first);
}
};
// handling 2 nodes that are periodic
auto match_found = [&](auto & info1, auto & info2) {
const auto & node1 = info1.node;
const auto & node2 = info2.node;
auto master = node1;
bool node1_side_master = false;
if (isPeriodicMaster(node1)) {
node1_side_master = true;
} else if (isPeriodicSlave(node1)) {
node1_side_master = true;
master = periodic_slave_master[node1];
}
auto node2_master = node2;
if (isPeriodicSlave(node2)) {
node2_master = periodic_slave_master[node2];
}
if (node1_side_master) {
if (isPeriodicSlave(node2)) {
updating_master(node2_master, master);
return;
}
if (isPeriodicMaster(node2)) {
updating_master(node2, master);
return;
}
addPeriodicSlave(node2, master);
} else {
if (isPeriodicSlave(node2)) {
addPeriodicSlave(node1, node2_master);
return;
}
if (isPeriodicMaster(node2)) {
addPeriodicSlave(node1, node2);
return;
}
addPeriodicSlave(node2, node1);
}
};
// matching the nodes from 2 lists
auto match_pairs = [&](auto & nodes_1, auto & nodes_2) {
// Guillaume to Nico: It seems that the list of nodes is not sorted
// as it was: therefore the loop cannot be truncated anymore.
// Otherwise many pairs are missing.
// I replaced (temporarily?) for the N^2 loop so as not to miss
// any pbc pair.
//
// auto it = nodes_2.begin();
// for every nodes in 1st list
for (auto && info1 : nodes_1) {
auto & pos1 = info1.position;
// auto it_cur = it;
// try to find a match in 2nd list
for (auto && info2 : nodes_2) {
// auto & info2 = *it_cur;
auto & pos2 = info2.position;
auto dist = pos1.distance(pos2) / length;
if (dist < tolerance) {
// handles the found matches
match_found(info1, info2);
// it = it_cur;
break;
}
}
}
};
match_pairs(nodes_left, nodes_right);
// match_pairs(nodes_right, nodes_left);
this->updatePeriodicSynchronizer();
this->is_periodic = true;
}
/* -------------------------------------------------------------------------- */
void Mesh::wipePeriodicInfo() {
this->is_periodic = false;
this->periodic_slave_master.clear();
this->periodic_master_slave.clear();
for (auto && flags : *nodes_flags) {
flags &= ~NodeFlag::_periodic_mask;
}
}
/* -------------------------------------------------------------------------- */
void Mesh::updatePeriodicSynchronizer() {
if (not this->periodic_node_synchronizer) {
this->periodic_node_synchronizer =
std::make_unique<PeriodicNodeSynchronizer>(
*this, this->getID() + ":periodic_synchronizer", false);
}
this->periodic_node_synchronizer->update();
}
} // namespace akantu
diff --git a/src/mesh/node_group.cc b/src/mesh/node_group.cc
index b0057f248..a507cc602 100644
--- a/src/mesh/node_group.cc
+++ b/src/mesh/node_group.cc
@@ -1,94 +1,93 @@
/**
* @file node_group.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Mar 04 2020
*
* @brief Implementation of the node group
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "node_group.hh"
#include "dumpable.hh"
#include "dumpable_inline_impl.hh"
#include "dumper_iohelper_paraview.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NodeGroup::NodeGroup(const std::string & name, const Mesh & mesh,
const std::string & id)
: name(name), node_group(0, 1, std::string(id + ":nodes")) {
this->registerDumper<DumperParaview>("paraview_" + name, name, true);
auto field = std::make_shared<dumpers::NodalField<Real, true>>(
mesh.getNodes(), 0, 0, &this->getNodes());
this->getDumper().registerField("positions", field);
}
/* -------------------------------------------------------------------------- */
NodeGroup::~NodeGroup() = default;
/* -------------------------------------------------------------------------- */
void NodeGroup::clear() { node_group.resize(0); }
/* -------------------------------------------------------------------------- */
// bool NodeGroup::empty() { return node_group.empty(); }
/* -------------------------------------------------------------------------- */
void NodeGroup::optimize() {
std::sort(node_group.begin(), node_group.end());
- Array<UInt>::iterator<> end =
- std::unique(node_group.begin(), node_group.end());
+ auto end = std::unique(node_group.begin(), node_group.end());
node_group.resize(end - node_group.begin());
}
/* -------------------------------------------------------------------------- */
void NodeGroup::append(const NodeGroup & other_group) {
AKANTU_DEBUG_IN();
- UInt nb_nodes = node_group.size();
+ auto nb_nodes = node_group.size();
/// append new nodes to current list
node_group.resize(nb_nodes + other_group.node_group.size());
std::copy(other_group.node_group.begin(), other_group.node_group.end(),
node_group.begin() + nb_nodes);
optimize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NodeGroup::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "NodeGroup [" << std::endl;
stream << space << " + name: " << name << std::endl;
node_group.printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
} // namespace akantu
diff --git a/src/mesh/node_group.hh b/src/mesh/node_group.hh
index 98afddd7e..2afefc671 100644
--- a/src/mesh/node_group.hh
+++ b/src/mesh/node_group.hh
@@ -1,134 +1,135 @@
/**
* @file node_group.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Node group definition
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "dumpable.hh"
#include "mesh_filter.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NODE_GROUP_HH_
#define AKANTU_NODE_GROUP_HH_
namespace akantu {
class NodeGroup : public Dumpable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NodeGroup(const std::string & name, const Mesh & mesh,
const std::string & id = "node_group");
~NodeGroup() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- using const_node_iterator = Array<UInt>::const_iterator<UInt>;
+ using const_node_iterator = Array<Idx>::const_scalar_iterator;
/// empty the node group
void clear();
/// returns treu if the group is empty \warning this changed beahavior if you
/// want to empty the group use clear
bool empty() const __attribute__((warn_unused_result));
/// iterator to the beginning of the node group
- inline const_node_iterator begin() const;
+ inline auto begin() const;
/// iterator to the end of the node group
- inline const_node_iterator end() const;
+ inline auto end() const;
+
/// add a node and give the local position through an iterator
- inline const_node_iterator add(UInt node, bool check_for_duplicate = true);
+ inline auto add(Idx node, bool check_for_duplicate = true);
/// remove a node
- inline void remove(UInt node);
+ inline void remove(Idx node);
- inline decltype(auto) find(UInt node) const { return node_group.find(node); }
+ inline decltype(auto) find(Idx node) const { return node_group.find(node); }
/// remove duplicated nodes
void optimize();
/// append a group to current one
void append(const NodeGroup & other_group);
/// apply a filter on current node group
template <typename T> void applyNodeFilter(T & filter);
/// function to print the contain of the class
virtual void printself(std::ostream & stream, int indent = 0) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO_NOT_CONST(Nodes, node_group, Array<UInt> &);
- AKANTU_GET_MACRO(Nodes, node_group, const Array<UInt> &);
- AKANTU_GET_MACRO(Name, name, const std::string &);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Nodes, node_group);
+ AKANTU_GET_MACRO_AUTO(Nodes, node_group);
+ AKANTU_GET_MACRO_AUTO(Name, name);
/// give the number of nodes in the current group
- inline UInt size() const;
+ inline Idx size() const;
- // UInt * storage() { return node_group.storage(); };
+ // UInt * storage() { return node_group.data(); };
friend class GroupManager;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// name of the group
std::string name;
/// list of nodes in the group
- Array<UInt> node_group;
+ Array<Idx> node_group;
/// reference to the mesh in question
// const Mesh & mesh;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const NodeGroup & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "node_group_inline_impl.hh"
#endif /* AKANTU_NODE_GROUP_HH_ */
diff --git a/src/mesh/node_group_inline_impl.hh b/src/mesh/node_group_inline_impl.hh
index d933608a9..754590db5 100644
--- a/src/mesh/node_group_inline_impl.hh
+++ b/src/mesh/node_group_inline_impl.hh
@@ -1,102 +1,97 @@
/**
* @file node_group_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Dec 09 2020
*
* @brief Node group inline function definitions
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
/* -------------------------------------------------------------------------- */
+#include "node_group.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline NodeGroup::const_node_iterator NodeGroup::begin() const {
- return node_group.begin();
-}
+inline auto NodeGroup::begin() const { return node_group.begin(); }
/* -------------------------------------------------------------------------- */
-inline NodeGroup::const_node_iterator NodeGroup::end() const {
- return node_group.end();
-}
+inline auto NodeGroup::end() const { return node_group.end(); }
/* -------------------------------------------------------------------------- */
-inline NodeGroup::const_node_iterator NodeGroup::add(UInt node,
- bool check_for_duplicate) {
+inline auto NodeGroup::add(Idx node, bool check_for_duplicate) {
+ const_node_iterator it;
if (check_for_duplicate) {
- const_node_iterator it = std::find(begin(), end(), node);
- if (it == node_group.end()) {
- node_group.push_back(node);
- return (node_group.end() - 1);
+ it = std::find(begin(), end(), node);
+ if (it != node_group.end()) {
+ return it;
}
- return it;
}
node_group.push_back(node);
- return (node_group.end() - 1);
+ it = (node_group.end() - 1);
+ return it;
}
/* -------------------------------------------------------------------------- */
-inline void NodeGroup::remove(UInt node) {
- Array<UInt>::iterator<> it = this->node_group.begin();
- Array<UInt>::iterator<> end = this->node_group.end();
+inline void NodeGroup::remove(Idx node) {
+ auto it = this->node_group.begin();
+ auto end = this->node_group.end();
AKANTU_DEBUG_ASSERT(it != end, "The node group is empty!!");
for (; it != node_group.end(); ++it) {
if (*it == node) {
it = node_group.erase(it);
}
}
AKANTU_DEBUG_ASSERT(it != end, "The node was not found!");
}
/* -------------------------------------------------------------------------- */
inline bool NodeGroup::empty() const { return node_group.empty(); }
/* -------------------------------------------------------------------------- */
-inline UInt NodeGroup::size() const { return node_group.size(); }
+inline Int NodeGroup::size() const { return node_group.size(); }
/* -------------------------------------------------------------------------- */
struct FilterFunctor;
template <typename T> void NodeGroup::applyNodeFilter(T & filter) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(T::type == FilterFunctor::_node_filter_functor,
"NodeFilter can only apply node filter functor");
- Array<UInt>::iterator<> it = this->node_group.begin();
+ auto it = this->node_group.begin();
for (; it != node_group.end(); ++it) {
/// filter == true -> keep node
if (!filter(*it)) {
it = node_group.erase(it);
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/mesh_utils/boost_graph_converter.cc b/src/mesh_utils/boost_graph_converter.cc
new file mode 100644
index 000000000..dd481ebaf
--- /dev/null
+++ b/src/mesh_utils/boost_graph_converter.cc
@@ -0,0 +1,111 @@
+#include "boost_graph_converter.hh"
+#include "mesh.hh"
+#include "mesh_iterators.hh"
+/* -------------------------------------------------------------------------- */
+#include <boost/graph/graphviz.hpp>
+#include <map>
+/* -------------------------------------------------------------------------- */
+
+namespace akantu {
+
+BoostGraphConverter::BoostGraphConverter(const Mesh & mesh) {
+ // adding all vertices
+ auto add_vertex = [&](auto element) {
+ auto && vertex = boost::add_vertex(this->graph);
+ element_to_vertex[element] = vertex;
+ vertex_to_element[vertex] = element;
+ };
+
+ // add_vertex(ElementNull);
+
+ auto && mesh_facets = mesh.getMeshFacets();
+
+ for_each_element(
+ mesh, [&](auto && element) { add_vertex(element); },
+ _element_kind = _ek_regular);
+ for_each_element(
+ mesh_facets, [&](auto && element) { add_vertex(element); },
+ _spatial_dimension = _all_dimensions);
+ for_each_element(
+ mesh, [&](auto && element) { add_vertex(element); },
+ _element_kind = _ek_cohesive);
+
+ auto get_vertex = [&](auto && element) {
+ if (element == ElementNull) {
+ return -1;
+ }
+
+ auto it = element_to_vertex.find(element);
+ if (it == element_to_vertex.end()) {
+ AKANTU_EXCEPTION("Element " << element << " not in element to vertex");
+ }
+ return it->second;
+ };
+
+ auto add_edge = [&](auto && element1, auto && element2,
+ EdgeType type = _none) {
+ auto vertex1 = get_vertex(element1);
+ auto vertex2 = get_vertex(element2);
+
+ if (vertex1 == -1 or vertex2 == -1) {
+ return;
+ }
+
+ // std::cout << element1 << " -> " << element2 << " " << type << std::endl;
+ auto && data = boost::add_edge(vertex1, vertex2, graph);
+ edge_type[data.first] = type;
+ };
+
+ auto add_neighbors = [&](auto && element) {
+ const auto & element_facets =
+ mesh_facets.getSubelementToElement().get(element);
+ for (auto && facet : element_facets) {
+ add_edge(element, facet, _up);
+ const auto & connected_elements_to_facets =
+ const_cast<const Mesh &>(mesh_facets).getElementToSubelement(facet);
+ for (auto && celement : connected_elements_to_facets) {
+ add_edge(facet, celement, _down);
+ }
+ }
+ };
+ // adding edges
+ for_each_element(mesh, add_neighbors, _element_kind = _ek_regular);
+ for (auto s : arange(1, mesh.getSpatialDimension())) {
+ for_each_element(mesh_facets, add_neighbors, _spatial_dimension = s);
+ }
+ for_each_element(mesh, add_neighbors, _element_kind = _ek_cohesive);
+}
+
+void BoostGraphConverter::toGraphviz(const std::string & filename) const {
+ std::ofstream fout;
+ fout.open(filename);
+
+ boost::write_graphviz(
+ fout, graph,
+ [&](std::ostream & out, vertex_descriptor vertex) {
+ auto it = vertex_to_element.find(vertex);
+ if (it == vertex_to_element.end()) {
+ return;
+ }
+
+ auto && element = it->second;
+ std::array<std::string, 4> colors{"gold", "cadetblue1", "coral1",
+ "antiquewhite2"};
+
+ std::string color{"deeppink4"}, bgcolor{"deeppink4"};
+ if (element != ElementNull) {
+ color = bgcolor = colors[Mesh::getSpatialDimension(element.type)];
+ }
+
+ out << "[label=\"" << std::to_string(element)
+ << "\", bgcolor=" << bgcolor << ", color=" << color << "]";
+ },
+ [&](std::ostream & out, edge_descriptor edge) {
+ auto && type = edge_type.at(edge);
+ std::map<EdgeType, std::string> colors{
+ {_none, "black"}, {_up, "darkorange"}, {_down, "blue2"}};
+ out << "[color=" << colors[type] << "]";
+ });
+}
+
+} // namespace akantu
diff --git a/src/mesh_utils/boost_graph_converter.hh b/src/mesh_utils/boost_graph_converter.hh
new file mode 100644
index 000000000..50f106848
--- /dev/null
+++ b/src/mesh_utils/boost_graph_converter.hh
@@ -0,0 +1,58 @@
+#ifndef AKANTU_BOOST_GRAPH_CONVERTER_HH_
+#define AKANTU_BOOST_GRAPH_CONVERTER_HH_
+
+/* -------------------------------------------------------------------------- */
+#include "element.hh"
+/* -------------------------------------------------------------------------- */
+#include <boost/graph/adjacency_list.hpp>
+#include <map>
+#include <unordered_map>
+/* -------------------------------------------------------------------------- */
+
+namespace akantu {
+class Mesh;
+} // namespace akantu
+
+namespace akantu {
+
+class BoostGraphConverter {
+ /* ------------------------------------------------------------------------ */
+ /* Constructors/Destructors */
+ /* ------------------------------------------------------------------------ */
+public:
+ BoostGraphConverter(const Mesh & mesh);
+
+ /* ------------------------------------------------------------------------ */
+ /* Methods */
+ /* ------------------------------------------------------------------------ */
+public:
+ void toGraphviz(const std::string & filename) const;
+
+ /* ------------------------------------------------------------------------ */
+ /* Class Members */
+ /* ------------------------------------------------------------------------ */
+private:
+ enum EdgeType {
+ _none,
+ _up,
+ _down,
+ };
+
+ using Graph = boost::adjacency_list<>;
+
+ using vertex_descriptor = boost::graph_traits<Graph>::vertex_descriptor;
+ using edge_descriptor = boost::graph_traits<Graph>::edge_descriptor;
+
+ using VertexInfo = std::map<vertex_descriptor, Element>;
+ using EdgeInfo = std::map<edge_descriptor, EdgeType>;
+
+ Graph graph;
+ std::map<Element, Int> element_to_vertex;
+
+ VertexInfo vertex_to_element;
+ EdgeInfo edge_type;
+};
+
+} // namespace akantu
+
+#endif // AKANTU_BOOST_GRAPH_CONVERTER_HH_
diff --git a/src/mesh_utils/cohesive_element_inserter.cc b/src/mesh_utils/cohesive_element_inserter.cc
index a0e122d75..e73bb328a 100644
--- a/src/mesh_utils/cohesive_element_inserter.cc
+++ b/src/mesh_utils/cohesive_element_inserter.cc
@@ -1,328 +1,328 @@
/**
* @file cohesive_element_inserter.cc
*
* @author Mathias Lebihain <mathias.lebihain@enpc.fr>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Dec 04 2013
* @date last modification: Wed Nov 11 2020
*
* @brief Cohesive element inserter functions
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "cohesive_element_inserter.hh"
#include "cohesive_element_inserter_helper.hh"
#include "communicator.hh"
#include "element_group.hh"
#include "element_synchronizer.hh"
#include "global_ids_updater.hh"
#include "mesh_accessor.hh"
#include "mesh_iterators.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <limits>
/* -------------------------------------------------------------------------- */
namespace akantu {
CohesiveElementInserter::CohesiveElementInserter(Mesh & mesh, const ID & id)
: Parsable(ParserType::_cohesive_inserter), id(id), mesh(mesh),
mesh_facets(mesh.initMeshFacets()),
insertion_facets("insertion_facets", id),
insertion_limits(mesh.getSpatialDimension(), 2),
check_facets("check_facets", id) {
this->registerParam("cohesive_surfaces", physical_surfaces, _pat_parsable,
"List of groups to consider for insertion");
this->registerParam("cohesive_zones", physical_zones, _pat_parsable,
"List of groups to consider for insertion");
this->registerParam("bounding_box", insertion_limits, _pat_parsable,
"Global limit for insertion");
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
/// init insertion limits
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
insertion_limits(dim, 0) = std::numeric_limits<Real>::max() * Real(-1.);
insertion_limits(dim, 1) = std::numeric_limits<Real>::max();
}
insertion_facets.initialize(mesh_facets,
_spatial_dimension = spatial_dimension - 1,
_with_nb_element = true, _default_value = false);
}
/* -------------------------------------------------------------------------- */
CohesiveElementInserter::~CohesiveElementInserter() = default;
/* -------------------------------------------------------------------------- */
void CohesiveElementInserter::parseSection(const ParserSection & section) {
Parsable::parseSection(section);
if (is_extrinsic) {
limitCheckFacets(this->check_facets);
}
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserter::limitCheckFacets() {
limitCheckFacets(this->check_facets);
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserter::setLimit(SpatialDirection axis, Real first_limit,
Real second_limit) {
AKANTU_DEBUG_ASSERT(
axis < mesh.getSpatialDimension(),
"You are trying to limit insertion in a direction that doesn't exist");
insertion_limits(axis, 0) = std::min(first_limit, second_limit);
insertion_limits(axis, 1) = std::max(first_limit, second_limit);
}
/* -------------------------------------------------------------------------- */
-UInt CohesiveElementInserter::insertIntrinsicElements() {
+Int CohesiveElementInserter::insertIntrinsicElements() {
limitCheckFacets(insertion_facets);
return insertElements();
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserter::limitCheckFacets(
ElementTypeMapArray<bool> & check_facets) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
check_facets.initialize(mesh_facets,
_spatial_dimension = spatial_dimension - 1,
_with_nb_element = true, _default_value = true);
check_facets.set(true);
// remove the pure ghost elements
for_each_element(
mesh_facets,
[&](auto && facet) {
const auto & element_to_facet = mesh_facets.getElementToSubelement(
facet.type, facet.ghost_type)(facet.element);
auto & left = element_to_facet[0];
auto & right = element_to_facet[1];
if (right == ElementNull ||
(left.ghost_type == _ghost && right.ghost_type == _ghost)) {
check_facets(facet) = false;
return;
}
#ifndef AKANTU_NDEBUG
if (left == ElementNull) {
AKANTU_DEBUG_WARNING("By convention element should not have "
"ElementNull on there first side: "
<< facet);
}
#endif
if (left.kind() == _ek_cohesive or right.kind() == _ek_cohesive) {
check_facets(facet) = false;
}
},
_spatial_dimension = spatial_dimension - 1);
auto tolerance = Math::getTolerance();
Vector<Real> bary_facet(spatial_dimension);
// set the limits to the bounding box
for_each_element(
mesh_facets,
[&](auto && facet) {
auto & need_check = check_facets(facet);
if (not need_check) {
return;
}
mesh_facets.getBarycenter(facet, bary_facet);
- UInt coord_in_limit = 0;
+ Int coord_in_limit = 0;
while (coord_in_limit < spatial_dimension and
bary_facet(coord_in_limit) >
(insertion_limits(coord_in_limit, 0) - tolerance) and
bary_facet(coord_in_limit) <
(insertion_limits(coord_in_limit, 1) + tolerance)) {
++coord_in_limit;
}
if (coord_in_limit != spatial_dimension) {
need_check = false;
}
},
_spatial_dimension = spatial_dimension - 1);
// remove the physical zones
if (mesh.hasData("physical_names") and not physical_zones.empty()) {
auto && physical_names = mesh.getData<std::string>("physical_names");
for_each_element(
mesh_facets,
[&](auto && facet) {
const auto & element_to_facet = mesh_facets.getElementToSubelement(
facet.type, facet.ghost_type)(facet.element);
auto count = 0;
for (auto i : arange(2)) {
const auto & element = element_to_facet[i];
if (element == ElementNull) {
continue;
}
const auto & name = physical_names(element);
count += find(physical_zones.begin(), physical_zones.end(), name) !=
physical_zones.end();
}
if (count != 2) {
check_facets(facet) = false;
}
},
_spatial_dimension = spatial_dimension - 1);
}
if (physical_surfaces.empty()) {
AKANTU_DEBUG_OUT();
return;
}
if (not mesh_facets.hasData("physical_names")) {
AKANTU_DEBUG_ASSERT(
physical_surfaces.empty(),
"No physical names in the mesh but insertion limited to a group");
AKANTU_DEBUG_OUT();
return;
}
const auto & physical_ids =
mesh_facets.getData<std::string>("physical_names");
// set the limits to the physical surfaces
for_each_element(
mesh_facets,
[&](auto && facet) {
auto & need_check = check_facets(facet, 0);
if (not need_check) {
return;
}
const auto & physical_id = physical_ids(facet);
auto it = find(physical_surfaces.begin(), physical_surfaces.end(),
physical_id);
need_check = (it != physical_surfaces.end());
},
_spatial_dimension = spatial_dimension - 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
UInt CohesiveElementInserter::insertElements(bool only_double_facets) {
CohesiveNewNodesEvent node_event(AKANTU_CURRENT_FUNCTION);
NewElementsEvent element_event(AKANTU_CURRENT_FUNCTION);
if (mesh_facets.isDistributed()) {
mesh_facets.getElementSynchronizer().synchronizeOnce(
*this, SynchronizationTag::_ce_groups);
}
CohesiveElementInserterHelper cohesive_element_inserter_helper(
mesh, insertion_facets);
UInt nb_new_elements{0};
if (only_double_facets) {
nb_new_elements = cohesive_element_inserter_helper.insertFacetsOnly();
} else {
nb_new_elements = cohesive_element_inserter_helper.insertCohesiveElement();
element_event.getList().copy(
cohesive_element_inserter_helper.getNewElements());
}
auto && doubled_nodes = cohesive_element_inserter_helper.getDoubledNodes();
auto nb_new_nodes = doubled_nodes.size();
node_event.getList().reserve(nb_new_nodes);
node_event.getOldNodesList().reserve(nb_new_nodes);
for (auto && doubled_node : make_view(doubled_nodes, 2)) {
node_event.getList().push_back(doubled_node(1));
node_event.getOldNodesList().push_back(doubled_node(0));
}
if (nb_new_elements > 0) {
updateInsertionFacets();
}
MeshAccessor mesh_accessor(mesh);
std::tie(nb_new_nodes, nb_new_elements) =
mesh_accessor.updateGlobalData(node_event, element_event);
return nb_new_elements;
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserter::updateInsertionFacets() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
for (auto && facet_gt : ghost_types) {
for (auto && facet_type :
mesh_facets.elementTypes(spatial_dimension - 1, facet_gt)) {
auto & ins_facets = insertion_facets(facet_type, facet_gt);
// this is the intrinsic case
if (not is_extrinsic) {
continue;
}
auto & f_check = check_facets(facet_type, facet_gt);
for (auto && pair : zip(ins_facets, f_check)) {
bool & ins = std::get<0>(pair);
bool & check = std::get<1>(pair);
if (ins) {
ins = check = false;
}
}
}
}
// resize for the newly added facets
insertion_facets.initialize(mesh_facets,
_spatial_dimension = spatial_dimension - 1,
_with_nb_element = true, _default_value = false);
// resize for the newly added facets
if (is_extrinsic) {
check_facets.initialize(mesh_facets,
_spatial_dimension = spatial_dimension - 1,
_with_nb_element = true, _default_value = false);
} else {
insertion_facets.set(false);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/mesh_utils/cohesive_element_inserter.hh b/src/mesh_utils/cohesive_element_inserter.hh
index 3ca856ceb..3d5995c03 100644
--- a/src/mesh_utils/cohesive_element_inserter.hh
+++ b/src/mesh_utils/cohesive_element_inserter.hh
@@ -1,181 +1,181 @@
/**
* @file cohesive_element_inserter.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Dec 04 2013
* @date last modification: Tue Jul 21 2020
*
* @brief Cohesive element inserter
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "data_accessor.hh"
#include "mesh_utils.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
#include <numeric>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COHESIVE_ELEMENT_INSERTER_HH_
#define AKANTU_COHESIVE_ELEMENT_INSERTER_HH_
namespace akantu {
class GlobalIdsUpdater;
class FacetSynchronizer;
class SolidMechanicsModeslCohesivel;
} // namespace akantu
namespace akantu {
class CohesiveElementInserter : public DataAccessor<Element>, public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
CohesiveElementInserter(Mesh & mesh,
const ID & id = "cohesive_element_inserter");
~CohesiveElementInserter() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// set range limitation for intrinsic cohesive element insertion
void setLimit(SpatialDirection axis, Real first_limit, Real second_limit);
/// insert intrinsic cohesive elements in a predefined range
- auto insertIntrinsicElements() -> UInt;
+ Int insertIntrinsicElements();
/// insert extrinsic cohesive elements (returns the number of new
/// cohesive elements)
UInt insertElements(bool only_double_facets = false);
/// limit check facets to match given insertion limits
void limitCheckFacets();
/// limit insertion to the surfaces
void addPhysicalSurface(const ID & surface_name);
/// limit insertion to the volumes
void addPhysicalVolume(const ID & surface_name);
protected:
void parseSection(const ParserSection & section) override;
protected:
/// internal version of limitCheckFacets
void limitCheckFacets(ElementTypeMapArray<bool> & check_facets);
/// update facet insertion arrays after facets doubling
void updateInsertionFacets();
/// functions for parallel communications
- inline UInt getNbData(const Array<Element> & elements,
+ inline Int getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO_NOT_CONST(InsertionFacetsByElement, insertion_facets,
ElementTypeMapArray<bool> &);
AKANTU_GET_MACRO(InsertionFacetsByElement, insertion_facets,
const ElementTypeMapArray<bool> &);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE(InsertionFacets, insertion_facets, bool);
AKANTU_GET_MACRO(CheckFacets, check_facets,
const ElementTypeMapArray<bool> &);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE(CheckFacets, check_facets, bool);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(CheckFacets, check_facets, bool);
AKANTU_GET_MACRO(MeshFacets, mesh_facets, const Mesh &);
AKANTU_GET_MACRO_NOT_CONST(MeshFacets, mesh_facets, Mesh &);
AKANTU_SET_MACRO(IsExtrinsic, is_extrinsic, bool);
public:
friend class SolidMechanicsModelCohesive;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// object id
ID id;
/// main mesh where to insert cohesive elements
Mesh & mesh;
/// mesh containing facets
Mesh & mesh_facets;
/// list of facets where to insert elements
ElementTypeMapArray<bool> insertion_facets;
/// limits for element insertion
Matrix<Real> insertion_limits;
/// list of groups to consider for insertion, ignored if empty
std::set<ID> physical_surfaces;
/// list of groups in between which an inside which element are insterted
std::set<ID> physical_zones;
/// vector containing facets in which extrinsic cohesive elements can be
/// inserted
ElementTypeMapArray<bool> check_facets;
/// global connectivity ids updater
std::unique_ptr<GlobalIdsUpdater> global_ids_updater;
/// is this inserter used in extrinsic
bool is_extrinsic{false};
};
class CohesiveNewNodesEvent : public NewNodesEvent {
public:
CohesiveNewNodesEvent(const std::string & origin) : NewNodesEvent(origin) {}
~CohesiveNewNodesEvent() override = default;
- AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &);
- AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &);
+ AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<Idx> &);
+ AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<Idx> &);
private:
- Array<UInt> old_nodes;
+ Array<Idx> old_nodes;
};
} // namespace akantu
#include "cohesive_element_inserter_inline_impl.hh"
#endif /* AKANTU_COHESIVE_ELEMENT_INSERTER_HH_ */
diff --git a/src/mesh_utils/cohesive_element_inserter_helper.cc b/src/mesh_utils/cohesive_element_inserter_helper.cc
index 0ebd97ef5..dcd64aee5 100644
--- a/src/mesh_utils/cohesive_element_inserter_helper.cc
+++ b/src/mesh_utils/cohesive_element_inserter_helper.cc
@@ -1,952 +1,947 @@
/**
* @file cohesive_element_inserter_helper.cc
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 08 2020
* @date last modification: Wed Dec 23 2020
*
* @brief An helper class to handle cohesive element insertion
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "cohesive_element_inserter_helper.hh"
/* -------------------------------------------------------------------------- */
#include "data_accessor.hh"
#include "element_synchronizer.hh"
#include "fe_engine.hh"
#include "mesh_accessor.hh"
/* -------------------------------------------------------------------------- */
#include <queue>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
CohesiveElementInserterHelper::CohesiveElementInserterHelper(
Mesh & mesh, const ElementTypeMapArray<bool> & facet_insertion)
: doubled_nodes(0, 2, "doubled_nodes"), mesh(mesh),
mesh_facets(mesh.getMeshFacets()) {
auto spatial_dimension = mesh_facets.getSpatialDimension();
for (auto gt : ghost_types) {
for (auto type : mesh_facets.elementTypes(_ghost_type = gt)) {
nb_new_facets(type, gt) = mesh_facets.getNbElement(type, gt);
}
}
std::array<Int, 2> nb_facet_to_insert{0, 0};
// creates a vector of the facets to insert
std::vector<Element> potential_facets_to_double;
for (auto gt_facet : ghost_types) {
for (auto type_facet :
mesh_facets.elementTypes(spatial_dimension - 1, gt_facet)) {
const auto & f_insertion = facet_insertion(type_facet, gt_facet);
auto & counter = nb_facet_to_insert[gt_facet == _not_ghost ? 0 : 1];
for (auto && data : enumerate(f_insertion)) {
if (std::get<1>(data)) {
- UInt el = std::get<0>(data);
+ auto el = std::get<0>(data);
potential_facets_to_double.push_back({type_facet, el, gt_facet});
++counter;
}
}
}
}
- // Defines a global order of insertion oof cohesive element to ensure node
- // doubling appens in the smae order, this is necessary for the global node
+ // Defines a global order of insertion of cohesive element to ensure node
+ // doubling happens in the same order, this is necessary for the global node
// numbering
if (mesh_facets.isDistributed()) {
const auto & comm = mesh_facets.getCommunicator();
ElementTypeMapArray<Int> global_orderings;
global_orderings.initialize(mesh_facets,
_spatial_dimension = spatial_dimension - 1,
_with_nb_element = true, _default_value = -1);
auto starting_index = nb_facet_to_insert[0];
comm.exclusiveScan(starting_index);
// define the local numbers for facet to insert
for (auto gt_facet : ghost_types) {
for (auto type_facet :
mesh_facets.elementTypes(spatial_dimension - 1, gt_facet)) {
for (auto data : zip(facet_insertion(type_facet, gt_facet),
global_orderings(type_facet, gt_facet))) {
if (std::get<0>(data)) {
std::get<1>(data) = starting_index;
++starting_index;
}
}
}
}
- // retreives the oorder number from neighoring processors
+ // retrieves the order number from neighboring processors
auto && synchronizer = mesh_facets.getElementSynchronizer();
SimpleElementDataAccessor<Int> data_accessor(
global_orderings, SynchronizationTag::_ce_insertion_order);
synchronizer.synchronizeOnce(data_accessor,
SynchronizationTag::_ce_insertion_order);
// sort the facets to double based on this global ordering
std::sort(potential_facets_to_double.begin(),
potential_facets_to_double.end(),
[&global_orderings](auto && el1, auto && el2) {
return global_orderings(el1) < global_orderings(el2);
});
}
for (auto d : arange(spatial_dimension)) {
facets_to_double_by_dim[d] = std::make_unique<Array<Element>>(
0, 2, "facets_to_double_" + std::to_string(d));
}
auto & facets_to_double = *facets_to_double_by_dim[spatial_dimension - 1];
MeshAccessor mesh_accessor(mesh_facets);
auto & elements_to_subelements = mesh_accessor.getElementToSubelement();
for (auto && facet_to_double : potential_facets_to_double) {
auto gt_facet = facet_to_double.ghost_type;
auto type_facet = facet_to_double.type;
auto & elements_to_facets = elements_to_subelements(type_facet, gt_facet);
-
auto & elements_to_facet = elements_to_facets(facet_to_double.element);
+
if (elements_to_facet[1].type == _not_defined
#if defined(AKANTU_COHESIVE_ELEMENT)
|| elements_to_facet[1].kind() == _ek_cohesive
#endif
) {
AKANTU_DEBUG_WARNING("attempt to double a facet on the boundary");
continue;
}
auto new_facet = nb_new_facets(type_facet, gt_facet)++;
facets_to_double.push_back(Vector<Element>{
- facet_to_double, Element{type_facet, new_facet, gt_facet}});
+ {facet_to_double, Element{type_facet, new_facet, gt_facet}}});
/// update facet_to_element vector
auto & element_to_update = elements_to_facet[1];
auto el = element_to_update.element;
const auto & facets_to_elements = mesh_facets.getSubelementToElement(
element_to_update.type, element_to_update.ghost_type);
- auto facets_to_element = Vector<Element>(
+ auto facets_to_element =
make_view(facets_to_elements, facets_to_elements.getNbComponent())
- .begin()[el]);
+ .begin()[el];
auto facet_to_update = std::find(facets_to_element.begin(),
facets_to_element.end(), facet_to_double);
AKANTU_DEBUG_ASSERT(facet_to_update != facets_to_element.end(),
"Facet not found");
facet_to_update->element = new_facet;
/// update elements connected to facet
const auto & first_facet_list = elements_to_facet;
elements_to_facets.push_back(first_facet_list);
/// set new and original facets as boundary facets
elements_to_facets(new_facet)[0] = elements_to_facets(new_facet)[1];
elements_to_facets(new_facet)[1] = ElementNull;
elements_to_facets(facet_to_double.element)[1] = ElementNull;
}
}
/* -------------------------------------------------------------------------- */
inline auto
-CohesiveElementInserterHelper::hasElement(const Vector<UInt> & nodes_element,
- const Vector<UInt> & nodes) -> bool {
+CohesiveElementInserterHelper::hasElement(const Vector<Idx> & nodes_element,
+ const Vector<Idx> & nodes) -> bool {
// if one of the nodes of "nodes" is not in "nodes_element" it stops
auto it = std::mismatch(nodes.begin(), nodes.end(), nodes_element.begin(),
[&](auto && node, auto && /*node2*/) -> bool {
auto it = std::find(nodes_element.begin(),
nodes_element.end(), node);
return (it != nodes_element.end());
});
// true if all "nodes" where found in "nodes_element"
return (it.first == nodes.end());
}
/* -------------------------------------------------------------------------- */
inline auto CohesiveElementInserterHelper::removeElementsInVector(
const std::vector<Element> & elem_to_remove,
std::vector<Element> & elem_list) -> bool {
if (elem_list.size() <= elem_to_remove.size()) {
return true;
}
auto el_it = elem_to_remove.begin();
auto el_last = elem_to_remove.end();
std::vector<Element>::iterator el_del;
UInt deletions = 0;
for (; el_it != el_last; ++el_it) {
el_del = std::find(elem_list.begin(), elem_list.end(), *el_it);
if (el_del != elem_list.end()) {
elem_list.erase(el_del);
++deletions;
}
}
AKANTU_DEBUG_ASSERT(deletions == 0 || deletions == elem_to_remove.size(),
"Not all elements have been erased");
return deletions == 0;
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserterHelper::updateElementalConnectivity(
- Mesh & mesh, UInt old_node, UInt new_node,
+ Mesh & mesh, Idx old_node, Idx new_node,
const std::vector<Element> & element_list,
const std::vector<Element> * facet_list) {
AKANTU_DEBUG_IN();
for (const auto & element : element_list) {
if (element.type == _not_defined) {
continue;
}
- Vector<UInt> connectivity = mesh.getConnectivity(element);
+ auto && connectivity = mesh.getConnectivity(element);
if (element.kind() == _ek_cohesive) {
AKANTU_DEBUG_ASSERT(
facet_list != nullptr,
"Provide a facet list in order to update cohesive elements");
- const Vector<Element> facets =
- mesh_facets.getSubelementToElement(element);
+ auto && facets = mesh_facets.getSubelementToElement(element);
auto facet_nb_nodes = connectivity.size() / 2;
/// loop over cohesive element's facets
for (const auto & facet : enumerate(facets)) {
/// skip facets if not present in the list
if (std::find(facet_list->begin(), facet_list->end(),
std::get<1>(facet)) == facet_list->end()) {
continue;
}
auto n = std::get<0>(facet);
auto begin =
connectivity.begin() + static_cast<UInt>(n * facet_nb_nodes);
auto end = begin + facet_nb_nodes;
auto it = std::find(begin, end, old_node);
AKANTU_DEBUG_ASSERT(it != end, "Node not found in current element");
*it = new_node;
}
} else {
auto it = std::find(connectivity.begin(), connectivity.end(), old_node);
AKANTU_DEBUG_ASSERT(it != connectivity.end(),
"Node not found in current element");
/// update connectivity
*it = new_node;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void CohesiveElementInserterHelper::updateSubelementToElement(UInt dim,
+void CohesiveElementInserterHelper::updateSubelementToElement(Int dim,
bool facet_mode) {
auto & facets_to_double = *facets_to_double_by_dim[dim];
auto & facets_to_subfacets = elementsOfDimToElementsOfDim(
dim + static_cast<decltype(dim)>(facet_mode), dim);
for (auto && data :
zip(make_view(facets_to_double, 2), facets_to_subfacets)) {
const auto & old_subfacet = std::get<0>(data)[0];
const auto & new_subfacet = std::get<0>(data)[1];
auto & facet_to_subfacets = std::get<1>(data);
MeshAccessor mesh_accessor(mesh_facets);
for (auto & facet : facet_to_subfacets) {
- Vector<Element> subfacets = mesh_accessor.getSubelementToElement(facet);
+ auto && subfacets = mesh_accessor.getSubelementToElement(facet);
auto && subfacet_to_update_it =
std::find(subfacets.begin(), subfacets.end(), old_subfacet);
AKANTU_DEBUG_ASSERT(subfacet_to_update_it != subfacets.end(),
"Subfacet not found");
*subfacet_to_update_it = new_subfacet;
}
}
}
/* -------------------------------------------------------------------------- */
-void CohesiveElementInserterHelper::updateElementToSubelement(UInt dim,
+void CohesiveElementInserterHelper::updateElementToSubelement(Int dim,
bool facet_mode) {
auto & facets_to_double = *facets_to_double_by_dim[dim];
auto & facets_to_subfacets = elementsOfDimToElementsOfDim(
dim + static_cast<decltype(dim)>(facet_mode), dim);
MeshAccessor mesh_accessor(mesh_facets);
// resize the arrays
mesh_accessor.getElementToSubelement().initialize(
mesh_facets, _spatial_dimension = dim, _with_nb_element = true);
for (auto && data :
zip(make_view(facets_to_double, 2), facets_to_subfacets)) {
const auto & new_facet = std::get<0>(data)[1];
mesh_accessor.getElementToSubelement(new_facet) = std::get<1>(data);
}
}
/* -------------------------------------------------------------------------- */
-void CohesiveElementInserterHelper::updateQuadraticSegments(UInt dim) {
+void CohesiveElementInserterHelper::updateQuadraticSegments(Int dim) {
AKANTU_DEBUG_IN();
auto spatial_dimension = mesh.getSpatialDimension();
auto & facets_to_double = *facets_to_double_by_dim[dim];
MeshAccessor mesh_accessor(mesh_facets);
auto & connectivities = mesh_accessor.getConnectivities();
/// this ones matter only for segments in 3D
Array<std::vector<Element>> * element_to_subfacet_double = nullptr;
Array<std::vector<Element>> * facet_to_subfacet_double = nullptr;
if (dim == spatial_dimension - 2) {
element_to_subfacet_double = &elementsOfDimToElementsOfDim(dim + 2, dim);
facet_to_subfacet_double = &elementsOfDimToElementsOfDim(dim + 1, dim);
}
const auto & element_to_subelement = mesh_facets.getElementToSubelement();
- std::vector<UInt> middle_nodes;
+ std::vector<Int> middle_nodes;
for (auto && facet_to_double : make_view(facets_to_double, 2)) {
auto & old_facet = facet_to_double[0];
if (old_facet.type != _segment_3) {
continue;
}
auto node = connectivities(old_facet, 2);
if (not mesh.isPureGhostNode(node)) {
middle_nodes.push_back(node);
}
}
auto n = doubled_nodes.size();
doubleNodes(middle_nodes);
for (auto && data : enumerate(make_view(facets_to_double, 2))) {
auto facet = std::get<0>(data);
auto & old_facet = std::get<1>(data)[0];
if (old_facet.type != _segment_3) {
continue;
}
auto old_node = connectivities(old_facet, 2);
if (mesh.isPureGhostNode(old_node)) {
continue;
}
auto new_node = doubled_nodes(n, 1);
auto & new_facet = std::get<1>(data)[1];
connectivities(new_facet, 2) = new_node;
if (dim == spatial_dimension - 2) {
updateElementalConnectivity(mesh_facets, old_node, new_node,
element_to_subelement(new_facet, 0));
updateElementalConnectivity(mesh, old_node, new_node,
(*element_to_subfacet_double)(facet),
&(*facet_to_subfacet_double)(facet));
} else {
updateElementalConnectivity(mesh, old_node, new_node,
element_to_subelement(new_facet, 0));
}
++n;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-UInt CohesiveElementInserterHelper::insertCohesiveElement() {
+Int CohesiveElementInserterHelper::insertCohesiveElement() {
auto nb_new_facets = insertFacetsOnly();
if (nb_new_facets == 0) {
return 0;
}
updateCohesiveData();
return nb_new_facets;
}
/* -------------------------------------------------------------------------- */
-UInt CohesiveElementInserterHelper::insertFacetsOnly() {
- UInt spatial_dimension = mesh.getSpatialDimension();
+Int CohesiveElementInserterHelper::insertFacetsOnly() {
+ auto spatial_dimension = mesh.getSpatialDimension();
if (facets_to_double_by_dim[spatial_dimension - 1]->empty()) {
return 0;
}
if (spatial_dimension == 1) {
doublePointFacet();
} else if (spatial_dimension == 2) {
doubleFacets<1>();
findSubfacetToDouble<1>();
doubleSubfacet<2>();
} else if (spatial_dimension == 3) {
doubleFacets<2>();
findSubfacetToDouble<2>();
doubleFacets<1>();
findSubfacetToDouble<1>();
doubleSubfacet<3>();
}
return facets_to_double_by_dim[spatial_dimension - 1]->size();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void CohesiveElementInserterHelper::doubleFacets() {
+template <Int dim> void CohesiveElementInserterHelper::doubleFacets() {
AKANTU_DEBUG_IN();
NewElementsEvent new_facets;
auto spatial_dimension = mesh_facets.getSpatialDimension();
auto & facets_to_double = *facets_to_double_by_dim[dim];
MeshAccessor mesh_accessor(mesh_facets);
for (auto && facet_to_double : make_view(facets_to_double, 2)) {
auto && old_facet = facet_to_double[0];
auto && new_facet = facet_to_double[1];
auto & facets_connectivities =
mesh_accessor.getConnectivity(old_facet.type, old_facet.ghost_type);
facets_connectivities.resize(
nb_new_facets(old_facet.type, old_facet.ghost_type));
auto facets_connectivities_begin =
make_view(facets_connectivities, facets_connectivities.getNbComponent())
.begin();
// copy the connectivities
- Vector<UInt> new_conn(facets_connectivities_begin[new_facet.element]);
- Vector<UInt> old_conn(facets_connectivities_begin[old_facet.element]);
+ auto && new_conn(facets_connectivities_begin[new_facet.element]);
+ auto && old_conn(facets_connectivities_begin[old_facet.element]);
new_conn = old_conn;
// this will fail if multiple facet types exists for a given element type
// \TODO handle multiple sub-facet types
auto nb_subfacet_per_facet = Mesh::getNbFacetsPerElement(old_facet.type);
auto & subfacets_to_facets = mesh_accessor.getSubelementToElementNC(
old_facet.type, old_facet.ghost_type);
subfacets_to_facets.resize(
nb_new_facets(old_facet.type, old_facet.ghost_type), ElementNull);
auto subfacets_to_facets_begin =
make_view(subfacets_to_facets, nb_subfacet_per_facet).begin();
// copy the subfacet to facets information
- Vector<Element> old_subfacets_to_facet(
+ auto && old_subfacets_to_facet(
subfacets_to_facets_begin[old_facet.element]);
- Vector<Element> new_subfacet_to_facet(
- subfacets_to_facets_begin[new_facet.element]);
+ auto && new_subfacet_to_facet(subfacets_to_facets_begin[new_facet.element]);
new_subfacet_to_facet = old_subfacets_to_facet;
for (auto & subfacet : old_subfacets_to_facet) {
if (subfacet == ElementNull) {
continue;
}
/// update facet_to_subfacet array
mesh_accessor.getElementToSubelement(subfacet).push_back(new_facet);
}
new_facets.getList().push_back(new_facet);
}
/// update facet_to_subfacet and _segment_3 facets if any
if (dim != spatial_dimension - 1) {
updateSubelementToElement(dim, true);
updateElementToSubelement(dim, true);
updateQuadraticSegments(dim);
} else {
updateQuadraticSegments(dim);
}
mesh_facets.sendEvent(new_facets);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void CohesiveElementInserterHelper::findSubfacetToDouble() {
+template <Int dim> void CohesiveElementInserterHelper::findSubfacetToDouble() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh_facets.getSpatialDimension();
+ auto spatial_dimension = mesh_facets.getSpatialDimension();
MeshAccessor mesh_accessor(mesh_facets);
auto & facets_to_double = *facets_to_double_by_dim[spatial_dimension - 1];
const auto & subfacets_to_facets = mesh_facets.getSubelementToElement();
auto & elements_to_facets = mesh_accessor.getElementToSubelement();
/// loop on every facet
for (auto f : arange(2)) {
for (auto && facet_to_double : make_view(facets_to_double, 2)) {
auto old_facet = facet_to_double[f];
auto new_facet = facet_to_double[1 - f];
const auto & starting_element = elements_to_facets(new_facet, 0)[0];
auto current_facet = old_facet;
- Vector<Element> subfacets_to_facet = subfacets_to_facets.get(old_facet);
+ auto && subfacets_to_facet = subfacets_to_facets.get(old_facet);
/// loop on every subfacet
for (auto & subfacet : subfacets_to_facet) {
if (subfacet == ElementNull) {
continue;
}
if (dim == spatial_dimension - 2) {
- Vector<Element> subsubfacets_to_subfacet =
- subfacets_to_facets.get(subfacet);
+ auto && subsubfacets_to_subfacet = subfacets_to_facets.get(subfacet);
/// loop on every subsubfacet
for (auto & subsubfacet : subsubfacets_to_subfacet) {
if (subsubfacet == ElementNull) {
continue;
}
- Vector<UInt> subsubfacet_connectivity =
+ auto && subsubfacet_connectivity =
mesh_facets.getConnectivity(subsubfacet);
std::vector<Element> element_list;
std::vector<Element> facet_list;
std::vector<Element> subfacet_list;
/// check if subsubfacet is to be doubled
if (!findElementsAroundSubfacet(
starting_element, current_facet, subsubfacet_connectivity,
element_list, facet_list, &subfacet_list) and
!removeElementsInVector(subfacet_list,
elements_to_facets(subsubfacet))) {
Element new_subsubfacet{
subsubfacet.type,
nb_new_facets(subsubfacet.type, subsubfacet.ghost_type)++,
subsubfacet.ghost_type};
facets_to_double_by_dim[dim - 1]->push_back(
Vector<Element>{subsubfacet, new_subsubfacet});
elementsOfDimToElementsOfDim(dim - 1, dim - 1)
.push_back(subfacet_list);
elementsOfDimToElementsOfDim(dim, dim - 1).push_back(facet_list);
elementsOfDimToElementsOfDim(dim + 1, dim - 1)
.push_back(element_list);
}
}
} else {
std::vector<Element> element_list;
std::vector<Element> facet_list;
- Vector<UInt> subfacet_connectivity =
- mesh_facets.getConnectivity(subfacet);
+ auto && subfacet_connectivity = mesh_facets.getConnectivity(subfacet);
/// check if subfacet is to be doubled
if (!findElementsAroundSubfacet(starting_element, current_facet,
subfacet_connectivity, element_list,
facet_list) and
!removeElementsInVector(facet_list,
elements_to_facets(subfacet))) {
Element new_subfacet{
subfacet.type,
nb_new_facets(subfacet.type, subfacet.ghost_type)++,
subfacet.ghost_type};
facets_to_double_by_dim[dim - 1]->push_back(
Vector<Element>{subfacet, new_subfacet});
elementsOfDimToElementsOfDim(dim, dim - 1).push_back(facet_list);
elementsOfDimToElementsOfDim(dim + 1, dim - 1)
.push_back(element_list);
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserterHelper::doubleNodes(
- const std::vector<UInt> & old_nodes) {
+ const std::vector<Idx> & old_nodes) {
auto & position = mesh.getNodes();
auto spatial_dimension = mesh.getSpatialDimension();
auto old_nb_nodes = position.size();
position.reserve(old_nb_nodes + old_nodes.size());
doubled_nodes.reserve(doubled_nodes.size() + old_nodes.size());
auto position_begin = position.begin(spatial_dimension);
for (auto && data : enumerate(old_nodes)) {
auto n = std::get<0>(data);
auto old_node = std::get<1>(data);
decltype(old_node) new_node = old_nb_nodes + n;
/// store doubled nodes
- doubled_nodes.push_back(Vector<UInt>{old_node, new_node});
+ doubled_nodes.push_back(Vector<Idx>{old_node, new_node});
/// update position
- Vector<Real> coords = Vector<Real>(position_begin[old_node]);
+ auto && coords = position_begin[old_node];
position.push_back(coords);
}
}
/* -------------------------------------------------------------------------- */
bool CohesiveElementInserterHelper::findElementsAroundSubfacet(
const Element & starting_element, const Element & end_facet,
- const Vector<UInt> & subfacet_connectivity,
+ const Vector<Idx> & subfacet_connectivity,
std::vector<Element> & element_list, std::vector<Element> & facet_list,
std::vector<Element> * subfacet_list) {
bool facet_matched = false;
element_list.push_back(starting_element);
std::queue<Element> elements_to_check;
elements_to_check.push(starting_element);
/// keep going as long as there are elements to check
while (not elements_to_check.empty()) {
/// check current element
Element & current_element = elements_to_check.front();
- const Vector<Element> facets_to_element =
+ auto && facets_to_element =
mesh_facets.getSubelementToElement(current_element);
// for every facet of the element
for (const auto & current_facet : facets_to_element) {
if (current_facet == ElementNull) {
continue;
}
if (current_facet == end_facet) {
facet_matched = true;
}
auto find_facet =
std::find(facet_list.begin(), facet_list.end(), current_facet);
// facet already listed or subfacet_connectivity is not in the
// connectivity of current_facet;
if ((find_facet != facet_list.end()) or
not hasElement(mesh_facets.getConnectivity(current_facet),
subfacet_connectivity)) {
continue;
}
facet_list.push_back(current_facet);
if (subfacet_list != nullptr) {
- const Vector<Element> subfacets_of_facet =
+ auto && subfacets_of_facet =
mesh_facets.getSubelementToElement(current_facet);
/// check subfacets
for (const auto & current_subfacet : subfacets_of_facet) {
if (current_subfacet == ElementNull) {
continue;
}
auto find_subfacet = std::find(
subfacet_list->begin(), subfacet_list->end(), current_subfacet);
if ((find_subfacet != subfacet_list->end()) or
not hasElement(mesh_facets.getConnectivity(current_subfacet),
subfacet_connectivity)) {
continue;
}
subfacet_list->push_back(current_subfacet);
}
}
/// consider opposing element
const auto & elements_to_facet =
mesh_facets.getElementToSubelement(current_facet);
- UInt opposing = 0;
+ Idx opposing = 0;
if (elements_to_facet[0] == current_element) {
opposing = 1;
}
const auto & opposing_element = elements_to_facet[opposing];
/// skip null elements since they are on a boundary
if (opposing_element == ElementNull) {
continue;
}
/// skip this element if already added
if (std::find(element_list.begin(), element_list.end(),
opposing_element) != element_list.end()) {
continue;
}
/// only regular elements have to be checked
if (opposing_element.kind() == _ek_regular) {
elements_to_check.push(opposing_element);
}
element_list.push_back(opposing_element);
AKANTU_DEBUG_ASSERT(hasElement(mesh.getConnectivity(opposing_element),
subfacet_connectivity),
"Subfacet doesn't belong to this element");
}
/// erased checked element from the list
elements_to_check.pop();
}
return facet_matched;
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserterHelper::updateCohesiveData() {
-
- UInt spatial_dimension = mesh.getSpatialDimension();
- bool third_dimension = spatial_dimension == 3;
+ auto spatial_dimension = mesh.getSpatialDimension();
+ auto third_dimension = spatial_dimension == 3;
MeshAccessor mesh_accessor(mesh);
MeshAccessor mesh_facets_accessor(mesh_facets);
for (auto ghost_type : ghost_types) {
for (auto cohesive_type : mesh.elementTypes(_element_kind = _ek_cohesive)) {
auto nb_cohesive_elements = mesh.getNbElement(cohesive_type, ghost_type);
nb_new_facets(cohesive_type, ghost_type) = nb_cohesive_elements;
mesh_facets_accessor.getSubelementToElement(cohesive_type, ghost_type);
}
}
auto & facets_to_double = *facets_to_double_by_dim[spatial_dimension - 1];
new_elements.reserve(new_elements.size() + facets_to_double.size());
std::array<Element, 2> facets;
auto & element_to_facet = mesh_facets_accessor.getElementToSubelement();
auto & facets_to_cohesive_elements =
mesh_facets_accessor.getSubelementToElement();
for (auto && facet_to_double : make_view(facets_to_double, 2)) {
auto & old_facet = facet_to_double[0];
/// (in 3D cohesive elements connectivity is inverted)
facets[third_dimension ? 1 : 0] = old_facet;
facets[third_dimension ? 0 : 1] = facet_to_double[1];
auto type_cohesive = FEEngine::getCohesiveElementType(old_facet.type);
auto & facet_connectivities =
mesh_facets.getConnectivity(old_facet.type, old_facet.ghost_type);
auto facet_connectivity_it =
facet_connectivities.begin(facet_connectivities.getNbComponent());
auto cohesive_element = Element{
type_cohesive, nb_new_facets(type_cohesive, old_facet.ghost_type)++,
old_facet.ghost_type};
auto & cohesives_connectivities =
mesh_accessor.getConnectivity(type_cohesive, old_facet.ghost_type);
- Matrix<UInt> connectivity(facet_connectivities.getNbComponent(), 2);
- Vector<Element> facets_to_cohesive_element(2);
+ Matrix<Idx> connectivity(facet_connectivities.getNbComponent(), 2);
+ Vector<Element, 2> facets_to_cohesive_element;
for (auto s : arange(2)) {
/// store doubled facets
facets_to_cohesive_element[s] = facets[s];
// update connectivities
- connectivity(s) = Vector<UInt>(facet_connectivity_it[facets[s].element]);
+ connectivity(s) = facet_connectivity_it[facets[s].element];
/// update element_to_facet vectors
element_to_facet(facets[s], 0)[1] = cohesive_element;
}
cohesives_connectivities.push_back(connectivity);
facets_to_cohesive_elements(type_cohesive, old_facet.ghost_type)
.push_back(facets_to_cohesive_element);
/// add cohesive element to the element event list
new_elements.push_back(cohesive_element);
}
}
/* -------------------------------------------------------------------------- */
void CohesiveElementInserterHelper::doublePointFacet() {
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
if (spatial_dimension != 1) {
return;
}
NewElementsEvent new_facets_event;
auto & facets_to_double = *facets_to_double_by_dim[spatial_dimension - 1];
const auto & element_to_facet = mesh_facets.getElementToSubelement();
auto & position = mesh.getNodes();
MeshAccessor mesh_accessor(mesh_facets);
for (auto ghost_type : ghost_types) {
for (auto facet_type : nb_new_facets.elementTypes(
spatial_dimension - 1, ghost_type, _ek_regular)) {
auto nb_new_element = nb_new_facets(facet_type, ghost_type);
auto & connectivities =
mesh_accessor.getConnectivity(facet_type, ghost_type);
connectivities.resize(nb_new_element);
}
}
position.reserve(position.size() + facets_to_double.size());
for (auto facet_to_double : make_view(facets_to_double, 2)) {
auto & old_facet = facet_to_double[0];
auto & new_facet = facet_to_double[1];
auto element = element_to_facet(new_facet)[0];
auto & facet_connectivities =
mesh_accessor.getConnectivity(old_facet.type, old_facet.ghost_type);
auto old_node = facet_connectivities(old_facet.element);
auto new_node = position.size();
/// update position
position.push_back(position(old_node));
facet_connectivities(new_facet.element) = new_node;
- Vector<UInt> segment_conectivity = mesh.getConnectivity(element);
+ auto && segment_conectivity = mesh.getConnectivity(element);
/// update facet connectivity
auto it = std::find(segment_conectivity.begin(), segment_conectivity.end(),
old_node);
*it = new_node;
- doubled_nodes.push_back(Vector<UInt>{old_node, new_node});
+ doubled_nodes.push_back(Vector<Idx>{old_node, new_node});
new_facets_event.getList().push_back(new_facet);
}
mesh_facets.sendEvent(new_facets_event);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void CohesiveElementInserterHelper::doubleSubfacet() {
if (spatial_dimension == 1) {
return;
}
NewElementsEvent new_facets_event;
- std::vector<UInt> nodes_to_double;
+ std::vector<Idx> nodes_to_double;
MeshAccessor mesh_accessor(mesh_facets);
auto & connectivities = mesh_accessor.getConnectivities();
auto & facets_to_double = *facets_to_double_by_dim[0];
ElementTypeMap<Int> nb_new_elements;
for (auto && facet_to_double : make_view(facets_to_double, 2)) {
auto && old_element = facet_to_double[0];
nb_new_elements(old_element.type, old_element.ghost_type) = 0;
}
for (auto && facet_to_double : make_view(facets_to_double, 2)) {
auto && old_element = facet_to_double[0];
++nb_new_elements(old_element.type, old_element.ghost_type);
}
for (auto ghost_type : ghost_types) {
for (auto facet_type :
nb_new_elements.elementTypes(0, ghost_type, _ek_regular)) {
auto & connectivities =
mesh_accessor.getConnectivity(facet_type, ghost_type);
connectivities.resize(connectivities.size() +
nb_new_elements(facet_type, ghost_type));
}
}
for (auto && facet_to_double : make_view(facets_to_double, 2)) {
auto & old_facet = facet_to_double(0);
// auto & new_facet = facet_to_double(1);
AKANTU_DEBUG_ASSERT(
old_facet.type == _point_1,
"Only _point_1 subfacet doubling is supported at the moment");
/// list nodes double
nodes_to_double.push_back(connectivities(old_facet));
}
auto old_nb_doubled_nodes = doubled_nodes.size();
doubleNodes(nodes_to_double);
auto double_nodes_view = make_view(doubled_nodes, 2);
for (auto && data :
zip(make_view(facets_to_double, 2),
range(double_nodes_view.begin() + old_nb_doubled_nodes,
double_nodes_view.end()),
arange(facets_to_double.size()))) {
// auto & old_facet = std::get<0>(data)[0];
auto & new_facet = std::get<0>(data)[1];
new_facets_event.getList().push_back(new_facet);
auto & nodes = std::get<1>(data);
auto old_node = nodes(0);
auto new_node = nodes(1);
auto f = std::get<2>(data);
/// add new nodes in connectivity
connectivities(new_facet) = new_node;
updateElementalConnectivity(mesh, old_node, new_node,
elementsOfDimToElementsOfDim(2, 0)(f),
&elementsOfDimToElementsOfDim(1, 0)(f));
updateElementalConnectivity(mesh_facets, old_node, new_node,
elementsOfDimToElementsOfDim(1, 0)(f));
if (spatial_dimension == 3) {
updateElementalConnectivity(mesh_facets, old_node, new_node,
elementsOfDimToElementsOfDim(0, 0)(f));
}
}
updateSubelementToElement(0, spatial_dimension == 2);
updateElementToSubelement(0, spatial_dimension == 2);
mesh_facets.sendEvent(new_facets_event);
}
} // namespace akantu
diff --git a/src/mesh_utils/cohesive_element_inserter_helper.hh b/src/mesh_utils/cohesive_element_inserter_helper.hh
index b330a8d86..e9244d13b 100644
--- a/src/mesh_utils/cohesive_element_inserter_helper.hh
+++ b/src/mesh_utils/cohesive_element_inserter_helper.hh
@@ -1,118 +1,118 @@
/**
* @file cohesive_element_inserter_helper.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 08 2020
* @date last modification: Wed Nov 11 2020
*
* @brief An helper class to handle cohesive element insertion
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_COHESIVE_ELEMENT_INSERTER_HELPER_HH__
#define __AKANTU_COHESIVE_ELEMENT_INSERTER_HELPER_HH__
namespace akantu {
/* -------------------------------------------------------------------------- */
class CohesiveElementInserterHelper {
public:
CohesiveElementInserterHelper(
Mesh & mesh, const ElementTypeMapArray<bool> & facet_insertion);
- UInt insertCohesiveElement();
- UInt insertFacetsOnly();
+ Int insertCohesiveElement();
+ Int insertFacetsOnly();
private:
- template <UInt dim> UInt insertFacetsOnlyImpl();
- template <UInt dim> void doubleFacets();
- template <UInt dim> void findSubfacetToDouble();
+ template <Int dim> Int insertFacetsOnlyImpl();
+ template <Int dim> void doubleFacets();
+ template <Int dim> void findSubfacetToDouble();
- void doubleNodes(const std::vector<UInt> & old_nodes);
+ void doubleNodes(const std::vector<Idx> & old_nodes);
bool findElementsAroundSubfacet(
const Element & starting_element, const Element & end_facet,
- const Vector<UInt> & subfacet_connectivity,
+ const Vector<Idx> & subfacet_connectivity,
std::vector<Element> & element_list, std::vector<Element> & facet_list,
std::vector<Element> * subfacet_list = nullptr);
- static inline bool hasElement(const Vector<UInt> & nodes_element,
- const Vector<UInt> & nodes);
+ static inline bool hasElement(const Vector<Idx> & nodes_element,
+ const Vector<Idx> & nodes);
static inline bool
removeElementsInVector(const std::vector<Element> & elem_to_remove,
std::vector<Element> & elem_list);
void updateElementalConnectivity(
- Mesh & mesh, UInt old_node, UInt new_node,
+ Mesh & mesh, Idx old_node, Idx new_node,
const std::vector<Element> & element_list,
const std::vector<Element> * facet_list = nullptr);
// update functions
- void updateElementToSubelement(UInt dim, bool facet_mode);
- void updateSubelementToElement(UInt dim, bool facet_mode);
- void updateQuadraticSegments(UInt dim);
+ void updateElementToSubelement(Int dim, bool facet_mode);
+ void updateSubelementToElement(Int dim, bool facet_mode);
+ void updateQuadraticSegments(Int dim);
void updateCohesiveData();
void doublePointFacet();
- template <UInt spatial_dimension> void doubleSubfacet();
+ template <Int spatial_dimension> void doubleSubfacet();
decltype(auto) elementsOfDimToElementsOfDim(Int dim1, Int dim2) {
AKANTU_DEBUG_ASSERT(dim1 >= 0 and dim1 <= 3,
"dimension of target element out of range");
AKANTU_DEBUG_ASSERT(dim2 >= 0 and dim2 <= 3,
"dimension of source element out of range");
auto & array = dimelements_to_dimelements[dim1][dim2];
if (not array) {
array = std::make_unique<Array<std::vector<Element>>>();
}
return (*array);
}
public:
decltype(auto) getNewElements() const { return (new_elements); }
decltype(auto) getDoubledNodes() const { return (doubled_nodes); }
private:
std::array<std::unique_ptr<Array<Element>>, 3> facets_to_double_by_dim;
std::array<std::array<std::unique_ptr<Array<std::vector<Element>>>, 2>, 4>
dimelements_to_dimelements;
- Array<UInt> doubled_nodes;
+ Array<Idx> doubled_nodes;
Array<Element> new_elements;
Mesh & mesh;
Mesh & mesh_facets;
- ElementTypeMap<UInt> nb_new_facets;
+ ElementTypeMap<Int> nb_new_facets;
};
} // namespace akantu
#endif /* __AKANTU_COHESIVE_ELEMENT_INSERTER_HELPER_HH__ */
diff --git a/src/mesh_utils/cohesive_element_inserter_inline_impl.hh b/src/mesh_utils/cohesive_element_inserter_inline_impl.hh
index f671cc812..abd269a7b 100644
--- a/src/mesh_utils/cohesive_element_inserter_inline_impl.hh
+++ b/src/mesh_utils/cohesive_element_inserter_inline_impl.hh
@@ -1,103 +1,103 @@
/**
* @file cohesive_element_inserter_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 11 2020
*
* @brief Cohesive element inserter inline functions
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "cohesive_element_inserter.hh"
+//#include "cohesive_element_inserter.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COHESIVE_ELEMENT_INSERTER_INLINE_IMPL_HH_
#define AKANTU_COHESIVE_ELEMENT_INSERTER_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline void
CohesiveElementInserter::addPhysicalSurface(const ID & surface_name) {
physical_surfaces.insert(surface_name);
}
/* -------------------------------------------------------------------------- */
inline void
CohesiveElementInserter::addPhysicalVolume(const ID & surface_name) {
physical_zones.insert(surface_name);
}
/* -------------------------------------------------------------------------- */
-inline UInt
+inline Int
CohesiveElementInserter::getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
- UInt size = 0;
+ Int size = 0;
if (tag == SynchronizationTag::_ce_groups) {
size = elements.size() * sizeof(bool);
}
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
inline void
CohesiveElementInserter::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
if (tag == SynchronizationTag::_ce_groups) {
for (const auto & el : elements) {
const bool & data = insertion_facets(el);
buffer << data;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
inline void
CohesiveElementInserter::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
if (tag == SynchronizationTag::_ce_groups) {
for (const auto & el : elements) {
bool & data = insertion_facets(el);
buffer >> data;
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif /* AKANTU_COHESIVE_ELEMENT_INSERTER_INLINE_IMPL_HH_ */
diff --git a/src/mesh_utils/global_ids_updater.cc b/src/mesh_utils/global_ids_updater.cc
index 70db9fd16..871da408a 100644
--- a/src/mesh_utils/global_ids_updater.cc
+++ b/src/mesh_utils/global_ids_updater.cc
@@ -1,143 +1,143 @@
/**
* @file global_ids_updater.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Apr 13 2012
* @date last modification: Tue Sep 08 2020
*
* @brief Functions of the GlobalIdsUpdater
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "global_ids_updater.hh"
#include "element_synchronizer.hh"
#include "mesh_accessor.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace akantu {
-UInt GlobalIdsUpdater::updateGlobalIDs(UInt local_nb_new_nodes) {
+Int GlobalIdsUpdater::updateGlobalIDs(Int local_nb_new_nodes) {
if (mesh.getCommunicator().getNbProc() == 1) {
return local_nb_new_nodes;
}
- UInt total_nb_new_nodes = this->updateGlobalIDsLocally(local_nb_new_nodes);
+ auto total_nb_new_nodes = this->updateGlobalIDsLocally(local_nb_new_nodes);
if (mesh.isDistributed()) {
this->synchronizeGlobalIDs();
}
return total_nb_new_nodes;
}
-UInt GlobalIdsUpdater::updateGlobalIDsLocally(UInt local_nb_new_nodes) {
+Int GlobalIdsUpdater::updateGlobalIDsLocally(Int local_nb_new_nodes) {
const auto & comm = mesh.getCommunicator();
- Int nb_proc = comm.getNbProc();
+ auto nb_proc = comm.getNbProc();
if (nb_proc == 1) {
return local_nb_new_nodes;
}
/// resize global ids array
MeshAccessor mesh_accessor(mesh);
auto && nodes_global_ids = mesh_accessor.getNodesGlobalIds();
- UInt old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes;
+ auto old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes;
nodes_global_ids.resize(mesh.getNbNodes(), -1);
auto && local_or_master_pred = [this](auto && n) {
return this->mesh.isLocalOrMasterNode(n);
};
- Vector<UInt> local_master_nodes(2, 0);
+ Vector<Int, 2> local_master_nodes(Vector<Int, 2>::Zero());
/// compute the number of global nodes based on the number of old nodes
auto range_old = arange(old_nb_nodes);
local_master_nodes(0) =
std::count_if(range_old.begin(), range_old.end(), local_or_master_pred);
/// compute amount of local or master doubled nodes
auto range_new = arange(old_nb_nodes, mesh.getNbNodes());
local_master_nodes(1) =
std::count_if(range_new.begin(), range_new.end(), local_or_master_pred);
auto starting_index = local_master_nodes(1);
comm.allReduce(local_master_nodes);
- UInt old_global_nodes = local_master_nodes(0);
- UInt total_nb_new_nodes = local_master_nodes(1);
+ auto old_global_nodes = local_master_nodes(0);
+ auto total_nb_new_nodes = local_master_nodes(1);
if (total_nb_new_nodes == 0) {
return 0;
}
/// set global ids of local and master nodes
comm.exclusiveScan(starting_index);
starting_index += old_global_nodes;
for (auto n : range_new) {
if (mesh.isLocalOrMasterNode(n)) {
nodes_global_ids(n) = starting_index;
++starting_index;
}
}
mesh_accessor.setNbGlobalNodes(old_global_nodes + total_nb_new_nodes);
return total_nb_new_nodes;
}
void GlobalIdsUpdater::synchronizeGlobalIDs() {
this->reduce = true;
- this->synchronizer.slaveReductionOnce(*this,
- SynchronizationTag::_giu_global_conn);
+ this->synchronizer->slaveReductionOnce(*this,
+ SynchronizationTag::_giu_global_conn);
#ifndef AKANTU_NDEBUG
for (auto node : nodes_flags) {
auto node_flag = mesh.getNodeFlag(node.first);
if (node_flag != NodeFlag::_pure_ghost) {
continue;
}
auto n = 0U;
for (auto & pair : node.second) {
if (std::get<1>(pair) == NodeFlag::_pure_ghost) {
++n;
}
}
if (n == node.second.size()) {
AKANTU_DEBUG_WARNING(
"The node " << n << "is ghost on all the neighboring processors");
}
}
#endif
this->reduce = false;
- this->synchronizer.synchronizeOnce(*this,
- SynchronizationTag::_giu_global_conn);
+ this->synchronizer->synchronizeOnce(*this,
+ SynchronizationTag::_giu_global_conn);
}
} // namespace akantu
diff --git a/src/mesh_utils/global_ids_updater.hh b/src/mesh_utils/global_ids_updater.hh
index 764d3630f..bddccda42 100644
--- a/src/mesh_utils/global_ids_updater.hh
+++ b/src/mesh_utils/global_ids_updater.hh
@@ -1,108 +1,108 @@
/**
* @file global_ids_updater.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 02 2015
* @date last modification: Thu Feb 20 2020
*
* @brief Class that updates the global ids of new nodes that are
* inserted in the mesh. The functions in this class must be called
* after updating the node types
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_GLOBAL_IDS_UPDATER_HH_
#define AKANTU_GLOBAL_IDS_UPDATER_HH_
/* -------------------------------------------------------------------------- */
#include "data_accessor.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class ElementSynchronizer;
} // namespace akantu
namespace akantu {
class GlobalIdsUpdater : public DataAccessor<Element> {
public:
- GlobalIdsUpdater(Mesh & mesh, ElementSynchronizer & synchronizer)
+ GlobalIdsUpdater(Mesh & mesh, ElementSynchronizer * synchronizer)
: mesh(mesh), synchronizer(synchronizer) {}
/// function to update and synchronize the global connectivity of
/// new inserted nodes. It must be called after updating the node
/// types. (It calls in sequence the functions
/// updateGlobalIDsLocally and synchronizeGlobalIDs)
- UInt updateGlobalIDs(UInt local_nb_new_nodes);
+ Int updateGlobalIDs(Int local_nb_new_nodes);
/// function to update the global connectivity (only locally) of new
/// inserted nodes. It must be called after updating the node types.
- UInt updateGlobalIDsLocally(UInt local_nb_new_nodes);
+ Int updateGlobalIDsLocally(Int local_nb_new_nodes);
/// function to synchronize the global connectivity of new inserted
/// nodes among the processors. It must be called after updating the
/// node types.
void synchronizeGlobalIDs();
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
template <bool pack_mode>
inline void
packUnpackGlobalConnectivity(CommunicationBuffer & buffer,
const Array<Element> & elements) const;
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
private:
/// Reference to the mesh to update
Mesh & mesh;
/// distributed synchronizer to communicate the connectivity
- ElementSynchronizer & synchronizer;
+ ElementSynchronizer * synchronizer;
/// Tells if a reduction is taking place or not
bool reduce{false};
- std::unordered_map<UInt, std::vector<std::pair<UInt, NodeFlag>>> nodes_flags;
+ std::unordered_map<Idx, std::vector<std::pair<Idx, NodeFlag>>> nodes_flags;
};
} // namespace akantu
#include "global_ids_updater_inline_impl.hh"
#endif /* AKANTU_GLOBAL_IDS_UPDATER_HH_ */
diff --git a/src/mesh_utils/global_ids_updater_inline_impl.hh b/src/mesh_utils/global_ids_updater_inline_impl.hh
index 63cc4d022..dda290853 100644
--- a/src/mesh_utils/global_ids_updater_inline_impl.hh
+++ b/src/mesh_utils/global_ids_updater_inline_impl.hh
@@ -1,157 +1,157 @@
/**
* @file global_ids_updater_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 02 2015
* @date last modification: Tue Sep 08 2020
*
* @brief Implementation of the inline functions of GlobalIdsUpdater
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
-#include "global_ids_updater.hh"
+//#include "global_ids_updater.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_GLOBAL_IDS_UPDATER_INLINE_IMPL_HH_
#define AKANTU_GLOBAL_IDS_UPDATER_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt GlobalIdsUpdater::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+inline Int GlobalIdsUpdater::getNbData(const Array<Element> &elements,
+ const SynchronizationTag &tag) const {
UInt size = 0;
if (tag == SynchronizationTag::_giu_global_conn) {
size += Mesh::getNbNodesPerElementList(elements) *
(sizeof(UInt) + sizeof(Int)) +
sizeof(int);
#ifndef AKANTU_NDEBUG
size += sizeof(NodeFlag) * Mesh::getNbNodesPerElementList(elements);
#endif
}
return size;
}
/* -------------------------------------------------------------------------- */
-inline void GlobalIdsUpdater::packData(CommunicationBuffer & buffer,
- const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+inline void GlobalIdsUpdater::packData(CommunicationBuffer &buffer,
+ const Array<Element> &elements,
+ const SynchronizationTag &tag) const {
if (tag != SynchronizationTag::_giu_global_conn) {
return;
}
int prank = mesh.getCommunicator().whoAmI();
- const auto & global_nodes_ids = mesh.getGlobalNodesIds();
+ const auto &global_nodes_ids = mesh.getGlobalNodesIds();
buffer << prank;
- for (const auto & element : elements) {
+ for (const auto &element : elements) {
/// get element connectivity
- const Vector<UInt> current_conn =
+ auto &&current_conn =
const_cast<const Mesh &>(mesh).getConnectivity(element);
/// loop on all connectivity nodes
for (auto node : current_conn) {
- UInt index = -1;
+ Int index = -1;
if ((this->reduce and mesh.isLocalOrMasterNode(node)) or
(not this->reduce and not mesh.isPureGhostNode(node))) {
index = global_nodes_ids(node);
}
buffer << index;
buffer << (mesh.isLocalOrMasterNode(node) ? prank
: mesh.getNodePrank(node));
#ifndef AKANTU_NDEBUG
auto node_flag = mesh.getNodeFlag(node);
buffer << node_flag;
#endif
}
}
}
/* -------------------------------------------------------------------------- */
-inline void GlobalIdsUpdater::unpackData(CommunicationBuffer & buffer,
- const Array<Element> & elements,
- const SynchronizationTag & tag) {
+inline void GlobalIdsUpdater::unpackData(CommunicationBuffer &buffer,
+ const Array<Element> &elements,
+ const SynchronizationTag &tag) {
if (tag != SynchronizationTag::_giu_global_conn) {
return;
}
MeshAccessor mesh_accessor(mesh);
- auto & global_nodes_ids = mesh_accessor.getNodesGlobalIds();
+ auto &global_nodes_ids = mesh_accessor.getNodesGlobalIds();
int proc;
buffer >> proc;
- for (const auto & element : elements) {
+ for (const auto &element : elements) {
/// get element connectivity
- Vector<UInt> current_conn =
+ auto &&current_conn =
const_cast<const Mesh &>(mesh).getConnectivity(element);
/// loop on all connectivity nodes
for (auto node : current_conn) {
- UInt index;
+ Int index;
Int node_prank;
buffer >> index;
buffer >> node_prank;
#ifndef AKANTU_NDEBUG
NodeFlag node_flag;
buffer >> node_flag;
if (reduce) {
nodes_flags[node].push_back(std::make_pair(proc, node_flag));
}
#endif
- if (index == UInt(-1)) {
+ if (index == Int(-1)) {
continue;
}
if (mesh.isSlaveNode(node)) {
- auto & gid = global_nodes_ids(node);
- AKANTU_DEBUG_ASSERT(gid == UInt(-1) or gid == index,
+ auto &gid = global_nodes_ids(node);
+ AKANTU_DEBUG_ASSERT(gid == -1 or gid == index,
"The node already has a global id, from proc "
<< proc << ", different from the one received "
<< gid << " " << index);
gid = index;
#ifndef AKANTU_NDEBUG
auto current_proc = mesh.getNodePrank(node);
AKANTU_DEBUG_ASSERT(
current_proc == -1 or current_proc == node_prank,
"The node "
<< index << " already has a prank: " << current_proc
<< ", that is different from the one we are trying to set "
<< node_prank << " " << node_flag);
#endif
mesh_accessor.setNodePrank(node, node_prank);
}
}
}
}
} // namespace akantu
#endif /* AKANTU_GLOBAL_IDS_UPDATER_INLINE_IMPL_HH_ */
diff --git a/src/mesh_utils/mesh_partition.cc b/src/mesh_utils/mesh_partition.cc
index 03d68bb22..bdd21c76d 100644
--- a/src/mesh_utils/mesh_partition.cc
+++ b/src/mesh_utils/mesh_partition.cc
@@ -1,406 +1,403 @@
/**
* @file mesh_partition.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Aug 17 2010
* @date last modification: Fri Jul 24 2020
*
* @brief implementation of common part of all partitioner
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_partition.hh"
#include "aka_iterators.hh"
#include "aka_types.hh"
#include "mesh_accessor.hh"
#include "mesh_iterators.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <numeric>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-MeshPartition::MeshPartition(Mesh & mesh, UInt spatial_dimension, const ID & id)
+MeshPartition::MeshPartition(Mesh & mesh, Int spatial_dimension, const ID & id)
: mesh(mesh), spatial_dimension(spatial_dimension),
partitions("partition", id), ghost_partitions("ghost_partition", id),
ghost_partitions_offset("ghost_partition_offset", id),
saved_connectivity("saved_connectivity", id) {
AKANTU_DEBUG_IN();
- UInt nb_total_element = 0;
+ Int nb_total_element = 0;
for (auto && type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) {
linearized_offsets.emplace_back(type, nb_total_element);
nb_total_element += mesh.getConnectivity(type).size();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
MeshPartition::~MeshPartition() = default;
/* -------------------------------------------------------------------------- */
-UInt MeshPartition::linearized(const Element & element) {
+Idx MeshPartition::linearized(const Element & element) {
auto it =
std::find_if(linearized_offsets.begin(), linearized_offsets.end(),
[&element](auto & a) { return a.first == element.type; });
AKANTU_DEBUG_ASSERT(it != linearized_offsets.end(),
"A bug might be crawling around this corner...");
return (it->second + element.element);
}
/* -------------------------------------------------------------------------- */
-Element MeshPartition::unlinearized(UInt lin_element) {
+Element MeshPartition::unlinearized(Idx lin_element) {
ElementType type{_not_defined};
- UInt offset{0};
+ Idx offset{0};
for (auto & pair : linearized_offsets) {
if (lin_element < pair.second) {
continue;
}
std::tie(type, offset) = pair;
}
return Element{type, lin_element - offset, _not_ghost};
}
/* -------------------------------------------------------------------------- */
/**
* conversion in c++ of the METIS_MeshToDual (mesh.c) function wrote by George
* in Metis (University of Minnesota)
*/
void MeshPartition::buildDualGraph(
Array<Int> & dxadj, Array<Int> & dadjncy, Array<Int> & edge_loads,
const std::function<Int(const Element &, const Element &)> & edge_load_func,
Array<Int> & vertex_loads,
const std::function<Int(const Element &)> & vertex_load_func) {
CSR<Element> nodes_to_elements;
MeshUtils::buildNode2Elements(mesh, nodes_to_elements);
- std::unordered_map<UInt, std::vector<UInt>> adjacent_elements;
+ std::unordered_map<Idx, std::vector<Idx>> adjacent_elements;
// for each elements look for its connected elements
for_each_element(
mesh,
[&](auto && element) {
const auto & conn =
const_cast<const Mesh &>(mesh).getConnectivity(element);
- std::map<Element, UInt> hits;
+ std::map<Element, Int> hits;
// count the number of nodes shared with a given element
for (auto && node : conn) {
for (auto && connected_element : nodes_to_elements.getRow(node)) {
++hits[connected_element];
}
}
// define a minumum number of nodes to share to be considered as a
// ajacent element
- UInt magic_number{conn.size()};
+ auto magic_number{conn.size()};
for (auto n : arange(mesh.getNbFacetTypes(element.type))) {
magic_number = std::min(
mesh.getNbNodesPerElement(mesh.getFacetType(element.type, n)),
magic_number);
}
// check all neighbors to see which ones are "adjacent"
for (auto && data : hits) {
const auto & adjacent_element = data.first;
// not adjacent to miself
if (adjacent_element == element) {
continue;
}
// not enough shared nodes
if (data.second < magic_number) {
continue;
}
/// Patch in order to prevent neighboring cohesive elements
/// from detecting each other
#if defined(AKANTU_COHESIVE_ELEMENT)
auto element_kind = element.kind();
auto adjacent_element_kind = adjacent_element.kind();
if (element_kind == adjacent_element_kind &&
element_kind == _ek_cohesive) {
continue;
}
#endif
adjacent_elements[this->linearized(element)].push_back(
this->linearized(adjacent_element));
}
},
_spatial_dimension = mesh.getSpatialDimension(),
_element_kind = _ek_not_defined);
// prepare the arrays
auto nb_elements{adjacent_elements.size()};
dxadj.resize(nb_elements + 1);
vertex_loads.resize(nb_elements);
for (auto && data : adjacent_elements) {
const auto & element{data.first};
const auto & neighbors{data.second};
dxadj[element] = neighbors.size();
}
/// convert the dxadj array of sizes in a csr one of offsets
- for (UInt i = 1; i < nb_elements; ++i) {
+ for (auto i : arange(1, nb_elements)) {
dxadj(i) += dxadj(i - 1);
}
- for (UInt i = nb_elements; i > 0; --i) {
+ for (auto i = nb_elements; i > 0; --i) {
dxadj(i) = dxadj(i - 1);
}
dxadj(0) = 0;
dadjncy.resize(dxadj(nb_elements));
edge_loads.resize(dadjncy.size());
// fill the different arrays
for (auto && data : adjacent_elements) {
const auto & element{data.first};
const auto & neighbors{data.second};
auto unlinearized_element = unlinearized(element);
vertex_loads(element) = vertex_load_func(unlinearized_element);
auto pos = dxadj(element);
for (auto && neighbor : neighbors) {
dadjncy(pos) = neighbor;
edge_loads(pos) =
edge_load_func(unlinearized_element, unlinearized(neighbor));
++pos;
}
}
}
/* -------------------------------------------------------------------------- */
void MeshPartition::fillPartitionInformation(
const Mesh & mesh, const Int * linearized_partitions) {
AKANTU_DEBUG_IN();
CSR<Element> node_to_elem;
MeshUtils::buildNode2Elements(mesh, node_to_elem);
- UInt linearized_el = 0;
+ Int linearized_el = 0;
for (const auto & type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) {
- UInt nb_element = mesh.getNbElement(type);
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_element = mesh.getNbElement(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto & partition = partitions.alloc(nb_element, 1, type, _not_ghost);
auto & ghost_part_csr = ghost_partitions_csr(type, _not_ghost);
ghost_part_csr.resizeRows(nb_element);
auto & ghost_partition_offset =
ghost_partitions_offset.alloc(nb_element + 1, 1, type, _ghost);
auto & ghost_partition = ghost_partitions.alloc(0, 1, type, _ghost);
const auto & connectivity = mesh.getConnectivity(type, _not_ghost);
auto conn_it = connectivity.begin(connectivity.getNbComponent());
- for (UInt el = 0; el < nb_element; ++el, ++linearized_el) {
- UInt part = linearized_partitions[linearized_el];
+ for (Int el = 0; el < nb_element; ++el, ++linearized_el) {
+ auto part = linearized_partitions[linearized_el];
partition(el) = part;
- std::list<UInt> list_adj_part;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- auto conn = Vector<UInt>(*(conn_it + el));
- UInt node = conn(n);
+ std::list<Int> list_adj_part;
+ auto conn = conn_it[el];
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
+ auto node = conn(n);
for (const auto & adj_element : node_to_elem.getRow(node)) {
- UInt adj_el = linearized(adj_element);
- UInt adj_part = linearized_partitions[adj_el];
+ auto adj_el = linearized(adj_element);
+ auto adj_part = linearized_partitions[adj_el];
if (part != adj_part) {
list_adj_part.push_back(adj_part);
}
}
}
list_adj_part.sort();
list_adj_part.unique();
for (auto & adj_part : list_adj_part) {
ghost_part_csr.getRows().push_back(adj_part);
ghost_part_csr.rowOffset(el)++;
ghost_partition.push_back(adj_part);
ghost_partition_offset(el)++;
}
}
ghost_part_csr.countToCSR();
/// convert the ghost_partitions_offset array in an offset array
auto & ghost_partitions_offset_ptr = ghost_partitions_offset(type, _ghost);
- for (UInt i = 1; i < nb_element; ++i) {
+ for (Int i = 1; i < nb_element; ++i) {
ghost_partitions_offset_ptr(i) += ghost_partitions_offset_ptr(i - 1);
}
- for (UInt i = nb_element; i > 0; --i) {
+ for (Int i = nb_element; i > 0; --i) {
ghost_partitions_offset_ptr(i) = ghost_partitions_offset_ptr(i - 1);
}
ghost_partitions_offset_ptr(0) = 0;
}
// All Facets
- for (Int sp = spatial_dimension - 1; sp >= 0; --sp) {
+ for (auto sp = spatial_dimension - 1; sp >= 0; --sp) {
for (const auto & type :
mesh.elementTypes(sp, _not_ghost, _ek_not_defined)) {
- UInt nb_element = mesh.getNbElement(type);
+ auto nb_element = mesh.getNbElement(type);
auto & partition = partitions.alloc(nb_element, 1, type, _not_ghost);
AKANTU_DEBUG_INFO("Allocating partitions for " << type);
auto & ghost_part_csr = ghost_partitions_csr(type, _not_ghost);
ghost_part_csr.resizeRows(nb_element);
auto & ghost_partition_offset =
ghost_partitions_offset.alloc(nb_element + 1, 1, type, _ghost);
auto & ghost_partition = ghost_partitions.alloc(0, 1, type, _ghost);
AKANTU_DEBUG_INFO("Allocating ghost_partitions for " << type);
- const Array<std::vector<Element>> & elem_to_subelem =
+ const auto & elem_to_subelem =
mesh.getElementToSubelement(type, _not_ghost);
// Facet loop
- for (UInt i(0); i < mesh.getNbElement(type, _not_ghost); ++i) {
+ for (Int i(0); i < mesh.getNbElement(type, _not_ghost); ++i) {
const auto & adjacent_elems = elem_to_subelem(i);
if (adjacent_elems.empty()) {
partition(i) = 0;
continue;
}
- Element min_elem{_max_element_type, std::numeric_limits<UInt>::max(),
+ Element min_elem{_max_element_type, std::numeric_limits<Idx>::max(),
*(ghost_type_t{}.end())};
- UInt min_part(std::numeric_limits<UInt>::max());
- std::set<UInt> adjacent_parts;
+ auto min_part(std::numeric_limits<Int>::max());
+ std::set<Idx> adjacent_parts;
for (auto adj_elem : adjacent_elems) {
if (adj_elem == ElementNull) { // case of boundary elements
continue;
}
auto adjacent_elem_part = partitions(adj_elem);
if (adjacent_elem_part < min_part) {
min_part = adjacent_elem_part;
min_elem = adj_elem;
}
adjacent_parts.insert(adjacent_elem_part);
}
partition(i) = min_part;
- auto git = ghost_partitions_csr(min_elem.type, _not_ghost)
- .begin(min_elem.element);
- auto gend = ghost_partitions_csr(min_elem.type, _not_ghost)
- .end(min_elem.element);
- for (; git != gend; ++git) {
- adjacent_parts.insert(*git);
+ for (auto & gp : ghost_partitions_csr(min_elem.type, _not_ghost)
+ .getRow(min_elem.element)) {
+ adjacent_parts.insert(gp);
}
adjacent_parts.erase(min_part);
for (const auto & part : adjacent_parts) {
ghost_part_csr.getRows().push_back(part);
ghost_part_csr.rowOffset(i)++;
ghost_partition.push_back(part);
}
ghost_partition_offset(i + 1) =
ghost_partition_offset(i + 1) + adjacent_elems.size();
}
ghost_part_csr.countToCSR();
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshPartition::tweakConnectivity() {
AKANTU_DEBUG_IN();
- MeshAccessor mesh_accessor(const_cast<Mesh &>(mesh));
+ MeshAccessor mesh_accessor(mesh);
for (auto && type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) {
auto & connectivity = mesh_accessor.getConnectivity(type, _not_ghost);
auto & saved_conn = saved_connectivity.alloc(
connectivity.size(), connectivity.getNbComponent(), type, _not_ghost);
saved_conn.copy(connectivity);
for (auto && conn :
make_view(connectivity, connectivity.getNbComponent())) {
for (auto && node : conn) {
if (mesh.isPeriodicSlave(node)) {
node = mesh.getPeriodicMaster(node);
}
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshPartition::restoreConnectivity() {
AKANTU_DEBUG_IN();
- MeshAccessor mesh_accessor(const_cast<Mesh &>(mesh));
+ MeshAccessor mesh_accessor(mesh);
for (auto && type : saved_connectivity.elementTypes(
spatial_dimension, _not_ghost, _ek_not_defined)) {
auto & conn = mesh_accessor.getConnectivity(type, _not_ghost);
auto & saved_conn = saved_connectivity(type, _not_ghost);
conn.copy(saved_conn);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
bool MeshPartition::hasPartitions(ElementType type, GhostType ghost_type) {
return partitions.exists(type, ghost_type);
}
/* -------------------------------------------------------------------------- */
void MeshPartition::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "MeshPartition ["
<< "\n";
stream << space << " + id : " << id << "\n";
stream << space << " + nb partitions: " << nb_partitions << "\n";
stream << space << " + partitions [ "
<< "\n";
partitions.printself(stream, indent + 2);
stream << space << " ]"
<< "\n";
stream << space << "]"
<< "\n";
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/mesh_utils/mesh_partition.hh b/src/mesh_utils/mesh_partition.hh
index de2c9df1f..aa384e15b 100644
--- a/src/mesh_utils/mesh_partition.hh
+++ b/src/mesh_utils/mesh_partition.hh
@@ -1,152 +1,151 @@
/**
* @file mesh_partition.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief tools to partitionate a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_csr.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_PARTITION_HH_
#define AKANTU_MESH_PARTITION_HH_
namespace akantu {
class MeshPartition {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- MeshPartition(Mesh & mesh, UInt spatial_dimension,
+ MeshPartition(Mesh & mesh, Int spatial_dimension,
const ID & id = "MeshPartitioner");
virtual ~MeshPartition();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// define a partition of the mesh
virtual void partitionate(
- UInt nb_part,
+ Int nb_part,
const std::function<Int(const Element &, const Element &)> &
edge_load_func =
[](auto && /*unused*/, auto && /*unused*/) { return 1; },
const std::function<Int(const Element &)> & vertex_load_func =
[](auto && /*unused*/) { return 1; }) = 0;
/// reorder the nodes to reduce the filling during the factorization of a
/// matrix that has a profil based on the connectivity of the mesh
virtual void reorder() = 0;
/// fill the partitions array with a given linearized partition information
void fillPartitionInformation(const Mesh & mesh,
const Int * linearized_partitions);
virtual void printself(std::ostream & stream, int indent = 0) const;
protected:
/// build the dual graph of the mesh, for all element of spatial_dimension
void
buildDualGraph(Array<Int> & dxadj, Array<Int> & dadjncy,
Array<Int> & edge_loads,
const std::function<Int(const Element &, const Element &)> &
edge_load_func,
Array<Int> & vertex_loads,
const std::function<Int(const Element &)> & vertex_load_func);
/// tweak the mesh to handle the PBC pairs
void tweakConnectivity();
/// restore the mesh that has been tweaked
void restoreConnectivity();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
bool hasPartitions(ElementType type, GhostType ghost_type);
- AKANTU_GET_MACRO(Partitions, partitions, const ElementTypeMapArray<UInt> &);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Partition, partitions, UInt);
+ AKANTU_GET_MACRO_AUTO(Partitions, partitions);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Partition, partitions, Idx);
- AKANTU_GET_MACRO(GhostPartitionCSR, ghost_partitions_csr,
- const ElementTypeMap<CSR<UInt>> &);
+ AKANTU_GET_MACRO_AUTO(GhostPartitionCSR, ghost_partitions_csr);
- AKANTU_GET_MACRO(NbPartition, nb_partitions, UInt);
- AKANTU_SET_MACRO(NbPartition, nb_partitions, UInt);
+ AKANTU_GET_MACRO_AUTO(NbPartition, nb_partitions);
+ AKANTU_SET_MACRO(NbPartition, nb_partitions, Int);
protected:
- UInt linearized(const Element & element);
- Element unlinearized(UInt lin_element);
+ Idx linearized(const Element & element);
+ Element unlinearized(Idx lin_element);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// id
ID id;
/// the mesh to partition
Mesh & mesh;
/// dimension of the elements to consider in the mesh
- UInt spatial_dimension;
+ Int spatial_dimension;
/// number of partitions
- UInt nb_partitions;
+ Int nb_partitions;
/// partition numbers
- ElementTypeMapArray<UInt> partitions;
+ ElementTypeMapArray<Idx> partitions;
- ElementTypeMap<CSR<UInt>> ghost_partitions_csr;
- ElementTypeMapArray<UInt> ghost_partitions;
- ElementTypeMapArray<UInt> ghost_partitions_offset;
+ ElementTypeMap<CSR<Idx>> ghost_partitions_csr;
+ ElementTypeMapArray<Idx> ghost_partitions;
+ ElementTypeMapArray<Idx> ghost_partitions_offset;
- Array<UInt> * permutation;
+ Array<Int> * permutation;
- ElementTypeMapArray<UInt> saved_connectivity;
+ ElementTypeMapArray<Idx> saved_connectivity;
// vector of pair to ensure the iteration order
- std::vector<std::pair<ElementType, UInt>> linearized_offsets;
+ std::vector<std::pair<ElementType, Idx>> linearized_offsets;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const MeshPartition & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#ifdef AKANTU_USE_SCOTCH
#include "mesh_partition_scotch.hh"
#endif
#endif /* AKANTU_MESH_PARTITION_HH_ */
diff --git a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc
index 4c78a0c9c..841054e81 100644
--- a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc
+++ b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.cc
@@ -1,141 +1,140 @@
/**
* @file mesh_partition_mesh_data.cc
*
* @author Dana Christen <dana.christen@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Fri May 03 2013
* @date last modification: Fri Jul 24 2020
*
* @brief implementation of the MeshPartitionMeshData class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "mesh_partition_mesh_data.hh"
#if !defined(AKANTU_NDEBUG)
#include <set>
#endif
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-MeshPartitionMeshData::MeshPartitionMeshData(Mesh & mesh,
- UInt spatial_dimension,
+MeshPartitionMeshData::MeshPartitionMeshData(Mesh & mesh, Int spatial_dimension,
const ID & id)
: MeshPartition(mesh, spatial_dimension, id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
MeshPartitionMeshData::MeshPartitionMeshData(
- Mesh & mesh, const ElementTypeMapArray<UInt> & mapping,
- UInt spatial_dimension, const ID & id)
+ Mesh & mesh, const ElementTypeMapArray<Idx> & mapping,
+ Int spatial_dimension, const ID & id)
: MeshPartition(mesh, spatial_dimension, id), partition_mapping(&mapping) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshPartitionMeshData::partitionate(
- UInt nb_part,
+ Int nb_part,
const std::function<Int(const Element &,
const Element &)> & /*edge_load_func*/,
const std::function<Int(const Element &)> & /*vertex_load_func*/) {
AKANTU_DEBUG_IN();
if (mesh.isPeriodic()) {
tweakConnectivity();
}
nb_partitions = nb_part;
auto ghost_type = _not_ghost;
auto spatial_dimension = mesh.getSpatialDimension();
- UInt linearized_el = 0;
+ Idx linearized_el = 0;
auto nb_elements = mesh.getNbElement(mesh.getSpatialDimension(), ghost_type);
auto * partition_list = new Int[nb_elements];
#if !defined(AKANTU_NDEBUG)
- std::set<UInt> partitions;
+ std::set<Int> partitions;
#endif
for (auto type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_not_defined)) {
const auto & partition_array = (*partition_mapping)(type, ghost_type);
AKANTU_DEBUG_ASSERT(partition_array.size() ==
mesh.getNbElement(type, ghost_type),
"The partition mapping does not have the right number "
<< "of entries for type " << type
<< " and ghost type " << ghost_type << "."
<< " Tags=" << partition_array.size()
<< " Mesh=" << mesh.getNbElement(type, ghost_type));
for (auto && part : partition_array) {
partition_list[linearized_el] = part;
#if !defined(AKANTU_NDEBUG)
partitions.insert(part);
#endif
++linearized_el;
}
}
#if !defined(AKANTU_NDEBUG)
- AKANTU_DEBUG_ASSERT(partitions.size() == nb_part,
+ AKANTU_DEBUG_ASSERT(partitions.size() == std::size_t(nb_part),
"The number of real partitions does not match with the "
"number of asked partitions");
#endif
fillPartitionInformation(mesh, partition_list);
delete[] partition_list;
if (mesh.isPeriodic()) {
restoreConnectivity();
}
AKANTU_DEBUG_OUT();
} // namespace akantu
/* -------------------------------------------------------------------------- */
void MeshPartitionMeshData::reorder() { AKANTU_TO_IMPLEMENT(); }
/* -------------------------------------------------------------------------- */
void MeshPartitionMeshData::setPartitionMapping(
- const ElementTypeMapArray<UInt> & mapping) {
+ const ElementTypeMapArray<Idx> & mapping) {
partition_mapping = &mapping;
}
/* -------------------------------------------------------------------------- */
void MeshPartitionMeshData::setPartitionMappingFromMeshData(
const std::string & data_name) {
- partition_mapping = &(mesh.getData<UInt>(data_name));
+ partition_mapping = &(mesh.getData<Int>(data_name));
}
} // namespace akantu
diff --git a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh
index 241d8abd0..758ec1c6b 100644
--- a/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh
+++ b/src/mesh_utils/mesh_partition/mesh_partition_mesh_data.hh
@@ -1,94 +1,89 @@
/**
* @file mesh_partition_mesh_data.hh
*
* @author Dana Christen <dana.christen@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief mesh partitioning based on data provided in the mesh
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_PARTITION_MESH_DATA_HH_
#define AKANTU_MESH_PARTITION_MESH_DATA_HH_
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "mesh_partition.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class MeshPartitionMeshData : public MeshPartition {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- MeshPartitionMeshData(Mesh & mesh, UInt spatial_dimension,
+ MeshPartitionMeshData(Mesh & mesh, Int spatial_dimension,
const ID & id = "MeshPartitionerMeshData");
- MeshPartitionMeshData(Mesh & mesh, const ElementTypeMapArray<UInt> & mapping,
- UInt spatial_dimension,
+ MeshPartitionMeshData(Mesh & mesh, const ElementTypeMapArray<Idx> & mapping,
+ Int spatial_dimension,
const ID & id = "MeshPartitionerMeshData");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void partitionate(
- UInt nb_part,
+ Int nb_part,
const std::function<Int(const Element &, const Element &)> &
edge_load_func =
[](auto && /*unused*/, auto && /*unused*/) { return 1; },
const std::function<Int(const Element &)> & vertex_load_func =
[](auto && /*unused*/) { return 1; }) override;
void reorder() override;
- void setPartitionMapping(const ElementTypeMapArray<UInt> & mapping);
+ void setPartitionMapping(const ElementTypeMapArray<Idx> & mapping);
void setPartitionMappingFromMeshData(const std::string & data_name);
-private:
- /* ------------------------------------------------------------------------ */
- /* Accessors */
- /* ------------------------------------------------------------------------ */
-public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
- const ElementTypeMapArray<UInt> * partition_mapping;
+ const ElementTypeMapArray<Idx> * partition_mapping;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_MESH_PARTITION_MESH_DATA_HH_ */
diff --git a/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc b/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc
index be839b1fd..f44ed5b0b 100644
--- a/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc
+++ b/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc
@@ -1,473 +1,460 @@
/**
* @file mesh_partition_scotch.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief implementation of the MeshPartitionScotch class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_partition_scotch.hh"
#include "aka_common.hh"
#include "aka_random_generator.hh"
#include "aka_static_if.hh"
#include "mesh_accessor.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <cstdio>
#include <fstream>
/* -------------------------------------------------------------------------- */
#if !defined(AKANTU_USE_PTSCOTCH)
#ifndef AKANTU_SCOTCH_NO_EXTERN
extern "C" {
#endif // AKANTU_SCOTCH_NO_EXTERN
#include <scotch.h>
#ifndef AKANTU_SCOTCH_NO_EXTERN
}
#endif // AKANTU_SCOTCH_NO_EXTERN
#else // AKANTU_USE_PTSCOTCH
#include <ptscotch.h>
#endif // AKANTU_USE_PTSCOTCH
namespace akantu {
namespace {
constexpr int scotch_version = int(SCOTCH_VERSION);
}
/* -------------------------------------------------------------------------- */
-MeshPartitionScotch::MeshPartitionScotch(Mesh & mesh, UInt spatial_dimension,
+MeshPartitionScotch::MeshPartitionScotch(Mesh & mesh, Int spatial_dimension,
const ID & id)
: MeshPartition(mesh, spatial_dimension, id) {
AKANTU_DEBUG_IN();
// check if the akantu types and Scotch one are consistent
static_assert(
sizeof(Int) == sizeof(SCOTCH_Num),
"The integer type of Akantu does not match the one from Scotch");
- static_if(aka::bool_constant<scotch_version >= 6>{})
- .then([](auto && y) { SCOTCH_randomSeed(y); })
- .else_([](auto && y) { srandom(y); })(
- std::forward<UInt>(RandomGenerator<UInt>::seed()));
+ if constexpr (scotch_version >= 6) {
+ SCOTCH_randomSeed(RandomGenerator<Int>::seed());
+ } else {
+ srandom(RandomGenerator<Int>::seed());
+ }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
static SCOTCH_Mesh * createMesh(const Mesh & mesh) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt nb_nodes = mesh.getNbNodes();
+ auto spatial_dimension = mesh.getSpatialDimension();
+ auto nb_nodes = mesh.getNbNodes();
- UInt total_nb_element = 0;
- UInt nb_edge = 0;
+ Int total_nb_element = 0;
+ Int nb_edge = 0;
for (const auto & type : mesh.elementTypes(spatial_dimension)) {
- UInt nb_element = mesh.getNbElement(type);
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_element = mesh.getNbElement(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
total_nb_element += nb_element;
nb_edge += nb_element * nb_nodes_per_element;
}
SCOTCH_Num vnodbas = 0;
SCOTCH_Num vnodnbr = nb_nodes;
SCOTCH_Num velmbas = vnodnbr;
SCOTCH_Num velmnbr = total_nb_element;
auto * verttab = new SCOTCH_Num[vnodnbr + velmnbr + 1];
SCOTCH_Num * vendtab = verttab + 1;
SCOTCH_Num * velotab = nullptr;
SCOTCH_Num * vnlotab = nullptr;
SCOTCH_Num * vlbltab = nullptr;
memset(verttab, 0, (vnodnbr + velmnbr + 1) * sizeof(SCOTCH_Num));
for (const auto & type : mesh.elementTypes(spatial_dimension)) {
if (Mesh::getSpatialDimension(type) != spatial_dimension) {
continue;
}
- UInt nb_element = mesh.getNbElement(type);
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost);
-
+ const auto & connectivity = mesh.getConnectivity(type, _not_ghost);
/// count number of occurrence of each node
- for (UInt el = 0; el < nb_element; ++el) {
- UInt * conn_val = connectivity.storage() + el * nb_nodes_per_element;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- verttab[*(conn_val++)]++;
- }
- }
+ for (auto && conn : make_view(connectivity, connectivity.getNbComponent()))
+ for (auto && node : conn)
+ verttab[node]++;
}
/// convert the occurrence array in a csr one
- for (UInt i = 1; i < nb_nodes; ++i) {
+ for (Int i = 1; i < nb_nodes; ++i) {
verttab[i] += verttab[i - 1];
}
- for (UInt i = nb_nodes; i > 0; --i) {
+ for (Int i = nb_nodes; i > 0; --i) {
verttab[i] = verttab[i - 1];
}
verttab[0] = 0;
/// rearrange element to get the node-element list
SCOTCH_Num edgenbr = verttab[vnodnbr] + nb_edge;
auto * edgetab = new SCOTCH_Num[edgenbr];
- UInt linearized_el = 0;
+ Idx linearized_el = 0;
for (const auto & type : mesh.elementTypes(spatial_dimension)) {
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
const auto & connectivity = mesh.getConnectivity(type, _not_ghost);
for (auto && conn : make_view(connectivity, nb_nodes_per_element)) {
for (auto c : conn) {
edgetab[verttab[c]++] = linearized_el + velmbas;
}
++linearized_el;
}
}
- for (UInt i = nb_nodes; i > 0; --i) {
+ for (Int i = nb_nodes; i > 0; --i) {
verttab[i] = verttab[i - 1];
}
verttab[0] = 0;
- SCOTCH_Num * verttab_tmp = verttab + vnodnbr + 1;
- SCOTCH_Num * edgetab_tmp = edgetab + verttab[vnodnbr];
+ auto * verttab_tmp = verttab + vnodnbr + 1;
+ auto * edgetab_tmp = edgetab + verttab[vnodnbr];
for (const auto & type : mesh.elementTypes(spatial_dimension)) {
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
const auto & connectivity = mesh.getConnectivity(type, _not_ghost);
for (auto && conn : make_view(connectivity, nb_nodes_per_element)) {
*verttab_tmp = *(verttab_tmp - 1) + nb_nodes_per_element;
verttab_tmp++;
for (auto c : conn) {
*(edgetab_tmp++) = c + vnodbas;
}
}
}
auto * meshptr = new SCOTCH_Mesh;
SCOTCH_meshInit(meshptr);
SCOTCH_meshBuild(meshptr, velmbas, vnodbas, velmnbr, vnodnbr, verttab,
vendtab, velotab, vnlotab, vlbltab, edgenbr, edgetab);
/// Check the mesh
AKANTU_DEBUG_ASSERT(SCOTCH_meshCheck(meshptr) == 0,
"Scotch mesh is not consistent");
#ifndef AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDump)) {
/// save initial graph
FILE * fmesh = fopen("ScotchMesh.msh", "w");
SCOTCH_meshSave(meshptr, fmesh);
fclose(fmesh);
/// write geometry file
std::ofstream fgeominit;
fgeominit.open("ScotchMesh.xyz");
fgeominit << spatial_dimension << std::endl << nb_nodes << std::endl;
const Array<Real> & nodes = mesh.getNodes();
- Real * nodes_val = nodes.storage();
- for (UInt i = 0; i < nb_nodes; ++i) {
+ Real * nodes_val = nodes.data();
+ for (Int i = 0; i < nb_nodes; ++i) {
fgeominit << i << " ";
- for (UInt s = 0; s < spatial_dimension; ++s) {
+ for (Int s = 0; s < spatial_dimension; ++s) {
fgeominit << *(nodes_val++) << " ";
}
fgeominit << std::endl;
- ;
}
fgeominit.close();
}
#endif
AKANTU_DEBUG_OUT();
return meshptr;
}
/* -------------------------------------------------------------------------- */
static void destroyMesh(SCOTCH_Mesh * meshptr) {
AKANTU_DEBUG_IN();
SCOTCH_Num velmbas;
SCOTCH_Num vnodbas;
SCOTCH_Num vnodnbr;
SCOTCH_Num velmnbr;
SCOTCH_Num * verttab;
SCOTCH_Num * vendtab;
SCOTCH_Num * velotab;
SCOTCH_Num * vnlotab;
SCOTCH_Num * vlbltab;
SCOTCH_Num edgenbr;
SCOTCH_Num * edgetab;
SCOTCH_Num degrptr;
SCOTCH_meshData(meshptr, &velmbas, &vnodbas, &velmnbr, &vnodnbr, &verttab,
&vendtab, &velotab, &vnlotab, &vlbltab, &edgenbr, &edgetab,
&degrptr);
delete[] verttab;
delete[] edgetab;
SCOTCH_meshExit(meshptr);
delete meshptr;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshPartitionScotch::partitionate(
- UInt nb_part,
+ Int nb_part,
const std::function<Int(const Element &, const Element &)> & edge_load_func,
const std::function<Int(const Element &)> & vertex_load_func) {
AKANTU_DEBUG_IN();
nb_partitions = nb_part;
if (mesh.isPeriodic()) {
tweakConnectivity();
}
AKANTU_DEBUG_INFO("Partitioning the mesh " << mesh.getID() << " in "
<< nb_part << " parts.");
Array<Int> dxadj;
Array<Int> dadjncy;
Array<Int> edge_loads;
Array<Int> vertex_loads;
buildDualGraph(dxadj, dadjncy, edge_loads, edge_load_func, vertex_loads,
vertex_load_func);
/// variables that will hold our structures in scotch format
SCOTCH_Graph scotch_graph;
SCOTCH_Strat scotch_strat;
/// description number and arrays for struct mesh for scotch
SCOTCH_Num baseval = 0; // base numbering for element and
// nodes (0 -> C , 1 -> fortran)
SCOTCH_Num vertnbr = dxadj.size() - 1; // number of vertexes
SCOTCH_Num * parttab; // array of partitions
SCOTCH_Num edgenbr = dxadj(vertnbr); // twice the number of "edges"
//(an "edge" bounds two nodes)
- SCOTCH_Num * verttab = dxadj.storage(); // array of start indices in edgetab
- SCOTCH_Num * vendtab = nullptr; // array of after-last indices in edgetab
- SCOTCH_Num * velotab =
- vertex_loads.storage(); // integer load associated with
+ SCOTCH_Num * verttab = dxadj.data(); // array of start indices in edgetab
+ SCOTCH_Num * vendtab = nullptr; // array of after-last indices in edgetab
+ SCOTCH_Num * velotab = vertex_loads.data(); // integer load associated with
// every vertex ( optional )
- SCOTCH_Num * edlotab = edge_loads.storage(); // integer load associated with
+ SCOTCH_Num * edlotab = edge_loads.data(); // integer load associated with
// every edge ( optional )
- SCOTCH_Num * edgetab = dadjncy.storage(); // adjacency array of every vertex
- SCOTCH_Num * vlbltab = nullptr; // vertex label array (optional)
+ SCOTCH_Num * edgetab = dadjncy.data(); // adjacency array of every vertex
+ SCOTCH_Num * vlbltab = nullptr; // vertex label array (optional)
/// Allocate space for Scotch arrays
- parttab = new SCOTCH_Num[vertnbr];
+ Array<SCOTCH_Num> parttab_array(vertnbr);
+ parttab = parttab_array.data();
/// Initialize the strategy structure
SCOTCH_stratInit(&scotch_strat);
/// Initialize the graph structure
SCOTCH_graphInit(&scotch_graph);
/// Build the graph from the adjacency arrays
SCOTCH_graphBuild(&scotch_graph, baseval, vertnbr, verttab, vendtab, velotab,
vlbltab, edgenbr, edgetab, edlotab);
#ifndef AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDump)) {
/// save initial graph
FILE * fgraphinit = fopen("GraphIniFile.grf", "w");
SCOTCH_graphSave(&scotch_graph, fgraphinit);
fclose(fgraphinit);
/// write geometry file
std::ofstream fgeominit;
fgeominit.open("GeomIniFile.xyz");
fgeominit << spatial_dimension << std::endl << vertnbr << std::endl;
- const Array<Real> & nodes = mesh.getNodes();
+ const auto & nodes = mesh.getNodes();
auto nodes_it = nodes.begin(spatial_dimension);
- UInt out_linerized_el = 0;
+ Int out_linerized_el = 0;
for (const auto & type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) {
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- const Array<UInt> & connectivity = mesh.getConnectivity(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ const auto & connectivity = mesh.getConnectivity(type);
Vector<Real> mid(spatial_dimension);
for (auto && conn : make_view(connectivity, nb_nodes_per_element)) {
mid.set(0.);
for (auto node : conn) {
- mid += Vector<Real>(nodes_it[node]);
+ mid += nodes_it[node];
}
- mid /= nb_nodes_per_element;
+ mid /= conn.size();
fgeominit << out_linerized_el++ << " ";
- for (UInt s = 0; s < spatial_dimension; ++s) {
+ for (Int s = 0; s < spatial_dimension; ++s) {
fgeominit << mid[s] << " ";
}
fgeominit << std::endl;
- ;
}
}
fgeominit.close();
}
#endif
/// Check the graph
AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0,
"Graph to partition is not consistent");
/// Partition the mesh
SCOTCH_graphPart(&scotch_graph, nb_part, &scotch_strat, parttab);
/// Check the graph
AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0,
"Partitioned graph is not consistent");
#ifndef AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDump)) {
/// save the partitioned graph
FILE * fgraph = fopen("GraphFile.grf", "w");
SCOTCH_graphSave(&scotch_graph, fgraph);
fclose(fgraph);
/// save the partition map
std::ofstream fmap;
fmap.open("MapFile.map");
fmap << vertnbr << std::endl;
for (Int i = 0; i < vertnbr; i++) {
fmap << i << " " << parttab[i] << std::endl;
}
fmap.close();
}
#endif
/// free the scotch data structures
SCOTCH_stratExit(&scotch_strat);
SCOTCH_graphFree(&scotch_graph);
SCOTCH_graphExit(&scotch_graph);
fillPartitionInformation(mesh, parttab);
- delete[] parttab;
-
if (mesh.isPeriodic()) {
restoreConnectivity();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshPartitionScotch::reorder() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Reordering the mesh " << mesh.getID());
SCOTCH_Mesh * scotch_mesh = createMesh(mesh);
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
SCOTCH_Strat scotch_strat;
// SCOTCH_Ordering scotch_order;
- auto * permtab = new SCOTCH_Num[nb_nodes];
+ Array<SCOTCH_Num> permtab(nb_nodes);
SCOTCH_Num * peritab = nullptr;
SCOTCH_Num cblknbr = 0;
SCOTCH_Num * rangtab = nullptr;
SCOTCH_Num * treetab = nullptr;
/// Initialize the strategy structure
SCOTCH_stratInit(&scotch_strat);
SCOTCH_Graph scotch_graph;
SCOTCH_graphInit(&scotch_graph);
SCOTCH_meshGraph(scotch_mesh, &scotch_graph);
#ifndef AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDump)) {
FILE * fgraphinit = fopen("ScotchMesh.grf", "w");
SCOTCH_graphSave(&scotch_graph, fgraphinit);
fclose(fgraphinit);
}
#endif
/// Check the graph
// AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0,
// "Mesh to Graph is not consistent");
- SCOTCH_graphOrder(&scotch_graph, &scotch_strat, permtab, peritab, &cblknbr,
- rangtab, treetab);
+ SCOTCH_graphOrder(&scotch_graph, &scotch_strat, permtab.data(), peritab,
+ &cblknbr, rangtab, treetab);
SCOTCH_graphExit(&scotch_graph);
SCOTCH_stratExit(&scotch_strat);
destroyMesh(scotch_mesh);
/// Renumbering
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
MeshAccessor mesh_accessor(mesh);
for (auto gt : ghost_types) {
for (const auto & type : mesh.elementTypes(_ghost_type = gt)) {
auto & connectivity = mesh_accessor.getConnectivity(type, gt);
for (auto && c : make_view(connectivity)) {
c = permtab[c];
}
}
}
/// \todo think of a in-place way to do it
- auto * new_coordinates = new Real[spatial_dimension * nb_nodes];
- Real * old_coordinates = mesh.getNodes().storage();
- for (UInt i = 0; i < nb_nodes; ++i) {
- memcpy(new_coordinates + permtab[i] * spatial_dimension,
- old_coordinates + i * spatial_dimension,
- spatial_dimension * sizeof(Real));
+ Array<Real> new_coordinates(nb_nodes, spatial_dimension);
+ auto new_nodes_it = make_view(new_coordinates, spatial_dimension).begin();
+ for (auto && data :
+ zip(make_view(mesh.getNodes(), spatial_dimension), permtab)) {
+ new_nodes_it[std::get<1>(data)] = std::get<0>(data);
}
- memcpy(old_coordinates, new_coordinates,
- nb_nodes * spatial_dimension * sizeof(Real));
- delete[] new_coordinates;
- delete[] permtab;
+ mesh_accessor.getNodes().copy(new_coordinates);
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh b/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh
index 382b1de69..de1db3057 100644
--- a/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh
+++ b/src/mesh_utils/mesh_partition/mesh_partition_scotch.hh
@@ -1,78 +1,78 @@
/**
* @file mesh_partition_scotch.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief mesh partitioning based on libScotch
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_partition.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_PARTITION_SCOTCH_HH_
#define AKANTU_MESH_PARTITION_SCOTCH_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class MeshPartitionScotch : public MeshPartition {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- MeshPartitionScotch(Mesh & mesh, UInt spatial_dimension,
+ MeshPartitionScotch(Mesh & mesh, Int spatial_dimension,
const ID & id = "mesh_partition_scotch");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void partitionate(
- UInt nb_part,
+ Int nb_part,
const std::function<Int(const Element &, const Element &)> &
edge_load_func =
[](auto && /*unused*/, auto && /*unused*/) { return 1; },
const std::function<Int(const Element &)> & vertex_load_func =
[](auto && /*unused*/) { return 1; }) override;
void reorder() override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
};
} // namespace akantu
#endif /* AKANTU_MESH_PARTITION_SCOTCH_HH_ */
diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc
index 032193b3b..667f1ccb4 100644
--- a/src/mesh_utils/mesh_utils.cc
+++ b/src/mesh_utils/mesh_utils.cc
@@ -1,812 +1,805 @@
/**
* @file mesh_utils.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Leonardo Snozzi <leonardo.snozzi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Aug 20 2010
* @date last modification: Thu Jan 14 2021
*
* @brief All mesh utils necessary for various tasks
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_utils.hh"
#include "element_synchronizer.hh"
#include "fe_engine.hh"
#include "mesh_accessor.hh"
#include "mesh_iterators.hh"
/* -------------------------------------------------------------------------- */
#include <limits>
#include <numeric>
#include <queue>
#include <set>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
void MeshUtils::buildNode2Elements(const Mesh & mesh,
CSR<Element> & node_to_elem,
- UInt spatial_dimension) {
+ Int spatial_dimension) {
AKANTU_DEBUG_IN();
if (spatial_dimension == _all_dimensions) {
spatial_dimension = mesh.getSpatialDimension();
}
/// count number of occurrence of each node
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
/// array for the node-element list
node_to_elem.resizeRows(nb_nodes);
node_to_elem.clearRows();
for_each_element(
mesh,
[&](auto && element) {
- Vector<UInt> conn = mesh.getConnectivity(element);
+ auto conn = mesh.getConnectivity(element);
for (auto && node : conn) {
++node_to_elem.rowOffset(node);
}
},
_spatial_dimension = spatial_dimension, _element_kind = _ek_not_defined);
node_to_elem.countToCSR();
node_to_elem.resizeCols();
/// rearrange element to get the node-element list
// Element e;
node_to_elem.beginInsertions();
for_each_element(
mesh,
[&](auto && element) {
- Vector<UInt> conn = mesh.getConnectivity(element);
+ auto conn = mesh.getConnectivity(element);
for (auto && node : conn) {
node_to_elem.insertInRow(node, element);
}
},
_spatial_dimension = spatial_dimension, _element_kind = _ek_not_defined);
node_to_elem.endInsertions();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildNode2ElementsElementTypeMap(const Mesh & mesh,
- CSR<UInt> & node_to_elem,
+ CSR<Idx> & node_to_elem,
ElementType type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_elements = mesh.getConnectivity(type, ghost_type).size();
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_elements = mesh.getConnectivity(type, ghost_type).size();
- UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage();
+ auto * conn_val = mesh.getConnectivity(type, ghost_type).data();
/// array for the node-element list
node_to_elem.resizeRows(nb_nodes);
node_to_elem.clearRows();
/// count number of occurrence of each node
- for (UInt el = 0; el < nb_elements; ++el) {
- UInt el_offset = el * nb_nodes_per_element;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int el = 0; el < nb_elements; ++el) {
+ auto el_offset = el * nb_nodes_per_element;
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
++node_to_elem.rowOffset(conn_val[el_offset + n]);
}
}
/// convert the occurrence array in a csr one
node_to_elem.countToCSR();
node_to_elem.resizeCols();
node_to_elem.beginInsertions();
/// save the element index in the node-element list
- for (UInt el = 0; el < nb_elements; ++el) {
- UInt el_offset = el * nb_nodes_per_element;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int el = 0; el < nb_elements; ++el) {
+ auto el_offset = el * nb_nodes_per_element;
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
node_to_elem.insertInRow(conn_val[el_offset + n], el);
}
}
node_to_elem.endInsertions();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildFacets(Mesh & mesh) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
for (auto ghost_type : ghost_types) {
for (const auto & type :
mesh.elementTypes(spatial_dimension - 1, ghost_type)) {
mesh.getConnectivity(type, ghost_type).resize(0);
// \todo inform the mesh event handler
}
}
buildFacetsDimension(mesh, mesh, true, spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets,
- UInt to_dimension) {
+ Int to_dimension) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
buildAllFacets(mesh, mesh_facets, spatial_dimension, to_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets,
- UInt from_dimension, UInt to_dimension) {
+ Int from_dimension, Int to_dimension) {
AKANTU_DEBUG_IN();
- to_dimension = std::max(to_dimension, UInt(0));
+ to_dimension = std::max(to_dimension, Int(0));
AKANTU_DEBUG_ASSERT(
mesh_facets.isMeshFacets(),
"The mesh_facets should be initialized with initMeshFacets");
/// generate facets
buildFacetsDimension(mesh, mesh_facets, false, from_dimension);
/// sort facets and generate sub-facets
- for (UInt i = from_dimension - 1; i > to_dimension; --i) {
+ for (Int i = from_dimension - 1; i > to_dimension; --i) {
buildFacetsDimension(mesh_facets, mesh_facets, false, i);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::buildFacetsDimension(const Mesh & mesh, Mesh & mesh_facets,
- bool boundary_only, UInt dimension) {
+ bool boundary_only, Int dimension) {
AKANTU_DEBUG_IN();
// save the current parent of mesh_facets and set it temporarly to mesh since
// mesh is the one containing the elements for which mesh_facets has the
// sub-elements
// example: if the function is called with mesh = mesh_facets
const Mesh * mesh_facets_parent = nullptr;
try {
mesh_facets_parent = &mesh_facets.getMeshParent();
} catch (...) {
}
mesh_facets.defineMeshParent(mesh);
MeshAccessor mesh_accessor(mesh_facets);
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto spatial_dimension = mesh.getSpatialDimension();
const Array<Real> & mesh_facets_nodes = mesh_facets.getNodes();
const auto mesh_facets_nodes_it = mesh_facets_nodes.begin(spatial_dimension);
CSR<Element> node_to_elem;
buildNode2Elements(mesh, node_to_elem, dimension);
- Array<UInt> counter;
+ Array<Int> counter;
std::vector<Element> connected_elements;
NewElementsEvent event(AKANTU_CURRENT_FUNCTION);
// init the SubelementToElement data to improve performance
for (auto && ghost_type : ghost_types) {
for (auto && type : mesh.elementTypes(dimension, ghost_type)) {
auto & subelement_to_element =
mesh_accessor.getSubelementToElement(type, ghost_type);
subelement_to_element.resize(mesh.getNbElement(type, ghost_type),
ElementNull);
auto facet_types = mesh.getAllFacetTypes(type);
- for (auto && ft : arange(facet_types.size())) {
- auto facet_type = facet_types(ft);
+ for (auto && facet_type : facet_types) {
mesh_accessor.getElementToSubelement(facet_type, ghost_type);
mesh_accessor.getConnectivity(facet_type, ghost_type);
}
}
}
const ElementSynchronizer * synchronizer = nullptr;
if (mesh.isDistributed()) {
synchronizer = &(mesh.getElementSynchronizer());
}
Element current_element;
for (auto && ghost_type : ghost_types) {
GhostType facet_ghost_type = ghost_type;
current_element.ghost_type = ghost_type;
for (auto && type : mesh.elementTypes(dimension, ghost_type)) {
auto facet_types = mesh.getAllFacetTypes(type);
current_element.type = type;
for (auto && ft : arange(facet_types.size())) {
auto facet_type = facet_types(ft);
auto nb_element = mesh.getNbElement(type, ghost_type);
auto && element_to_subelement =
&mesh_accessor.getElementToSubelementNC(facet_type, ghost_type);
auto && connectivity_facets =
&mesh_accessor.getConnectivity(facet_type, ghost_type);
auto nb_nodes_per_facet = connectivity_facets->getNbComponent();
// Vector<UInt> facet(nb_nodes_per_facet);
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
current_element.element = el;
- auto && facets =
+ Matrix<Idx> facets =
mesh.getFacetConnectivity(current_element, ft).transpose();
- for (auto facet : facets) {
+ for (auto & facet : facets) {
// facet = facets(f);
- UInt first_node_nb_elements = node_to_elem.getNbCols(facet(0));
+ auto first_node_nb_elements = node_to_elem.getNbCols(facet(0));
counter.resize(first_node_nb_elements);
counter.zero();
// loop over the other nodes to search intersecting elements,
// which are the elements that share another node with the
// starting element after first_node
for (auto && data : enumerate(node_to_elem.getRow(facet(0)))) {
auto && local_el = std::get<0>(data);
auto && first_node = std::get<1>(data);
for (auto n : arange(1, nb_nodes_per_facet)) {
auto && node_elements = node_to_elem.getRow(facet(n));
counter(local_el) += std::count(
node_elements.begin(), node_elements.end(), first_node);
}
}
// counting the number of elements connected to the facets and
// taking the minimum element number, because the facet should
// be inserted just once
- UInt nb_element_connected_to_facet = 0;
- Element minimum_el = ElementNull;
+ auto nb_element_connected_to_facet = 0;
+ auto minimum_el = ElementNull;
connected_elements.clear();
for (auto && data : enumerate(node_to_elem.getRow(facet(0)))) {
if (not(counter(std::get<0>(data)) == nb_nodes_per_facet - 1)) {
continue;
}
auto && real_el = std::get<1>(data);
++nb_element_connected_to_facet;
minimum_el = std::min(minimum_el, real_el);
connected_elements.push_back(real_el);
}
if (minimum_el != current_element) {
continue;
}
bool full_ghost_facet = false;
- UInt n = 0;
+ Int n = 0;
while (n < nb_nodes_per_facet and mesh.isPureGhostNode(facet(n))) {
++n;
}
if (n == nb_nodes_per_facet) {
full_ghost_facet = true;
}
if (full_ghost_facet) {
continue;
}
if (boundary_only and nb_element_connected_to_facet != 1) {
continue;
}
std::vector<Element> elements;
// build elements_on_facets: linearized_el must come first
// in order to store the facet in the correct direction
// and avoid to invert the sign in the normal computation
elements.reserve(elements.size() + connected_elements.size());
for (auto && connected_element : connected_elements) {
elements.push_back(connected_element);
}
if (nb_element_connected_to_facet == 1) { /// boundary facet
elements.push_back(ElementNull);
} else if (nb_element_connected_to_facet == 2) { /// internal facet
/// check if facet is in between ghost and normal
/// elements: if it's the case, the facet is either
/// ghost or not ghost. The criterion to decide this
/// is arbitrary. It was chosen to check the processor
/// id (prank) of the two neighboring elements. If
/// prank of the ghost element is lower than prank of
/// the normal one, the facet is not ghost, otherwise
/// it's ghost
GhostType gt[2] = {_not_ghost, _not_ghost};
- for (UInt el = 0; el < connected_elements.size(); ++el) {
- gt[el] = connected_elements[el].ghost_type;
+ for (auto && data : enumerate(connected_elements)) {
+ gt[std::get<0>(data)] = std::get<1>(data).ghost_type;
}
if ((gt[0] == _not_ghost) xor (gt[1] == _not_ghost)) {
- UInt prank[2];
- for (UInt el = 0; el < 2; ++el) {
+ Int prank[2];
+ for (Int el = 0; el < 2; ++el) {
prank[el] = synchronizer->getRank(connected_elements[el]);
}
// ugly trick from Marco detected :P
bool ghost_one = (gt[0] != _ghost);
if (prank[ghost_one] > prank[!ghost_one]) {
facet_ghost_type = _not_ghost;
} else {
facet_ghost_type = _ghost;
}
connectivity_facets = &mesh_accessor.getConnectivity(
facet_type, facet_ghost_type);
element_to_subelement = &mesh_accessor.getElementToSubelementNC(
facet_type, facet_ghost_type);
}
}
element_to_subelement->push_back(elements);
connectivity_facets->push_back(facet);
/// current facet index
- UInt current_facet = connectivity_facets->size() - 1;
+ auto current_facet = connectivity_facets->size() - 1;
Element facet_element{facet_type, current_facet, facet_ghost_type};
event.getList().push_back(facet_element);
/// loop on every element connected to current facet and
/// insert current facet in the first free spot of the
/// subelement_to_element vector
for (auto & loc_el : elements) {
if (loc_el == ElementNull) {
continue;
}
auto && subelements =
mesh_accessor.getSubelementToElement(loc_el);
for (auto & el : subelements) {
if (el != ElementNull) {
continue;
}
el = facet_element;
break;
}
}
/// reset connectivity in case a facet was found in
/// between ghost and normal elements
if (facet_ghost_type != ghost_type) {
facet_ghost_type = ghost_type;
connectivity_facets =
&mesh_accessor.getConnectivity(facet_type, facet_ghost_type);
element_to_subelement = &mesh_accessor.getElementToSubelement(
facet_type, facet_ghost_type);
}
}
}
}
}
}
mesh_facets.sendEvent(event);
// restore the parent of mesh_facet
if (mesh_facets_parent != nullptr) {
mesh_facets.defineMeshParent(*mesh_facets_parent);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::renumberMeshNodes(Mesh & mesh,
- Array<UInt> & local_connectivities,
- UInt nb_local_element, UInt nb_ghost_element,
+ Array<Idx> & local_connectivities,
+ Int nb_local_element, Int nb_ghost_element,
ElementType type,
- Array<UInt> & old_nodes_numbers) {
+ Array<Idx> & old_nodes_numbers) {
AKANTU_DEBUG_IN();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- std::map<UInt, UInt> renumbering_map;
- for (UInt i = 0; i < old_nodes_numbers.size(); ++i) {
+ std::map<Idx, Idx> renumbering_map;
+ for (Int i = 0; i < old_nodes_numbers.size(); ++i) {
renumbering_map[old_nodes_numbers(i)] = i;
}
/// renumber the nodes
renumberNodesInConnectivity(local_connectivities,
(nb_local_element + nb_ghost_element) *
nb_nodes_per_element,
renumbering_map);
old_nodes_numbers.resize(renumbering_map.size());
for (auto & renumber_pair : renumbering_map) {
old_nodes_numbers(renumber_pair.second) = renumber_pair.first;
}
renumbering_map.clear();
MeshAccessor mesh_accessor(mesh);
/// copy the renumbered connectivity to the right place
auto & local_conn = mesh_accessor.getConnectivity(type);
local_conn.resize(nb_local_element);
if (nb_local_element > 0) {
- memcpy(local_conn.storage(), local_connectivities.storage(),
- nb_local_element * nb_nodes_per_element * sizeof(UInt));
+ std::copy_n(local_connectivities.data(),
+ nb_local_element * nb_nodes_per_element, local_conn.data());
}
auto & ghost_conn = mesh_accessor.getConnectivity(type, _ghost);
ghost_conn.resize(nb_ghost_element);
if (nb_ghost_element > 0) {
- std::memcpy(ghost_conn.storage(),
- local_connectivities.storage() +
+ std::copy_n(local_connectivities.data() +
nb_local_element * nb_nodes_per_element,
- nb_ghost_element * nb_nodes_per_element * sizeof(UInt));
+ nb_ghost_element * nb_nodes_per_element, ghost_conn.data());
}
- auto & ghost_counter = mesh_accessor.getGhostsCounters(type, _ghost);
- ghost_counter.resize(nb_ghost_element, 1);
-
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::renumberNodesInConnectivity(
- Array<UInt> & list_nodes, UInt nb_nodes,
- std::map<UInt, UInt> & renumbering_map) {
+ Array<Idx> & list_nodes, Int nb_nodes,
+ std::map<Idx, Idx> & renumbering_map) {
AKANTU_DEBUG_IN();
- UInt * connectivity = list_nodes.storage();
- UInt new_node_num = renumbering_map.size();
- for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) {
- UInt & node = *connectivity;
+ auto * connectivity = list_nodes.data();
+ auto new_node_num = renumbering_map.size();
+ for (Int n = 0; n < nb_nodes; ++n, ++connectivity) {
+ auto & node = *connectivity;
auto it = renumbering_map.find(node);
if (it == renumbering_map.end()) {
- UInt old_node = node;
+ auto old_node = node;
renumbering_map[old_node] = new_node_num;
node = new_node_num;
++new_node_num;
} else {
node = it->second;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::purifyMesh(Mesh & mesh) {
AKANTU_DEBUG_IN();
- std::map<UInt, UInt> renumbering_map;
+ std::map<Idx, Idx> renumbering_map;
RemovedNodesEvent remove_nodes(mesh, AKANTU_CURRENT_FUNCTION);
- Array<UInt> & nodes_removed = remove_nodes.getList();
+ auto & nodes_removed = remove_nodes.getList();
for (auto ghost_type : ghost_types) {
for (auto type :
mesh.elementTypes(_all_dimensions, ghost_type, _ek_not_defined)) {
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
- UInt nb_element(connectivity.size());
+ auto & connectivity = mesh.getConnectivity(type, ghost_type);
+ auto nb_element(connectivity.size());
renumberNodesInConnectivity(
connectivity, nb_element * nb_nodes_per_element, renumbering_map);
}
}
- Array<UInt> & new_numbering = remove_nodes.getNewNumbering();
- std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1));
+ auto & new_numbering = remove_nodes.getNewNumbering();
+ std::fill(new_numbering.begin(), new_numbering.end(), Int(-1));
for (auto && pair : renumbering_map) {
new_numbering(std::get<0>(pair)) = std::get<1>(pair);
}
- for (UInt i = 0; i < new_numbering.size(); ++i) {
- if (new_numbering(i) == UInt(-1)) {
+ for (Int i = 0; i < new_numbering.size(); ++i) {
+ if (new_numbering(i) == Int(-1)) {
nodes_removed.push_back(i);
}
}
mesh.sendEvent(remove_nodes);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::flipFacets(
Mesh & mesh_facets,
- const ElementTypeMapArray<UInt> & remote_global_connectivities,
+ const ElementTypeMapArray<Idx> & remote_global_connectivities,
GhostType gt_facet) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh_facets.getSpatialDimension();
+ auto spatial_dimension = mesh_facets.getSpatialDimension();
/// get global connectivity for local mesh
- ElementTypeMapArray<UInt> local_global_connectivities(
+ ElementTypeMapArray<Idx> local_global_connectivities(
"local_global_connectivity", mesh_facets.getID());
local_global_connectivities.initialize(
mesh_facets, _spatial_dimension = spatial_dimension - 1,
_ghost_type = gt_facet, _with_nb_nodes_per_element = true,
_with_nb_element = true);
mesh_facets.getGlobalConnectivity(local_global_connectivities);
MeshAccessor mesh_accessor(mesh_facets);
/// loop on every facet
for (auto type_facet :
mesh_facets.elementTypes(spatial_dimension - 1, gt_facet)) {
auto & connectivity = mesh_accessor.getConnectivity(type_facet, gt_facet);
auto & local_global_connectivity =
local_global_connectivities(type_facet, gt_facet);
const auto & remote_global_connectivity =
remote_global_connectivities(type_facet, gt_facet);
auto & element_per_facet =
mesh_accessor.getElementToSubelementNC(type_facet, gt_facet);
auto & subfacet_to_facet =
mesh_accessor.getSubelementToElementNC(type_facet, gt_facet);
auto nb_nodes_per_facet = connectivity.getNbComponent();
auto nb_nodes_per_P1_facet =
Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type_facet));
for (auto && data :
zip(make_view(connectivity, nb_nodes_per_facet),
make_view(local_global_connectivity, nb_nodes_per_facet),
make_view(remote_global_connectivity, nb_nodes_per_facet),
make_view(subfacet_to_facet, subfacet_to_facet.getNbComponent()),
make_view(element_per_facet))) {
auto & conn = std::get<0>(data);
auto & local_gconn = std::get<1>(data);
const auto & remote_gconn = std::get<2>(data);
/// skip facet if connectivities are the same
if (local_gconn == remote_gconn) {
continue;
}
/// re-arrange connectivity
- auto conn_tmp = conn;
+ Vector<Idx> conn_tmp = conn;
auto begin = local_gconn.begin();
auto end = local_gconn.end();
AKANTU_DEBUG_ASSERT(std::is_permutation(begin, end, remote_gconn.begin()),
"This facets are not just permutation of each other, "
<< local_gconn << " and " << remote_gconn);
for (auto && data : enumerate(remote_gconn)) {
auto it = std::find(begin, end, std::get<1>(data));
AKANTU_DEBUG_ASSERT(it != end, "Node not found");
- UInt new_position = it - begin;
+ auto new_position = it - begin;
conn(new_position) = conn_tmp(std::get<0>(data));
- ;
}
// std::transform(remote_gconn.begin(), remote_gconn.end(), conn.begin(),
// [&](auto && gnode) {
// auto it = std::find(begin, end, gnode);
// AKANTU_DEBUG_ASSERT(it != end, "Node not found");
// return conn_tmp(it - begin);
// });
/// if 3D, check if facets are just rotated
if (spatial_dimension == 3) {
auto begin = remote_gconn.begin();
/// find first node
auto it = std::find(begin, remote_gconn.end(), local_gconn(0));
- UInt n;
- UInt start = it - begin;
+ auto start = it - begin;
+ decltype(start) n;
/// count how many nodes in the received connectivity follow
/// the same order of those in the local connectivity
for (n = 1; n < nb_nodes_per_P1_facet &&
local_gconn(n) ==
remote_gconn((start + n) % nb_nodes_per_P1_facet);
++n) {
;
}
/// skip the facet inversion if facet is just rotated
if (n == nb_nodes_per_P1_facet) {
continue;
}
}
/// update data to invert facet
auto & element_per_facet = std::get<4>(data);
if (element_per_facet[1] !=
ElementNull) { // by convention the first facet
// cannot be a ElementNull
std::swap(element_per_facet[0], element_per_facet[1]);
}
auto & subfacets_of_facet = std::get<3>(data);
std::swap(subfacets_of_facet(0), subfacets_of_facet(1));
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MeshUtils::fillElementToSubElementsData(Mesh & mesh) {
AKANTU_DEBUG_IN();
if (mesh.getNbElement(mesh.getSpatialDimension() - 1) == 0) {
AKANTU_DEBUG_INFO("There are not facets, add them in the mesh file or call "
"the buildFacet method.");
return;
}
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
ElementTypeMapArray<Real> barycenters("barycenter_tmp", mesh.getID());
barycenters.initialize(mesh, _nb_component = spatial_dimension,
_spatial_dimension = _all_dimensions);
Element element;
for (auto ghost_type : ghost_types) {
element.ghost_type = ghost_type;
for (const auto & type : mesh.elementTypes(_all_dimensions, ghost_type)) {
element.type = type;
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- Array<Real> & barycenters_arr = barycenters(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
+ auto & barycenters_arr = barycenters(type, ghost_type);
barycenters_arr.resize(nb_element);
auto bary = barycenters_arr.begin(spatial_dimension);
auto bary_end = barycenters_arr.end(spatial_dimension);
- for (UInt el = 0; bary != bary_end; ++bary, ++el) {
+ for (Int el = 0; bary != bary_end; ++bary, ++el) {
element.element = el;
mesh.getBarycenter(element, *bary);
}
}
}
MeshAccessor mesh_accessor(mesh);
for (Int sp(spatial_dimension); sp >= 1; --sp) {
if (mesh.getNbElement(sp) == 0) {
continue;
}
for (auto ghost_type : ghost_types) {
for (const auto & type : mesh.elementTypes(sp, ghost_type)) {
auto & subelement_to_element =
mesh_accessor.getSubelementToElement(type, ghost_type);
subelement_to_element.resize(mesh.getNbElement(type, ghost_type));
subelement_to_element.set(ElementNull);
}
for (const auto & type : mesh.elementTypes(sp - 1, ghost_type)) {
auto & element_to_subelement =
mesh_accessor.getElementToSubelement(type, ghost_type);
element_to_subelement.resize(mesh.getNbElement(type, ghost_type));
element_to_subelement.clear();
}
}
CSR<Element> nodes_to_elements;
buildNode2Elements(mesh, nodes_to_elements, sp);
Element facet_element;
for (auto ghost_type : ghost_types) {
facet_element.ghost_type = ghost_type;
for (const auto & type : mesh.elementTypes(sp - 1, ghost_type)) {
facet_element.type = type;
auto & element_to_subelement =
mesh_accessor.getElementToSubelement(type, ghost_type);
const auto & connectivity = mesh.getConnectivity(type, ghost_type);
- // element_to_subelement.resize(connectivity.size());
for (auto && data : enumerate(
- make_view(connectivity, mesh.getNbNodesPerElement(type)))) {
+ make_view(connectivity, connectivity.getNbComponent()))) {
const auto & facet = std::get<1>(data);
facet_element.element = std::get<0>(data);
- std::map<Element, UInt> element_seen_counter;
+ std::map<Element, Int> element_seen_counter;
auto nb_nodes_per_facet =
mesh.getNbNodesPerElement(Mesh::getP1ElementType(type));
// count the number of node in common between the facet and the
// other element connected to the nodes of the facet
for (auto node : arange(nb_nodes_per_facet)) {
for (auto & elem : nodes_to_elements.getRow(facet(node))) {
auto cit = element_seen_counter.find(elem);
if (cit != element_seen_counter.end()) {
cit->second++;
} else {
element_seen_counter[elem] = 1;
}
}
}
// check which are the connected elements
std::vector<Element> connected_elements;
for (auto && cit : element_seen_counter) {
if (cit.second == nb_nodes_per_facet) {
connected_elements.push_back(cit.first);
}
}
// add the connected elements as sub-elements
for (auto & connected_element : connected_elements) {
element_to_subelement(facet_element.element)
.push_back(connected_element);
}
// add the element as sub-element to the connected elements
for (auto & connected_element : connected_elements) {
- Vector<Element> subelements_to_element =
+ auto subelements_to_element =
mesh.getSubelementToElement(connected_element);
// find the position where to insert the element
auto it = std::find(subelements_to_element.begin(),
subelements_to_element.end(), ElementNull);
AKANTU_DEBUG_ASSERT(
it != subelements_to_element.end(),
"The element "
<< connected_element << " seems to have too many facets!! ("
<< (it - subelements_to_element.begin()) << " < "
<< mesh.getNbFacetsPerElement(connected_element.type)
<< ")");
*it = facet_element;
}
}
}
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/mesh_utils/mesh_utils.hh b/src/mesh_utils/mesh_utils.hh
index a2013784b..97f349860 100644
--- a/src/mesh_utils/mesh_utils.hh
+++ b/src/mesh_utils/mesh_utils.hh
@@ -1,139 +1,139 @@
/**
* @file mesh_utils.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Leonardo Snozzi <leonardo.snozzi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Jan 14 2021
*
* @brief All mesh utils necessary for various tasks
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_csr.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MESH_UTILS_HH_
#define AKANTU_MESH_UTILS_HH_
namespace akantu {
class MeshUtils {
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// build a CSR<Element> that contains for each node the list of connected
/// elements of a given spatial dimension
static void buildNode2Elements(const Mesh & mesh, CSR<Element> & node_to_elem,
- UInt spatial_dimension = _all_dimensions);
+ Int spatial_dimension = _all_dimensions);
/// build a CSR<UInt> that contains for each node the number of
/// the connected elements of a given ElementType
static void
- buildNode2ElementsElementTypeMap(const Mesh & mesh, CSR<UInt> & node_to_elem,
+ buildNode2ElementsElementTypeMap(const Mesh & mesh, CSR<Idx> & node_to_elem,
ElementType type,
GhostType ghost_type = _not_ghost);
/// build the facets elements on the boundaries of a mesh
static void buildFacets(Mesh & mesh);
/// build all the facets elements: boundary and internals and store them in
/// the mesh_facets for element of dimension from_dimension to to_dimension
static void buildAllFacets(const Mesh & mesh, Mesh & mesh_facets,
- UInt from_dimension, UInt to_dimension);
+ Int from_dimension, Int to_dimension);
/// build all the facets elements: boundary and internals and store them in
/// the mesh_facets
static void buildAllFacets(const Mesh & mesh, Mesh & mesh_facets,
- UInt to_dimension = 0);
+ Int to_dimension = 0);
/// build facets for a given spatial dimension
static void buildFacetsDimension(const Mesh & mesh, Mesh & mesh_facets,
- bool boundary_only, UInt dimension);
+ bool boundary_only, Int dimension);
/// take the local_connectivity array as the array of local and ghost
/// connectivity, renumber the nodes and set the connectivity of the mesh
- static void renumberMeshNodes(Mesh & mesh, Array<UInt> & local_connectivities,
- UInt nb_local_element, UInt nb_ghost_element,
- ElementType type, Array<UInt> & old_nodes);
+ static void renumberMeshNodes(Mesh & mesh, Array<Idx> & local_connectivities,
+ Int nb_local_element, Int nb_ghost_element,
+ ElementType type, Array<Idx> & old_nodes);
/// compute pbc pair for a given direction
- static void computePBCMap(const Mesh & mymesh, UInt dir,
- std::map<UInt, UInt> & pbc_pair);
+ static void computePBCMap(const Mesh & mymesh, Int dir,
+ std::map<Idx, Idx> & pbc_pair);
/// compute pbc pair for a surface pair
static void computePBCMap(const Mesh & mymesh,
const std::pair<ID, ID> & surface_pair,
- std::map<UInt, UInt> & pbc_pair);
+ std::map<Idx, Idx> & pbc_pair);
/// remove not connected nodes /!\ this functions renumbers the nodes.
static void purifyMesh(Mesh & mesh);
/// fill the subelement to element and the elements to subelements data
static void fillElementToSubElementsData(Mesh & mesh);
/// flip facets based on global connectivity
static void
flipFacets(Mesh & mesh_facets,
- const ElementTypeMapArray<UInt> & remote_global_connectivities,
+ const ElementTypeMapArray<Idx> & remote_global_connectivities,
GhostType gt_facet);
private:
/// match pairs that are on the associated pbc's
- static void matchPBCPairs(const Mesh & mymesh, UInt dir,
- Array<UInt> & selected_left,
- Array<UInt> & selected_right,
- std::map<UInt, UInt> & pbc_pair);
+ static void matchPBCPairs(const Mesh & mymesh, Int dir,
+ Array<Idx> & selected_left,
+ Array<Idx> & selected_right,
+ std::map<Idx, Idx> & pbc_pair);
/// function used by all the renumbering functions
static void
- renumberNodesInConnectivity(Array<UInt> & list_nodes, UInt nb_nodes,
- std::map<UInt, UInt> & renumbering_map);
+ renumberNodesInConnectivity(Array<Idx> & list_nodes, Int nb_nodes,
+ std::map<Idx, Idx> & renumbering_map);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "mesh_utils_inline_impl.hh"
#endif /* AKANTU_MESH_UTILS_HH_ */
diff --git a/src/mesh_utils/mesh_utils_distribution.cc b/src/mesh_utils/mesh_utils_distribution.cc
index 3d80c271c..2917d7108 100644
--- a/src/mesh_utils/mesh_utils_distribution.cc
+++ b/src/mesh_utils/mesh_utils_distribution.cc
@@ -1,164 +1,162 @@
/**
* @file mesh_utils_distribution.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Wed Mar 04 2020
*
* @brief Implementation of the methods of mesh utils distribute
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_utils_distribution.hh"
#include "element_info_per_processor.hh"
#include "element_synchronizer.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
#include "mesh_partition.hh"
#include "mesh_utils.hh"
#include "node_info_per_processor.hh"
#include "node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace MeshUtilsDistribution {
/* ------------------------------------------------------------------------ */
void distributeMeshCentralized(Mesh & mesh, UInt /*unused*/,
const MeshPartition & partition) {
MeshAccessor mesh_accessor(mesh);
- ElementSynchronizer & element_synchronizer =
- mesh_accessor.getElementSynchronizer();
- NodeSynchronizer & node_synchronizer = mesh_accessor.getNodeSynchronizer();
+ auto & element_synchronizer = mesh_accessor.getElementSynchronizer();
+ auto & node_synchronizer = mesh_accessor.getNodeSynchronizer();
- const Communicator & comm = element_synchronizer.getCommunicator();
+ const auto & comm = element_synchronizer.getCommunicator();
- UInt nb_proc = comm.getNbProc();
- UInt my_rank = comm.whoAmI();
+ auto nb_proc = comm.getNbProc();
+ auto my_rank = comm.whoAmI();
mesh_accessor.setNbGlobalNodes(mesh.getNbNodes());
auto & gids = mesh_accessor.getNodesGlobalIds();
if (nb_proc == 1) {
return;
}
gids.resize(0);
mesh.synchronizeGroupNames();
AKANTU_DEBUG_ASSERT(
partition.getNbPartition() == nb_proc,
"The number of partition does not match the number of processors: "
<< partition.getNbPartition() << " != " << nb_proc);
/**
* connectivity and communications scheme construction
*/
UInt count = 0;
/* --- MAIN LOOP ON TYPES --- */
for (auto && type :
mesh.elementTypes(_all_dimensions, _not_ghost, _ek_not_defined)) {
/// \todo change this ugly way to avoid a problem if an element
/// type is present in the mesh but not in the partitions
try {
partition.getPartition(type, _not_ghost);
} catch (...) {
continue;
}
MasterElementInfoPerProc proc_infos(element_synchronizer, count, my_rank,
type, partition);
proc_infos.synchronize();
++count;
}
{ /// Ending the synchronization of elements by sending a stop message
MasterElementInfoPerProc proc_infos(element_synchronizer, count, my_rank,
_not_defined, partition);
proc_infos.synchronize();
++count;
}
/**
* Nodes synchronization
*/
MasterNodeInfoPerProc node_proc_infos(node_synchronizer, count, my_rank);
node_proc_infos.synchronize();
MeshUtils::fillElementToSubElementsData(mesh);
mesh_accessor.setDistributed();
AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------ */
void distributeMeshCentralized(Mesh & mesh, UInt root) {
MeshAccessor mesh_accessor(mesh);
- ElementSynchronizer & element_synchronizer =
- mesh_accessor.getElementSynchronizer();
- NodeSynchronizer & node_synchronizer = mesh_accessor.getNodeSynchronizer();
+ auto & element_synchronizer = mesh_accessor.getElementSynchronizer();
+ auto & node_synchronizer = mesh_accessor.getNodeSynchronizer();
- const Communicator & comm = element_synchronizer.getCommunicator();
+ const auto & comm = element_synchronizer.getCommunicator();
- UInt nb_proc = comm.getNbProc();
+ auto nb_proc = comm.getNbProc();
mesh_accessor.getNodesGlobalIds().resize(0);
if (nb_proc == 1) {
return;
}
mesh.synchronizeGroupNames();
/**
* connectivity and communications scheme construction on distant
* processors
*/
UInt count = 0;
bool need_synchronize = true;
do {
/* --------<<<<-SIZE--------------------------------------------------- */
SlaveElementInfoPerProc proc_infos(element_synchronizer, count, root);
need_synchronize = proc_infos.synchronize();
++count;
} while (need_synchronize);
/**
* Nodes synchronization
*/
SlaveNodeInfoPerProc node_proc_infos(node_synchronizer, count, root);
node_proc_infos.synchronize();
MeshUtils::fillElementToSubElementsData(mesh);
mesh_accessor.setDistributed();
}
} // namespace MeshUtilsDistribution
} // namespace akantu
diff --git a/src/mesh_utils/mesh_utils_pbc.cc b/src/mesh_utils/mesh_utils_pbc.cc
index 33465e238..dad487e5b 100644
--- a/src/mesh_utils/mesh_utils_pbc.cc
+++ b/src/mesh_utils/mesh_utils_pbc.cc
@@ -1,311 +1,307 @@
/**
* @file mesh_utils_pbc.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Wed Feb 09 2011
* @date last modification: Wed Mar 04 2020
*
* @brief periodic boundary condition connectivity tweak
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "mesh_accessor.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/// class that sorts a set of nodes of same coordinates in 'dir' direction
class CoordinatesComparison {
public:
- CoordinatesComparison(const UInt dimension, const UInt dir_1,
- const UInt dir_2, Real normalization, Real tolerance,
+ CoordinatesComparison(const Int dimension, const Int dir_1, const Int dir_2,
+ Real normalization, Real tolerance,
const Array<Real> & coords)
: dim(dimension), dir_1(dir_1), dir_2(dir_2),
normalization(normalization), tolerance(tolerance),
coords_it(coords.begin(dim)) {}
// answers the question whether n2 is larger or equal to n1
- bool operator()(const UInt n1, const UInt n2) {
+ bool operator()(const Idx n1, const Idx n2) {
Vector<Real> coords_n1 = coords_it[n1];
Vector<Real> coords_n2 = coords_it[n2];
return this->operator()(coords_n1, coords_n2);
}
bool operator()(const Vector<Real> & coords_n1,
const Vector<Real> & coords_n2) const {
Real diff = coords_n1(dir_1) - coords_n2(dir_1);
;
if (dim == 2 || std::abs(diff) / normalization > tolerance) {
return (diff <= 0.);
}
if (dim > 2) {
diff = coords_n1(dir_2) - coords_n2(dir_2);
return (diff <= 0);
}
return true;
}
private:
- UInt dim;
- UInt dir_1;
- UInt dir_2;
+ Int dim;
+ Int dir_1;
+ Int dir_2;
Real normalization;
Real tolerance;
- const Array<Real>::const_vector_iterator coords_it;
+ Array<Real>::const_vector_iterator coords_it;
};
/* -------------------------------------------------------------------------- */
-void MeshUtils::computePBCMap(const Mesh & mesh, const UInt dir,
- std::map<UInt, UInt> & pbc_pair) {
- Array<UInt> selected_left;
- Array<UInt> selected_right;
-
- const UInt dim = mesh.getSpatialDimension();
- auto it = mesh.getNodes().begin(dim);
- auto end = mesh.getNodes().end(dim);
+void MeshUtils::computePBCMap(const Mesh & mesh, const Int dir,
+ std::map<Idx, Idx> & pbc_pair) {
+ Array<Idx> selected_left;
+ Array<Idx> selected_right;
+ const auto dim = mesh.getSpatialDimension();
if (dim <= dir) {
return;
}
- const Vector<Real> & lower_bounds = mesh.getLowerBounds();
- const Vector<Real> & upper_bounds = mesh.getUpperBounds();
+ const auto & lower_bounds = mesh.getLowerBounds();
+ const auto & upper_bounds = mesh.getUpperBounds();
AKANTU_DEBUG_INFO("min " << lower_bounds(dir));
AKANTU_DEBUG_INFO("max " << upper_bounds(dir));
- for (UInt node = 0; it != end; ++it, ++node) {
- const Vector<Real> & coords = *it;
+ for (auto && data : enumerate(make_view(mesh.getNodes(), dim))) {
+ auto node = std::get<0>(data);
+ auto && coords = std::get<1>(data);
+
AKANTU_DEBUG_TRACE("treating " << coords(dir));
if (Math::are_float_equal(coords(dir), lower_bounds(dir))) {
AKANTU_DEBUG_TRACE("pushing node " << node << " on the left side");
selected_left.push_back(node);
} else if (Math::are_float_equal(coords(dir), upper_bounds(dir))) {
selected_right.push_back(node);
AKANTU_DEBUG_TRACE("pushing node " << node << " on the right side");
}
}
AKANTU_DEBUG_INFO("found "
<< selected_left.size() << " and " << selected_right.size()
<< " nodes at each boundary for direction " << dir);
// match pairs
MeshUtils::matchPBCPairs(mesh, dir, selected_left, selected_right, pbc_pair);
}
/* -------------------------------------------------------------------------- */
void MeshUtils::computePBCMap(const Mesh & mesh,
const std::pair<ID, ID> & surface_pair,
- std::map<UInt, UInt> & pbc_pair) {
+ std::map<Idx, Idx> & pbc_pair) {
- Array<UInt> selected_first;
- Array<UInt> selected_second;
+ Array<Idx> selected_first;
+ Array<Idx> selected_second;
// find nodes on surfaces
- const ElementGroup & first_surf = mesh.getElementGroup(surface_pair.first);
- const ElementGroup & second_surf = mesh.getElementGroup(surface_pair.second);
+ const auto & first_surf = mesh.getElementGroup(surface_pair.first);
+ const auto & second_surf = mesh.getElementGroup(surface_pair.second);
// if this surface pair is not on this proc
if (first_surf.getNbNodes() == 0 || second_surf.getNbNodes() == 0) {
AKANTU_DEBUG_WARNING("computePBCMap has at least one surface without any "
"nodes. I will ignore it.");
return;
}
// copy nodes from element group
selected_first.copy(first_surf.getNodeGroup().getNodes());
selected_second.copy(second_surf.getNodeGroup().getNodes());
// coordinates
- const Array<Real> & coords = mesh.getNodes();
- const UInt dim = mesh.getSpatialDimension();
+ const auto & coords = mesh.getNodes();
+ const auto dim = mesh.getSpatialDimension();
// variables to find min and max of surfaces
- Real first_max[3];
- Real first_min[3];
- Real second_max[3];
- Real second_min[3];
- for (UInt i = 0; i < dim; ++i) {
+ Real first_max[3], first_min[3];
+ Real second_max[3], second_min[3];
+ for (Int i = 0; i < dim; ++i) {
first_min[i] = std::numeric_limits<Real>::max();
second_min[i] = std::numeric_limits<Real>::max();
first_max[i] = -std::numeric_limits<Real>::max();
second_max[i] = -std::numeric_limits<Real>::max();
}
// find min and max of surface nodes
for (auto it = selected_first.begin(); it != selected_first.end(); ++it) {
- for (UInt i = 0; i < dim; ++i) {
+ for (Int i = 0; i < dim; ++i) {
if (first_min[i] > coords(*it, i)) {
first_min[i] = coords(*it, i);
}
if (first_max[i] < coords(*it, i)) {
first_max[i] = coords(*it, i);
}
}
}
for (auto it = selected_second.begin(); it != selected_second.end(); ++it) {
- for (UInt i = 0; i < dim; ++i) {
+ for (Int i = 0; i < dim; ++i) {
if (second_min[i] > coords(*it, i)) {
second_min[i] = coords(*it, i);
}
if (second_max[i] < coords(*it, i)) {
second_max[i] = coords(*it, i);
}
}
}
// find direction of pbc
Int first_dir = -1;
#ifndef AKANTU_NDEBUG
Int second_dir = -2;
#endif
- for (UInt i = 0; i < dim; ++i) {
+ for (Int i = 0; i < dim; ++i) {
if (Math::are_float_equal(first_min[i], first_max[i])) {
first_dir = i;
}
#ifndef AKANTU_NDEBUG
if (Math::are_float_equal(second_min[i], second_max[i])) {
second_dir = i;
}
#endif
}
AKANTU_DEBUG_ASSERT(first_dir == second_dir,
"Surface pair has not same direction. Surface "
<< surface_pair.first << " dir=" << first_dir
<< " ; Surface " << surface_pair.second
<< " dir=" << second_dir);
- UInt dir = first_dir;
+ auto dir = first_dir;
// match pairs
if (first_min[dir] < second_min[dir]) {
MeshUtils::matchPBCPairs(mesh, dir, selected_first, selected_second,
pbc_pair);
} else {
MeshUtils::matchPBCPairs(mesh, dir, selected_second, selected_first,
pbc_pair);
}
}
/* -------------------------------------------------------------------------- */
-void MeshUtils::matchPBCPairs(const Mesh & mesh, const UInt dir,
- Array<UInt> & selected_left,
- Array<UInt> & selected_right,
- std::map<UInt, UInt> & pbc_pair) {
+void MeshUtils::matchPBCPairs(const Mesh & mesh, const Int dir,
+ Array<Idx> & selected_left,
+ Array<Idx> & selected_right,
+ std::map<Idx, Idx> & pbc_pair) {
// tolerance is that large because most meshers generate points coordinates
// with single precision only (it is the case of GMSH for instance)
Real tolerance = 1e-7;
- const UInt dim = mesh.getSpatialDimension();
- Real normalization = mesh.getUpperBounds()(dir) - mesh.getLowerBounds()(dir);
+ const auto dim = mesh.getSpatialDimension();
+ auto normalization = mesh.getUpperBounds()(dir) - mesh.getLowerBounds()(dir);
AKANTU_DEBUG_ASSERT(std::abs(normalization) > Math::getTolerance(),
"In matchPBCPairs: The normalization is zero. "
<< "Did you compute the bounding box of the mesh?");
- auto odir_1 = UInt(-1);
- auto odir_2 = UInt(-1);
+ auto odir_1 = Int(-1), odir_2 = Int(-1);
if (dim == 3) {
if (dir == _x) {
odir_1 = _y;
odir_2 = _z;
} else if (dir == _y) {
odir_1 = _x;
odir_2 = _z;
} else if (dir == _z) {
odir_1 = _x;
odir_2 = _y;
}
} else if (dim == 2) {
if (dir == _x) {
odir_1 = _y;
} else if (dir == _y) {
odir_1 = _x;
}
}
CoordinatesComparison compare_nodes(dim, odir_1, odir_2, normalization,
tolerance, mesh.getNodes());
std::sort(selected_left.begin(), selected_left.end(), compare_nodes);
std::sort(selected_right.begin(), selected_right.end(), compare_nodes);
auto it_left = selected_left.begin();
auto end_left = selected_left.end();
auto it_right = selected_right.begin();
auto end_right = selected_right.end();
auto nit = mesh.getNodes().begin(dim);
while ((it_left != end_left) && (it_right != end_right)) {
- UInt i1 = *it_left;
- UInt i2 = *it_right;
+ auto i1 = *it_left;
+ auto i2 = *it_right;
- Vector<Real> coords1 = nit[i1];
- Vector<Real> coords2 = nit[i2];
+ auto coords1 = nit[i1];
+ auto coords2 = nit[i2];
AKANTU_DEBUG_TRACE("do I pair? " << i1 << "(" << coords1 << ") with" << i2
<< "(" << coords2 << ") in direction "
<< dir);
Real dx = 0.0;
Real dy = 0.0;
if (dim >= 2) {
dx = coords1(odir_1) - coords2(odir_1);
}
if (dim == 3) {
dy = coords1(odir_2) - coords2(odir_2);
}
if (std::abs(dx * dx + dy * dy) / normalization < tolerance) {
// then i match these pairs
if (pbc_pair.count(i2) != 0U) {
i2 = pbc_pair[i2];
}
pbc_pair[i1] = i2;
AKANTU_DEBUG_TRACE("pairing " << i1 << "(" << coords1 << ") with" << i2
<< "(" << coords2 << ") in direction "
<< dir);
++it_left;
++it_right;
} else if (compare_nodes(coords1, coords2)) {
++it_left;
} else {
++it_right;
}
}
AKANTU_DEBUG_INFO("found " << pbc_pair.size() << " pairs for direction "
<< dir);
}
} // namespace akantu
diff --git a/src/model/common/boundary_condition/boundary_condition.hh b/src/model/common/boundary_condition/boundary_condition.hh
index 30c4147c2..9908582f6 100644
--- a/src/model/common/boundary_condition/boundary_condition.hh
+++ b/src/model/common/boundary_condition/boundary_condition.hh
@@ -1,100 +1,97 @@
/**
* @file boundary_condition.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief XXX
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_BOUNDARY_CONDITION_HH_
#define AKANTU_BOUNDARY_CONDITION_HH_
#include "aka_common.hh"
#include "boundary_condition_functor.hh"
#include "fe_engine.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
namespace akantu {
template <class ModelType> class BoundaryCondition {
-
/* ------------------------------------------------------------------------ */
/* Typedefs */
/* ------------------------------------------------------------------------ */
private:
/* ------------------------------------------------------------------------ */
/* Constructors / Destructors / Initializers */
/* ------------------------------------------------------------------------ */
public:
BoundaryCondition() : model(nullptr) {}
/// Initialize the boundary conditions
void initBC(ModelType & model, Array<Real> & primal, Array<Real> & dual);
void initBC(ModelType & model, Array<Real> & primal,
Array<Real> & primal_increment, Array<Real> & dual);
/* ------------------------------------------------------------------------ */
/* Methods and accessors */
/* ------------------------------------------------------------------------ */
public:
/// Apply the boundary conditions
template <typename FunctorType> inline void applyBC(const FunctorType & func);
template <class FunctorType>
inline void applyBC(const FunctorType & func, const std::string & group_name);
template <class FunctorType>
inline void applyBC(const FunctorType & func,
const ElementGroup & element_group);
AKANTU_GET_MACRO_NOT_CONST(Model, *model, ModelType &);
AKANTU_GET_MACRO_NOT_CONST(Primal, *primal, Array<Real> &);
AKANTU_GET_MACRO_NOT_CONST(Dual, *dual, Array<Real> &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
public:
template <class FunctorType, BC::Functor::Type type = FunctorType::type>
struct TemplateFunctionWrapper;
private:
ModelType * model;
Array<Real> * primal{nullptr};
Array<Real> * dual{nullptr};
Array<Real> * primal_increment{nullptr};
};
} // namespace akantu
#include "boundary_condition_tmpl.hh"
#endif /* AKANTU_BOUNDARY_CONDITION_HH_ */
diff --git a/src/model/common/boundary_condition/boundary_condition_functor.hh b/src/model/common/boundary_condition/boundary_condition_functor.hh
index 1faab2239..8e0df6a8a 100644
--- a/src/model/common/boundary_condition/boundary_condition_functor.hh
+++ b/src/model/common/boundary_condition/boundary_condition_functor.hh
@@ -1,215 +1,201 @@
/**
* @file boundary_condition_functor.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri May 03 2013
* @date last modification: Fri Jul 24 2020
*
* @brief Definitions of the functors to apply boundary conditions
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
#include "fe_engine.hh"
#include "integration_point.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH_
#define AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
namespace BC {
using Axis = ::akantu::SpatialDirection;
/* ---------------------------------------------------------------------- */
struct Functor {
enum Type { _dirichlet, _neumann };
virtual ~Functor() = default;
};
/* ---------------------------------------------------------------------- */
namespace Dirichlet {
class DirichletFunctor : public Functor {
public:
DirichletFunctor() = default;
explicit DirichletFunctor(Axis ax) : axis(ax) {}
- virtual void operator()(__attribute__((unused)) UInt node,
- __attribute__((unused)) Vector<bool> & flags,
- __attribute__((unused)) Vector<Real> & primal,
- __attribute__((unused))
- const Vector<Real> & coord) const {
+ virtual void operator()(Idx /*node*/, Vector<bool> & /*flags*/,
+ Vector<Real> & /*primal*/,
+ const Vector<Real> & /*coord*/) const {
AKANTU_TO_IMPLEMENT();
}
public:
static const Type type = _dirichlet;
protected:
Axis axis{_x};
};
/* ---------------------------------------------------------------------- */
class FlagOnly : public DirichletFunctor {
public:
explicit FlagOnly(Axis ax = _x) : DirichletFunctor(ax) {}
public:
- inline void operator()(UInt node, Vector<bool> & flags,
+ inline void operator()(Idx node, Vector<bool> & flags,
Vector<Real> & primal,
const Vector<Real> & coord) const override;
};
- /* ---------------------------------------------------------------------- */
- // class FreeBoundary : public DirichletFunctor {
- // public:
- // explicit FreeBoundary(Axis ax = _x) : DirichletFunctor(ax) {}
-
- // public:
- // inline void operator()(UInt node, Vector<bool> & flags,
- // Vector<Real> & primal,
- // const Vector<Real> & coord) const;
- // };
-
/* ---------------------------------------------------------------------- */
class FixedValue : public DirichletFunctor {
public:
FixedValue(Real val, Axis ax = _x) : DirichletFunctor(ax), value(val) {}
public:
- inline void operator()(UInt node, Vector<bool> & flags,
+ inline void operator()(Idx node, Vector<bool> & flags,
Vector<Real> & primal,
const Vector<Real> & coord) const override;
protected:
Real value;
};
/* ---------------------------------------------------------------------- */
class IncrementValue : public DirichletFunctor {
public:
IncrementValue(Real val, Axis ax = _x)
: DirichletFunctor(ax), value(val) {}
public:
- inline void operator()(UInt node, Vector<bool> & flags,
+ inline void operator()(Idx node, Vector<bool> & flags,
Vector<Real> & primal,
const Vector<Real> & coord) const override;
inline void setIncrement(Real val) { this->value = val; }
protected:
Real value;
};
/* ---------------------------------------------------------------------- */
class Increment : public DirichletFunctor {
public:
explicit Increment(const Vector<Real> & val)
: DirichletFunctor(_x), value(val) {}
public:
- inline void operator()(UInt node, Vector<bool> & flags,
+ inline void operator()(Idx node, Vector<bool> & flags,
Vector<Real> & primal,
const Vector<Real> & coord) const override;
inline void setIncrement(const Vector<Real> & val) { this->value = val; }
protected:
Vector<Real> value;
};
} // namespace Dirichlet
/* ------------------------------------------------------------------------ */
/* Neumann */
/* ------------------------------------------------------------------------ */
namespace Neumann {
class NeumannFunctor : public Functor {
protected:
NeumannFunctor() = default;
public:
virtual void operator()(const IntegrationPoint & quad_point,
Vector<Real> & dual, const Vector<Real> & coord,
const Vector<Real> & normals) const = 0;
~NeumannFunctor() override = default;
public:
static const Type type = _neumann;
};
/* ---------------------------------------------------------------------- */
class FromHigherDim : public NeumannFunctor {
public:
explicit FromHigherDim(const Matrix<Real> & mat) : bc_data(mat) {}
~FromHigherDim() override = default;
public:
inline void operator()(const IntegrationPoint & quad_point,
Vector<Real> & dual, const Vector<Real> & coord,
const Vector<Real> & normals) const override;
protected:
Matrix<Real> bc_data;
};
/* ---------------------------------------------------------------------- */
class FromSameDim : public NeumannFunctor {
public:
explicit FromSameDim(const Vector<Real> & vec) : bc_data(vec) {}
~FromSameDim() override = default;
public:
inline void operator()(const IntegrationPoint & quad_point,
Vector<Real> & dual, const Vector<Real> & coord,
const Vector<Real> & normals) const override;
protected:
Vector<Real> bc_data;
};
/* ---------------------------------------------------------------------- */
class FreeBoundary : public NeumannFunctor {
public:
inline void operator()(const IntegrationPoint & quad_point,
Vector<Real> & dual, const Vector<Real> & coord,
const Vector<Real> & normals) const override;
};
} // namespace Neumann
} // namespace BC
} // namespace akantu
#include "boundary_condition_functor_inline_impl.hh"
#endif /* AKANTU_BOUNDARY_CONDITION_FUNCTOR_HH_ */
diff --git a/src/model/common/boundary_condition/boundary_condition_functor_inline_impl.hh b/src/model/common/boundary_condition/boundary_condition_functor_inline_impl.hh
index cddbd6e63..771eee253 100644
--- a/src/model/common/boundary_condition/boundary_condition_functor_inline_impl.hh
+++ b/src/model/common/boundary_condition/boundary_condition_functor_inline_impl.hh
@@ -1,148 +1,125 @@
/**
* @file boundary_condition_functor_inline_impl.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri May 03 2013
* @date last modification: Sat Dec 22 2018
*
* @brief implementation of the BC::Functors
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "boundary_condition_functor.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_BOUNDARY_CONDITION_FUNCTOR_INLINE_IMPL_HH_
-#define AKANTU_BOUNDARY_CONDITION_FUNCTOR_INLINE_IMPL_HH_
+//#ifndef AKANTU_BOUNDARY_CONDITION_FUNCTOR_INLINE_IMPL_HH_
+//#define AKANTU_BOUNDARY_CONDITION_FUNCTOR_INLINE_IMPL_HH_
/* -------------------------------------------------------------------------- */
#define DIRICHLET_SANITY_CHECK \
AKANTU_DEBUG_ASSERT( \
primal.size() <= flags.size(), \
"The primal vector and flags vectors given" \
<< " to the boundary condition functor have different sizes!");
#define NEUMANN_SANITY_CHECK \
AKANTU_DEBUG_ASSERT( \
coord.size() <= normals.size(), \
"The coordinates and normals vectors given to the" \
<< " boundary condition functor have different sizes!");
namespace akantu {
namespace BC {
/* ---------------------------------------------------------------------- */
namespace Dirichlet {
- inline void FlagOnly::operator()(__attribute__((unused)) UInt node,
- Vector<bool> & flags,
- __attribute__((unused))
- Vector<Real> & primal,
- __attribute__((unused))
- const Vector<Real> & coord) const {
-
+ inline void FlagOnly::operator()(Idx /*node*/, Vector<bool> & flags,
+ [[gnu::unused]] Vector<Real> & primal,
+ const Vector<Real> & /*coord*/) const {
DIRICHLET_SANITY_CHECK;
-
flags(this->axis) = true;
}
/* ---------------------------------------------------------------------- */
- // inline void FreeBoundary::
- // operator()(__attribute__((unused)) UInt node, Vector<bool> & flags,
- // __attribute__((unused)) Vector<Real> & primal,
- // __attribute__((unused)) const Vector<Real> & coord) const {
-
- // DIRICHLET_SANITY_CHECK;
-
- // flags(this->axis) = false;
- // }
-
- /* ---------------------------------------------------------------------- */
- inline void FixedValue::operator()(__attribute__((unused)) UInt node,
- Vector<bool> & flags,
- Vector<Real> & primal,
- __attribute__((unused))
- const Vector<Real> & coord) const {
+ inline void FixedValue::operator()(Idx /*node*/, Vector<bool> & flags,
+ [[gnu::unused]] Vector<Real> & primal,
+ const Vector<Real> & /*coord*/) const {
DIRICHLET_SANITY_CHECK;
flags(this->axis) = true;
primal(this->axis) = value;
}
/* ---------------------------------------------------------------------- */
- inline void IncrementValue::operator()(__attribute__((unused)) UInt node,
- Vector<bool> & flags,
- Vector<Real> & primal,
- __attribute__((unused))
- const Vector<Real> & coord) const {
+ inline void
+ IncrementValue::operator()(Idx /*node*/, Vector<bool> & flags,
+ [[gnu::unused]] Vector<Real> & primal,
+ const Vector<Real> & /*coord*/) const {
DIRICHLET_SANITY_CHECK;
flags(this->axis) = true;
primal(this->axis) += value;
}
/* ---------------------------------------------------------------------- */
- inline void Increment::operator()(__attribute__((unused)) UInt node,
- Vector<bool> & flags,
+ inline void Increment::operator()(Int /*node*/, Vector<bool> & flags,
Vector<Real> & primal,
- __attribute__((unused))
- const Vector<Real> & coord) const {
+ const Vector<Real> & /*coord*/) const {
DIRICHLET_SANITY_CHECK;
flags.set(true);
primal += value;
}
} // namespace Dirichlet
/* ------------------------------------------------------------------------ */
/* Neumann */
/* ------------------------------------------------------------------------ */
namespace Neumann {
- inline void FreeBoundary::operator()(
- __attribute__((unused)) const IntegrationPoint & quad_point,
- Vector<Real> & dual, __attribute__((unused)) const Vector<Real> & coord,
- __attribute__((unused)) const Vector<Real> & normals) const {
- for (UInt i(0); i < dual.size(); ++i) {
+ inline void
+ FreeBoundary::operator()(const IntegrationPoint & /*quad_point*/,
+ Vector<Real> & dual,
+ const Vector<Real> & /*coord*/,
+ const Vector<Real> & /*normals*/) const {
+ for (Idx i(0); i < dual.size(); ++i) {
dual(i) = 0.0;
}
}
/* ---------------------------------------------------------------------- */
- inline void FromHigherDim::operator()(__attribute__((unused))
- const IntegrationPoint & quad_point,
- Vector<Real> & dual,
- __attribute__((unused))
- const Vector<Real> & coord,
- const Vector<Real> & normals) const {
- dual.mul<false>(this->bc_data, normals);
+ inline void FromHigherDim::operator()(
+ const IntegrationPoint & /*quad_point*/, Vector<Real> & dual,
+ const Vector<Real> & /*coord*/, const Vector<Real> & normals) const {
+ dual = this->bc_data * normals;
}
/* ---------------------------------------------------------------------- */
- inline void FromSameDim::operator()(
- __attribute__((unused)) const IntegrationPoint & quad_point,
- Vector<Real> & dual, __attribute__((unused)) const Vector<Real> & coord,
- __attribute__((unused)) const Vector<Real> & normals) const {
+ inline void
+ FromSameDim::operator()(const IntegrationPoint &, Vector<Real> & dual,
+ const Vector<Real> & /* coord */,
+ const Vector<Real> & /* normals */) const {
dual = this->bc_data;
}
} // namespace Neumann
} // namespace BC
} // namespace akantu
-#endif /* AKANTU_BOUNDARY_CONDITION_FUNCTOR_INLINE_IMPL_HH_ */
+//#endif /* AKANTU_BOUNDARY_CONDITION_FUNCTOR_INLINE_IMPL_HH_ */
diff --git a/src/model/common/boundary_condition/boundary_condition_tmpl.hh b/src/model/common/boundary_condition/boundary_condition_tmpl.hh
index ecbcfad58..c4ab445c0 100644
--- a/src/model/common/boundary_condition/boundary_condition_tmpl.hh
+++ b/src/model/common/boundary_condition/boundary_condition_tmpl.hh
@@ -1,233 +1,243 @@
/**
* @file boundary_condition_tmpl.hh
*
* @author Dana Christen <dana.christen@gmail.com>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri May 03 2013
* @date last modification: Mon Oct 28 2019
*
* @brief implementation of the applyBC
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "boundary_condition.hh"
#include "element_group.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_BOUNDARY_CONDITION_TMPL_HH_
#define AKANTU_BOUNDARY_CONDITION_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename ModelType>
void BoundaryCondition<ModelType>::initBC(ModelType & model,
Array<Real> & primal,
Array<Real> & dual) {
this->model = &model;
this->primal = &primal;
this->dual = &dual;
}
/* -------------------------------------------------------------------------- */
template <typename ModelType>
void BoundaryCondition<ModelType>::initBC(ModelType & model,
Array<Real> & primal,
Array<Real> & primal_increment,
Array<Real> & dual) {
this->initBC(model, primal, dual);
this->primal_increment = &primal_increment;
}
/* -------------------------------------------------------------------------- */
/* Partial specialization for DIRICHLET functors */
template <typename ModelType>
template <typename FunctorType>
struct BoundaryCondition<ModelType>::TemplateFunctionWrapper<
FunctorType, BC::Functor::_dirichlet> {
static inline void applyBC(const FunctorType & func,
const ElementGroup & group,
BoundaryCondition<ModelType> & bc_instance) {
auto & model = bc_instance.getModel();
auto & primal = bc_instance.getPrimal();
const auto & coords = model.getMesh().getNodes();
auto & boundary_flags = model.getBlockedDOFs();
- UInt dim = model.getMesh().getSpatialDimension();
+ Int dim = model.getMesh().getSpatialDimension();
auto primal_iter = primal.begin(primal.getNbComponent());
auto coords_iter = coords.begin(dim);
auto flags_iter = boundary_flags.begin(boundary_flags.getNbComponent());
for (auto n : group.getNodeGroup()) {
- Vector<bool> flag(flags_iter[n]);
- Vector<Real> primal(primal_iter[n]);
- Vector<Real> coords(coords_iter[n]);
- func(n, flag, primal, coords);
+ auto && flags = flags_iter[n];
+ auto && primal = primal_iter[n];
+
+ // The copy it to avoid the user to template is functor
+ Vector<bool> flags_ = flags;
+ Vector<Real> primal_ = primal;
+ Vector<Real> coords = coords_iter[n];
+
+ func(n, flags_, primal_, coords);
+
+ flags = flags_;
+ primal = primal_;
}
}
};
/* -------------------------------------------------------------------------- */
/* Partial specialization for NEUMANN functors */
template <typename ModelType>
template <typename FunctorType>
struct BoundaryCondition<ModelType>::TemplateFunctionWrapper<
FunctorType, BC::Functor::_neumann> {
static inline void applyBC(const FunctorType & func,
const ElementGroup & group,
BoundaryCondition<ModelType> & bc_instance) {
- UInt dim = bc_instance.getModel().getSpatialDimension();
- switch (dim) {
- case 1: {
+ auto dim = bc_instance.getModel().getSpatialDimension();
+
+ if (dim == 1) {
AKANTU_TO_IMPLEMENT();
- break;
- }
- case 2:
- case 3: {
- applyBC(func, group, bc_instance, _not_ghost);
- applyBC(func, group, bc_instance, _ghost);
- break;
- }
}
+ applyBC(func, group, bc_instance, _not_ghost);
+ applyBC(func, group, bc_instance, _ghost);
}
static inline void applyBC(const FunctorType & func,
const ElementGroup & group,
BoundaryCondition<ModelType> & bc_instance,
GhostType ghost_type) {
auto & model = bc_instance.getModel();
auto & dual = bc_instance.getDual();
const auto & mesh = model.getMesh();
const auto & nodes_coords = mesh.getNodes();
const auto & fem_boundary = model.getFEEngineBoundary();
- UInt dim = model.getSpatialDimension();
- UInt nb_degree_of_freedom = dual.getNbComponent();
+ Int dim = model.getSpatialDimension();
+ Int nb_degree_of_freedom = dual.getNbComponent();
IntegrationPoint quad_point;
quad_point.ghost_type = ghost_type;
// Loop over the boundary element types
for (auto && type : group.elementTypes(dim - 1, ghost_type)) {
const auto & element_ids = group.getElements(type, ghost_type);
- UInt nb_quad_points =
+ auto nb_quad_points =
fem_boundary.getNbIntegrationPoints(type, ghost_type);
- UInt nb_elements = element_ids.size();
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ auto nb_elements = element_ids.size();
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> dual_before_integ(nb_elements * nb_quad_points,
nb_degree_of_freedom, 0.);
Array<Real> quad_coords(nb_elements * nb_quad_points, dim);
const auto & normals_on_quad =
fem_boundary.getNormalsOnIntegrationPoints(type, ghost_type);
fem_boundary.interpolateOnIntegrationPoints(
nodes_coords, quad_coords, dim, type, ghost_type, element_ids);
auto normals_begin = normals_on_quad.begin(dim);
decltype(normals_begin) normals_iter;
auto quad_coords_iter = quad_coords.begin(dim);
auto dual_iter = dual_before_integ.begin(nb_degree_of_freedom);
quad_point.type = type;
for (auto el : element_ids) {
quad_point.element = el;
normals_iter = normals_begin + el * nb_quad_points;
for (auto q : arange(nb_quad_points)) {
quad_point.num_point = q;
- func(quad_point, *dual_iter, *quad_coords_iter, *normals_iter);
+
+ Vector<Real> dual(*dual_iter);
+ Vector<Real> quad_coords(*quad_coords_iter);
+ Vector<Real> normals(*normals_iter);
+
+ func(quad_point, dual, quad_coords, normals);
+
+ *dual_iter = dual;
+
++dual_iter;
++quad_coords_iter;
++normals_iter;
}
}
Array<Real> dual_by_shapes(nb_elements * nb_quad_points,
nb_degree_of_freedom * nb_nodes_per_element);
fem_boundary.computeNtb(dual_before_integ, dual_by_shapes, type,
ghost_type, element_ids);
Array<Real> dual_by_shapes_integ(nb_elements, nb_degree_of_freedom *
nb_nodes_per_element);
fem_boundary.integrate(dual_by_shapes, dual_by_shapes_integ,
nb_degree_of_freedom * nb_nodes_per_element, type,
ghost_type, element_ids);
// assemble the result into force vector
model.getDOFManager().assembleElementalArrayLocalArray(
dual_by_shapes_integ, dual, type, ghost_type, 1., element_ids);
}
}
};
/* -------------------------------------------------------------------------- */
template <typename ModelType>
template <typename FunctorType>
inline void BoundaryCondition<ModelType>::applyBC(const FunctorType & func) {
auto bit = model->getMesh().getGroupManager().element_group_begin();
auto bend = model->getMesh().getGroupManager().element_group_end();
for (; bit != bend; ++bit) {
applyBC(func, *bit);
}
}
/* -------------------------------------------------------------------------- */
template <typename ModelType>
template <typename FunctorType>
inline void
BoundaryCondition<ModelType>::applyBC(const FunctorType & func,
const std::string & group_name) {
try {
const ElementGroup & element_group =
model->getMesh().getElementGroup(group_name);
applyBC(func, element_group);
} catch (akantu::debug::Exception & e) {
AKANTU_EXCEPTION("Error applying a boundary condition onto \""
<< group_name << "\"! [" << e.what() << "]");
}
}
/* -------------------------------------------------------------------------- */
template <typename ModelType>
template <typename FunctorType>
inline void
BoundaryCondition<ModelType>::applyBC(const FunctorType & func,
const ElementGroup & element_group) {
#if !defined(AKANTU_NDEBUG)
if (element_group.getDimension() != model->getSpatialDimension() - 1) {
AKANTU_DEBUG_INFO("The group "
<< element_group.getName()
<< " does not contain only boundaries elements");
}
#endif
TemplateFunctionWrapper<FunctorType>::applyBC(func, element_group, *this);
}
#endif /* AKANTU_BOUNDARY_CONDITION_TMPL_HH_ */
} // namespace akantu
diff --git a/src/model/common/dof_manager/dof_manager.cc b/src/model/common/dof_manager/dof_manager.cc
index 8dfe93c43..87092acc8 100644
--- a/src/model/common/dof_manager/dof_manager.cc
+++ b/src/model/common/dof_manager/dof_manager.cc
@@ -1,1040 +1,1032 @@
/**
* @file dof_manager.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Aug 18 2015
* @date last modification: Sat Mar 06 2021
*
* @brief Implementation of the common parts of the DOFManagers
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager.hh"
#include "communicator.hh"
#include "mesh.hh"
#include "mesh_utils.hh"
#include "node_group.hh"
#include "node_synchronizer.hh"
#include "non_linear_solver.hh"
#include "periodic_node_synchronizer.hh"
#include "time_step_solver.hh"
/* -------------------------------------------------------------------------- */
#include <memory>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
DOFManager::DOFManager(const ID & id)
: id(id), dofs_flag(0, 1, std::string(id + ":dofs_type")),
global_equation_number(0, 1, "global_equation_number"),
communicator(Communicator::getStaticCommunicator()) {}
/* -------------------------------------------------------------------------- */
DOFManager::DOFManager(Mesh & mesh, const ID & id)
: id(id), mesh(&mesh), dofs_flag(0, 1, std::string(id + ":dofs_type")),
global_equation_number(0, 1, "global_equation_number"),
communicator(mesh.getCommunicator()) {
this->mesh->registerEventHandler(*this, _ehp_dof_manager);
}
/* -------------------------------------------------------------------------- */
DOFManager::~DOFManager() = default;
/* -------------------------------------------------------------------------- */
std::vector<ID> DOFManager::getDOFIDs() const {
std::vector<ID> keys;
for (const auto & dof_data : this->dofs) {
keys.push_back(dof_data.first);
}
return keys;
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleElementalArrayLocalArray(
const Array<Real> & elementary_vect, Array<Real> & array_assembeled,
ElementType type, GhostType ghost_type, Real scale_factor,
- const Array<UInt> & filter_elements) {
+ const Array<Int> & filter_elements) {
AKANTU_DEBUG_IN();
- UInt nb_element;
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_degree_of_freedom =
+ Int nb_element;
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_degree_of_freedom =
elementary_vect.getNbComponent() / nb_nodes_per_element;
- UInt * filter_it = nullptr;
+ Idx * filter_it = nullptr;
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
- filter_it = filter_elements.storage();
+ filter_it = filter_elements.data();
} else {
nb_element = this->mesh->getNbElement(type, ghost_type);
}
AKANTU_DEBUG_ASSERT(elementary_vect.size() == nb_element,
"The vector elementary_vect("
<< elementary_vect.getID()
<< ") has not the good size.");
- const Array<UInt> & connectivity =
- this->mesh->getConnectivity(type, ghost_type);
+ const auto & connectivity = this->mesh->getConnectivity(type, ghost_type);
- Array<Real>::const_matrix_iterator elem_it =
- elementary_vect.begin(nb_degree_of_freedom, nb_nodes_per_element);
+ auto elem_it =
+ make_view(elementary_vect, nb_degree_of_freedom, nb_nodes_per_element)
+ .begin();
+ auto assemble_it = make_view(array_assembeled, nb_degree_of_freedom).begin();
- for (UInt el = 0; el < nb_element; ++el, ++elem_it) {
- UInt element = el;
+ for (Int el = 0; el < nb_element; ++el, ++elem_it) {
+ auto element = el;
if (filter_it != nullptr) {
- // conn_it = conn_begin + *filter_it;
+
element = *filter_it;
}
// const Vector<UInt> & conn = *conn_it;
- const Matrix<Real> & elemental_val = *elem_it;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- UInt offset_node = connectivity(element, n) * nb_degree_of_freedom;
- Vector<Real> assemble(array_assembeled.storage() + offset_node,
- nb_degree_of_freedom);
- Vector<Real> elem_val = elemental_val(n);
- assemble.aXplusY(elem_val, scale_factor);
+ const auto & elemental_val = *elem_it;
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
+ auto node = connectivity(element, n);
+
+ auto && assemble = assemble_it[node];
+ assemble += scale_factor * elemental_val(n);
}
if (filter_it != nullptr) {
++filter_it;
}
// else
// ++conn_it;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleElementalArrayToResidual(
const ID & dof_id, const Array<Real> & elementary_vect, ElementType type,
GhostType ghost_type, Real scale_factor,
- const Array<UInt> & filter_elements) {
+ const Array<Int> & filter_elements) {
AKANTU_DEBUG_IN();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_degree_of_freedom =
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_degree_of_freedom =
elementary_vect.getNbComponent() / nb_nodes_per_element;
Array<Real> array_localy_assembeled(this->mesh->getNbNodes(),
nb_degree_of_freedom);
array_localy_assembeled.zero();
this->assembleElementalArrayLocalArray(
elementary_vect, array_localy_assembeled, type, ghost_type, scale_factor,
filter_elements);
this->assembleToResidual(dof_id, array_localy_assembeled, 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleElementalArrayToLumpedMatrix(
const ID & dof_id, const Array<Real> & elementary_vect,
const ID & lumped_mtx, ElementType type, GhostType ghost_type,
- Real scale_factor, const Array<UInt> & filter_elements) {
+ Real scale_factor, const Array<Int> & filter_elements) {
AKANTU_DEBUG_IN();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_degree_of_freedom =
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_degree_of_freedom =
elementary_vect.getNbComponent() / nb_nodes_per_element;
Array<Real> array_localy_assembeled(this->mesh->getNbNodes(),
nb_degree_of_freedom);
array_localy_assembeled.zero();
this->assembleElementalArrayLocalArray(
elementary_vect, array_localy_assembeled, type, ghost_type, scale_factor,
filter_elements);
this->assembleToLumpedMatrix(dof_id, array_localy_assembeled, lumped_mtx, 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleMatMulDOFsToResidual(const ID & A_id,
Real scale_factor) {
for (auto & pair : this->dofs) {
const auto & dof_id = pair.first;
auto & dof_data = *pair.second;
this->assembleMatMulVectToResidual(dof_id, A_id, *dof_data.dof,
scale_factor);
}
}
/* -------------------------------------------------------------------------- */
void DOFManager::splitSolutionPerDOFs() {
for (auto && data : this->dofs) {
auto & dof_data = *data.second;
dof_data.solution.resize(dof_data.dof->size() *
dof_data.dof->getNbComponent());
this->getSolutionPerDOFs(data.first, dof_data.solution);
}
}
/* -------------------------------------------------------------------------- */
void DOFManager::getSolutionPerDOFs(const ID & dof_id,
Array<Real> & solution_array) {
AKANTU_DEBUG_IN();
this->getArrayPerDOFs(dof_id, this->getSolution(), solution_array);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManager::getLumpedMatrixPerDOFs(const ID & dof_id,
const ID & lumped_mtx,
Array<Real> & lumped) {
AKANTU_DEBUG_IN();
this->getArrayPerDOFs(dof_id, this->getLumpedMatrix(lumped_mtx), lumped);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleToResidual(const ID & dof_id,
Array<Real> & array_to_assemble,
Real scale_factor) {
AKANTU_DEBUG_IN();
// this->makeConsistentForPeriodicity(dof_id, array_to_assemble);
this->assembleToGlobalArray(dof_id, array_to_assemble, this->getResidual(),
scale_factor);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleToLumpedMatrix(const ID & dof_id,
Array<Real> & array_to_assemble,
const ID & lumped_mtx,
Real scale_factor) {
AKANTU_DEBUG_IN();
// this->makeConsistentForPeriodicity(dof_id, array_to_assemble);
auto & lumped = this->getLumpedMatrix(lumped_mtx);
this->assembleToGlobalArray(dof_id, array_to_assemble, lumped, scale_factor);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
DOFManager::DOFData::DOFData(const ID & dof_id)
: support_type(_dst_generic), group_support("__mesh__"),
solution(0, 1, dof_id + ":solution"),
local_equation_number(0, 1, dof_id + ":local_equation_number"),
associated_nodes(0, 1, dof_id + "associated_nodes") {}
/* -------------------------------------------------------------------------- */
DOFManager::DOFData::~DOFData() = default;
/* -------------------------------------------------------------------------- */
template <typename Func>
-auto DOFManager::countDOFsForNodes(const DOFData & dof_data, UInt nb_nodes,
+auto DOFManager::countDOFsForNodes(const DOFData & dof_data, Int nb_nodes,
Func && getNode) {
auto nb_local_dofs = nb_nodes;
decltype(nb_local_dofs) nb_pure_local = 0;
for (auto n : arange(nb_nodes)) {
UInt node = getNode(n);
// http://www.open-std.org/jtc1/sc22/open/n2356/conv.html
// bool are by convention casted to 0 and 1 when promoted to int
nb_pure_local += this->mesh->isLocalOrMasterNode(node);
nb_local_dofs -= this->mesh->isPeriodicSlave(node);
}
const auto & dofs_array = *dof_data.dof;
nb_pure_local *= dofs_array.getNbComponent();
nb_local_dofs *= dofs_array.getNbComponent();
return std::make_pair(nb_local_dofs, nb_pure_local);
}
/* -------------------------------------------------------------------------- */
auto DOFManager::getNewDOFDataInternal(const ID & dof_id) -> DOFData & {
auto it = this->dofs.find(dof_id);
if (it != this->dofs.end()) {
AKANTU_EXCEPTION("This dof array has already been registered");
}
std::unique_ptr<DOFData> dof_data_ptr = this->getNewDOFData(dof_id);
DOFData & dof_data = *dof_data_ptr;
this->dofs[dof_id] = std::move(dof_data_ptr);
return dof_data;
}
/* -------------------------------------------------------------------------- */
void DOFManager::registerDOFs(const ID & dof_id, Array<Real> & dofs_array,
- const DOFSupportType & support_type) {
+ DOFSupportType support_type) {
auto & dofs_storage = this->getNewDOFDataInternal(dof_id);
dofs_storage.support_type = support_type;
this->registerDOFsInternal(dof_id, dofs_array);
resizeGlobalArrays();
}
/* -------------------------------------------------------------------------- */
void DOFManager::registerDOFs(const ID & dof_id, Array<Real> & dofs_array,
const ID & support_group) {
auto & dofs_storage = this->getNewDOFDataInternal(dof_id);
dofs_storage.support_type = _dst_nodal;
dofs_storage.group_support = support_group;
this->registerDOFsInternal(dof_id, dofs_array);
resizeGlobalArrays();
}
/* -------------------------------------------------------------------------- */
-std::tuple<UInt, UInt, UInt>
+std::tuple<Int, Int, Int>
DOFManager::registerDOFsInternal(const ID & dof_id, Array<Real> & dofs_array) {
DOFData & dof_data = this->getDOFData(dof_id);
dof_data.dof = &dofs_array;
- UInt nb_local_dofs = 0;
- UInt nb_pure_local = 0;
+ Int nb_local_dofs = 0;
+ Int nb_pure_local = 0;
const auto & support_type = dof_data.support_type;
switch (support_type) {
case _dst_nodal: {
const auto & group = dof_data.group_support;
- std::function<UInt(UInt)> getNode;
+ std::function<Idx(Idx)> getNode;
if (group == "__mesh__") {
AKANTU_DEBUG_ASSERT(
dofs_array.size() == this->mesh->getNbNodes(),
"The array of dof is too short to be associated to nodes.");
std::tie(nb_local_dofs, nb_pure_local) = countDOFsForNodes(
dof_data, this->mesh->getNbNodes(), [](auto && n) { return n; });
} else {
const auto & node_group =
this->mesh->getElementGroup(group).getNodeGroup().getNodes();
AKANTU_DEBUG_ASSERT(
dofs_array.size() == node_group.size(),
"The array of dof is too shot to be associated to nodes.");
std::tie(nb_local_dofs, nb_pure_local) =
countDOFsForNodes(dof_data, node_group.size(),
[&node_group](auto && n) { return node_group(n); });
}
break;
}
case _dst_generic: {
nb_local_dofs = nb_pure_local =
dofs_array.size() * dofs_array.getNbComponent();
break;
}
default: {
AKANTU_EXCEPTION("This type of dofs is not handled yet.");
}
}
dof_data.local_nb_dofs = nb_local_dofs;
dof_data.pure_local_nb_dofs = nb_pure_local;
dof_data.ghosts_nb_dofs = nb_local_dofs - nb_pure_local;
this->pure_local_system_size += nb_pure_local;
this->local_system_size += nb_local_dofs;
auto nb_total_pure_local = nb_pure_local;
communicator.allReduce(nb_total_pure_local, SynchronizerOperation::_sum);
this->system_size += nb_total_pure_local;
// updating the dofs data after counting is finished
switch (support_type) {
case _dst_nodal: {
const auto & group = dof_data.group_support;
if (group != "__mesh__") {
auto & support_nodes =
this->mesh->getElementGroup(group).getNodeGroup().getNodes();
this->updateDOFsData(
dof_data, nb_local_dofs, nb_pure_local, support_nodes.size(),
- [&support_nodes](UInt node) -> UInt { return support_nodes[node]; });
+ [&support_nodes](Idx node) -> Idx { return support_nodes[node]; });
} else {
this->updateDOFsData(dof_data, nb_local_dofs, nb_pure_local,
mesh->getNbNodes(),
- [](UInt node) -> UInt { return node; });
+ [](Idx node) -> Idx { return node; });
}
break;
}
case _dst_generic: {
this->updateDOFsData(dof_data, nb_local_dofs, nb_pure_local);
break;
}
}
return std::make_tuple(nb_local_dofs, nb_pure_local, nb_total_pure_local);
}
/* -------------------------------------------------------------------------- */
void DOFManager::registerDOFsPrevious(const ID & dof_id, Array<Real> & array) {
DOFData & dof = this->getDOFData(dof_id);
if (dof.previous != nullptr) {
AKANTU_EXCEPTION("The previous dofs array for "
<< dof_id << " has already been registered");
}
dof.previous = &array;
}
/* -------------------------------------------------------------------------- */
void DOFManager::registerDOFsIncrement(const ID & dof_id, Array<Real> & array) {
DOFData & dof = this->getDOFData(dof_id);
if (dof.increment != nullptr) {
AKANTU_EXCEPTION("The dofs increment array for "
<< dof_id << " has already been registered");
}
dof.increment = &array;
}
/* -------------------------------------------------------------------------- */
-void DOFManager::registerDOFsDerivative(const ID & dof_id, UInt order,
+void DOFManager::registerDOFsDerivative(const ID & dof_id, Int order,
Array<Real> & dofs_derivative) {
- DOFData & dof = this->getDOFData(dof_id);
- std::vector<Array<Real> *> & derivatives = dof.dof_derivatives;
+ auto & dof = this->getDOFData(dof_id);
+ auto & derivatives = dof.dof_derivatives;
- if (derivatives.size() < order) {
+ if (Int(derivatives.size()) < order) {
derivatives.resize(order, nullptr);
} else {
if (derivatives[order - 1] != nullptr) {
AKANTU_EXCEPTION("The dof derivatives of order "
<< order << " already been registered for this dof ("
<< dof_id << ")");
}
}
derivatives[order - 1] = &dofs_derivative;
}
/* -------------------------------------------------------------------------- */
void DOFManager::registerBlockedDOFs(const ID & dof_id,
Array<bool> & blocked_dofs) {
- DOFData & dof = this->getDOFData(dof_id);
+ auto & dof = this->getDOFData(dof_id);
if (dof.blocked_dofs != nullptr) {
AKANTU_EXCEPTION("The blocked dofs array for "
<< dof_id << " has already been registered");
}
dof.blocked_dofs = &blocked_dofs;
}
/* -------------------------------------------------------------------------- */
SparseMatrix &
DOFManager::registerSparseMatrix(const ID & matrix_id,
std::unique_ptr<SparseMatrix> & matrix) {
auto it = this->matrices.find(matrix_id);
if (it != this->matrices.end()) {
AKANTU_EXCEPTION("The matrix " << matrix_id << " already exists in "
<< this->id);
}
auto & ret = *matrix;
this->matrices[matrix_id] = std::move(matrix);
return ret;
}
/* -------------------------------------------------------------------------- */
/// Get an instance of a new SparseMatrix
SolverVector &
DOFManager::registerLumpedMatrix(const ID & matrix_id,
std::unique_ptr<SolverVector> & matrix) {
auto it = this->lumped_matrices.find(matrix_id);
if (it != this->lumped_matrices.end()) {
AKANTU_EXCEPTION("The lumped matrix " << matrix_id << " already exists in "
<< this->id);
}
auto & ret = *matrix;
this->lumped_matrices[matrix_id] = std::move(matrix);
ret.resize();
return ret;
}
/* -------------------------------------------------------------------------- */
NonLinearSolver & DOFManager::registerNonLinearSolver(
const ID & non_linear_solver_id,
std::unique_ptr<NonLinearSolver> & non_linear_solver) {
NonLinearSolversMap::const_iterator it =
this->non_linear_solvers.find(non_linear_solver_id);
if (it != this->non_linear_solvers.end()) {
AKANTU_EXCEPTION("The non linear solver " << non_linear_solver_id
<< " already exists in "
<< this->id);
}
NonLinearSolver & ret = *non_linear_solver;
this->non_linear_solvers[non_linear_solver_id] = std::move(non_linear_solver);
return ret;
}
/* -------------------------------------------------------------------------- */
TimeStepSolver & DOFManager::registerTimeStepSolver(
const ID & time_step_solver_id,
std::unique_ptr<TimeStepSolver> & time_step_solver) {
TimeStepSolversMap::const_iterator it =
this->time_step_solvers.find(time_step_solver_id);
if (it != this->time_step_solvers.end()) {
AKANTU_EXCEPTION("The non linear solver " << time_step_solver_id
<< " already exists in "
<< this->id);
}
TimeStepSolver & ret = *time_step_solver;
this->time_step_solvers[time_step_solver_id] = std::move(time_step_solver);
return ret;
}
/* -------------------------------------------------------------------------- */
SparseMatrix & DOFManager::getMatrix(const ID & id) {
ID matrix_id = this->id + ":mtx:" + id;
SparseMatricesMap::const_iterator it = this->matrices.find(matrix_id);
if (it == this->matrices.end()) {
AKANTU_SILENT_EXCEPTION("The matrix " << matrix_id << " does not exists in "
<< this->id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
bool DOFManager::hasMatrix(const ID & id) const {
ID mtx_id = this->id + ":mtx:" + id;
auto it = this->matrices.find(mtx_id);
return it != this->matrices.end();
}
/* -------------------------------------------------------------------------- */
SolverVector & DOFManager::getLumpedMatrix(const ID & id) {
ID matrix_id = this->id + ":lumped_mtx:" + id;
LumpedMatricesMap::const_iterator it = this->lumped_matrices.find(matrix_id);
if (it == this->lumped_matrices.end()) {
AKANTU_SILENT_EXCEPTION("The lumped matrix "
<< matrix_id << " does not exists in " << this->id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
const SolverVector & DOFManager::getLumpedMatrix(const ID & id) const {
ID matrix_id = this->id + ":lumped_mtx:" + id;
auto it = this->lumped_matrices.find(matrix_id);
if (it == this->lumped_matrices.end()) {
AKANTU_SILENT_EXCEPTION("The lumped matrix "
<< matrix_id << " does not exists in " << this->id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
bool DOFManager::hasLumpedMatrix(const ID & id) const {
ID mtx_id = this->id + ":lumped_mtx:" + id;
auto it = this->lumped_matrices.find(mtx_id);
return it != this->lumped_matrices.end();
}
/* -------------------------------------------------------------------------- */
NonLinearSolver & DOFManager::getNonLinearSolver(const ID & id) {
ID non_linear_solver_id = this->id + ":nls:" + id;
NonLinearSolversMap::const_iterator it =
this->non_linear_solvers.find(non_linear_solver_id);
if (it == this->non_linear_solvers.end()) {
AKANTU_EXCEPTION("The non linear solver " << non_linear_solver_id
<< " does not exists in "
<< this->id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
bool DOFManager::hasNonLinearSolver(const ID & id) const {
ID solver_id = this->id + ":nls:" + id;
auto it = this->non_linear_solvers.find(solver_id);
return it != this->non_linear_solvers.end();
}
/* -------------------------------------------------------------------------- */
TimeStepSolver & DOFManager::getTimeStepSolver(const ID & id) {
ID time_step_solver_id = this->id + ":tss:" + id;
TimeStepSolversMap::const_iterator it =
this->time_step_solvers.find(time_step_solver_id);
if (it == this->time_step_solvers.end()) {
AKANTU_EXCEPTION("The non linear solver " << time_step_solver_id
<< " does not exists in "
<< this->id);
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
bool DOFManager::hasTimeStepSolver(const ID & solver_id) const {
ID time_step_solver_id = this->id + ":tss:" + solver_id;
auto it = this->time_step_solvers.find(time_step_solver_id);
return it != this->time_step_solvers.end();
}
/* -------------------------------------------------------------------------- */
void DOFManager::savePreviousDOFs(const ID & dofs_id) {
this->getPreviousDOFs(dofs_id).copy(this->getDOFs(dofs_id));
}
/* -------------------------------------------------------------------------- */
void DOFManager::zeroResidual() { this->residual->zero(); }
/* -------------------------------------------------------------------------- */
void DOFManager::zeroMatrix(const ID & mtx) { this->getMatrix(mtx).zero(); }
/* -------------------------------------------------------------------------- */
void DOFManager::zeroLumpedMatrix(const ID & mtx) {
this->getLumpedMatrix(mtx).zero();
}
/* -------------------------------------------------------------------------- */
/* Mesh Events */
/* -------------------------------------------------------------------------- */
-std::pair<UInt, UInt>
-DOFManager::updateNodalDOFs(const ID & dof_id, const Array<UInt> & nodes_list) {
+std::pair<Int, Int> DOFManager::updateNodalDOFs(const ID & dof_id,
+ const Array<Idx> & nodes_list) {
auto & dof_data = this->getDOFData(dof_id);
- UInt nb_new_local_dofs;
- UInt nb_new_pure_local;
+ Int nb_new_local_dofs, nb_new_pure_local;
std::tie(nb_new_local_dofs, nb_new_pure_local) =
countDOFsForNodes(dof_data, nodes_list.size(),
[&nodes_list](auto && n) { return nodes_list(n); });
this->pure_local_system_size += nb_new_pure_local;
this->local_system_size += nb_new_local_dofs;
- UInt nb_new_global = nb_new_pure_local;
+ auto nb_new_global = nb_new_pure_local;
communicator.allReduce(nb_new_global, SynchronizerOperation::_sum);
this->system_size += nb_new_global;
dof_data.solution.resize(local_system_size);
updateDOFsData(dof_data, nb_new_local_dofs, nb_new_pure_local,
nodes_list.size(),
- [&nodes_list](UInt pos) -> UInt { return nodes_list[pos]; });
+ [&nodes_list](auto pos) -> UInt { return nodes_list[pos]; });
return std::make_pair(nb_new_local_dofs, nb_new_pure_local);
}
/* -------------------------------------------------------------------------- */
void DOFManager::resizeGlobalArrays() {
// resize all relevant arrays
this->residual->resize();
this->solution->resize();
this->data_cache->resize();
for (auto & lumped_matrix : lumped_matrices) {
lumped_matrix.second->resize();
}
for (auto & matrix : matrices) {
matrix.second->clearProfile();
}
}
/* -------------------------------------------------------------------------- */
-void DOFManager::onNodesAdded(const Array<UInt> & nodes_list,
- const NewNodesEvent & /*unused*/) {
+void DOFManager::onNodesAdded(const Array<Idx> & nodes_list,
+ const NewNodesEvent &) {
for (auto & pair : this->dofs) {
const auto & dof_id = pair.first;
auto & dof_data = this->getDOFData(dof_id);
if (dof_data.support_type != _dst_nodal) {
continue;
}
const auto & group = dof_data.group_support;
if (group == "__mesh__") {
this->updateNodalDOFs(dof_id, nodes_list);
} else {
const auto & node_group =
this->mesh->getElementGroup(group).getNodeGroup();
- Array<UInt> new_nodes_list;
+ Array<Idx> new_nodes_list;
for (const auto & node : nodes_list) {
- if (node_group.find(node) != UInt(-1)) {
+ if (node_group.find(node) != Int(-1)) {
new_nodes_list.push_back(node);
}
}
this->updateNodalDOFs(dof_id, new_nodes_list);
}
}
this->resizeGlobalArrays();
}
/* -------------------------------------------------------------------------- */
-void DOFManager::onMeshIsDistributed(const Mesh & mesh_,
- const MeshIsDistributedEvent & event) {
+void DOFManager::onMeshIsDistributed(const MeshIsDistributedEvent & /*event*/) {
AKANTU_DEBUG_ASSERT(this->mesh != nullptr, "The `Mesh` pointer is not set.");
// check if the distributed state of the residual and the mesh are the same.
if (this->mesh->isDistributed() != this->residual->isDistributed()) {
// TODO: Allow to reallocate the internals, in that case one could actually
// react on that event.
auto is_or_is_not = [](bool q) {
return ((q) ? std::string("is") : std::string("is not"));
};
AKANTU_EXCEPTION("There is an inconsistency about the distribution state "
"of the `DOFManager`."
" It seams that the `Mesh` "
<< is_or_is_not(this->mesh->isDistributed())
<< " distributed, but the `DOFManager`'s residual "
<< is_or_is_not(this->residual->isDistributed())
<< ", which is of type "
<< debug::demangle(typeid(this->residual).name()) << ".");
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-class GlobalDOFInfoDataAccessor : public DataAccessor<UInt> {
+class GlobalDOFInfoDataAccessor : public DataAccessor<Idx> {
public:
- using size_type =
- typename std::unordered_map<UInt, std::vector<UInt>>::size_type;
-
GlobalDOFInfoDataAccessor(DOFManager::DOFData & dof_data,
DOFManager & dof_manager)
: dof_data(dof_data), dof_manager(dof_manager) {
for (auto && pair :
zip(dof_data.local_equation_number, dof_data.associated_nodes)) {
- UInt node;
- Int dof;
+ Idx node;
+ Idx dof;
std::tie(dof, node) = pair;
dofs_per_node[node].push_back(dof);
}
}
- UInt getNbData(const Array<UInt> & nodes,
- const SynchronizationTag & tag) const override {
+ Int getNbData(const Array<Idx> & nodes,
+ const SynchronizationTag & tag) const override {
if (tag == SynchronizationTag::_ask_nodes or
tag == SynchronizationTag::_giu_global_conn) {
- return nodes.size() * dof_data.dof->getNbComponent() * sizeof(Int);
+ return nodes.size() * dof_data.dof->getNbComponent() * sizeof(Idx);
}
return 0;
}
- void packData(CommunicationBuffer & buffer, const Array<UInt> & nodes,
+ void packData(CommunicationBuffer & buffer, const Array<Idx> & nodes,
const SynchronizationTag & tag) const override {
if (tag == SynchronizationTag::_ask_nodes or
tag == SynchronizationTag::_giu_global_conn) {
for (const auto & node : nodes) {
const auto & dofs = dofs_per_node.at(node);
for (const auto & dof : dofs) {
buffer << dof_manager.global_equation_number(dof);
}
}
}
}
- void unpackData(CommunicationBuffer & buffer, const Array<UInt> & nodes,
+ void unpackData(CommunicationBuffer & buffer, const Array<Idx> & nodes,
const SynchronizationTag & tag) override {
if (tag == SynchronizationTag::_ask_nodes or
tag == SynchronizationTag::_giu_global_conn) {
for (const auto & node : nodes) {
const auto & dofs = dofs_per_node[node];
for (const auto & dof : dofs) {
- Int global_dof;
+ Idx global_dof;
buffer >> global_dof;
AKANTU_DEBUG_ASSERT(
(dof_manager.global_equation_number(dof) == -1 or
dof_manager.global_equation_number(dof) == global_dof),
"This dof already had a global_dof_id which is different from "
"the received one. "
<< dof_manager.global_equation_number(dof)
<< " != " << global_dof);
dof_manager.global_equation_number(dof) = global_dof;
dof_manager.global_to_local_mapping[global_dof] = dof;
}
}
}
}
protected:
- std::unordered_map<UInt, std::vector<Int>> dofs_per_node;
+ std::unordered_map<Idx, std::vector<Idx>> dofs_per_node;
DOFManager::DOFData & dof_data;
DOFManager & dof_manager;
};
/* -------------------------------------------------------------------------- */
-auto DOFManager::computeFirstDOFIDs(UInt nb_new_local_dofs,
- UInt nb_new_pure_local) {
+auto DOFManager::computeFirstDOFIDs(Int nb_new_local_dofs,
+ Int nb_new_pure_local) {
// determine the first local/global dof id to use
- UInt offset = 0;
+ Int offset = 0;
this->communicator.exclusiveScan(nb_new_pure_local, offset);
auto first_global_dof_id = this->first_global_dof_id + offset;
auto first_local_dof_id = this->local_system_size - nb_new_local_dofs;
offset = nb_new_pure_local;
this->communicator.allReduce(offset);
this->first_global_dof_id += offset;
return std::make_pair(first_local_dof_id, first_global_dof_id);
}
/* -------------------------------------------------------------------------- */
-void DOFManager::updateDOFsData(DOFData & dof_data, UInt nb_new_local_dofs,
- UInt nb_new_pure_local, UInt nb_node,
- const std::function<UInt(UInt)> & getNode) {
+void DOFManager::updateDOFsData(DOFData & dof_data, Int nb_new_local_dofs,
+ Int nb_new_pure_local, Int nb_node,
+ const std::function<Idx(Idx)> & getNode) {
auto nb_local_dofs_added = nb_node * dof_data.dof->getNbComponent();
auto first_dof_pos = dof_data.local_equation_number.size();
dof_data.local_equation_number.reserve(dof_data.local_equation_number.size() +
nb_local_dofs_added);
dof_data.associated_nodes.reserve(dof_data.associated_nodes.size() +
nb_local_dofs_added);
this->dofs_flag.resize(this->local_system_size, NodeFlag::_normal);
this->global_equation_number.resize(this->local_system_size, -1);
- std::unordered_map<std::pair<UInt, UInt>, UInt> masters_dofs;
+ std::unordered_map<std::pair<Idx, Idx>, Idx> masters_dofs;
// update per dof info
- UInt local_eq_num;
- UInt first_global_dof_id;
+ Int local_eq_num, first_global_dof_id;
std::tie(local_eq_num, first_global_dof_id) =
computeFirstDOFIDs(nb_new_local_dofs, nb_new_pure_local);
for (auto d : arange(nb_local_dofs_added)) {
auto node = getNode(d / dof_data.dof->getNbComponent());
auto dof_flag = this->mesh->getNodeFlag(node);
dof_data.associated_nodes.push_back(node);
auto is_local_dof = this->mesh->isLocalOrMasterNode(node);
auto is_periodic_slave = this->mesh->isPeriodicSlave(node);
auto is_periodic_master = this->mesh->isPeriodicMaster(node);
if (is_periodic_slave) {
dof_data.local_equation_number.push_back(-1);
continue;
}
// update equation numbers
this->dofs_flag(local_eq_num) = dof_flag;
dof_data.local_equation_number.push_back(local_eq_num);
if (is_local_dof) {
this->global_equation_number(local_eq_num) = first_global_dof_id;
this->global_to_local_mapping[first_global_dof_id] = local_eq_num;
++first_global_dof_id;
} else {
this->global_equation_number(local_eq_num) = -1;
}
if (is_periodic_master) {
auto node = getNode(d / dof_data.dof->getNbComponent());
auto dof = d % dof_data.dof->getNbComponent();
masters_dofs.insert(
std::make_pair(std::make_pair(node, dof), local_eq_num));
}
++local_eq_num;
}
// correct periodic slave equation numbers
if (this->mesh->isPeriodic()) {
auto assoc_begin = dof_data.associated_nodes.begin();
for (auto d : arange(nb_local_dofs_added)) {
auto node = dof_data.associated_nodes(first_dof_pos + d);
if (not this->mesh->isPeriodicSlave(node)) {
continue;
}
auto master_node = this->mesh->getPeriodicMaster(node);
auto dof = d % dof_data.dof->getNbComponent();
dof_data.local_equation_number(first_dof_pos + d) =
masters_dofs[std::make_pair(master_node, dof)];
}
}
// synchronize the global numbering for slaves nodes
if (this->mesh->isDistributed()) {
GlobalDOFInfoDataAccessor data_accessor(dof_data, *this);
if (this->mesh->isPeriodic()) {
mesh->getPeriodicNodeSynchronizer().synchronizeOnce(
data_accessor, SynchronizationTag::_giu_global_conn);
}
auto & node_synchronizer = this->mesh->getNodeSynchronizer();
node_synchronizer.synchronizeOnce(data_accessor,
SynchronizationTag::_ask_nodes);
}
}
/* -------------------------------------------------------------------------- */
-void DOFManager::updateDOFsData(DOFData & dof_data, UInt nb_new_local_dofs,
- UInt nb_new_pure_local) {
+void DOFManager::updateDOFsData(DOFData & dof_data, Int nb_new_local_dofs,
+ Int nb_new_pure_local) {
dof_data.local_equation_number.reserve(dof_data.local_equation_number.size() +
nb_new_local_dofs);
- UInt first_local_dof_id;
- UInt first_global_dof_id;
+ Int first_local_dof_id, first_global_dof_id;
std::tie(first_local_dof_id, first_global_dof_id) =
computeFirstDOFIDs(nb_new_local_dofs, nb_new_pure_local);
this->dofs_flag.resize(this->local_system_size, NodeFlag::_normal);
this->global_equation_number.resize(this->local_system_size, -1);
// update per dof info
for (auto _ [[gnu::unused]] : arange(nb_new_local_dofs)) {
// update equation numbers
this->dofs_flag(first_local_dof_id) = NodeFlag::_normal;
dof_data.local_equation_number.push_back(first_local_dof_id);
this->global_equation_number(first_local_dof_id) = first_global_dof_id;
this->global_to_local_mapping[first_global_dof_id] = first_local_dof_id;
++first_global_dof_id;
++first_local_dof_id;
}
}
/* -------------------------------------------------------------------------- */
-void DOFManager::onNodesRemoved(const Array<UInt> & /*unused*/,
- const Array<UInt> & /*unused*/,
- const RemovedNodesEvent & /*unused*/) {}
+void DOFManager::onNodesRemoved(const Array<Idx> &, const Array<Idx> &,
+ const RemovedNodesEvent &) {}
/* -------------------------------------------------------------------------- */
void DOFManager::onElementsAdded(const Array<Element> & /*unused*/,
const NewElementsEvent & /*unused*/) {}
/* -------------------------------------------------------------------------- */
-void DOFManager::onElementsRemoved(const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const RemovedElementsEvent & /*unused*/) {}
+void DOFManager::onElementsRemoved(const Array<Element> &,
+ const ElementTypeMapArray<Idx> &,
+ const RemovedElementsEvent &) {}
/* -------------------------------------------------------------------------- */
-void DOFManager::onElementsChanged(const Array<Element> & /*unused*/,
- const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const ChangedElementsEvent & /*unused*/) {}
+void DOFManager::onElementsChanged(const Array<Element> &,
+ const Array<Element> &,
+ const ElementTypeMapArray<Idx> &,
+ const ChangedElementsEvent &) {}
/* -------------------------------------------------------------------------- */
void DOFManager::updateGlobalBlockedDofs() {
this->previous_global_blocked_dofs.copy(this->global_blocked_dofs);
this->global_blocked_dofs.reserve(this->local_system_size, 0);
this->previous_global_blocked_dofs_release =
this->global_blocked_dofs_release;
for (auto & pair : dofs) {
if (not this->hasBlockedDOFs(pair.first)) {
continue;
}
DOFData & dof_data = *pair.second;
for (auto && data : zip(dof_data.getLocalEquationsNumbers(),
make_view(*dof_data.blocked_dofs))) {
const auto & dof = std::get<0>(data);
const auto & is_blocked = std::get<1>(data);
if (is_blocked) {
this->global_blocked_dofs.push_back(dof);
}
}
}
std::sort(this->global_blocked_dofs.begin(), this->global_blocked_dofs.end());
auto last = std::unique(this->global_blocked_dofs.begin(),
this->global_blocked_dofs.end());
this->global_blocked_dofs.resize(last - this->global_blocked_dofs.begin());
auto are_equal =
global_blocked_dofs.size() == previous_global_blocked_dofs.size() and
std::equal(global_blocked_dofs.begin(), global_blocked_dofs.end(),
previous_global_blocked_dofs.begin());
if (not are_equal) {
++this->global_blocked_dofs_release;
}
}
/* -------------------------------------------------------------------------- */
void DOFManager::applyBoundary(const ID & matrix_id) {
auto & J = this->getMatrix(matrix_id);
if (this->jacobian_release == J.getRelease()) {
if (this->hasBlockedDOFsChanged()) {
J.applyBoundary();
}
previous_global_blocked_dofs.copy(global_blocked_dofs);
} else {
J.applyBoundary();
}
this->jacobian_release = J.getRelease();
this->previous_global_blocked_dofs_release =
this->global_blocked_dofs_release;
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleMatMulVectToGlobalArray(const ID & dof_id,
const ID & A_id,
const Array<Real> & x,
SolverVector & array,
Real scale_factor) {
auto & A = this->getMatrix(A_id);
data_cache->resize();
data_cache->zero();
this->assembleToGlobalArray(dof_id, x, *data_cache, 1.);
A.matVecMul(*data_cache, array, scale_factor, 1.);
}
/* -------------------------------------------------------------------------- */
void DOFManager::assembleMatMulVectToResidual(const ID & dof_id,
const ID & A_id,
const Array<Real> & x,
Real scale_factor) {
assembleMatMulVectToGlobalArray(dof_id, A_id, x, *residual, scale_factor);
}
} // namespace akantu
diff --git a/src/model/common/dof_manager/dof_manager.hh b/src/model/common/dof_manager/dof_manager.hh
index 73c9bbf98..3f38c1099 100644
--- a/src/model/common/dof_manager/dof_manager.hh
+++ b/src/model/common/dof_manager/dof_manager.hh
@@ -1,720 +1,718 @@
/**
* @file dof_manager.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Aug 18 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Class handling the different types of dofs
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_factory.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <map>
#include <set>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DOF_MANAGER_HH_
#define AKANTU_DOF_MANAGER_HH_
namespace akantu {
class TermsToAssemble;
class NonLinearSolver;
class TimeStepSolver;
class SparseMatrix;
class SolverVector;
class SolverCallback;
} // namespace akantu
namespace akantu {
class DOFManager : protected MeshEventHandler {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
protected:
struct DOFData;
public:
DOFManager(const ID & id = "dof_manager");
DOFManager(Mesh & mesh, const ID & id = "dof_manager");
~DOFManager() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// register an array of degree of freedom
virtual void registerDOFs(const ID & dof_id, Array<Real> & dofs_array,
- const DOFSupportType & support_type);
+ DOFSupportType support_type);
/// the dof as an implied type of _dst_nodal and is defined only on a subset
/// of nodes
virtual void registerDOFs(const ID & dof_id, Array<Real> & dofs_array,
const ID & support_group);
/// register an array of previous values of the degree of freedom
virtual void registerDOFsPrevious(const ID & dof_id,
Array<Real> & dofs_array);
/// register an array of increment of degree of freedom
virtual void registerDOFsIncrement(const ID & dof_id,
Array<Real> & dofs_array);
/// register an array of derivatives for a particular dof array
- virtual void registerDOFsDerivative(const ID & dof_id, UInt order,
+ virtual void registerDOFsDerivative(const ID & dof_id, Int order,
Array<Real> & dofs_derivative);
/// register array representing the blocked degree of freedoms
virtual void registerBlockedDOFs(const ID & dof_id,
Array<bool> & blocked_dofs);
/// Assemble an array to the global residual array
virtual void assembleToResidual(const ID & dof_id,
Array<Real> & array_to_assemble,
Real scale_factor = 1.);
/// Assemble an array to the global lumped matrix array
virtual void assembleToLumpedMatrix(const ID & dof_id,
Array<Real> & array_to_assemble,
const ID & lumped_mtx,
Real scale_factor = 1.);
/**
* Assemble elementary values to a local array of the size nb_nodes *
* nb_dof_per_node. The dof number is implicitly considered as
* conn(el, n) * nb_nodes_per_element + d.
* With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node
**/
virtual void assembleElementalArrayLocalArray(
const Array<Real> & elementary_vect, Array<Real> & array_assembeled,
ElementType type, GhostType ghost_type, Real scale_factor = 1.,
- const Array<UInt> & filter_elements = empty_filter);
+ const Array<Int> & filter_elements = empty_filter);
/**
* Assemble elementary values to the global residual array. The dof number is
* implicitly considered as conn(el, n) * nb_nodes_per_element + d.
* With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node
**/
virtual void assembleElementalArrayToResidual(
const ID & dof_id, const Array<Real> & elementary_vect, ElementType type,
GhostType ghost_type, Real scale_factor = 1.,
- const Array<UInt> & filter_elements = empty_filter);
+ const Array<Int> & filter_elements = empty_filter);
/**
* Assemble elementary values to a global array corresponding to a lumped
* matrix
*/
virtual void assembleElementalArrayToLumpedMatrix(
const ID & dof_id, const Array<Real> & elementary_vect,
const ID & lumped_mtx, ElementType type, GhostType ghost_type,
Real scale_factor = 1.,
- const Array<UInt> & filter_elements = empty_filter);
+ const Array<Int> & filter_elements = empty_filter);
/**
* Assemble elementary values to the global residual array. The dof number is
* implicitly considered as conn(el, n) * nb_nodes_per_element + d. With 0 <
* n < nb_nodes_per_element and 0 < d < nb_dof_per_node
**/
virtual void assembleElementalMatricesToMatrix(
const ID & matrix_id, const ID & dof_id,
const Array<Real> & elementary_mat, ElementType type,
GhostType ghost_type = _not_ghost,
const MatrixType & elemental_matrix_type = _symmetric,
- const Array<UInt> & filter_elements = empty_filter) = 0;
+ const Array<Int> & filter_elements = empty_filter) = 0;
/// multiply a vector by a matrix and assemble the result to the residual
virtual void assembleMatMulVectToArray(const ID & dof_id, const ID & A_id,
const Array<Real> & x,
Array<Real> & array,
Real scale_factor = 1) = 0;
/// multiply a vector by a lumped matrix and assemble the result to the
/// residual
virtual void assembleLumpedMatMulVectToResidual(const ID & dof_id,
const ID & A_id,
const Array<Real> & x,
Real scale_factor = 1) = 0;
/// assemble coupling terms between to dofs
virtual void assemblePreassembledMatrix(const ID & matrix_id,
const TermsToAssemble & terms) = 0;
/// multiply a vector by a matrix and assemble the result to the residual
virtual void assembleMatMulVectToResidual(const ID & dof_id, const ID & A_id,
const Array<Real> & x,
Real scale_factor = 1);
/// multiply the dofs by a matrix and assemble the result to the residual
virtual void assembleMatMulDOFsToResidual(const ID & A_id,
Real scale_factor = 1);
/// updates the global blocked_dofs array
virtual void updateGlobalBlockedDofs();
/// sets the residual to 0
virtual void zeroResidual();
/// sets the matrix to 0
virtual void zeroMatrix(const ID & mtx);
/// sets the lumped matrix to 0
virtual void zeroLumpedMatrix(const ID & mtx);
virtual void applyBoundary(const ID & matrix_id = "J");
// virtual void applyBoundaryLumped(const ID & matrix_id = "J");
/// extract a lumped matrix part corresponding to a given dof
virtual void getLumpedMatrixPerDOFs(const ID & dof_id, const ID & lumped_mtx,
Array<Real> & lumped);
/// splits the solution storage from a global view to the per dof storages
void splitSolutionPerDOFs();
private:
/// dispatch the creation of the dof data and register it
DOFData & getNewDOFDataInternal(const ID & dof_id);
protected:
/// common function to help registering dofs the return values are the add new
/// numbers of local dofs, pure local dofs, and system size
- virtual std::tuple<UInt, UInt, UInt>
+ virtual std::tuple<Int, Int, Int>
registerDOFsInternal(const ID & dof_id, Array<Real> & dofs_array);
/// minimum functionality to implement per derived version of the DOFManager
/// to allow the splitSolutionPerDOFs function to work
virtual void getSolutionPerDOFs(const ID & dof_id,
Array<Real> & solution_array);
/// fill a Vector with the equation numbers corresponding to the given
/// connectivity
static inline void extractElementEquationNumber(
- const Array<Int> & equation_numbers, const Vector<UInt> & connectivity,
- UInt nb_degree_of_freedom, Vector<Int> & element_equation_number);
+ const Array<Int> & equation_numbers, const Vector<Idx> & connectivity,
+ Int nb_degree_of_freedom, Vector<Idx> & local_equation_number);
/// Assemble a array to a global one
void assembleMatMulVectToGlobalArray(const ID & dof_id, const ID & A_id,
const Array<Real> & x,
SolverVector & array,
Real scale_factor = 1.);
/// common function that can be called by derived class with proper matrice
/// types
template <typename Mat>
void assemblePreassembledMatrix_(Mat & A, const TermsToAssemble & terms);
template <typename Mat>
void
assembleElementalMatricesToMatrix_(Mat & A, const ID & dof_id,
const Array<Real> & elementary_mat,
ElementType type, GhostType ghost_type,
const MatrixType & elemental_matrix_type,
- const Array<UInt> & filter_elements);
+ const Array<Idx> & filter_elements);
template <typename Vec>
void assembleMatMulVectToArray_(const ID & dof_id, const ID & A_id,
const Array<Real> & x, Array<Real> & array,
Real scale_factor);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Get the location type of a given dof
- inline bool isLocalOrMasterDOF(UInt local_dof_num);
+ inline bool isLocalOrMasterDOF(Idx local_dof_num);
/// Answer to the question is a dof a slave dof ?
- inline bool isSlaveDOF(UInt local_dof_num);
+ inline bool isSlaveDOF(Idx local_dof_num);
/// Answer to the question is a dof a slave dof ?
- inline bool isPureGhostDOF(UInt local_dof_num);
+ inline bool isPureGhostDOF(Idx local_dof_num);
/// tells if the dof manager knows about a global dof
- bool hasGlobalEquationNumber(Int global) const;
+ bool hasGlobalEquationNumber(Idx global) const;
/// return the local index of the global equation number
- inline Int globalToLocalEquationNumber(Int global) const;
+ inline Idx globalToLocalEquationNumber(Idx global) const;
/// converts local equation numbers to global equation numbers;
- inline Int localToGlobalEquationNumber(Int local) const;
+ inline Idx localToGlobalEquationNumber(Idx local) const;
/// get the array of dof types (use only if you know what you do...)
- inline NodeFlag getDOFFlag(Int local_id) const;
+ inline NodeFlag getDOFFlag(Idx local_id) const;
/// defines if the boundary changed
bool hasBlockedDOFsChanged() const {
return this->global_blocked_dofs_release !=
this->previous_global_blocked_dofs_release;
}
/// Global number of dofs
- AKANTU_GET_MACRO(SystemSize, this->system_size, UInt);
+ AKANTU_GET_MACRO_AUTO(SystemSize, this->system_size);
/// Local number of dofs
- AKANTU_GET_MACRO(LocalSystemSize, this->local_system_size, UInt);
+ AKANTU_GET_MACRO_AUTO(LocalSystemSize, this->local_system_size);
/// Pure local number of dofs
- AKANTU_GET_MACRO(PureLocalSystemSize, this->pure_local_system_size, UInt);
+ AKANTU_GET_MACRO_AUTO(PureLocalSystemSize, this->pure_local_system_size);
/// Retrieve all the registered DOFs
std::vector<ID> getDOFIDs() const;
/* ------------------------------------------------------------------------ */
/* DOFs and derivatives accessors */
/* ------------------------------------------------------------------------ */
/// Get a reference to the registered dof array for a given id
inline Array<Real> & getDOFs(const ID & dofs_id);
/// Get the support type of a given dof
inline DOFSupportType getSupportType(const ID & dofs_id) const;
/// are the dofs registered
inline bool hasDOFs(const ID & dof_id) const;
/// Get a reference to the registered dof derivatives array for a given id
- inline Array<Real> & getDOFsDerivatives(const ID & dofs_id, UInt order);
+ inline Array<Real> & getDOFsDerivatives(const ID & dofs_id, Int order);
/// Does the dof has derivatives
- inline bool hasDOFsDerivatives(const ID & dofs_id, UInt order) const;
+ inline bool hasDOFsDerivatives(const ID & dofs_id, Int order) const;
/// Get a reference to the blocked dofs array registered for the given id
inline const Array<bool> & getBlockedDOFs(const ID & dofs_id) const;
/// Does the dof has a blocked array
inline bool hasBlockedDOFs(const ID & dofs_id) const;
/// Get a reference to the registered dof increment array for a given id
inline Array<Real> & getDOFsIncrement(const ID & dofs_id);
/// Does the dof has a increment array
inline bool hasDOFsIncrement(const ID & dofs_id) const;
/// Does the dof has a previous array
inline Array<Real> & getPreviousDOFs(const ID & dofs_id);
/// Get a reference to the registered dof array for previous step values a
/// given id
inline bool hasPreviousDOFs(const ID & dofs_id) const;
/// saves the values from dofs to previous dofs
virtual void savePreviousDOFs(const ID & dofs_id);
/// Get a reference to the solution array registered for the given id
inline const Array<Real> & getSolution(const ID & dofs_id) const;
/// Get a reference to the solution array registered for the given id
inline Array<Real> & getSolution(const ID & dofs_id);
/// Get the blocked dofs array
- AKANTU_GET_MACRO(GlobalBlockedDOFs, global_blocked_dofs, const Array<Int> &);
+ AKANTU_GET_MACRO_AUTO(GlobalBlockedDOFs, global_blocked_dofs);
/// Get the blocked dofs array
- AKANTU_GET_MACRO(PreviousGlobalBlockedDOFs, previous_global_blocked_dofs,
- const Array<Int> &);
+ AKANTU_GET_MACRO_AUTO(PreviousGlobalBlockedDOFs,
+ previous_global_blocked_dofs);
/* ------------------------------------------------------------------------ */
/* Matrices accessors */
/* ------------------------------------------------------------------------ */
/// Get an instance of a new SparseMatrix
virtual SparseMatrix & getNewMatrix(const ID & matrix_id,
const MatrixType & matrix_type) = 0;
/// Get an instance of a new SparseMatrix as a copy of the SparseMatrix
/// matrix_to_copy_id
virtual SparseMatrix & getNewMatrix(const ID & matrix_id,
const ID & matrix_to_copy_id) = 0;
/// Get the equation numbers corresponding to a dof_id. This might be used to
/// access the matrix.
- inline const Array<Int> & getLocalEquationsNumbers(const ID & dof_id) const;
+ inline decltype(auto) getLocalEquationsNumbers(const ID & dof_id) const;
protected:
/// get the array of dof types (use only if you know what you do...)
- inline const Array<UInt> & getDOFsAssociatedNodes(const ID & dof_id) const;
+ inline decltype(auto) getDOFsAssociatedNodes(const ID & dof_id) const;
protected:
/* ------------------------------------------------------------------------ */
/// register a matrix
SparseMatrix & registerSparseMatrix(const ID & matrix_id,
std::unique_ptr<SparseMatrix> & matrix);
/// register a lumped matrix (aka a Vector)
SolverVector & registerLumpedMatrix(const ID & matrix_id,
std::unique_ptr<SolverVector> & matrix);
/// register a non linear solver instantiated by a derived class
NonLinearSolver &
registerNonLinearSolver(const ID & non_linear_solver_id,
std::unique_ptr<NonLinearSolver> & non_linear_solver);
/// register a time step solver instantiated by a derived class
TimeStepSolver &
registerTimeStepSolver(const ID & time_step_solver_id,
std::unique_ptr<TimeStepSolver> & time_step_solver);
template <class NLSType, class DMType>
NonLinearSolver & registerNonLinearSolver(DMType & dm, const ID & id,
const NonLinearSolverType & type) {
ID non_linear_solver_id = this->id + ":nls:" + id;
std::unique_ptr<NonLinearSolver> nls =
std::make_unique<NLSType>(dm, type, non_linear_solver_id);
return this->registerNonLinearSolver(non_linear_solver_id, nls);
}
template <class TSSType, class DMType>
TimeStepSolver & registerTimeStepSolver(DMType & dm, const ID & id,
const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver,
SolverCallback & solver_callback) {
ID time_step_solver_id = this->id + ":tss:" + id;
std::unique_ptr<TimeStepSolver> tss = std::make_unique<TSSType>(
dm, type, non_linear_solver, solver_callback, time_step_solver_id);
return this->registerTimeStepSolver(time_step_solver_id, tss);
}
template <class MatType, class DMType>
SparseMatrix & registerSparseMatrix(DMType & dm, const ID & id,
const MatrixType & matrix_type) {
ID matrix_id = this->id + ":mtx:" + id;
std::unique_ptr<SparseMatrix> sm =
std::make_unique<MatType>(dm, matrix_type, matrix_id);
return this->registerSparseMatrix(matrix_id, sm);
}
template <class MatType>
SparseMatrix & registerSparseMatrix(const ID & id,
const ID & matrix_to_copy_id) {
ID matrix_id = this->id + ":mtx:" + id;
auto & sm_to_copy =
aka::as_type<MatType>(this->getMatrix(matrix_to_copy_id));
std::unique_ptr<SparseMatrix> sm =
std::make_unique<MatType>(sm_to_copy, matrix_id);
return this->registerSparseMatrix(matrix_id, sm);
}
template <class MatType, class DMType>
SolverVector & registerLumpedMatrix(DMType & dm, const ID & id) {
ID matrix_id = this->id + ":lumped_mtx:" + id;
std::unique_ptr<SolverVector> sm = std::make_unique<MatType>(dm, matrix_id);
return this->registerLumpedMatrix(matrix_id, sm);
}
protected:
virtual void makeConsistentForPeriodicity(const ID & dof_id,
SolverVector & array) = 0;
virtual void assembleToGlobalArray(const ID & dof_id,
const Array<Real> & array_to_assemble,
SolverVector & global_array,
Real scale_factor) = 0;
public:
/// extract degrees of freedom (identified by ID) from a global solver array
virtual void getArrayPerDOFs(const ID & dof_id, const SolverVector & global,
Array<Real> & local) = 0;
/// Get the reference of an existing matrix
SparseMatrix & getMatrix(const ID & matrix_id);
/// check if the given matrix exists
bool hasMatrix(const ID & matrix_id) const;
/// Get an instance of a new lumped matrix
virtual SolverVector & getNewLumpedMatrix(const ID & matrix_id) = 0;
/// Get the lumped version of a given matrix
const SolverVector & getLumpedMatrix(const ID & matrix_id) const;
/// Get the lumped version of a given matrix
SolverVector & getLumpedMatrix(const ID & matrix_id);
/// check if the given matrix exists
bool hasLumpedMatrix(const ID & matrix_id) const;
/* ------------------------------------------------------------------------ */
/* Non linear system solver */
/* ------------------------------------------------------------------------ */
/// Get instance of a non linear solver
virtual NonLinearSolver & getNewNonLinearSolver(
const ID & nls_solver_id,
const NonLinearSolverType & _non_linear_solver_type) = 0;
/// get instance of a non linear solver
virtual NonLinearSolver & getNonLinearSolver(const ID & nls_solver_id);
/// check if the given solver exists
bool hasNonLinearSolver(const ID & solver_id) const;
/* ------------------------------------------------------------------------ */
/* Time-Step Solver */
/* ------------------------------------------------------------------------ */
/// Get instance of a time step solver
virtual TimeStepSolver &
getNewTimeStepSolver(const ID & time_step_solver_id,
const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver,
SolverCallback & solver_callback) = 0;
/// get instance of a time step solver
virtual TimeStepSolver & getTimeStepSolver(const ID & time_step_solver_id);
/// check if the given solver exists
bool hasTimeStepSolver(const ID & solver_id) const;
/* ------------------------------------------------------------------------ */
const Mesh & getMesh() {
if (mesh != nullptr) {
return *mesh;
}
AKANTU_EXCEPTION("No mesh registered in this dof manager");
}
/* ------------------------------------------------------------------------ */
- AKANTU_GET_MACRO(Communicator, communicator, const auto &);
- AKANTU_GET_MACRO_NOT_CONST(Communicator, communicator, auto &);
+ AKANTU_GET_MACRO_AUTO(Communicator, communicator);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Communicator, communicator);
/* ------------------------------------------------------------------------ */
- AKANTU_GET_MACRO(Solution, *(solution.get()), const auto &);
- AKANTU_GET_MACRO_NOT_CONST(Solution, *(solution.get()), auto &);
+ AKANTU_GET_MACRO_DEREF_PTR(Solution, solution);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Solution, solution);
- AKANTU_GET_MACRO(Residual, *(residual.get()), const auto &);
- AKANTU_GET_MACRO_NOT_CONST(Residual, *(residual.get()), auto &);
+ AKANTU_GET_MACRO_DEREF_PTR(Residual, residual);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Residual, residual);
/* ------------------------------------------------------------------------ */
/* MeshEventHandler interface */
/* ------------------------------------------------------------------------ */
protected:
friend class GlobalDOFInfoDataAccessor;
/// helper function for the DOFManager::onNodesAdded method
- virtual std::pair<UInt, UInt> updateNodalDOFs(const ID & dof_id,
- const Array<UInt> & nodes_list);
+ virtual std::pair<Int, Int> updateNodalDOFs(const ID & dof_id,
+ const Array<Idx> & nodes_list);
template <typename Func>
- auto countDOFsForNodes(const DOFData & dof_data, UInt nb_nodes,
+ auto countDOFsForNodes(const DOFData & dof_data, Int nb_nodes,
Func && getNode);
- void updateDOFsData(DOFData & dof_data, UInt nb_new_local_dofs,
- UInt nb_new_pure_local, UInt nb_nodes,
- const std::function<UInt(UInt)> & getNode);
+ void updateDOFsData(DOFData & dof_data, Int nb_new_local_dofs,
+ Int nb_new_pure_local, Int nb_nodes,
+ const std::function<Idx(Idx)> & getNode);
- void updateDOFsData(DOFData & dof_data, UInt nb_new_local_dofs,
- UInt nb_new_pure_local);
+ void updateDOFsData(DOFData & dof_data, Int nb_new_local_dofs,
+ Int nb_new_pure_local);
- auto computeFirstDOFIDs(UInt nb_new_local_dofs, UInt nb_new_pure_local);
+ auto computeFirstDOFIDs(Int nb_new_local_dofs, Int nb_new_pure_local);
/// resize all the global information and takes the needed measure like
/// cleaning matrices profiles
virtual void resizeGlobalArrays();
public:
/// function to implement to react on akantu::NewNodesEvent
- void onNodesAdded(const Array<UInt> & nodes_list,
+ void onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) override;
/// function to implement to react on akantu::RemovedNodesEvent
- void onNodesRemoved(const Array<UInt> & nodes_list,
- const Array<UInt> & new_numbering,
+ void onNodesRemoved(const Array<Idx> & nodes_list,
+ const Array<Idx> & new_numbering,
const RemovedNodesEvent & event) override;
/// function to implement to react on akantu::NewElementsEvent
void onElementsAdded(const Array<Element> & elements_list,
const NewElementsEvent & event) override;
/// function to implement to react on akantu::RemovedElementsEvent
void onElementsRemoved(const Array<Element> & elements_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) override;
/// function to implement to react on akantu::ChangedElementsEvent
void onElementsChanged(const Array<Element> & old_elements_list,
const Array<Element> & new_elements_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const ChangedElementsEvent & event) override;
/// function to implement to react on akantu::MeshIsDistributedEvent
- void
- onMeshIsDistributed(const Mesh& mesh,
- const MeshIsDistributedEvent & event) override;
+ void onMeshIsDistributed(const MeshIsDistributedEvent & event) override;
protected:
inline DOFData & getDOFData(const ID & dof_id);
inline const DOFData & getDOFData(const ID & dof_id) const;
template <class DOFData_>
inline DOFData_ & getDOFDataTyped(const ID & dof_id);
template <class DOFData_>
inline const DOFData_ & getDOFDataTyped(const ID & dof_id) const;
virtual std::unique_ptr<DOFData> getNewDOFData(const ID & dof_id) = 0;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// dof representations in the dof manager
struct DOFData {
DOFData() = delete;
explicit DOFData(const ID & dof_id);
virtual ~DOFData();
/// DOF support type (nodal, general) this is needed to determine how the
/// dof are shared among processors
DOFSupportType support_type;
ID group_support;
/// Degree of freedom array
Array<Real> * dof{nullptr};
/// Blocked degree of freedoms array
Array<bool> * blocked_dofs{nullptr};
/// Degree of freedoms increment
Array<Real> * increment{nullptr};
/// Degree of freedoms at previous step
Array<Real> * previous{nullptr};
/// Solution associated to the dof
Array<Real> solution;
/* ---------------------------------------------------------------------- */
/* data for dynamic simulations */
/* ---------------------------------------------------------------------- */
/// Degree of freedom derivatives arrays
std::vector<Array<Real> *> dof_derivatives;
/* ---------------------------------------------------------------------- */
/// number of dofs to consider locally for this dof id
- UInt local_nb_dofs{0};
+ Int local_nb_dofs{0};
/// Number of purely local dofs
- UInt pure_local_nb_dofs{0};
+ Int pure_local_nb_dofs{0};
/// number of ghost dofs
- UInt ghosts_nb_dofs{0};
+ Int ghosts_nb_dofs{0};
/// local numbering equation numbers
- Array<Int> local_equation_number;
+ Array<Idx> local_equation_number;
/// associated node for _dst_nodal dofs only
- Array<UInt> associated_nodes;
+ Array<Idx> associated_nodes;
- virtual Array<Int> & getLocalEquationsNumbers() {
+ virtual Array<Idx> & getLocalEquationsNumbers() {
return local_equation_number;
}
};
/// type to store dofs information
using DOFStorage = std::map<ID, std::unique_ptr<DOFData>>;
/// type to store all the matrices
using SparseMatricesMap = std::map<ID, std::unique_ptr<SparseMatrix>>;
/// type to store all the lumped matrices
using LumpedMatricesMap = std::map<ID, std::unique_ptr<SolverVector>>;
/// type to store all the non linear solver
using NonLinearSolversMap = std::map<ID, std::unique_ptr<NonLinearSolver>>;
/// type to store all the time step solver
using TimeStepSolversMap = std::map<ID, std::unique_ptr<TimeStepSolver>>;
ID id;
/// store a reference to the dof arrays
DOFStorage dofs;
/// list of sparse matrices that where created
SparseMatricesMap matrices;
/// list of lumped matrices
LumpedMatricesMap lumped_matrices;
/// non linear solvers storage
NonLinearSolversMap non_linear_solvers;
/// time step solvers storage
TimeStepSolversMap time_step_solvers;
/// reference to the underlying mesh
Mesh * mesh{nullptr};
/// Total number of degrees of freedom (size with the ghosts)
- UInt local_system_size{0};
+ Int local_system_size{0};
/// Number of purely local dofs (size without the ghosts)
- UInt pure_local_system_size{0};
+ Int pure_local_system_size{0};
/// Total number of degrees of freedom
- UInt system_size{0};
+ Int system_size{0};
/// rhs to the system of equation corresponding to the residual linked to the
/// different dofs
std::unique_ptr<SolverVector> residual;
/// solution of the system of equation corresponding to the different dofs
std::unique_ptr<SolverVector> solution;
/// a vector that helps internally to perform some tasks
std::unique_ptr<SolverVector> data_cache;
/// define the dofs type, local, shared, ghost
Array<NodeFlag> dofs_flag;
/// equation number in global numbering
Array<Int> global_equation_number;
using equation_numbers_map = std::unordered_map<Int, Int>;
/// dual information of global_equation_number
equation_numbers_map global_to_local_mapping;
/// Communicator used for this manager, should be the same as in the mesh if a
/// mesh is registered
Communicator & communicator;
/// accumulator to know what would be the next global id to use
- UInt first_global_dof_id{0};
+ Int first_global_dof_id{0};
/// Release at last apply boundary on jacobian
- UInt jacobian_release{0};
+ Int jacobian_release{0};
/// blocked degree of freedom in the system equation corresponding to the
/// different dofs
Array<Int> global_blocked_dofs;
- UInt global_blocked_dofs_release{0};
+ Int global_blocked_dofs_release{0};
/// blocked degree of freedom in the system equation corresponding to the
/// different dofs
Array<Int> previous_global_blocked_dofs;
- UInt previous_global_blocked_dofs_release{0};
+ Int previous_global_blocked_dofs_release{0};
private:
/// This is for unit testing
friend class DOFManagerTester;
};
using DefaultDOFManagerFactory = Factory<DOFManager, ID, const ID &>;
using DOFManagerFactory = Factory<DOFManager, ID, Mesh &, const ID &>;
} // namespace akantu
#include "dof_manager_inline_impl.hh"
#endif /* AKANTU_DOF_MANAGER_HH_ */
diff --git a/src/model/common/dof_manager/dof_manager_default.cc b/src/model/common/dof_manager/dof_manager_default.cc
index 8fe96c51f..7e20c0dcc 100644
--- a/src/model/common/dof_manager/dof_manager_default.cc
+++ b/src/model/common/dof_manager/dof_manager_default.cc
@@ -1,489 +1,486 @@
/**
* @file dof_manager_default.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Aug 18 2015
* @date last modification: Tue Mar 30 2021
*
* @brief Implementation of the default DOFManager
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager_default.hh"
#include "communicator.hh"
#include "dof_synchronizer.hh"
#include "element_group.hh"
#include "non_linear_solver_default.hh"
#include "periodic_node_synchronizer.hh"
#include "solver_vector_default.hh"
#include "solver_vector_distributed.hh"
#include "sparse_matrix_aij.hh"
#include "time_step_solver_default.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <memory>
#include <numeric>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
DOFManagerDefault::DOFManagerDefault(const ID & id)
: DOFManager(id), synchronizer(nullptr) {
residual = std::make_unique<SolverVectorDefault>(
*this, std::string(id + ":residual"));
solution = std::make_unique<SolverVectorDefault>(
*this, std::string(id + ":solution"));
data_cache = std::make_unique<SolverVectorDefault>(
*this, std::string(id + ":data_cache"));
}
/* -------------------------------------------------------------------------- */
DOFManagerDefault::DOFManagerDefault(Mesh & mesh, const ID & id)
: DOFManager(mesh, id), synchronizer(nullptr) {
if (this->mesh->isDistributed()) {
this->synchronizer = std::make_unique<DOFSynchronizer>(
*this, this->id + ":dof_synchronizer");
residual = std::make_unique<SolverVectorDistributed>(
*this, std::string(id + ":residual"));
solution = std::make_unique<SolverVectorDistributed>(
*this, std::string(id + ":solution"));
data_cache = std::make_unique<SolverVectorDistributed>(
*this, std::string(id + ":data_cache"));
} else {
residual = std::make_unique<SolverVectorDefault>(
*this, std::string(id + ":residual"));
solution = std::make_unique<SolverVectorDefault>(
*this, std::string(id + ":solution"));
data_cache = std::make_unique<SolverVectorDefault>(
*this, std::string(id + ":data_cache"));
}
}
/* -------------------------------------------------------------------------- */
DOFManagerDefault::~DOFManagerDefault() = default;
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::makeConsistentForPeriodicity(const ID & dof_id,
SolverVector & array) {
auto & dof_data = this->getDOFDataTyped<DOFDataDefault>(dof_id);
if (dof_data.support_type != _dst_nodal) {
return;
}
if (not mesh->isPeriodic()) {
return;
}
this->mesh->getPeriodicNodeSynchronizer()
.reduceSynchronizeWithPBCSlaves<AddOperation>(
aka::as_type<SolverVectorDefault>(array).getVector());
}
/* -------------------------------------------------------------------------- */
template <typename T>
void DOFManagerDefault::assembleToGlobalArray(
const ID & dof_id, const Array<T> & array_to_assemble,
Array<T> & global_array, T scale_factor) {
AKANTU_DEBUG_IN();
auto & dof_data = this->getDOFDataTyped<DOFDataDefault>(dof_id);
AKANTU_DEBUG_ASSERT(dof_data.local_equation_number.size() ==
array_to_assemble.size() *
array_to_assemble.getNbComponent(),
"The array to assemble does not have a correct size."
<< " (" << array_to_assemble.getID() << ")");
if (dof_data.support_type == _dst_nodal and mesh->isPeriodic()) {
for (auto && data :
zip(dof_data.local_equation_number, dof_data.associated_nodes,
make_view(array_to_assemble))) {
auto && equ_num = std::get<0>(data);
// auto && node = std::get<1>(data);
auto && arr = std::get<2>(data);
// Guillaume to Nico:
// This filter of periodic slave should not be.
// Indeed you want to get the contribution even
// from periodic slaves and cumulate to the right
// equation number.
global_array(equ_num) += scale_factor * (arr);
// scale_factor * (arr) * (not this->mesh->isPeriodicSlave(node));
}
} else {
for (auto && data :
zip(dof_data.local_equation_number, make_view(array_to_assemble))) {
auto && equ_num = std::get<0>(data);
auto && arr = std::get<1>(data);
global_array(equ_num) += scale_factor * (arr);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::assembleToGlobalArray(
const ID & dof_id, const Array<Real> & array_to_assemble,
SolverVector & global_array_v, Real scale_factor) {
assembleToGlobalArray(
dof_id, array_to_assemble,
aka::as_type<SolverVectorDefault>(global_array_v).getVector(),
scale_factor);
}
/* -------------------------------------------------------------------------- */
DOFManagerDefault::DOFDataDefault::DOFDataDefault(const ID & dof_id)
: DOFData(dof_id) {}
/* -------------------------------------------------------------------------- */
auto DOFManagerDefault::getNewDOFData(const ID & dof_id)
-> std::unique_ptr<DOFData> {
return std::make_unique<DOFDataDefault>(dof_id);
}
/* -------------------------------------------------------------------------- */
-std::tuple<UInt, UInt, UInt>
+std::tuple<Int, Int, Int>
DOFManagerDefault::registerDOFsInternal(const ID & dof_id,
Array<Real> & dofs_array) {
auto ret = DOFManager::registerDOFsInternal(dof_id, dofs_array);
// update the synchronizer if needed
if (this->synchronizer) {
this->synchronizer->registerDOFs(dof_id);
}
return ret;
}
/* -------------------------------------------------------------------------- */
SparseMatrix & DOFManagerDefault::getNewMatrix(const ID & id,
const MatrixType & matrix_type) {
return this->registerSparseMatrix<SparseMatrixAIJ>(*this, id, matrix_type);
}
/* -------------------------------------------------------------------------- */
SparseMatrix & DOFManagerDefault::getNewMatrix(const ID & id,
const ID & matrix_to_copy_id) {
return this->registerSparseMatrix<SparseMatrixAIJ>(id, matrix_to_copy_id);
}
/* -------------------------------------------------------------------------- */
SolverVector & DOFManagerDefault::getNewLumpedMatrix(const ID & id) {
return this->registerLumpedMatrix<SolverVectorDefault>(*this, id);
}
/* -------------------------------------------------------------------------- */
SparseMatrixAIJ & DOFManagerDefault::getMatrix(const ID & id) {
auto & matrix = DOFManager::getMatrix(id);
return aka::as_type<SparseMatrixAIJ>(matrix);
}
/* -------------------------------------------------------------------------- */
NonLinearSolver &
DOFManagerDefault::getNewNonLinearSolver(const ID & id,
const NonLinearSolverType & type) {
switch (type) {
#if defined(AKANTU_USE_MUMPS)
case NonLinearSolverType::_newton_raphson:
/* FALLTHRU */
/* [[fallthrough]]; un-comment when compiler will get it */
case NonLinearSolverType::_newton_raphson_contact:
case NonLinearSolverType::_newton_raphson_modified: {
return this->registerNonLinearSolver<NonLinearSolverNewtonRaphson>(
*this, id, type);
}
case NonLinearSolverType::_linear: {
return this->registerNonLinearSolver<NonLinearSolverLinear>(*this, id,
type);
}
#endif
case NonLinearSolverType::_lumped: {
return this->registerNonLinearSolver<NonLinearSolverLumped>(*this, id,
type);
}
default:
AKANTU_EXCEPTION("The asked type of non linear solver is not supported by "
"this dof manager");
}
}
/* -------------------------------------------------------------------------- */
TimeStepSolver & DOFManagerDefault::getNewTimeStepSolver(
const ID & id, const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver, SolverCallback & solver_callback) {
return this->registerTimeStepSolver<TimeStepSolverDefault>(
*this, id, type, non_linear_solver, solver_callback);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void DOFManagerDefault::getArrayPerDOFs(const ID & dof_id,
const Array<T> & global_array,
Array<T> & local_array) const {
AKANTU_DEBUG_IN();
- const Array<Int> & equation_number = this->getLocalEquationsNumbers(dof_id);
+ const auto & equation_number = this->getLocalEquationsNumbers(dof_id);
- UInt nb_degree_of_freedoms = equation_number.size();
+ auto nb_degree_of_freedoms = equation_number.size();
local_array.resize(nb_degree_of_freedoms / local_array.getNbComponent());
- auto loc_it = local_array.begin_reinterpret(nb_degree_of_freedoms);
- auto equ_it = equation_number.begin();
-
- for (UInt d = 0; d < nb_degree_of_freedoms; ++d, ++loc_it, ++equ_it) {
- (*loc_it) = global_array(*equ_it);
+ for (auto data : zip(equation_number, make_view(local_array))) {
+ std::get<1>(data) = global_array(std::get<0>(data));
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::getArrayPerDOFs(const ID & dof_id,
const SolverVector & global_array,
Array<Real> & local_array) {
getArrayPerDOFs(dof_id,
aka::as_type<SolverVectorDefault>(global_array).getVector(),
local_array);
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::assembleLumpedMatMulVectToResidual(
const ID & dof_id, const ID & A_id, const Array<Real> & x,
Real scale_factor) {
- const Array<Real> & A = this->getLumpedMatrix(A_id);
+ const auto & A =
+ aka::as_type<SolverVectorArray>(this->getLumpedMatrix(A_id)).getVector();
auto & cache = aka::as_type<SolverVectorArray>(*this->data_cache);
cache.zero();
this->assembleToGlobalArray(dof_id, x, cache.getVector(), scale_factor);
for (auto && data : zip(make_view(A), make_view(cache.getVector()),
make_view(this->getResidualArray()))) {
const auto & A = std::get<0>(data);
const auto & x = std::get<1>(data);
auto & r = std::get<2>(data);
r += A * x;
}
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::assembleElementalMatricesToMatrix(
const ID & matrix_id, const ID & dof_id, const Array<Real> & elementary_mat,
ElementType type, GhostType ghost_type,
const MatrixType & elemental_matrix_type,
- const Array<UInt> & filter_elements) {
+ const Array<Int> & filter_elements) {
this->addToProfile(matrix_id, dof_id, type, ghost_type);
auto & A = getMatrix(matrix_id);
DOFManager::assembleElementalMatricesToMatrix_(
A, dof_id, elementary_mat, type, ghost_type, elemental_matrix_type,
filter_elements);
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::assemblePreassembledMatrix(
const ID & matrix_id, const TermsToAssemble & terms) {
auto & A = getMatrix(matrix_id);
DOFManager::assemblePreassembledMatrix_(A, terms);
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::assembleMatMulVectToArray(const ID & dof_id,
const ID & A_id,
const Array<Real> & x,
Array<Real> & array,
Real scale_factor) {
if (mesh->isDistributed()) {
DOFManager::assembleMatMulVectToArray_<SolverVectorDistributed>(
dof_id, A_id, x, array, scale_factor);
} else {
DOFManager::assembleMatMulVectToArray_<SolverVectorDefault>(
dof_id, A_id, x, array, scale_factor);
}
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::addToProfile(const ID & matrix_id, const ID & dof_id,
ElementType type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
const auto & dof_data = this->getDOFData(dof_id);
if (dof_data.support_type != _dst_nodal) {
return;
}
auto mat_dof = std::make_pair(matrix_id, dof_id);
auto type_pair = std::make_pair(type, ghost_type);
auto prof_it = this->matrix_profiled_dofs.find(mat_dof);
if (prof_it != this->matrix_profiled_dofs.end() &&
std::find(prof_it->second.begin(), prof_it->second.end(), type_pair) !=
prof_it->second.end()) {
return;
}
auto nb_degree_of_freedom_per_node = dof_data.dof->getNbComponent();
const auto & equation_number = this->getLocalEquationsNumbers(dof_id);
auto & A = this->getMatrix(matrix_id);
A.resize(system_size);
auto size = A.size();
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
const auto & connectivity = this->mesh->getConnectivity(type, ghost_type);
auto cbegin = connectivity.begin(nb_nodes_per_element);
auto cit = cbegin;
auto nb_elements = connectivity.size();
- UInt * ge_it = nullptr;
+ Int * ge_it = nullptr;
if (dof_data.group_support != "__mesh__") {
const auto & group_elements =
this->mesh->getElementGroup(dof_data.group_support)
.getElements(type, ghost_type);
- ge_it = group_elements.storage();
+ ge_it = group_elements.data();
nb_elements = group_elements.size();
}
- UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom_per_node;
+ auto size_mat = nb_nodes_per_element * nb_degree_of_freedom_per_node;
Vector<Int> element_eq_nb(size_mat);
- for (UInt e = 0; e < nb_elements; ++e) {
+ for (Int e = 0; e < nb_elements; ++e) {
if (ge_it != nullptr) {
cit = cbegin + *ge_it;
}
this->extractElementEquationNumber(
equation_number, *cit, nb_degree_of_freedom_per_node, element_eq_nb);
std::transform(
- element_eq_nb.storage(), element_eq_nb.storage() + element_eq_nb.size(),
- element_eq_nb.storage(),
+ element_eq_nb.begin(), element_eq_nb.end(), element_eq_nb.begin(),
[&](auto & local) { return this->localToGlobalEquationNumber(local); });
if (ge_it != nullptr) {
++ge_it;
} else {
++cit;
}
- for (UInt i = 0; i < size_mat; ++i) {
- UInt c_irn = element_eq_nb(i);
+ for (Int i = 0; i < size_mat; ++i) {
+ auto c_irn = element_eq_nb(i);
if (c_irn < size) {
- for (UInt j = 0; j < size_mat; ++j) {
- UInt c_jcn = element_eq_nb(j);
+ for (Int j = 0; j < size_mat; ++j) {
+ auto c_jcn = element_eq_nb(j);
if (c_jcn < size) {
A.add(c_irn, c_jcn);
}
}
}
}
}
this->matrix_profiled_dofs[mat_dof].push_back(type_pair);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Array<Real> & DOFManagerDefault::getSolutionArray() {
return dynamic_cast<SolverVectorDefault *>(this->solution.get())->getVector();
}
/* -------------------------------------------------------------------------- */
const Array<Real> & DOFManagerDefault::getResidualArray() const {
return dynamic_cast<SolverVectorDefault *>(this->residual.get())->getVector();
}
/* -------------------------------------------------------------------------- */
Array<Real> & DOFManagerDefault::getResidualArray() {
return dynamic_cast<SolverVectorDefault *>(this->residual.get())->getVector();
}
/* -------------------------------------------------------------------------- */
-void DOFManagerDefault::onNodesAdded(const Array<UInt> & nodes_list,
+void DOFManagerDefault::onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) {
DOFManager::onNodesAdded(nodes_list, event);
if (this->synchronizer) {
this->synchronizer->onNodesAdded(nodes_list);
}
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::resizeGlobalArrays() {
DOFManager::resizeGlobalArrays();
this->global_blocked_dofs.resize(this->local_system_size, 1);
this->previous_global_blocked_dofs.resize(this->local_system_size, 1);
matrix_profiled_dofs.clear();
}
/* -------------------------------------------------------------------------- */
void DOFManagerDefault::updateGlobalBlockedDofs() {
DOFManager::updateGlobalBlockedDofs();
if (this->global_blocked_dofs_release ==
this->previous_global_blocked_dofs_release) {
return;
}
global_blocked_dofs_uint.resize(local_system_size);
global_blocked_dofs_uint.set(false);
for (const auto & dof : global_blocked_dofs) {
global_blocked_dofs_uint[dof] = true;
}
}
/* -------------------------------------------------------------------------- */
Array<bool> & DOFManagerDefault::getBlockedDOFs() {
return global_blocked_dofs_uint;
}
/* -------------------------------------------------------------------------- */
const Array<bool> & DOFManagerDefault::getBlockedDOFs() const {
return global_blocked_dofs_uint;
}
/* -------------------------------------------------------------------------- */
static bool dof_manager_is_registered =
DOFManagerFactory::getInstance().registerAllocator(
"default",
[](Mesh & mesh, const ID & id) -> std::unique_ptr<DOFManager> {
return std::make_unique<DOFManagerDefault>(mesh, id);
});
static bool dof_manager_is_registered_mumps =
DOFManagerFactory::getInstance().registerAllocator(
"mumps", [](Mesh & mesh, const ID & id) -> std::unique_ptr<DOFManager> {
return std::make_unique<DOFManagerDefault>(mesh, id);
});
} // namespace akantu
diff --git a/src/model/common/dof_manager/dof_manager_default.hh b/src/model/common/dof_manager/dof_manager_default.hh
index 4c576ccb5..ca2c9eecd 100644
--- a/src/model/common/dof_manager/dof_manager_default.hh
+++ b/src/model/common/dof_manager/dof_manager_default.hh
@@ -1,254 +1,254 @@
/**
* @file dof_manager_default.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Aug 18 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Default implementation of the dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager.hh"
/* -------------------------------------------------------------------------- */
#include <functional>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DOF_MANAGER_DEFAULT_HH_
#define AKANTU_DOF_MANAGER_DEFAULT_HH_
namespace akantu {
class SparseMatrixAIJ;
class NonLinearSolverDefault;
class TimeStepSolverDefault;
class DOFSynchronizer;
} // namespace akantu
namespace akantu {
class DOFManagerDefault : public DOFManager {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
DOFManagerDefault(const ID & id = "dof_manager_default");
DOFManagerDefault(Mesh & mesh, const ID & id = "dof_manager_default");
~DOFManagerDefault() override;
protected:
struct DOFDataDefault : public DOFData {
explicit DOFDataDefault(const ID & dof_id);
};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
// /// register an array of degree of freedom
// void registerDOFs(const ID & dof_id, Array<Real> & dofs_array,
// const DOFSupportType & support_type) override;
// /// the dof as an implied type of _dst_nodal and is defined only on a
// subset
// /// of nodes
// void registerDOFs(const ID & dof_id, Array<Real> & dofs_array,
// const ID & group_support) override;
/**
* Assemble elementary values to the global matrix. The dof number is
* implicitly considered as conn(el, n) * nb_nodes_per_element + d.
* With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node
**/
void assembleElementalMatricesToMatrix(
const ID & matrix_id, const ID & dof_id,
const Array<Real> & elementary_mat, ElementType type,
GhostType ghost_type, const MatrixType & elemental_matrix_type,
- const Array<UInt> & filter_elements) override;
+ const Array<Int> & filter_elements) override;
void assembleMatMulVectToArray(const ID & dof_id, const ID & A_id,
const Array<Real> & x, Array<Real> & array,
Real scale_factor = 1.) override;
/// multiply a vector by a lumped matrix and assemble the result to the
/// residual
void assembleLumpedMatMulVectToResidual(const ID & dof_id, const ID & A_id,
const Array<Real> & x,
Real scale_factor = 1) override;
/// assemble coupling terms between to dofs
void assemblePreassembledMatrix(const ID & matrix_id,
const TermsToAssemble & terms) override;
protected:
void assembleToGlobalArray(const ID & dof_id,
const Array<Real> & array_to_assemble,
SolverVector & global_array,
Real scale_factor) override;
template <typename T>
void assembleToGlobalArray(const ID & dof_id,
const Array<T> & array_to_assemble,
Array<T> & global_array, T scale_factor);
void getArrayPerDOFs(const ID & dof_id, const SolverVector & global,
Array<Real> & local) override;
template <typename T>
void getArrayPerDOFs(const ID & dof_id, const Array<T> & global_array,
Array<T> & local_array) const;
void makeConsistentForPeriodicity(const ID & dof_id,
SolverVector & array) override;
public:
/// update the global dofs vector
void updateGlobalBlockedDofs() override;
// /// apply boundary conditions to jacobian matrix
// void applyBoundary(const ID & matrix_id = "J") override;
private:
/// Add a symmetric matrices to a symmetric sparse matrix
void addSymmetricElementalMatrixToSymmetric(
SparseMatrixAIJ & matrix, const Matrix<Real> & element_mat,
- const Vector<Int> & equation_numbers, UInt max_size);
+ const Vector<Idx> & equation_numbers, Int max_size);
/// Add a unsymmetric matrices to a symmetric sparse matrix (i.e. cohesive
/// elements)
void addUnsymmetricElementalMatrixToSymmetric(
SparseMatrixAIJ & matrix, const Matrix<Real> & element_mat,
- const Vector<Int> & equation_numbers, UInt max_size);
+ const Vector<Idx> & equation_numbers, Int max_size);
/// Add a matrices to a unsymmetric sparse matrix
void addElementalMatrixToUnsymmetric(SparseMatrixAIJ & matrix,
const Matrix<Real> & element_mat,
- const Vector<Int> & equation_numbers,
+ const Vector<Idx> & equation_numbers,
UInt max_size);
void addToProfile(const ID & matrix_id, const ID & dof_id, ElementType type,
GhostType ghost_type);
/* ------------------------------------------------------------------------ */
/* MeshEventHandler interface */
/* ------------------------------------------------------------------------ */
protected:
- std::tuple<UInt, UInt, UInt>
+ std::tuple<Int, Int, Int>
registerDOFsInternal(const ID & dof_id, Array<Real> & dofs_array) override;
// std::pair<UInt, UInt>
// updateNodalDOFs(const ID & dof_id, const Array<UInt> & nodes_list)
// override;
void resizeGlobalArrays() override;
public:
/// function to implement to react on akantu::NewNodesEvent
- void onNodesAdded(const Array<UInt> & nodes_list,
+ void onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Get an instance of a new SparseMatrix
SparseMatrix & getNewMatrix(const ID & matrix_id,
const MatrixType & matrix_type) override;
/// Get an instance of a new SparseMatrix as a copy of the SparseMatrix
/// matrix_to_copy_id
SparseMatrix & getNewMatrix(const ID & matrix_id,
const ID & matrix_to_copy_id) override;
/// Get the reference of an existing matrix
SparseMatrixAIJ & getMatrix(const ID & matrix_id);
/// Get an instance of a new lumped matrix
SolverVector & getNewLumpedMatrix(const ID & matrix_id) override;
/* ------------------------------------------------------------------------ */
/* Non Linear Solver */
/* ------------------------------------------------------------------------ */
/// Get instance of a non linear solver
NonLinearSolver & getNewNonLinearSolver(
const ID & nls_solver_id,
const NonLinearSolverType & _non_linear_solver_type) override;
/* ------------------------------------------------------------------------ */
/* Time-Step Solver */
/* ------------------------------------------------------------------------ */
/// Get instance of a time step solver
TimeStepSolver &
getNewTimeStepSolver(const ID & id, const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver,
SolverCallback & solver_callback) override;
/* ------------------------------------------------------------------------ */
private:
/// Get the solution array
Array<Real> & getSolutionArray();
/// Get the residual array
const Array<Real> & getResidualArray() const;
/// Get the residual array
Array<Real> & getResidualArray();
public:
/// access the internal dof_synchronizer
AKANTU_GET_MACRO_NOT_CONST(Synchronizer, *synchronizer, DOFSynchronizer &);
/// access the internal dof_synchronizer
bool hasSynchronizer() const { return synchronizer != nullptr; }
Array<bool> & getBlockedDOFs();
const Array<bool> & getBlockedDOFs() const;
protected:
std::unique_ptr<DOFData> getNewDOFData(const ID & dof_id) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
using DOFToMatrixProfile =
std::map<std::pair<ID, ID>,
std::vector<std::pair<ElementType, GhostType>>>;
/// contains the the dofs that where added to the profile of a given matrix.
DOFToMatrixProfile matrix_profiled_dofs;
/// synchronizer to maintain coherency in dof fields
std::unique_ptr<DOFSynchronizer> synchronizer;
friend class DOFSynchronizer;
/// Array containing the true or false if the node is in global_blocked_dofs
Array<bool> global_blocked_dofs_uint;
};
} // namespace akantu
#include "dof_manager_default_inline_impl.hh"
#endif /* AKANTU_DOF_MANAGER_DEFAULT_HH_ */
diff --git a/src/model/common/dof_manager/dof_manager_inline_impl.hh b/src/model/common/dof_manager/dof_manager_inline_impl.hh
index 7c251e8ce..72f5be7f5 100644
--- a/src/model/common/dof_manager/dof_manager_inline_impl.hh
+++ b/src/model/common/dof_manager/dof_manager_inline_impl.hh
@@ -1,339 +1,337 @@
/**
* @file dof_manager_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Thu Feb 20 2020
*
* @brief inline functions of the dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager.hh"
#include "element_group.hh"
#include "solver_vector.hh"
#include "sparse_matrix.hh"
#include "terms_to_assemble.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_DOF_MANAGER_INLINE_IMPL_HH_
-#define AKANTU_DOF_MANAGER_INLINE_IMPL_HH_
+// #ifndef __AKANTU_DOF_MANAGER_INLINE_IMPL_CC__
+// #define __AKANTU_DOF_MANAGER_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
inline bool DOFManager::hasDOFs(const ID & dof_id) const {
auto it = this->dofs.find(dof_id);
return it != this->dofs.end();
}
/* -------------------------------------------------------------------------- */
inline DOFManager::DOFData & DOFManager::getDOFData(const ID & dof_id) {
auto it = this->dofs.find(dof_id);
if (it == this->dofs.end()) {
AKANTU_EXCEPTION("The dof " << dof_id << " does not exists in "
<< this->id);
}
return *it->second;
}
/* -------------------------------------------------------------------------- */
const DOFManager::DOFData & DOFManager::getDOFData(const ID & dof_id) const {
auto it = this->dofs.find(dof_id);
if (it == this->dofs.end()) {
AKANTU_EXCEPTION("The dof " << dof_id << " does not exists in "
<< this->id);
}
return *it->second;
}
/* -------------------------------------------------------------------------- */
inline void DOFManager::extractElementEquationNumber(
- const Array<Int> & equation_numbers, const Vector<UInt> & connectivity,
- UInt nb_degree_of_freedom, Vector<Int> & element_equation_number) {
- for (UInt i = 0, ld = 0; i < connectivity.size(); ++i) {
- UInt n = connectivity(i);
- for (UInt d = 0; d < nb_degree_of_freedom; ++d, ++ld) {
+ const Array<Idx> & equation_numbers, const Vector<Idx> & connectivity,
+ Int nb_degree_of_freedom, Vector<Idx> & element_equation_number) {
+ for (Int i = 0, ld = 0; i < connectivity.size(); ++i) {
+ auto n = connectivity(i);
+ for (Int d = 0; d < nb_degree_of_freedom; ++d, ++ld) {
element_equation_number(ld) =
equation_numbers(n * nb_degree_of_freedom + d);
}
}
}
/* -------------------------------------------------------------------------- */
template <class DOFData_>
inline DOFData_ & DOFManager::getDOFDataTyped(const ID & dof_id) {
return aka::as_type<DOFData_>(this->getDOFData(dof_id));
}
/* -------------------------------------------------------------------------- */
template <class DOFData_>
inline const DOFData_ & DOFManager::getDOFDataTyped(const ID & dof_id) const {
return aka::as_type<DOFData_>(this->getDOFData(dof_id));
}
/* -------------------------------------------------------------------------- */
inline Array<Real> & DOFManager::getDOFs(const ID & dofs_id) {
return *(this->getDOFData(dofs_id).dof);
}
/* -------------------------------------------------------------------------- */
inline DOFSupportType DOFManager::getSupportType(const ID & dofs_id) const {
return this->getDOFData(dofs_id).support_type;
}
/* -------------------------------------------------------------------------- */
inline Array<Real> & DOFManager::getPreviousDOFs(const ID & dofs_id) {
return *(this->getDOFData(dofs_id).previous);
}
/* -------------------------------------------------------------------------- */
inline bool DOFManager::hasPreviousDOFs(const ID & dofs_id) const {
return (this->getDOFData(dofs_id).previous != nullptr);
}
/* -------------------------------------------------------------------------- */
inline Array<Real> & DOFManager::getDOFsIncrement(const ID & dofs_id) {
return *(this->getDOFData(dofs_id).increment);
}
/* -------------------------------------------------------------------------- */
inline bool DOFManager::hasDOFsIncrement(const ID & dofs_id) const {
return (this->getDOFData(dofs_id).increment != nullptr);
}
/* -------------------------------------------------------------------------- */
inline Array<Real> & DOFManager::getDOFsDerivatives(const ID & dofs_id,
- UInt order) {
+ Int order) {
if (order == 0) {
return getDOFs(dofs_id);
}
- std::vector<Array<Real> *> & derivatives =
- this->getDOFData(dofs_id).dof_derivatives;
- if ((order > derivatives.size()) || (derivatives[order - 1] == nullptr)) {
+ auto & derivatives = this->getDOFData(dofs_id).dof_derivatives;
+ if ((order > Int(derivatives.size())) ||
+ (derivatives[order - 1] == nullptr)) {
AKANTU_EXCEPTION("No derivatives of order " << order << " present in "
<< this->id << " for dof "
<< dofs_id);
}
return *derivatives[order - 1];
}
/* -------------------------------------------------------------------------- */
inline bool DOFManager::hasDOFsDerivatives(const ID & dofs_id,
- UInt order) const {
- const std::vector<Array<Real> *> & derivatives =
- this->getDOFData(dofs_id).dof_derivatives;
- return ((order < derivatives.size()) && (derivatives[order - 1] != nullptr));
+ Int order) const {
+ const auto & derivatives = this->getDOFData(dofs_id).dof_derivatives;
+ return ((order < Int(derivatives.size())) &&
+ (derivatives[order - 1] != nullptr));
}
/* -------------------------------------------------------------------------- */
inline const Array<Real> & DOFManager::getSolution(const ID & dofs_id) const {
return this->getDOFData(dofs_id).solution;
}
/* -------------------------------------------------------------------------- */
inline Array<Real> & DOFManager::getSolution(const ID & dofs_id) {
return this->getDOFData(dofs_id).solution;
}
/* -------------------------------------------------------------------------- */
inline const Array<bool> &
DOFManager::getBlockedDOFs(const ID & dofs_id) const {
return *(this->getDOFData(dofs_id).blocked_dofs);
}
/* -------------------------------------------------------------------------- */
inline bool DOFManager::hasBlockedDOFs(const ID & dofs_id) const {
return (this->getDOFData(dofs_id).blocked_dofs != nullptr);
}
/* -------------------------------------------------------------------------- */
-inline bool DOFManager::isLocalOrMasterDOF(UInt dof_num) {
+inline bool DOFManager::isLocalOrMasterDOF(Idx dof_num) {
auto dof_flag = this->dofs_flag(dof_num);
return (dof_flag & NodeFlag::_local_master_mask) == NodeFlag::_normal;
}
/* -------------------------------------------------------------------------- */
-inline bool DOFManager::isSlaveDOF(UInt dof_num) {
+inline bool DOFManager::isSlaveDOF(Idx dof_num) {
auto dof_flag = this->dofs_flag(dof_num);
return (dof_flag & NodeFlag::_shared_mask) == NodeFlag::_slave;
}
/* -------------------------------------------------------------------------- */
-inline bool DOFManager::isPureGhostDOF(UInt dof_num) {
+inline bool DOFManager::isPureGhostDOF(Idx dof_num) {
auto dof_flag = this->dofs_flag(dof_num);
return (dof_flag & NodeFlag::_shared_mask) == NodeFlag::_pure_ghost;
}
/* -------------------------------------------------------------------------- */
-inline Int DOFManager::localToGlobalEquationNumber(Int local) const {
+inline Idx DOFManager::localToGlobalEquationNumber(Idx local) const {
return this->global_equation_number(local);
}
/* -------------------------------------------------------------------------- */
-inline bool DOFManager::hasGlobalEquationNumber(Int global) const {
+inline bool DOFManager::hasGlobalEquationNumber(Idx global) const {
auto it = this->global_to_local_mapping.find(global);
return (it != this->global_to_local_mapping.end());
}
/* -------------------------------------------------------------------------- */
-inline Int DOFManager::globalToLocalEquationNumber(Int global) const {
+inline Idx DOFManager::globalToLocalEquationNumber(Idx global) const {
auto it = this->global_to_local_mapping.find(global);
AKANTU_DEBUG_ASSERT(it != this->global_to_local_mapping.end(),
"This global equation number "
<< global << " does not exists in " << this->id);
return it->second;
}
/* -------------------------------------------------------------------------- */
-inline NodeFlag DOFManager::getDOFFlag(Int local_id) const {
+inline NodeFlag DOFManager::getDOFFlag(Idx local_id) const {
return this->dofs_flag(local_id);
}
/* -------------------------------------------------------------------------- */
-inline const Array<UInt> &
+inline decltype(auto)
DOFManager::getDOFsAssociatedNodes(const ID & dof_id) const {
const auto & dof_data = this->getDOFData(dof_id);
return dof_data.associated_nodes;
}
/* -------------------------------------------------------------------------- */
-const Array<Int> &
-DOFManager::getLocalEquationsNumbers(const ID & dof_id) const {
+decltype(auto) DOFManager::getLocalEquationsNumbers(const ID & dof_id) const {
return getDOFData(dof_id).local_equation_number;
}
/* -------------------------------------------------------------------------- */
template <typename Vec>
void DOFManager::assembleMatMulVectToArray_(const ID & dof_id, const ID & A_id,
const Array<Real> & x,
Array<Real> & array,
Real scale_factor) {
Vec tmp_array(aka::as_type<Vec>(*data_cache), this->id + ":tmp_array");
tmp_array.zero();
assembleMatMulVectToGlobalArray(dof_id, A_id, x, tmp_array, scale_factor);
getArrayPerDOFs(dof_id, tmp_array, array);
}
/* -------------------------------------------------------------------------- */
template <typename Mat>
void DOFManager::assembleElementalMatricesToMatrix_(
Mat & A, const ID & dof_id, const Array<Real> & elementary_mat,
ElementType type, GhostType ghost_type,
const MatrixType & elemental_matrix_type,
- const Array<UInt> & filter_elements) {
+ const Array<Idx> & filter_elements) {
AKANTU_DEBUG_IN();
auto & dof_data = this->getDOFData(dof_id);
AKANTU_DEBUG_ASSERT(dof_data.support_type == _dst_nodal,
"This function applies only on Nodal dofs");
const auto & equation_number = this->getLocalEquationsNumbers(dof_id);
- UInt nb_element;
- UInt * filter_it = nullptr;
+ Int nb_element;
+ Idx * filter_it = nullptr;
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
- filter_it = filter_elements.storage();
+ filter_it = filter_elements.data();
} else {
if (dof_data.group_support != "__mesh__") {
const auto & group_elements =
this->mesh->getElementGroup(dof_data.group_support)
.getElements(type, ghost_type);
nb_element = group_elements.size();
- filter_it = group_elements.storage();
+ filter_it = group_elements.data();
} else {
nb_element = this->mesh->getNbElement(type, ghost_type);
}
}
AKANTU_DEBUG_ASSERT(elementary_mat.size() == nb_element,
"The vector elementary_mat("
<< elementary_mat.getID()
<< ") has not the good size.");
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_degree_of_freedom = dof_data.dof->getNbComponent();
+ auto nb_degree_of_freedom = dof_data.dof->getNbComponent();
- const Array<UInt> & connectivity =
- this->mesh->getConnectivity(type, ghost_type);
+ const auto & connectivity = this->mesh->getConnectivity(type, ghost_type);
auto conn_begin = connectivity.begin(nb_nodes_per_element);
auto conn_it = conn_begin;
auto size_mat = nb_nodes_per_element * nb_degree_of_freedom;
- Vector<Int> element_eq_nb(nb_degree_of_freedom * nb_nodes_per_element);
+ Vector<Idx> element_eq_nb(nb_degree_of_freedom * nb_nodes_per_element);
auto el_mat_it = elementary_mat.begin(size_mat, size_mat);
- for (UInt e = 0; e < nb_element; ++e, ++el_mat_it) {
+ for (Int e = 0; e < nb_element; ++e, ++el_mat_it) {
if (filter_it) {
conn_it = conn_begin + *filter_it;
}
this->extractElementEquationNumber(equation_number, *conn_it,
nb_degree_of_freedom, element_eq_nb);
std::transform(element_eq_nb.begin(), element_eq_nb.end(),
element_eq_nb.begin(), [&](auto && local) {
return this->localToGlobalEquationNumber(local);
});
if (filter_it) {
++filter_it;
} else {
++conn_it;
}
A.addValues(element_eq_nb, element_eq_nb, *el_mat_it,
elemental_matrix_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename Mat>
void DOFManager::assemblePreassembledMatrix_(Mat & A,
const TermsToAssemble & terms) {
const auto & dof_id_m = terms.getDOFIdM();
const auto & dof_id_n = terms.getDOFIdN();
const auto & equation_number_m = this->getLocalEquationsNumbers(dof_id_m);
const auto & equation_number_n = this->getLocalEquationsNumbers(dof_id_n);
for (const auto & term : terms) {
auto gi = this->localToGlobalEquationNumber(equation_number_m(term.i()));
auto gj = this->localToGlobalEquationNumber(equation_number_n(term.j()));
A.add(gi, gj, term);
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
-#endif /* AKANTU_DOF_MANAGER_INLINE_IMPL_HH_ */
+//#endif /* __AKANTU_DOF_MANAGER_INLINE_IMPL_CC__ */
diff --git a/src/model/common/dof_manager/dof_manager_petsc.cc b/src/model/common/dof_manager/dof_manager_petsc.cc
index ae0177c43..c432cf83b 100644
--- a/src/model/common/dof_manager/dof_manager_petsc.cc
+++ b/src/model/common/dof_manager/dof_manager_petsc.cc
@@ -1,300 +1,300 @@
/**
* @file dof_manager_petsc.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Oct 07 2015
* @date last modification: Fri Jul 24 2020
*
* @brief DOFManaterPETSc is the PETSc implementation of the DOFManager
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager_petsc.hh"
#include "aka_iterators.hh"
#include "communicator.hh"
#include "cppargparse.hh"
#include "non_linear_solver_petsc.hh"
#include "solver_vector_petsc.hh"
#include "sparse_matrix_petsc.hh"
#include "time_step_solver_default.hh"
#if defined(AKANTU_USE_MPI)
#include "mpi_communicator_data.hh"
#endif
/* -------------------------------------------------------------------------- */
#include <petscis.h>
#include <petscsys.h>
/* -------------------------------------------------------------------------- */
namespace akantu {
class PETScSingleton {
private:
PETScSingleton() {
PETSc_call(PetscInitialized, &is_initialized);
if (is_initialized == 0U) {
cppargparse::ArgumentParser & argparser = getStaticArgumentParser();
int & argc = argparser.getArgC();
char **& argv = argparser.getArgV();
PETSc_call(PetscInitialize, &argc, &argv, nullptr, nullptr);
PETSc_call(
PetscPopErrorHandler); // remove the default PETSc signal handler
PETSc_call(PetscPushErrorHandler, PetscIgnoreErrorHandler, nullptr);
}
}
public:
PETScSingleton(const PETScSingleton &) = delete;
PETScSingleton & operator=(const PETScSingleton &) = delete;
~PETScSingleton() {
if (is_initialized == 0U) {
PetscFinalize();
}
}
static PETScSingleton & getInstance() {
static PETScSingleton instance;
return instance;
}
private:
PetscBool is_initialized;
};
/* -------------------------------------------------------------------------- */
DOFManagerPETSc::DOFDataPETSc::DOFDataPETSc(const ID & dof_id)
: DOFData(dof_id) {}
/* -------------------------------------------------------------------------- */
DOFManagerPETSc::DOFManagerPETSc(const ID & id) : DOFManager(id) { init(); }
/* -------------------------------------------------------------------------- */
DOFManagerPETSc::DOFManagerPETSc(Mesh & mesh, const ID & id)
: DOFManager(mesh, id) {
init();
}
/* -------------------------------------------------------------------------- */
void DOFManagerPETSc::init() {
// check if the akantu types and PETSc one are consistant
static_assert(sizeof(Int) == sizeof(PetscInt),
"The integer type of Akantu does not match the one from PETSc");
static_assert(sizeof(Real) == sizeof(PetscReal),
"The integer type of Akantu does not match the one from PETSc");
#if defined(AKANTU_USE_MPI)
const auto & mpi_data =
aka::as_type<MPICommunicatorData>(communicator.getCommunicatorData());
MPI_Comm mpi_comm = mpi_data.getMPICommunicator();
this->mpi_communicator = mpi_comm;
#else
this->mpi_communicator = PETSC_COMM_SELF;
#endif
PETScSingleton & instance [[gnu::unused]] = PETScSingleton::getInstance();
}
/* -------------------------------------------------------------------------- */
auto DOFManagerPETSc::getNewDOFData(const ID & dof_id)
-> std::unique_ptr<DOFData> {
return std::make_unique<DOFDataPETSc>(dof_id);
}
/* -------------------------------------------------------------------------- */
-std::tuple<UInt, UInt, UInt>
+std::tuple<Int, Int, Int>
DOFManagerPETSc::registerDOFsInternal(const ID & dof_id,
Array<Real> & dofs_array) {
dofs_ids.push_back(dof_id);
auto ret = DOFManager::registerDOFsInternal(dof_id, dofs_array);
UInt nb_dofs;
UInt nb_pure_local_dofs;
std::tie(nb_dofs, nb_pure_local_dofs, std::ignore) = ret;
auto && vector = std::make_unique<SolverVectorPETSc>(*this, id + ":solution");
auto * x = vector->getVec();
PETSc_call(VecGetLocalToGlobalMapping, x, &is_ltog_map);
// redoing the indexes based on the petsc numbering
for (auto & dof_id : dofs_ids) {
auto & dof_data = this->getDOFDataTyped<DOFDataPETSc>(dof_id);
Array<PetscInt> gidx(dof_data.local_equation_number.size());
for (auto && data : zip(dof_data.local_equation_number, gidx)) {
std::get<1>(data) = localToGlobalEquationNumber(std::get<0>(data));
}
auto & lidx = dof_data.local_equation_number_petsc;
if (is_ltog_map != nullptr) {
lidx.resize(gidx.size());
PetscInt n;
PETSc_call(ISGlobalToLocalMappingApply, is_ltog_map, IS_GTOLM_MASK,
- gidx.size(), gidx.storage(), &n, lidx.storage());
+ gidx.size(), gidx.data(), &n, lidx.data());
}
}
residual = std::make_unique<SolverVectorPETSc>(*vector, id + ":residual");
data_cache = std::make_unique<SolverVectorPETSc>(*vector, id + ":data_cache");
solution = std::move(vector);
for (auto & mat : matrices) {
auto & A = this->getMatrix(mat.first);
A.resize();
}
return ret;
}
/* -------------------------------------------------------------------------- */
void DOFManagerPETSc::assembleToGlobalArray(
const ID & dof_id, const Array<Real> & array_to_assemble,
SolverVector & global_array, Real scale_factor) {
const auto & dof_data = getDOFDataTyped<DOFDataPETSc>(dof_id);
auto & g = aka::as_type<SolverVectorPETSc>(global_array);
AKANTU_DEBUG_ASSERT(array_to_assemble.size() *
array_to_assemble.getNbComponent() ==
dof_data.local_nb_dofs,
"The array to assemble does not have the proper size");
g.addValuesLocal(dof_data.local_equation_number_petsc, array_to_assemble,
scale_factor);
}
/* -------------------------------------------------------------------------- */
void DOFManagerPETSc::getArrayPerDOFs(const ID & dof_id,
const SolverVector & global_array,
Array<Real> & local) {
const auto & dof_data = getDOFDataTyped<DOFDataPETSc>(dof_id);
const auto & petsc_vector = aka::as_type<SolverVectorPETSc>(global_array);
AKANTU_DEBUG_ASSERT(
local.size() * local.getNbComponent() == dof_data.local_nb_dofs,
"The array to get the values does not have the proper size");
petsc_vector.getValuesLocal(dof_data.local_equation_number_petsc, local);
}
/* -------------------------------------------------------------------------- */
void DOFManagerPETSc::assembleElementalMatricesToMatrix(
const ID & matrix_id, const ID & dof_id, const Array<Real> & elementary_mat,
ElementType type, GhostType ghost_type,
const MatrixType & elemental_matrix_type,
- const Array<UInt> & filter_elements) {
+ const Array<Int> & filter_elements) {
auto & A = getMatrix(matrix_id);
DOFManager::assembleElementalMatricesToMatrix_(
A, dof_id, elementary_mat, type, ghost_type, elemental_matrix_type,
filter_elements);
A.applyModifications();
}
/* -------------------------------------------------------------------------- */
void DOFManagerPETSc::assemblePreassembledMatrix(
const ID & matrix_id, const TermsToAssemble & terms) {
auto & A = getMatrix(matrix_id);
DOFManager::assemblePreassembledMatrix_(A, terms);
A.applyModifications();
}
/* -------------------------------------------------------------------------- */
void DOFManagerPETSc::assembleMatMulVectToArray(const ID & dof_id,
const ID & A_id,
const Array<Real> & x,
Array<Real> & array,
Real scale_factor) {
DOFManager::assembleMatMulVectToArray_<SolverVectorPETSc>(
dof_id, A_id, x, array, scale_factor);
}
/* -------------------------------------------------------------------------- */
void DOFManagerPETSc::makeConsistentForPeriodicity(const ID & /*dof_id*/,
SolverVector & /*array*/) {}
/* -------------------------------------------------------------------------- */
NonLinearSolver &
DOFManagerPETSc::getNewNonLinearSolver(const ID & id,
const NonLinearSolverType & type) {
return this->registerNonLinearSolver<NonLinearSolverPETSc>(*this, id, type);
}
/* -------------------------------------------------------------------------- */
TimeStepSolver & DOFManagerPETSc::getNewTimeStepSolver(
const ID & id, const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver, SolverCallback & callback) {
return this->registerTimeStepSolver<TimeStepSolverDefault>(
*this, id, type, non_linear_solver, callback);
}
/* -------------------------------------------------------------------------- */
SparseMatrix & DOFManagerPETSc::getNewMatrix(const ID & id,
const MatrixType & matrix_type) {
return this->registerSparseMatrix<SparseMatrixPETSc>(*this, id, matrix_type);
}
/* -------------------------------------------------------------------------- */
SparseMatrix & DOFManagerPETSc::getNewMatrix(const ID & id,
const ID & matrix_to_copy_id) {
return this->registerSparseMatrix<SparseMatrixPETSc>(id, matrix_to_copy_id);
}
/* -------------------------------------------------------------------------- */
SparseMatrixPETSc & DOFManagerPETSc::getMatrix(const ID & id) {
auto & matrix = DOFManager::getMatrix(id);
return aka::as_type<SparseMatrixPETSc>(matrix);
}
/* -------------------------------------------------------------------------- */
SolverVector & DOFManagerPETSc::getNewLumpedMatrix(const ID & id) {
return this->registerLumpedMatrix<SolverVectorPETSc>(*this, id);
}
/* -------------------------------------------------------------------------- */
SolverVectorPETSc & DOFManagerPETSc::getSolution() {
return aka::as_type<SolverVectorPETSc>(*this->solution);
}
const SolverVectorPETSc & DOFManagerPETSc::getSolution() const {
return aka::as_type<SolverVectorPETSc>(*this->solution);
}
SolverVectorPETSc & DOFManagerPETSc::getResidual() {
return aka::as_type<SolverVectorPETSc>(*this->residual);
}
const SolverVectorPETSc & DOFManagerPETSc::getResidual() const {
return aka::as_type<SolverVectorPETSc>(*this->residual);
}
/* -------------------------------------------------------------------------- */
static bool dof_manager_is_registered =
DOFManagerFactory::getInstance().registerAllocator(
"petsc", [](Mesh & mesh, const ID & id) -> std::unique_ptr<DOFManager> {
return std::make_unique<DOFManagerPETSc>(mesh, id);
});
} // namespace akantu
diff --git a/src/model/common/dof_manager/dof_manager_petsc.hh b/src/model/common/dof_manager/dof_manager_petsc.hh
index fec01821c..933eed0d1 100644
--- a/src/model/common/dof_manager/dof_manager_petsc.hh
+++ b/src/model/common/dof_manager/dof_manager_petsc.hh
@@ -1,216 +1,217 @@
/**
* @file dof_manager_petsc.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Aug 18 2015
* @date last modification: Fri Jul 24 2020
*
* @brief PETSc implementation of the dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager.hh"
/* -------------------------------------------------------------------------- */
#include <petscis.h>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DOF_MANAGER_PETSC_HH_
#define AKANTU_DOF_MANAGER_PETSC_HH_
#define PETSc_call(func, ...) \
do { \
auto ierr = func(__VA_ARGS__); \
if (PetscUnlikely(ierr != 0)) { \
const char * desc; \
PetscErrorMessage(ierr, &desc, nullptr); \
AKANTU_EXCEPTION("Error in PETSc call to \'" << #func \
<< "\': " << desc); \
} \
} while (false)
namespace akantu {
namespace detail {
template <typename T> void PETScSetName(T t, const ID & id) {
PETSc_call(PetscObjectSetName, reinterpret_cast<PetscObject>(t),
id.c_str());
}
} // namespace detail
} // namespace akantu
namespace akantu {
class SparseMatrixPETSc;
class SolverVectorPETSc;
} // namespace akantu
namespace akantu {
class DOFManagerPETSc : public DOFManager {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
DOFManagerPETSc(const ID & id = "dof_manager_petsc");
DOFManagerPETSc(Mesh & mesh, const ID & id = "dof_manager_petsc");
~DOFManagerPETSc() override = default;
protected:
void init();
struct DOFDataPETSc : public DOFData {
explicit DOFDataPETSc(const ID & dof_id);
/// petsc compressed version of local_equation_number
Array<PetscInt> local_equation_number_petsc;
Array<Int> & getLocalEquationsNumbers() override {
return local_equation_number_petsc;
}
};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void assembleToLumpedMatrix(const ID & /*dof_id*/,
Array<Real> & /*array_to_assemble*/,
const ID & /*lumped_mtx*/,
Real /*scale_factor*/ = 1.) override {
AKANTU_TO_IMPLEMENT();
}
void assembleElementalMatricesToMatrix(
const ID & /*matrix_id*/, const ID & /*dof_id*/,
const Array<Real> & /*elementary_mat*/, ElementType /*type*/,
- GhostType /*ghost_type*/, const MatrixType & /*elemental_matrix_type*/,
- const Array<UInt> & /*filter_elements*/) override;
+ GhostType /*ghost_type*/,
+ const MatrixType & /*elemental_matrix_type*/,
+ const Array<Idx> & /*filter_elements*/) override;
void assembleMatMulVectToArray(const ID & /*dof_id*/, const ID & /*A_id*/,
const Array<Real> & /*x*/,
Array<Real> & /*array*/,
Real /*scale_factor*/ = 1.) override;
void assembleLumpedMatMulVectToResidual(const ID & /*dof_id*/,
const ID & /*A_id*/,
const Array<Real> & /*x*/,
Real /*scale_factor*/ = 1) override {
AKANTU_TO_IMPLEMENT();
}
void assemblePreassembledMatrix(const ID & matrix_id,
const TermsToAssemble & /*terms*/) override;
protected:
void assembleToGlobalArray(const ID & dof_id,
const Array<Real> & array_to_assemble,
SolverVector & global_array,
Real scale_factor) override;
void getArrayPerDOFs(const ID & dof_id, const SolverVector & global,
Array<Real> & local) override;
void makeConsistentForPeriodicity(const ID & dof_id,
SolverVector & array) override;
std::unique_ptr<DOFData> getNewDOFData(const ID & dof_id) override;
- std::tuple<UInt, UInt, UInt>
+ std::tuple<Int, Int, Int>
registerDOFsInternal(const ID & dof_id, Array<Real> & dofs_array) override;
- void updateDOFsData(DOFDataPETSc & dof_data, UInt nb_new_local_dofs,
- UInt nb_new_pure_local, UInt nb_node,
- const std::function<UInt(UInt)> & getNode);
+ void updateDOFsData(DOFDataPETSc & dof_data, Int nb_new_local_dofs,
+ Int nb_new_pure_local, Int nb_node,
+ const std::function<Idx(Idx)> & getNode);
protected:
void getLumpedMatrixPerDOFs(const ID & /*dof_id*/, const ID & /*lumped_mtx*/,
Array<Real> & /*lumped*/) override {}
NonLinearSolver & getNewNonLinearSolver(
const ID & nls_solver_id,
const NonLinearSolverType & non_linear_solver_type) override;
TimeStepSolver &
getNewTimeStepSolver(const ID & id, const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver,
SolverCallback & solver_callback) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Get an instance of a new SparseMatrix
SparseMatrix & getNewMatrix(const ID & matrix_id,
const MatrixType & matrix_type) override;
/// Get an instance of a new SparseMatrix as a copy of the SparseMatrix
/// matrix_to_copy_id
SparseMatrix & getNewMatrix(const ID & matrix_id,
const ID & matrix_to_copy_id) override;
/// Get the reference of an existing matrix
SparseMatrixPETSc & getMatrix(const ID & matrix_id);
/// Get an instance of a new lumped matrix
SolverVector & getNewLumpedMatrix(const ID & matrix_id) override;
/// Get the blocked dofs array
// AKANTU_GET_MACRO(BlockedDOFs, blocked_dofs, const Array<bool> &);
AKANTU_GET_MACRO(MPIComm, mpi_communicator, MPI_Comm);
AKANTU_GET_MACRO_NOT_CONST(ISLocalToGlobalMapping, is_ltog_map,
ISLocalToGlobalMapping &);
SolverVectorPETSc & getSolution();
const SolverVectorPETSc & getSolution() const;
SolverVectorPETSc & getResidual();
const SolverVectorPETSc & getResidual() const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
using PETScMatrixMap = std::map<ID, SparseMatrixPETSc *>;
using PETScLumpedMatrixMap = std::map<ID, SolverVectorPETSc *>;
/// list of matrices registered to the dof manager
PETScMatrixMap petsc_matrices;
/// list of lumped matrices registered
PETScLumpedMatrixMap petsc_lumped_matrices;
/// PETSc local to global mapping of dofs
ISLocalToGlobalMapping is_ltog_map{nullptr};
/// Communicator associated to PETSc
MPI_Comm mpi_communicator;
/// list of the dof ids to be able to always iterate in the same order
std::vector<ID> dofs_ids;
};
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_DOF_MANAGER_PETSC_HH_ */
diff --git a/src/model/common/integration_scheme/generalized_trapezoidal.cc b/src/model/common/integration_scheme/generalized_trapezoidal.cc
index b490141bf..5f9807ba9 100644
--- a/src/model/common/integration_scheme/generalized_trapezoidal.cc
+++ b/src/model/common/integration_scheme/generalized_trapezoidal.cc
@@ -1,197 +1,197 @@
/**
* @file generalized_trapezoidal.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Oct 23 2015
* @date last modification: Wed Mar 27 2019
*
* @brief implementation of inline functions
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "generalized_trapezoidal.hh"
#include "aka_array.hh"
#include "dof_manager.hh"
#include "mesh.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
GeneralizedTrapezoidal::GeneralizedTrapezoidal(DOFManager & dof_manager,
const ID & dof_id, Real alpha)
: IntegrationScheme1stOrder(dof_manager, dof_id), alpha(alpha) {
this->registerParam("alpha", this->alpha, alpha, _pat_parsmod,
"The alpha parameter");
}
/* -------------------------------------------------------------------------- */
void GeneralizedTrapezoidal::predictor(Real delta_t, Array<Real> & u,
Array<Real> & u_dot,
const Array<bool> & blocked_dofs) const {
AKANTU_DEBUG_IN();
- UInt nb_nodes = u.size();
- UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
+ Int nb_nodes = u.size();
+ Int nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
- Real * u_val = u.storage();
- Real * u_dot_val = u_dot.storage();
- bool * blocked_dofs_val = blocked_dofs.storage();
+ Real * u_val = u.data();
+ Real * u_dot_val = u_dot.data();
+ bool * blocked_dofs_val = blocked_dofs.data();
- for (UInt d = 0; d < nb_degree_of_freedom; d++) {
+ for (Int d = 0; d < nb_degree_of_freedom; d++) {
if (!(*blocked_dofs_val)) {
*u_val += (1. - alpha) * delta_t * *u_dot_val;
}
u_val++;
u_dot_val++;
blocked_dofs_val++;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void GeneralizedTrapezoidal::corrector(const SolutionType & type, Real delta_t,
Array<Real> & u, Array<Real> & u_dot,
const Array<bool> & blocked_dofs,
const Array<Real> & delta) const {
AKANTU_DEBUG_IN();
switch (type) {
case _temperature:
this->allCorrector<_temperature>(delta_t, u, u_dot, blocked_dofs, delta);
break;
case _temperature_rate:
this->allCorrector<_temperature_rate>(delta_t, u, u_dot, blocked_dofs,
delta);
break;
default:
AKANTU_EXCEPTION("The corrector type : "
<< type
<< " is not supported by this type of integration scheme");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Real GeneralizedTrapezoidal::getTemperatureCoefficient(
const SolutionType & type, Real delta_t) const {
switch (type) {
case _temperature:
return 1.;
case _temperature_rate:
return alpha * delta_t;
default:
AKANTU_EXCEPTION("The corrector type : "
<< type
<< " is not supported by this type of integration scheme");
}
}
/* -------------------------------------------------------------------------- */
Real GeneralizedTrapezoidal::getTemperatureRateCoefficient(
const SolutionType & type, Real delta_t) const {
switch (type) {
case _temperature:
return 1. / (alpha * delta_t);
case _temperature_rate:
return 1.;
default:
AKANTU_EXCEPTION("The corrector type : "
<< type
<< " is not supported by this type of integration scheme");
}
}
/* -------------------------------------------------------------------------- */
template <IntegrationScheme::SolutionType type>
void GeneralizedTrapezoidal::allCorrector(Real delta_t, Array<Real> & u,
Array<Real> & u_dot,
const Array<bool> & blocked_dofs,
const Array<Real> & delta) const {
AKANTU_DEBUG_IN();
- UInt nb_nodes = u.size();
- UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
+ Int nb_nodes = u.size();
+ Int nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
Real e = getTemperatureCoefficient(type, delta_t);
Real d = getTemperatureRateCoefficient(type, delta_t);
- Real * u_val = u.storage();
- Real * u_dot_val = u_dot.storage();
- Real * delta_val = delta.storage();
- bool * blocked_dofs_val = blocked_dofs.storage();
+ Real * u_val = u.data();
+ Real * u_dot_val = u_dot.data();
+ Real * delta_val = delta.data();
+ bool * blocked_dofs_val = blocked_dofs.data();
- for (UInt dof = 0; dof < nb_degree_of_freedom; dof++) {
+ for (Int dof = 0; dof < nb_degree_of_freedom; dof++) {
if (!(*blocked_dofs_val)) {
*u_val += e * *delta_val;
*u_dot_val += d * *delta_val;
}
u_val++;
u_dot_val++;
delta_val++;
blocked_dofs_val++;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void GeneralizedTrapezoidal::assembleJacobian(const SolutionType & type,
Real delta_t) {
AKANTU_DEBUG_IN();
SparseMatrix & J = this->dof_manager.getMatrix("J");
const SparseMatrix & M = this->dof_manager.getMatrix("M");
const SparseMatrix & K = this->dof_manager.getMatrix("K");
bool does_j_need_update = false;
does_j_need_update |= M.getRelease() != m_release;
does_j_need_update |= K.getRelease() != k_release;
does_j_need_update |= this->dof_manager.hasBlockedDOFsChanged();
if (not does_j_need_update) {
AKANTU_DEBUG_OUT();
return;
}
J.copyProfile(K);
// J.zero();
Real d = this->getTemperatureRateCoefficient(type, delta_t);
Real e = this->getTemperatureCoefficient(type, delta_t);
J.add(M, d);
J.add(K, e);
m_release = M.getRelease();
k_release = K.getRelease();
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/model/common/integration_scheme/generalized_trapezoidal.hh b/src/model/common/integration_scheme/generalized_trapezoidal.hh
index b1673acfd..441168c64 100644
--- a/src/model/common/integration_scheme/generalized_trapezoidal.hh
+++ b/src/model/common/integration_scheme/generalized_trapezoidal.hh
@@ -1,163 +1,163 @@
/**
* @file generalized_trapezoidal.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jul 04 2011
* @date last modification: Wed Mar 13 2019
*
* @brief Generalized Trapezoidal Method. This implementation is taken from
* Méthodes numériques en mécanique des solides by Alain Curnier \note{ISBN:
* 2-88074-247-1}
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_GENERALIZED_TRAPEZOIDAL_HH_
#define AKANTU_GENERALIZED_TRAPEZOIDAL_HH_
#include "integration_scheme_1st_order.hh"
namespace akantu {
/**
* The two differentiate equation (thermal and kinematic) are :
* \f{eqnarray*}{
* C\dot{u}_{n+1} + Ku_{n+1} = q_{n+1}\\
* u_{n+1} = u_{n} + (1-\alpha) \Delta t \dot{u}_{n} + \alpha \Delta t
*\dot{u}_{n+1}
* \f}
*
* To solve it :
* Predictor :
* \f{eqnarray*}{
* u^0_{n+1} &=& u_{n} + (1-\alpha) \Delta t v_{n} \\
* \dot{u}^0_{n+1} &=& \dot{u}_{n}
* \f}
*
* Solve :
* \f[ (a C + b K^i_{n+1}) w = q_{n+1} - f^i_{n+1} - C \dot{u}^i_{n+1} \f]
*
* Corrector :
* \f{eqnarray*}{
* \dot{u}^{i+1}_{n+1} &=& \dot{u}^{i}_{n+1} + a w \\
* u^{i+1}_{n+1} &=& u^{i}_{n+1} + b w
* \f}
*
* a and b depends on the resolution method : temperature (u) or temperature
*rate (\f$\dot{u}\f$)
*
* For temperature : \f$ w = \delta u, a = 1 / (\alpha \Delta t) , b = 1 \f$ @n
* For temperature rate : \f$ w = \delta \dot{u}, a = 1, b = \alpha \Delta t \f$
*/
class GeneralizedTrapezoidal : public IntegrationScheme1stOrder {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- GeneralizedTrapezoidal(DOFManager & dof_manager, const ID & dof_id,
+ GeneralizedTrapezoidal(DOFManager &dof_manager, const ID &dof_id,
Real alpha = 0);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- void predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot,
- const Array<bool> & blocked_dofs) const override;
+ void predictor(Real delta_t, Array<Real> &u, Array<Real> &u_dot,
+ const Array<bool> &blocked_dofs) const override;
- void corrector(const SolutionType & type, Real delta_t, Array<Real> & u,
- Array<Real> & u_dot, const Array<bool> & blocked_dofs,
- const Array<Real> & delta) const override;
+ void corrector(const SolutionType &type, Real delta_t, Array<Real> &u,
+ Array<Real> &u_dot, const Array<bool> &blocked_dofs,
+ const Array<Real> &delta) const override;
- void assembleJacobian(const SolutionType & type, Real delta_t) override;
+ void assembleJacobian(const SolutionType &type, Real delta_t) override;
public:
/// the coeffichent \f$ b \f$ in the description
- Real getTemperatureCoefficient(const SolutionType & type,
+ Real getTemperatureCoefficient(const SolutionType &type,
Real delta_t) const override;
/// the coeffichent \f$ a \f$ in the description
- Real getTemperatureRateCoefficient(const SolutionType & type,
+ Real getTemperatureRateCoefficient(const SolutionType &type,
Real delta_t) const override;
private:
template <SolutionType type>
- void allCorrector(Real delta_t, Array<Real> & u, Array<Real> & u_dot,
- const Array<bool> & blocked_dofs,
- const Array<Real> & delta) const;
+ void allCorrector(Real delta_t, Array<Real> &u, Array<Real> &u_dot,
+ const Array<bool> &blocked_dofs,
+ const Array<Real> &delta) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(Alpha, alpha, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// the \f$\alpha\f$ parameter
Real alpha;
/// last release of K matrix
- UInt k_release;
+ Int k_release;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* Forward Euler (explicit) -> condition on delta_t
*/
class ForwardEuler : public GeneralizedTrapezoidal {
public:
- ForwardEuler(DOFManager & dof_manager, const ID & dof_id)
+ ForwardEuler(DOFManager &dof_manager, const ID &dof_id)
: GeneralizedTrapezoidal(dof_manager, dof_id, 0.){};
std::vector<std::string> getNeededMatrixList() override { return {"M"}; }
};
/**
* Trapezoidal rule (implicit), midpoint rule or Crank-Nicolson
*/
class TrapezoidalRule1 : public GeneralizedTrapezoidal {
public:
- TrapezoidalRule1(DOFManager & dof_manager, const ID & dof_id)
+ TrapezoidalRule1(DOFManager &dof_manager, const ID &dof_id)
: GeneralizedTrapezoidal(dof_manager, dof_id, .5){};
};
/**
* Backward Euler (implicit)
*/
class BackwardEuler : public GeneralizedTrapezoidal {
public:
- BackwardEuler(DOFManager & dof_manager, const ID & dof_id)
+ BackwardEuler(DOFManager &dof_manager, const ID &dof_id)
: GeneralizedTrapezoidal(dof_manager, dof_id, 1.){};
};
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_GENERALIZED_TRAPEZOIDAL_HH_ */
diff --git a/src/model/common/integration_scheme/integration_scheme.hh b/src/model/common/integration_scheme/integration_scheme.hh
index 6c861fc62..907e2ebb3 100644
--- a/src/model/common/integration_scheme/integration_scheme.hh
+++ b/src/model/common/integration_scheme/integration_scheme.hh
@@ -1,125 +1,125 @@
/**
* @file integration_scheme.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Dec 09 2020
*
* @brief This class is just a base class for the integration schemes
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_INTEGRATION_SCHEME_HH_
#define AKANTU_INTEGRATION_SCHEME_HH_
namespace akantu {
class DOFManager;
}
namespace akantu {
class IntegrationScheme : public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
enum SolutionType {
_not_defined = -1,
_displacement = 0,
_temperature = 0,
_damage = 0,
_velocity = 1,
_temperature_rate = 1,
_acceleration = 2,
};
- IntegrationScheme(DOFManager & dof_manager, const ID & dof_id, UInt order);
+ IntegrationScheme(DOFManager &dof_manager, const ID &dof_id, UInt order);
~IntegrationScheme() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// generic interface of a predictor
virtual void predictor(Real delta_t) = 0;
/// generic interface of a corrector
- virtual void corrector(const SolutionType & type, Real delta_t) = 0;
+ virtual void corrector(const SolutionType &type, Real delta_t) = 0;
/// assemble the jacobian matrix
- virtual void assembleJacobian(const SolutionType & type, Real delta_t) = 0;
+ virtual void assembleJacobian(const SolutionType &type, Real delta_t) = 0;
/// assemble the residual
virtual void assembleResidual(bool is_lumped) = 0;
/// returns a list of needed matrices
virtual std::vector<std::string> getNeededMatrixList() = 0;
/// store dofs info (beginning of steps)
virtual void store();
/// restore dofs (solve failed)
virtual void restore();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// return the order of the integration scheme
UInt getOrder() const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// The underlying DOFManager
- DOFManager & dof_manager;
+ DOFManager &dof_manager;
/// The id of the dof treated by this integration scheme.
ID dof_id;
/// The order of the integrator
- UInt order;
+ Int order;
/// last release of M matrix
- UInt m_release{UInt(-1)};
+ Int m_release{-1};
/// stores the values at begining of solve
std::vector<std::unique_ptr<Array<Real>>> u_store;
};
/* -------------------------------------------------------------------------- */
// std::ostream & operator<<(std::ostream & stream,
// const IntegrationScheme::SolutionType & type);
-std::istream & operator>>(std::istream & stream,
- IntegrationScheme::SolutionType & type);
+std::istream &operator>>(std::istream &stream,
+ IntegrationScheme::SolutionType &type);
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_INTEGRATION_SCHEME_HH_ */
diff --git a/src/model/common/integration_scheme/newmark-beta.cc b/src/model/common/integration_scheme/newmark-beta.cc
index 35bce5053..316723061 100644
--- a/src/model/common/integration_scheme/newmark-beta.cc
+++ b/src/model/common/integration_scheme/newmark-beta.cc
@@ -1,269 +1,269 @@
/**
* @file newmark-beta.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Oct 23 2015
* @date last modification: Wed Mar 27 2019
*
* @brief implementation of the newmark-@f$\beta@f$ integration scheme. This
* implementation is taken from Méthodes numériques en mécanique des solides by
* Alain Curnier \note{ISBN: 2-88074-247-1}
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "newmark-beta.hh"
#include "dof_manager.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NewmarkBeta::NewmarkBeta(DOFManager & dof_manager, const ID & dof_id,
Real alpha, Real beta)
- : IntegrationScheme2ndOrder(dof_manager, dof_id), beta(beta), alpha(alpha),
- k(0.), h(0.), m_release(0), k_release(0), c_release(0) {
+ : IntegrationScheme2ndOrder(dof_manager, dof_id), beta(beta), alpha(alpha) {
this->registerParam("alpha", this->alpha, alpha, _pat_parsmod,
"The alpha parameter");
this->registerParam("beta", this->beta, beta, _pat_parsmod,
"The beta parameter");
}
/* -------------------------------------------------------------------------- */
/*
* @f$ \tilde{u_{n+1}} = u_{n} + \Delta t \dot{u}_n + \frac{\Delta t^2}{2}
* \ddot{u}_n @f$
* @f$ \tilde{\dot{u}_{n+1}} = \dot{u}_{n} + \Delta t \ddot{u}_{n} @f$
* @f$ \tilde{\ddot{u}_{n}} = \ddot{u}_{n} @f$
*/
void NewmarkBeta::predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot,
Array<Real> & u_dot_dot,
const Array<bool> & blocked_dofs) const {
AKANTU_DEBUG_IN();
- UInt nb_nodes = u.size();
- UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
+ auto nb_nodes = u.size();
+ auto nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
- Real * u_val = u.storage();
- Real * u_dot_val = u_dot.storage();
- Real * u_dot_dot_val = u_dot_dot.storage();
- bool * blocked_dofs_val = blocked_dofs.storage();
+ auto * u_val = u.data();
+ auto * u_dot_val = u_dot.data();
+ auto * u_dot_dot_val = u_dot_dot.data();
+ auto * blocked_dofs_val = blocked_dofs.data();
- for (UInt d = 0; d < nb_degree_of_freedom; d++) {
+ for (Int d = 0; d < nb_degree_of_freedom; d++) {
if (!(*blocked_dofs_val)) {
Real dt_a_n = delta_t * *u_dot_dot_val;
*u_val += (1 - k * alpha) * delta_t * *u_dot_val +
(.5 - h * alpha * beta) * delta_t * dt_a_n;
*u_dot_val = (1 - k) * *u_dot_val + (1 - h * beta) * dt_a_n;
*u_dot_dot_val = (1 - h) * *u_dot_dot_val;
}
u_val++;
u_dot_val++;
u_dot_dot_val++;
blocked_dofs_val++;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NewmarkBeta::corrector(const SolutionType & type, Real delta_t,
Array<Real> & u, Array<Real> & u_dot,
Array<Real> & u_dot_dot,
const Array<bool> & blocked_dofs,
const Array<Real> & delta) const {
AKANTU_DEBUG_IN();
switch (type) {
case _acceleration: {
this->allCorrector<_acceleration>(delta_t, u, u_dot, u_dot_dot,
blocked_dofs, delta);
break;
}
case _velocity: {
this->allCorrector<_velocity>(delta_t, u, u_dot, u_dot_dot, blocked_dofs,
delta);
break;
}
case _displacement: {
this->allCorrector<_displacement>(delta_t, u, u_dot, u_dot_dot,
blocked_dofs, delta);
break;
}
default:
AKANTU_EXCEPTION("The corrector type : "
<< type
<< " is not supported by this type of integration scheme");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Real NewmarkBeta::getAccelerationCoefficient(const SolutionType & type,
Real delta_t) const {
switch (type) {
case _acceleration:
return 1.;
case _velocity:
return 1. / (beta * delta_t);
case _displacement:
return 1. / (alpha * beta * delta_t * delta_t);
default:
AKANTU_EXCEPTION("The corrector type : "
<< type
<< " is not supported by this type of integration scheme");
}
}
/* -------------------------------------------------------------------------- */
Real NewmarkBeta::getVelocityCoefficient(const SolutionType & type,
Real delta_t) const {
switch (type) {
case _acceleration:
return beta * delta_t;
case _velocity:
return 1.;
case _displacement:
return 1. / (alpha * delta_t);
default:
AKANTU_EXCEPTION("The corrector type : "
<< type
<< " is not supported by this type of integration scheme");
}
}
/* -------------------------------------------------------------------------- */
Real NewmarkBeta::getDisplacementCoefficient(const SolutionType & type,
Real delta_t) const {
switch (type) {
case _acceleration:
return alpha * beta * delta_t * delta_t;
case _velocity:
return alpha * delta_t;
case _displacement:
return 1.;
default:
AKANTU_EXCEPTION("The corrector type : "
<< type
<< " is not supported by this type of integration scheme");
}
}
/* -------------------------------------------------------------------------- */
template <IntegrationScheme::SolutionType type>
void NewmarkBeta::allCorrector(Real delta_t, Array<Real> & u,
Array<Real> & u_dot, Array<Real> & u_dot_dot,
const Array<bool> & blocked_dofs,
const Array<Real> & delta) const {
AKANTU_DEBUG_IN();
- UInt nb_nodes = u.size();
- UInt nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
+ auto nb_nodes = u.size();
+ auto nb_degree_of_freedom = u.getNbComponent() * nb_nodes;
- Real c = getAccelerationCoefficient(type, delta_t);
- Real d = getVelocityCoefficient(type, delta_t);
- Real e = getDisplacementCoefficient(type, delta_t);
+ auto c = getAccelerationCoefficient(type, delta_t);
+ auto d = getVelocityCoefficient(type, delta_t);
+ auto e = getDisplacementCoefficient(type, delta_t);
- Real * u_val = u.storage();
- Real * u_dot_val = u_dot.storage();
- Real * u_dot_dot_val = u_dot_dot.storage();
- Real * delta_val = delta.storage();
- bool * blocked_dofs_val = blocked_dofs.storage();
+ auto * u_val = u.data();
+ auto * u_dot_val = u_dot.data();
+ auto * u_dot_dot_val = u_dot_dot.data();
+ auto * delta_val = delta.data();
+ auto * blocked_dofs_val = blocked_dofs.data();
- for (UInt dof = 0; dof < nb_degree_of_freedom; dof++) {
+ for (Int dof = 0; dof < nb_degree_of_freedom; dof++) {
if (!(*blocked_dofs_val)) {
*u_val += e * *delta_val;
*u_dot_val += d * *delta_val;
*u_dot_dot_val += c * *delta_val;
}
u_val++;
u_dot_val++;
u_dot_dot_val++;
delta_val++;
blocked_dofs_val++;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NewmarkBeta::assembleJacobian(const SolutionType & type, Real delta_t) {
AKANTU_DEBUG_IN();
- SparseMatrix & J = this->dof_manager.getMatrix("J");
+ auto & J = this->dof_manager.getMatrix("J");
- const SparseMatrix & M = this->dof_manager.getMatrix("M");
+ const auto & M = this->dof_manager.getMatrix("M");
- Real c = this->getAccelerationCoefficient(type, delta_t);
- Real e = this->getDisplacementCoefficient(type, delta_t);
+ auto c = this->getAccelerationCoefficient(type, delta_t);
+ auto e = this->getDisplacementCoefficient(type, delta_t);
bool does_j_need_update = false;
does_j_need_update |= M.getRelease() != m_release;
// in explicit this coefficient is exactly 0.
if (not(e == 0.)) {
- const SparseMatrix & K = this->dof_manager.getMatrix("K");
+ const auto & K = this->dof_manager.getMatrix("K");
does_j_need_update |= K.getRelease() != k_release;
}
if (this->dof_manager.hasMatrix("C")) {
- const SparseMatrix & C = this->dof_manager.getMatrix("C");
+ const auto & C = this->dof_manager.getMatrix("C");
does_j_need_update |= C.getRelease() != c_release;
}
does_j_need_update |= this->dof_manager.hasBlockedDOFsChanged();
if (not does_j_need_update) {
AKANTU_DEBUG_OUT();
return;
}
J.copyProfile(M);
// J.zero();
if (not(e == 0.)) {
- const SparseMatrix & K = this->dof_manager.getMatrix("K");
+ const auto & K = this->dof_manager.getMatrix("K");
J.add(K, e);
k_release = K.getRelease();
}
J.add(M, c);
m_release = M.getRelease();
if (this->dof_manager.hasMatrix("C")) {
- Real d = this->getVelocityCoefficient(type, delta_t);
- const SparseMatrix & C = this->dof_manager.getMatrix("C");
+ auto d = this->getVelocityCoefficient(type, delta_t);
+ const auto & C = this->dof_manager.getMatrix("C");
J.add(C, d);
c_release = C.getRelease();
}
AKANTU_DEBUG_OUT();
}
+
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/common/integration_scheme/newmark-beta.hh b/src/model/common/integration_scheme/newmark-beta.hh
index db05c2085..845159075 100644
--- a/src/model/common/integration_scheme/newmark-beta.hh
+++ b/src/model/common/integration_scheme/newmark-beta.hh
@@ -1,200 +1,197 @@
/**
* @file newmark-beta.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Oct 05 2010
* @date last modification: Sat Sep 12 2020
*
* @brief implementation of the newmark-@f$\beta@f$ integration scheme. This
* implementation is taken from Méthodes numériques en mécanique des solides by
* Alain Curnier \note{ISBN: 2-88074-247-1}
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "integration_scheme_2nd_order.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NEWMARK_BETA_HH_
#define AKANTU_NEWMARK_BETA_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* The three differentiate equations (dynamic and cinematic) are :
* \f{eqnarray*}{
* M \ddot{u}_{n+1} + C \dot{u}_{n+1} + K u_{n+1} &=& q_{n+1} \\
* u_{n+1} &=& u_{n} + (1 - \alpha) \Delta t \dot{u}_{n} + \alpha \Delta t
*\dot{u}_{n+1} + (1/2 - \alpha) \Delta t^2 \ddot{u}_n \\
* \dot{u}_{n+1} &=& \dot{u}_{n} + (1 - \beta) \Delta t \ddot{u}_{n} + \beta
*\Delta t \ddot{u}_{n+1}
* \f}
*
* Predictor:
* \f{eqnarray*}{
* u^{0}_{n+1} &=& u_{n} + \Delta t \dot{u}_n + \frac{\Delta t^2}{2}
*\ddot{u}_n \\
* \dot{u}^{0}_{n+1} &=& \dot{u}_{n} + \Delta t \ddot{u}_{n} \\
* \ddot{u}^{0}_{n+1} &=& \ddot{u}_{n}
* \f}
*
* Solve :
* \f[ (c M + d C + e K^i_{n+1}) w = = q_{n+1} - f^i_{n+1} - C \dot{u}^i_{n+1}
*- M \ddot{u}^i_{n+1} \f]
*
* Corrector :
* \f{eqnarray*}{
* \ddot{u}^{i+1}_{n+1} &=& \ddot{u}^{i}_{n+1} + c w \\
* \dot{u}^{i+1}_{n+1} &=& \dot{u}^{i}_{n+1} + d w \\
* u^{i+1}_{n+1} &=& u^{i}_{n+1} + e w
* \f}
*
* c, d and e are parameters depending on the method used to solve the equations
*\n
* For acceleration : \f$ w = \delta \ddot{u}, e = \alpha \beta \Delta t^2, d =
*\beta \Delta t, c = 1 \f$ \n
* For velocity : \f$ w = \delta \dot{u}, e = 1/\beta \Delta t, d =
*1, c = \alpha \Delta t \f$ \n
* For displacement : \f$ w = \delta u, e = 1, d =
*1/\alpha \Delta t, c = 1/\alpha \beta \Delta t^2 \f$
*/
class NewmarkBeta : public IntegrationScheme2ndOrder {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- NewmarkBeta(DOFManager & dof_manager, const ID & dof_id, Real alpha = 0.,
+ NewmarkBeta(DOFManager &dof_manager, const ID &dof_id, Real alpha = 0.,
Real beta = 0.);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- void predictor(Real delta_t, Array<Real> & u, Array<Real> & u_dot,
- Array<Real> & u_dot_dot,
- const Array<bool> & blocked_dofs) const override;
+ void predictor(Real delta_t, Array<Real> &u, Array<Real> &u_dot,
+ Array<Real> &u_dot_dot,
+ const Array<bool> &blocked_dofs) const override;
- void corrector(const SolutionType & type, Real delta_t, Array<Real> & u,
- Array<Real> & u_dot, Array<Real> & u_dot_dot,
- const Array<bool> & blocked_dofs,
- const Array<Real> & delta) const override;
+ void corrector(const SolutionType &type, Real delta_t, Array<Real> &u,
+ Array<Real> &u_dot, Array<Real> &u_dot_dot,
+ const Array<bool> &blocked_dofs,
+ const Array<Real> &delta) const override;
- void assembleJacobian(const SolutionType & type, Real delta_t) override;
+ void assembleJacobian(const SolutionType &type, Real delta_t) override;
public:
- Real getAccelerationCoefficient(const SolutionType & type,
+ Real getAccelerationCoefficient(const SolutionType &type,
Real delta_t) const override;
- Real getVelocityCoefficient(const SolutionType & type,
+ Real getVelocityCoefficient(const SolutionType &type,
Real delta_t) const override;
- Real getDisplacementCoefficient(const SolutionType & type,
+ Real getDisplacementCoefficient(const SolutionType &type,
Real delta_t) const override;
private:
template <SolutionType type>
- void allCorrector(Real delta_t, Array<Real> & u, Array<Real> & u_dot,
- Array<Real> & u_dot_dot, const Array<bool> & blocked_dofs,
- const Array<Real> & delta) const;
+ void allCorrector(Real delta_t, Array<Real> &u, Array<Real> &u_dot,
+ Array<Real> &u_dot_dot, const Array<bool> &blocked_dofs,
+ const Array<Real> &delta) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(Beta, beta, Real);
AKANTU_SET_MACRO(Beta, beta, Real);
AKANTU_GET_MACRO(Alpha, alpha, Real);
AKANTU_SET_MACRO(Alpha, alpha, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// the \f$\beta\f$ parameter
Real beta;
/// the \f$\alpha\f$ parameter
Real alpha;
- Real k;
- Real h;
-
- /// last release of M matrix
- UInt m_release;
+ Real k{0};
+ Real h{0};
/// last release of K matrix
- UInt k_release;
+ Int k_release{0};
/// last release of C matrix
- UInt c_release;
+ Int c_release{0};
};
/**
* central difference method (explicit)
* undamped stability condition :
* \f$ \Delta t = \alpha \Delta t_{crit} = \frac{2}{\omega_{max}} \leq \min_{e}
*\frac{l_e}{c_e}\f$
*
*/
class CentralDifference : public NewmarkBeta {
public:
- CentralDifference(DOFManager & dof_manager, const ID & dof_id)
+ CentralDifference(DOFManager &dof_manager, const ID &dof_id)
: NewmarkBeta(dof_manager, dof_id, 0., 1. / 2.){};
std::vector<std::string> getNeededMatrixList() override { return {"M", "C"}; }
};
//#include "integration_scheme/central_difference.hh"
/// undamped trapezoidal rule (implicit)
class TrapezoidalRule2 : public NewmarkBeta {
public:
- TrapezoidalRule2(DOFManager & dof_manager, const ID & dof_id)
+ TrapezoidalRule2(DOFManager &dof_manager, const ID &dof_id)
: NewmarkBeta(dof_manager, dof_id, 1. / 2., 1. / 2.){};
};
/// Fox-Goodwin rule (implicit)
class FoxGoodwin : public NewmarkBeta {
public:
- FoxGoodwin(DOFManager & dof_manager, const ID & dof_id)
+ FoxGoodwin(DOFManager &dof_manager, const ID &dof_id)
: NewmarkBeta(dof_manager, dof_id, 1. / 6., 1. / 2.){};
};
/// Linear acceleration (implicit)
class LinearAceleration : public NewmarkBeta {
public:
- LinearAceleration(DOFManager & dof_manager, const ID & dof_id)
+ LinearAceleration(DOFManager &dof_manager, const ID &dof_id)
: NewmarkBeta(dof_manager, dof_id, 1. / 3., 1. / 2.){};
};
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_NEWMARK_BETA_HH_ */
diff --git a/src/model/common/integration_scheme/pseudo_time.cc b/src/model/common/integration_scheme/pseudo_time.cc
index f4d49cbe4..865caf305 100644
--- a/src/model/common/integration_scheme/pseudo_time.cc
+++ b/src/model/common/integration_scheme/pseudo_time.cc
@@ -1,91 +1,91 @@
/**
* @file pseudo_time.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Feb 19 2016
* @date last modification: Wed Mar 27 2019
*
* @brief Implementation of a really simple integration scheme
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "pseudo_time.hh"
#include "dof_manager.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
PseudoTime::PseudoTime(DOFManager & dof_manager, const ID & dof_id)
- : IntegrationScheme(dof_manager, dof_id, 0), k_release(0) {}
+ : IntegrationScheme(dof_manager, dof_id, 0) {}
/* -------------------------------------------------------------------------- */
std::vector<std::string> PseudoTime::getNeededMatrixList() { return {"K"}; }
/* -------------------------------------------------------------------------- */
void PseudoTime::predictor(Real /*delta_t*/) {}
/* -------------------------------------------------------------------------- */
void PseudoTime::corrector(const SolutionType & /*type*/, Real /*delta_t*/) {
auto & us = this->dof_manager.getDOFs(this->dof_id);
const auto & deltas = this->dof_manager.getSolution(this->dof_id);
const auto & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id);
for (auto && tuple : zip(make_view(us), deltas, make_view(blocked_dofs))) {
auto & u = std::get<0>(tuple);
const auto & delta = std::get<1>(tuple);
const auto & bld = std::get<2>(tuple);
if (not bld) {
u += delta;
}
}
}
/* -------------------------------------------------------------------------- */
void PseudoTime::assembleJacobian(const SolutionType & /*type*/,
Real /*delta_t*/) {
SparseMatrix & J = this->dof_manager.getMatrix("J");
const SparseMatrix & K = this->dof_manager.getMatrix("K");
bool does_j_need_update = false;
does_j_need_update |= K.getRelease() != k_release;
does_j_need_update |= this->dof_manager.hasBlockedDOFsChanged();
if (not does_j_need_update) {
AKANTU_DEBUG_OUT();
return;
}
J.copyProfile(K);
// J.zero();
J.add(K);
k_release = K.getRelease();
}
/* -------------------------------------------------------------------------- */
void PseudoTime::assembleResidual(bool /*is_lumped*/) {}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/common/integration_scheme/pseudo_time.hh b/src/model/common/integration_scheme/pseudo_time.hh
index ca7cacf84..27a07b94d 100644
--- a/src/model/common/integration_scheme/pseudo_time.hh
+++ b/src/model/common/integration_scheme/pseudo_time.hh
@@ -1,74 +1,74 @@
/**
* @file pseudo_time.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Jan 31 2018
*
* @brief Pseudo time integration scheme
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "integration_scheme.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PSEUDO_TIME_HH_
#define AKANTU_PSEUDO_TIME_HH_
namespace akantu {
class PseudoTime : public IntegrationScheme {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- PseudoTime(DOFManager & dof_manager, const ID & dof_id);
+ PseudoTime(DOFManager &dof_manager, const ID &dof_id);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// get list of needed matrices
std::vector<std::string> getNeededMatrixList() override;
/// generic interface of a predictor
void predictor(Real delta_t) override;
/// generic interface of a corrector
- void corrector(const SolutionType & type, Real delta_t) override;
+ void corrector(const SolutionType &type, Real delta_t) override;
/// assemble the jacobian matrix
- void assembleJacobian(const SolutionType & type, Real delta_t) override;
+ void assembleJacobian(const SolutionType &type, Real delta_t) override;
/// assemble the residual
void assembleResidual(bool is_lumped) override;
protected:
/// last release of K matrix
- UInt k_release;
+ Int k_release{-1};
};
} // namespace akantu
#endif /* AKANTU_PSEUDO_TIME_HH_ */
diff --git a/src/model/common/non_linear_solver/non_linear_solver.hh b/src/model/common/non_linear_solver/non_linear_solver.hh
index bc8127e8f..5e968a217 100644
--- a/src/model/common/non_linear_solver/non_linear_solver.hh
+++ b/src/model/common/non_linear_solver/non_linear_solver.hh
@@ -1,115 +1,115 @@
/**
* @file non_linear_solver.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Mar 27 2019
*
* @brief Non linear solver interface
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
#include <set>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LINEAR_SOLVER_HH_
#define AKANTU_NON_LINEAR_SOLVER_HH_
namespace akantu {
class DOFManager;
class SolverCallback;
} // namespace akantu
namespace akantu {
class NonLinearSolver : public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NonLinearSolver(DOFManager & dof_manager,
const NonLinearSolverType & non_linear_solver_type,
const ID & id = "non_linear_solver");
~NonLinearSolver() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// solve the system described by the jacobian matrix, and rhs contained in
/// the dof manager
virtual void solve(SolverCallback & callback) = 0;
/// intercept the call to set for options
template <typename T> void set(const ID & param, T && t) {
if (has_internal_set_param) {
set_param(param, std::to_string(t));
} else {
ParameterRegistry::set(param, t);
}
}
protected:
void checkIfTypeIsSupported();
void assembleResidual(SolverCallback & callback);
/// internal set param for solvers that should intercept the parameters
virtual void set_param(const ID & /*param*/, const std::string & /*value*/) {}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ID id;
DOFManager & _dof_manager;
/// type of non linear solver
NonLinearSolverType non_linear_solver_type;
/// list of supported non linear solver types
std::set<NonLinearSolverType> supported_type;
/// specifies if the set param should be redirected
bool has_internal_set_param{false};
};
namespace debug {
class NLSNotConvergedException : public Exception {
public:
- NLSNotConvergedException(Real threshold, UInt niter, Real error)
+ NLSNotConvergedException(Real threshold, Int niter, Real error)
: Exception("The non linear solver did not converge."),
threshold(threshold), niter(niter), error(error) {}
Real threshold;
- UInt niter;
+ Int niter;
Real error;
};
} // namespace debug
} // namespace akantu
#endif /* AKANTU_NON_LINEAR_SOLVER_HH_ */
diff --git a/src/model/common/non_linear_solver/non_linear_solver_lumped.cc b/src/model/common/non_linear_solver/non_linear_solver_lumped.cc
index d1439e974..201832377 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_lumped.cc
+++ b/src/model/common/non_linear_solver/non_linear_solver_lumped.cc
@@ -1,103 +1,102 @@
/**
* @file non_linear_solver_lumped.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Feb 16 2016
* @date last modification: Sat May 23 2020
*
* @brief Implementation of the default NonLinearSolver
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver_lumped.hh"
#include "communicator.hh"
#include "dof_manager_default.hh"
#include "solver_callback.hh"
#include "solver_vector_default.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NonLinearSolverLumped::NonLinearSolverLumped(
DOFManagerDefault & dof_manager,
const NonLinearSolverType & non_linear_solver_type, const ID & id)
: NonLinearSolver(dof_manager, non_linear_solver_type, id),
dof_manager(dof_manager) {
this->supported_type.insert(NonLinearSolverType::_lumped);
this->checkIfTypeIsSupported();
this->registerParam("b_a2x", this->alpha, 1., _pat_parsmod,
"Conversion coefficient between x and A^{-1} b");
}
/* -------------------------------------------------------------------------- */
NonLinearSolverLumped::~NonLinearSolverLumped() = default;
/* ------------------------------------------------------------------------ */
void NonLinearSolverLumped::solve(SolverCallback & solver_callback) {
solver_callback.beforeSolveStep();
this->dof_manager.updateGlobalBlockedDofs();
solver_callback.predictor();
solver_callback.assembleResidual();
auto & x = aka::as_type<SolverVectorDefault>(this->dof_manager.getSolution());
const auto & b = this->dof_manager.getResidual();
x.resize();
const auto & blocked_dofs = this->dof_manager.getBlockedDOFs();
const auto & A = this->dof_manager.getLumpedMatrix("M");
// alpha is the conversion factor from from force/mass to acceleration needed
// in model coupled with atomistic \todo find a way to define alpha per dof
// type
+ x.zero();
NonLinearSolverLumped::solveLumped(A, x, b, alpha, blocked_dofs);
this->dof_manager.splitSolutionPerDOFs();
solver_callback.corrector();
solver_callback.afterSolveStep(true);
}
/* -------------------------------------------------------------------------- */
-void NonLinearSolverLumped::solveLumped(const Array<Real> & A, Array<Real> & x,
- const Array<Real> & b, Real alpha,
+void NonLinearSolverLumped::solveLumped(const Array<Real> & As,
+ Array<Real> & xs,
+ const Array<Real> & bs, Real alpha,
const Array<bool> & blocked_dofs) {
- for (auto && data :
- zip(make_view(A), make_view(x), make_view(b), make_view(blocked_dofs))) {
- const auto & A = std::get<0>(data);
- auto & x = std::get<1>(data);
- const auto & b = std::get<2>(data);
- const auto & blocked = std::get<3>(data);
+ for (auto && [A, x, b, blocked] :
+ zip(make_view(As), make_view(xs), make_view(bs),
+ make_view(blocked_dofs))) {
if (not blocked) {
x = alpha * (b / A);
}
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/common/non_linear_solver/non_linear_solver_newton_raphson.cc b/src/model/common/non_linear_solver/non_linear_solver_newton_raphson.cc
index 39f94397a..cbecc2975 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_newton_raphson.cc
+++ b/src/model/common/non_linear_solver/non_linear_solver_newton_raphson.cc
@@ -1,210 +1,210 @@
/**
* @file non_linear_solver_newton_raphson.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 15 2015
* @date last modification: Tue Mar 30 2021
*
* @brief Implementation of the default NonLinearSolver
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver_newton_raphson.hh"
#include "communicator.hh"
#include "dof_manager_default.hh"
#include "solver_callback.hh"
#include "solver_vector.hh"
#include "sparse_solver_mumps.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NonLinearSolverNewtonRaphson::NonLinearSolverNewtonRaphson(
DOFManagerDefault & dof_manager,
const NonLinearSolverType & non_linear_solver_type, const ID & id)
: NonLinearSolver(dof_manager, non_linear_solver_type, id),
dof_manager(dof_manager), solver(std::make_unique<SparseSolverMumps>(
dof_manager, "J", id + ":sparse_solver")) {
this->supported_type.insert(NonLinearSolverType::_newton_raphson_modified);
this->supported_type.insert(NonLinearSolverType::_newton_raphson_contact);
this->supported_type.insert(NonLinearSolverType::_newton_raphson);
this->supported_type.insert(NonLinearSolverType::_linear);
this->checkIfTypeIsSupported();
this->registerParam("threshold", convergence_criteria, 1e-10, _pat_parsmod,
"Threshold to consider results as converged");
this->registerParam("convergence_type", convergence_criteria_type,
SolveConvergenceCriteria::_solution, _pat_parsmod,
"Type of convergence criteria");
this->registerParam("max_iterations", max_iterations, 10, _pat_parsmod,
"Max number of iterations");
this->registerParam("error", error, _pat_readable, "Last reached error");
this->registerParam("nb_iterations", n_iter, _pat_readable,
"Last reached number of iterations");
this->registerParam("converged", converged, _pat_readable,
"Did last solve converged");
this->registerParam("force_linear_recompute", force_linear_recompute, true,
_pat_modifiable,
"Force reassembly of the jacobian matrix");
}
/* -------------------------------------------------------------------------- */
NonLinearSolverNewtonRaphson::~NonLinearSolverNewtonRaphson() = default;
/* ------------------------------------------------------------------------ */
void NonLinearSolverNewtonRaphson::solve(SolverCallback & solver_callback) {
solver_callback.beforeSolveStep();
this->dof_manager.updateGlobalBlockedDofs();
solver_callback.predictor();
if (non_linear_solver_type == NonLinearSolverType::_linear and
solver_callback.canSplitResidual()) {
solver_callback.assembleMatrix("K");
}
this->assembleResidual(solver_callback);
if (this->non_linear_solver_type ==
NonLinearSolverType::_newton_raphson_modified ||
(this->non_linear_solver_type == NonLinearSolverType::_linear &&
this->force_linear_recompute)) {
solver_callback.assembleMatrix("J");
this->force_linear_recompute = false;
}
this->n_iter = 0;
this->converged = false;
this->convergence_criteria_normalized = this->convergence_criteria;
if (this->convergence_criteria_type == SolveConvergenceCriteria::_residual) {
this->converged = this->testConvergence(this->dof_manager.getResidual());
if (this->converged) {
return;
}
this->convergence_criteria_normalized =
this->error * this->convergence_criteria;
}
do {
if (this->non_linear_solver_type == NonLinearSolverType::_newton_raphson or
this->non_linear_solver_type ==
NonLinearSolverType::_newton_raphson_contact) {
solver_callback.assembleMatrix("J");
}
this->solver->solve();
solver_callback.corrector();
// EventManager::sendEvent(NonLinearSolver::AfterSparseSolve(method));
if (this->convergence_criteria_type ==
SolveConvergenceCriteria::_residual) {
this->assembleResidual(solver_callback);
this->converged = this->testConvergence(this->dof_manager.getResidual());
} else {
this->converged = this->testConvergence(this->dof_manager.getSolution());
}
if (this->convergence_criteria_type ==
SolveConvergenceCriteria::_solution and
not this->converged) {
this->assembleResidual(solver_callback);
}
this->n_iter++;
AKANTU_DEBUG_INFO(
"[" << this->convergence_criteria_type << "] Convergence iteration "
<< std::setw(std::log10(this->max_iterations)) << this->n_iter
<< ": error " << this->error << (this->converged ? " < " : " > ")
<< this->convergence_criteria);
} while (not this->converged and this->n_iter <= this->max_iterations);
// this makes sure that you have correct strains and stresses after the
// solveStep function (e.g., for dumping)
if (this->convergence_criteria_type == SolveConvergenceCriteria::_solution) {
this->assembleResidual(solver_callback);
}
this->converged =
this->converged and not(this->n_iter > this->max_iterations);
solver_callback.afterSolveStep(this->converged);
if (not this->converged) {
AKANTU_CUSTOM_EXCEPTION(debug::NLSNotConvergedException(
this->convergence_criteria, this->n_iter, this->error));
AKANTU_DEBUG_WARNING("[" << this->convergence_criteria_type
<< "] Convergence not reached after "
<< std::setw(std::log10(this->max_iterations))
<< this->n_iter << " iteration"
<< (this->n_iter == 1 ? "" : "s") << "!");
}
}
/* -------------------------------------------------------------------------- */
bool NonLinearSolverNewtonRaphson::testConvergence(
const SolverVector & solver_vector) {
AKANTU_DEBUG_IN();
const auto & blocked_dofs = this->dof_manager.getBlockedDOFs();
const Array<Real> & array(solver_vector);
- UInt nb_degree_of_freedoms = array.size();
+ Int nb_degree_of_freedoms = array.size();
auto arr_it = array.begin();
auto bld_it = blocked_dofs.begin();
Real norm = 0.;
- for (UInt n = 0; n < nb_degree_of_freedoms; ++n, ++arr_it, ++bld_it) {
+ for (Int n = 0; n < nb_degree_of_freedoms; ++n, ++arr_it, ++bld_it) {
bool is_local_node = this->dof_manager.isLocalOrMasterDOF(n);
if ((!*bld_it) && is_local_node) {
norm += *arr_it * *arr_it;
}
}
dof_manager.getCommunicator().allReduce(norm, SynchronizerOperation::_sum);
norm = std::sqrt(norm);
AKANTU_DEBUG_ASSERT(!Math::isnan(norm),
"Something went wrong in the solve phase");
this->error = norm;
return (error < this->convergence_criteria_normalized);
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/common/non_linear_solver/non_linear_solver_petsc.cc b/src/model/common/non_linear_solver/non_linear_solver_petsc.cc
index c3351976e..cbc3007fd 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_petsc.cc
+++ b/src/model/common/non_linear_solver/non_linear_solver_petsc.cc
@@ -1,227 +1,240 @@
/**
* @file non_linear_solver_petsc.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Feb 03 2018
* @date last modification: Sat May 23 2020
*
* @brief Interface to non linear solver of PETSc
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver_petsc.hh"
#include "dof_manager_petsc.hh"
#include "mpi_communicator_data.hh"
#include "solver_callback.hh"
#include "solver_vector_petsc.hh"
#include "sparse_matrix_petsc.hh"
/* -------------------------------------------------------------------------- */
#include <petscoptions.h>
/* -------------------------------------------------------------------------- */
namespace akantu {
NonLinearSolverPETSc::NonLinearSolverPETSc(
DOFManagerPETSc & dof_manager,
const NonLinearSolverType & non_linear_solver_type, const ID & id)
: NonLinearSolver(dof_manager, non_linear_solver_type, id),
dof_manager(dof_manager) {
std::unordered_map<NonLinearSolverType, SNESType>
petsc_non_linear_solver_types{
{NonLinearSolverType::_newton_raphson, SNESNEWTONLS},
{NonLinearSolverType::_linear, SNESKSPONLY},
{NonLinearSolverType::_gmres, SNESNGMRES},
{NonLinearSolverType::_bfgs, SNESQN},
{NonLinearSolverType::_cg, SNESNCG}};
this->has_internal_set_param = true;
for (const auto & pair : petsc_non_linear_solver_types) {
supported_type.insert(pair.first);
}
this->checkIfTypeIsSupported();
auto && mpi_comm = dof_manager.getMPIComm();
PETSc_call(SNESCreate, mpi_comm, &snes);
auto it = petsc_non_linear_solver_types.find(non_linear_solver_type);
if (it != petsc_non_linear_solver_types.end()) {
PETSc_call(SNESSetType, snes, it->second);
}
SNESSetFromOptions(snes);
}
/* -------------------------------------------------------------------------- */
NonLinearSolverPETSc::~NonLinearSolverPETSc() {
PETSc_call(SNESDestroy, &snes);
}
/* -------------------------------------------------------------------------- */
class NonLinearSolverPETScCallback {
public:
- NonLinearSolverPETScCallback(DOFManagerPETSc & dof_manager,
+ NonLinearSolverPETScCallback(DOFManagerPETSc & dof_manager, SNES snes,
SolverVectorPETSc & x)
- : dof_manager(dof_manager), x(x), x_prev(x, "previous_solution") {}
+ : dof_manager(dof_manager), snes(snes), x_prev(x, "previous solution") {}
+
+ void corrector(Vec & x) {
+ PetscInt iteration;
+ PETSc_call(SNESGetIterationNumber, snes, &iteration);
+
+ if (prev_iteration == iteration) {
+ return;
+ }
+
+ prev_iteration = iteration;
- void corrector() {
auto & dx = dof_manager.getSolution();
PETSc_call(VecWAXPY, dx, -1., x_prev, x);
-
dof_manager.splitSolutionPerDOFs();
+
callback->corrector();
PETSc_call(VecCopy, x, x_prev);
}
- void assembleResidual() {
- corrector();
+ void assembleResidual(Vec x) {
+ corrector(x);
callback->assembleResidual();
}
- void assembleJacobian() {
- // corrector();
+ void assembleJacobian(Vec x) {
+ corrector(x);
callback->assembleMatrix("J");
}
+ void reset() { prev_iteration = -1; }
+
void setInitialSolution(SolverVectorPETSc & x) {
PETSc_call(VecCopy, x, x_prev);
}
void setCallback(SolverCallback & callback) { this->callback = &callback; }
private:
- // SNES & snes;
SolverCallback * callback;
DOFManagerPETSc & dof_manager;
+ SNES snes;
- SolverVectorPETSc & x;
+ // SolverVectorPETSc & x;
SolverVectorPETSc x_prev;
+ PetscInt prev_iteration{-1};
}; // namespace akantu
/* -------------------------------------------------------------------------- */
-PetscErrorCode NonLinearSolverPETSc::FormFunction(SNES /*snes*/, Vec /*dx*/,
+PetscErrorCode NonLinearSolverPETSc::FormFunction(SNES /*snes*/, Vec x,
Vec /*f*/, void * ctx) {
auto * _this = reinterpret_cast<NonLinearSolverPETScCallback *>(ctx);
- _this->assembleResidual();
+ _this->assembleResidual(x);
return 0;
}
/* -------------------------------------------------------------------------- */
-PetscErrorCode NonLinearSolverPETSc::FormJacobian(SNES /*snes*/, Vec /*dx*/,
+PetscErrorCode NonLinearSolverPETSc::FormJacobian(SNES /*snes*/, Vec x,
Mat /*J*/, Mat /*P*/,
void * ctx) {
auto * _this = reinterpret_cast<NonLinearSolverPETScCallback *>(ctx);
- _this->assembleJacobian();
+ _this->assembleJacobian(x);
return 0;
}
/* -------------------------------------------------------------------------- */
void NonLinearSolverPETSc::solve(SolverCallback & callback) {
callback.beforeSolveStep();
this->dof_manager.updateGlobalBlockedDofs();
callback.assembleMatrix("J");
auto & global_x = dof_manager.getSolution();
global_x.zero();
if (not x) {
x = std::make_unique<SolverVectorPETSc>(global_x, "temporary_solution");
}
*x = global_x;
if (not ctx) {
- ctx = std::make_unique<NonLinearSolverPETScCallback>(dof_manager, *x);
+ ctx = std::make_unique<NonLinearSolverPETScCallback>(dof_manager, snes, *x);
+ } else {
+ ctx->reset();
}
ctx->setCallback(callback);
ctx->setInitialSolution(global_x);
auto & rhs = dof_manager.getResidual();
auto & J = dof_manager.getMatrix("J");
PETSc_call(SNESSetFunction, snes, rhs, NonLinearSolverPETSc::FormFunction,
ctx.get());
PETSc_call(SNESSetJacobian, snes, J, J, NonLinearSolverPETSc::FormJacobian,
ctx.get());
rhs.zero();
callback.predictor();
- callback.assembleResidual();
+ // callback.assembleResidual();
PETSc_call(SNESSolve, snes, nullptr, *x);
PETSc_call(SNESGetConvergedReason, snes, &reason);
PETSc_call(SNESGetIterationNumber, snes, &n_iter);
PETSc_call(VecAXPY, global_x, -1.0, *x);
-
dof_manager.splitSolutionPerDOFs();
callback.corrector();
bool converged = reason >= 0;
callback.afterSolveStep(converged);
if (not converged) {
PetscReal atol;
PetscReal rtol;
PetscReal stol;
PetscInt maxit;
PetscInt maxf;
PETSc_call(SNESGetTolerances, snes, &atol, &rtol, &stol, &maxit, &maxf);
AKANTU_CUSTOM_EXCEPTION(debug::SNESNotConvergedException(
this->reason, this->n_iter, stol, atol, rtol, maxit));
}
}
/* -------------------------------------------------------------------------- */
void NonLinearSolverPETSc::set_param(const ID & param,
const std::string & value) {
std::map<ID, ID> akantu_to_petsc_option = {{"max_iterations", "snes_max_it"},
{"threshold", "snes_stol"}};
auto it = akantu_to_petsc_option.find(param);
auto p = it == akantu_to_petsc_option.end() ? param : it->second;
PetscOptionsSetValue(nullptr, p.c_str(), value.c_str());
SNESSetFromOptions(snes);
PetscOptionsClear(nullptr);
}
/* -------------------------------------------------------------------------- */
void NonLinearSolverPETSc::parseSection(const ParserSection & section) {
auto parameters = section.getParameters();
for (auto && param : range(parameters.first, parameters.second)) {
PetscOptionsSetValue(nullptr, param.getName().c_str(),
param.getValue().c_str());
}
SNESSetFromOptions(snes);
PetscOptionsClear(nullptr);
}
} // namespace akantu
diff --git a/src/model/common/non_linear_solver/non_linear_solver_petsc.hh b/src/model/common/non_linear_solver/non_linear_solver_petsc.hh
index 585f39449..f293966d7 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_petsc.hh
+++ b/src/model/common/non_linear_solver/non_linear_solver_petsc.hh
@@ -1,111 +1,111 @@
/**
* @file non_linear_solver_petsc.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Feb 03 2018
* @date last modification: Sat May 23 2020
*
* @brief Interface to non linear solver of PETSc
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver.hh"
/* -------------------------------------------------------------------------- */
#include <petscsnes.h>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LINEAR_SOLVER_PETSC_HH_
#define AKANTU_NON_LINEAR_SOLVER_PETSC_HH_
namespace akantu {
class DOFManagerPETSc;
class NonLinearSolverPETScCallback;
class SolverVectorPETSc;
} // namespace akantu
namespace akantu {
class NonLinearSolverPETSc : public NonLinearSolver {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NonLinearSolverPETSc(DOFManagerPETSc & dof_manager,
const NonLinearSolverType & non_linear_solver_type,
const ID & id = "non_linear_solver_petsc");
~NonLinearSolverPETSc() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// solve the system described by the jacobian matrix, and rhs contained in
/// the dof manager
void solve(SolverCallback & callback) override;
/// parse the arguments from the input file
void parseSection(const ParserSection & section) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
static PetscErrorCode FormFunction(SNES snes, Vec dx, Vec f, void * ctx);
static PetscErrorCode FormJacobian(SNES snes, Vec dx, Mat J, Mat P,
void * ctx);
void set_param(const ID & param, const std::string & value) override;
DOFManagerPETSc & dof_manager;
/// PETSc non linear solver
SNES snes;
SNESConvergedReason reason;
SolverCallback * callback{nullptr};
std::unique_ptr<SolverVectorPETSc> x;
std::unique_ptr<NonLinearSolverPETScCallback> ctx;
Int n_iter{0};
};
namespace debug {
class SNESNotConvergedException : public NLSNotConvergedException {
public:
- SNESNotConvergedException(SNESConvergedReason reason, UInt niter,
- Real error, Real absolute_tolerance,
- Real relative_tolerance, UInt max_iterations)
+ SNESNotConvergedException(SNESConvergedReason reason, Int niter, Real error,
+ Real absolute_tolerance, Real relative_tolerance,
+ Int max_iterations)
: NLSNotConvergedException(relative_tolerance, niter, error),
reason(reason), absolute_tolerance(absolute_tolerance),
max_iterations(max_iterations) {}
SNESConvergedReason reason;
Real absolute_tolerance;
- UInt max_iterations;
+ Int max_iterations;
};
} // namespace debug
} // namespace akantu
#endif /* AKANTU_NON_LINEAR_SOLVER_PETSC_HH_ */
diff --git a/src/model/common/non_local_toolbox/base_weight_function.cc b/src/model/common/non_local_toolbox/base_weight_function.cc
new file mode 100644
index 000000000..9f4491b8c
--- /dev/null
+++ b/src/model/common/non_local_toolbox/base_weight_function.cc
@@ -0,0 +1,36 @@
+/**
+ * @file base_weight_function.cc
+ *
+ * @author Nicolas Richart
+ *
+ * @date creation sam jan 22 2022
+ *
+ * @brief A Documented file.
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "base_weight_function.hh"
+
+namespace akantu {
+
+INSTANTIATE_NL_NEIGHBORHOOD(base_wf, BaseWeightFunction);
+
+} // namespace akantu
diff --git a/src/model/common/non_local_toolbox/base_weight_function.hh b/src/model/common/non_local_toolbox/base_weight_function.hh
index c9b94993c..9576c11ad 100644
--- a/src/model/common/non_local_toolbox/base_weight_function.hh
+++ b/src/model/common/non_local_toolbox/base_weight_function.hh
@@ -1,173 +1,189 @@
/**
* @file base_weight_function.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Mon Aug 24 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Base weight function for non local materials
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "aka_factory.hh"
#include "data_accessor.hh"
#include "model.hh"
#include "non_local_manager.hh"
+#include "non_local_neighborhood.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_BASE_WEIGHT_FUNCTION_HH_
#define AKANTU_BASE_WEIGHT_FUNCTION_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Normal weight function */
/* -------------------------------------------------------------------------- */
class BaseWeightFunction : public Parsable, public DataAccessor<Element> {
public:
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
BaseWeightFunction(NonLocalManager & manager,
const std::string & type = "base")
: Parsable(ParserType::_weight_function, "weight_function:" + type),
manager(manager), type(type),
spatial_dimension(manager.getModel().getMesh().getSpatialDimension()) {
- this->registerParam("update_rate", update_rate, UInt(1), _pat_parsmod,
+ this->registerParam("update_rate", update_rate, Int(1), _pat_parsmod,
"Update frequency");
}
~BaseWeightFunction() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
/// initialize the weight function
virtual inline void init();
/// update the internal parameters
virtual void updateInternals(){};
/* ------------------------------------------------------------------------ */
/// set the non-local radius
inline void setRadius(Real radius);
/* ------------------------------------------------------------------------ */
/// compute the weight for a given distance between two quadrature points
inline Real operator()(Real r, const IntegrationPoint & q1,
const IntegrationPoint & q2) const;
/// print function
void printself(std::ostream & stream, int indent = 0) const override {
std::string space;
for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) {
;
}
stream << space << "WeightFunction " << type << " [" << std::endl;
Parsable::printself(stream, indent);
stream << space << "]" << std::endl;
}
/* --------------------------------------------------------------------------
*/
/* Accessors */
/* --------------------------------------------------------------------------
*/
public:
/// get the radius
Real getRadius() const { return R; }
/// get the update rate
- UInt getUpdateRate() const { return update_rate; }
+ Int getUpdateRate() const { return update_rate; }
public:
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
- UInt getNbData(const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/) const override {
+ Int getNbData(const Array<Element> &,
+ const SynchronizationTag &) const override {
return 0;
}
inline void packData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*element*/,
const SynchronizationTag & /*tag*/) const override {}
inline void unpackData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*element*/,
const SynchronizationTag & /*tag*/) override {}
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(Type, type, const ID &);
protected:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
/// reference to the non-local manager
NonLocalManager & manager;
/// the non-local radius
Real R;
/// the non-local radius squared
Real R2;
/// the update rate
- UInt update_rate;
+ Int update_rate;
/// name of the type of weight function
const std::string type;
/// the spatial dimension
- UInt spatial_dimension;
+ Int spatial_dimension;
};
inline std::ostream & operator<<(std::ostream & stream,
const BaseWeightFunction & _this) {
_this.printself(stream);
return stream;
}
+using NonLocalNeighborhoodFactory =
+ Factory<NonLocalNeighborhoodBase, ID, ID, NonLocalManager &,
+ const ElementTypeMapReal &, const ID &>;
+
+#define INSTANTIATE_NL_NEIGHBORHOOD(id, weight_fun_name) \
+ static bool weigth_is_alocated_##id [[gnu::unused]] = \
+ NonLocalNeighborhoodFactory::getInstance().registerAllocator( \
+ #id, \
+ [](const ID & /*name*/, NonLocalManager & non_local_manager, \
+ const ElementTypeMapReal & quad_point_positions, const ID & id) { \
+ return std::make_unique<NonLocalNeighborhood<weight_fun_name>>( \
+ non_local_manager, quad_point_positions, id); \
+ })
+
} // namespace akantu
#include "base_weight_function_inline_impl.hh"
/* -------------------------------------------------------------------------- */
/* Include all other weight function types */
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_DAMAGE_NON_LOCAL)
#include "damaged_weight_function.hh"
#include "remove_damaged_weight_function.hh"
#include "remove_damaged_with_damage_rate_weight_function.hh"
#include "stress_based_weight_function.hh"
#endif
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_BASE_WEIGHT_FUNCTION_HH_ */
diff --git a/src/model/common/non_local_toolbox/base_weight_function_inline_impl.hh b/src/model/common/non_local_toolbox/base_weight_function_inline_impl.hh
index cf0216f96..b0b0a062a 100644
--- a/src/model/common/non_local_toolbox/base_weight_function_inline_impl.hh
+++ b/src/model/common/non_local_toolbox/base_weight_function_inline_impl.hh
@@ -1,73 +1,74 @@
/**
* @file base_weight_function_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Wed Sep 01 2010
* @date last modification: Wed Sep 27 2017
*
* @brief Implementation of inline function of base weight function
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "base_weight_function.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_BASE_WEIGHT_FUNCTION_INLINE_IMPL_HH_
#define AKANTU_BASE_WEIGHT_FUNCTION_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline void BaseWeightFunction::init() {
/// compute R^2 for a given non-local radius
this->R2 = this->R * this->R;
}
/* -------------------------------------------------------------------------- */
inline void BaseWeightFunction::setRadius(Real radius) {
/// set the non-local radius and update R^2 accordingly
this->R = radius;
this->R2 = this->R * this->R;
}
/* -------------------------------------------------------------------------- */
inline Real
BaseWeightFunction::operator()(Real r, const IntegrationPoint & /* q1 */,
const IntegrationPoint & /* q2 */) const {
/// initialize the weight
Real w = 0;
/// compute weight for given r
if (r <= this->R) {
Real alpha = (1. - r * r / this->R2);
w = alpha * alpha;
// *weight = 1 - sqrt(r / radius);
}
return w;
}
} // namespace akantu
+
#endif /* AKANTU_BASE_WEIGHT_FUNCTION_INLINE_IMPL_HH_ */
diff --git a/src/model/common/non_local_toolbox/neighborhood_base.cc b/src/model/common/non_local_toolbox/neighborhood_base.cc
index 1622cdba8..930f031fa 100644
--- a/src/model/common/non_local_toolbox/neighborhood_base.cc
+++ b/src/model/common/non_local_toolbox/neighborhood_base.cc
@@ -1,305 +1,291 @@
/**
* @file neighborhood_base.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Implementation of generic neighborhood base
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "neighborhood_base.hh"
#include "grid_synchronizer.hh"
#include "mesh_accessor.hh"
#include "model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NeighborhoodBase::NeighborhoodBase(Model & model,
const ElementTypeMapReal & quad_coordinates,
const ID & id)
: id(id), model(model), quad_coordinates(quad_coordinates),
spatial_dimension(this->model.getMesh().getSpatialDimension()) {
-
- AKANTU_DEBUG_IN();
-
this->registerDataAccessor(*this);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
NeighborhoodBase::~NeighborhoodBase() = default;
-/* -------------------------------------------------------------------------- */
-// void NeighborhoodBase::createSynchronizerRegistry(
-// DataAccessor<Element> * data_accessor) {
-// this->synch_registry = new SynchronizerRegistry(*data_accessor);
-// }
-
/* -------------------------------------------------------------------------- */
void NeighborhoodBase::initNeighborhood() {
- AKANTU_DEBUG_IN();
-
AKANTU_DEBUG_INFO("Creating the grid");
this->createGrid();
-
- AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------- */
void NeighborhoodBase::createGrid() {
AKANTU_DEBUG_IN();
const Real safety_factor = 1.2; // for the cell grid spacing
Mesh & mesh = this->model.getMesh();
- const auto & lower_bounds = mesh.getLocalLowerBounds();
- const auto & upper_bounds = mesh.getLocalUpperBounds();
- Vector<Real> center = 0.5 * (upper_bounds + lower_bounds);
- Vector<Real> spacing(spatial_dimension,
- this->neighborhood_radius * safety_factor);
+ const auto & lower_bounds = mesh.getLowerBounds();
+ const auto & upper_bounds = mesh.getUpperBounds();
+ Vector<Real> center = (upper_bounds + lower_bounds) / 2.;
+ Vector<Real> spacing(spatial_dimension);
+ spacing.fill(this->neighborhood_radius * safety_factor);
spatial_grid = std::make_unique<SpatialGrid<IntegrationPoint>>(
spatial_dimension, spacing, center);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NeighborhoodBase::updatePairList() {
AKANTU_DEBUG_IN();
//// loop over all quads -> all cells
for (auto && cell_id : *spatial_grid) {
AKANTU_DEBUG_INFO("Looping on next cell");
for (auto && q1 : spatial_grid->getCell(cell_id)) {
if (q1.ghost_type == _ghost) {
break;
}
auto coords_type_1_it = this->quad_coordinates(q1.type, q1.ghost_type)
.begin(spatial_dimension);
auto q1_coords = Vector<Real>(coords_type_1_it[q1.global_num]);
AKANTU_DEBUG_INFO("Current quadrature point in this cell: " << q1);
auto cell_id = spatial_grid->getCellID(q1_coords);
/// loop over all the neighboring cells of the current quad
for (auto && neighbor_cell : cell_id.neighbors()) {
// loop over the quadrature point in the current neighboring cell
for (auto && q2 : spatial_grid->getCell(neighbor_cell)) {
auto coords_type_2_it = this->quad_coordinates(q2.type, q2.ghost_type)
.begin(spatial_dimension);
auto q2_coords = Vector<Real>(coords_type_2_it[q2.global_num]);
Real distance = q1_coords.distance(q2_coords);
if (distance <= this->neighborhood_radius + Math::getTolerance() &&
(q2.ghost_type == _ghost ||
(q2.ghost_type == _not_ghost &&
q1.global_num <= q2.global_num))) { // storing only half lists
pair_list[q2.ghost_type].push_back(std::make_pair(q1, q2));
}
}
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NeighborhoodBase::savePairs(const std::string & filename) const {
std::stringstream sstr;
const Communicator & comm = model.getMesh().getCommunicator();
Int prank = comm.whoAmI();
sstr << filename << "." << prank;
std::ofstream pout;
pout.open(sstr.str().c_str());
for (auto && ghost_type : ghost_types) {
for (const auto & pair : pair_list[ghost_type]) {
const auto & q1 = pair.first;
const auto & q2 = pair.second;
pout << q1 << " " << q2 << " " << std::endl;
}
}
pout.close();
if (comm.getNbProc() != 1) {
return;
}
Mesh mesh_out(spatial_dimension);
MeshAccessor mesh_accessor(mesh_out);
auto & connectivity = mesh_accessor.getConnectivity(_segment_2);
- auto & tag = mesh_accessor.getData<UInt>("tag_1", _segment_2);
+ auto & tag = mesh_accessor.getData<Int>("tag_1", _segment_2);
auto & nodes = mesh_accessor.getNodes();
- std::map<IntegrationPoint, UInt> quad_to_nodes;
- UInt node = 0;
+ std::map<IntegrationPoint, Idx> quad_to_nodes;
+ Idx node = 0;
IntegrationPoint q1;
IntegrationPoint q2;
bool inserted;
for (auto && ghost_type : ghost_types) {
for (const auto & pair : pair_list[ghost_type]) {
std::tie(q1, q2) = pair;
auto add_node = [&](auto && q) {
std::tie(std::ignore, inserted) =
quad_to_nodes.insert(std::make_pair(q, node));
if (not inserted) {
return;
}
auto coords_it = this->quad_coordinates(q.type, q.ghost_type)
.begin(spatial_dimension);
auto && coords = Vector<Real>(coords_it[q.global_num]);
nodes.push_back(coords);
++node;
};
add_node(q1);
add_node(q2);
}
}
for (auto && ghost_type : ghost_types) {
for (const auto & pair : pair_list[ghost_type]) {
std::tie(q1, q2) = pair;
- UInt node1 = quad_to_nodes[q1];
- UInt node2 = quad_to_nodes[q2];
+ Idx node1 = quad_to_nodes[q1];
+ Idx node2 = quad_to_nodes[q2];
- connectivity.push_back(Vector<UInt>{node1, node2});
+ connectivity.push_back(Vector<Idx>{node1, node2});
tag.push_back(node1 + 1);
if (node1 != node2) {
- connectivity.push_back(Vector<UInt>{node2, node1});
+ connectivity.push_back(Vector<Idx>{node2, node1});
tag.push_back(node2 + 1);
}
}
}
mesh_out.write(filename + ".msh");
}
/* -------------------------------------------------------------------------- */
void NeighborhoodBase::saveNeighborCoords(const std::string & filename) const {
// this function is not optimized and only used for tests on small meshes
// @todo maybe optimize this function for better performance?
IntegrationPoint q2;
std::stringstream sstr;
const Communicator & comm = model.getMesh().getCommunicator();
Int prank = comm.whoAmI();
sstr << filename << "." << prank;
std::ofstream pout;
pout.open(sstr.str().c_str());
/// loop over all the quads and write the position of their neighbors
for (auto && cell_id : *spatial_grid) {
for (auto && q1 : spatial_grid->getCell(cell_id)) {
auto coords_type_1_it = this->quad_coordinates(q1.type, q1.ghost_type)
.begin(spatial_dimension);
auto && q1_coords = Vector<Real>(coords_type_1_it[q1.global_num]);
pout << "#neighbors for quad " << q1.global_num << std::endl;
pout << q1_coords << std::endl;
for (auto && ghost_type2 : ghost_types) {
for (auto && pair : pair_list[ghost_type2]) {
if (q1 == pair.first && pair.second != q1) {
q2 = pair.second;
} else if (q1 == pair.second && pair.first != q1) {
q2 = pair.first;
} else {
continue;
}
auto coords_type_2_it = this->quad_coordinates(q2.type, q2.ghost_type)
.begin(spatial_dimension);
auto && q2_coords = Vector<Real>(coords_type_2_it[q2.global_num]);
pout << q2_coords << std::endl;
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void NeighborhoodBase::onElementsRemoved(
const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) {
AKANTU_DEBUG_IN();
- FEEngine & fem = this->model.getFEEngine();
- UInt nb_quad = 0;
+ auto & fem = this->model.getFEEngine();
+ Int nb_quad = 0;
+
auto cleanPoint = [&](auto && q) {
if (new_numbering.exists(q.type, q.ghost_type)) {
- UInt q_new_el = new_numbering(q.type, q.ghost_type)(q.element);
- AKANTU_DEBUG_ASSERT(q_new_el != UInt(-1),
+ auto q_new_el = new_numbering(q.type, q.ghost_type)(q.element);
+ AKANTU_DEBUG_ASSERT(q_new_el != Int(-1),
"A local quadrature_point "
<< q
<< " as been removed instead of "
"just being renumbered: "
<< id);
q.element = q_new_el;
nb_quad = fem.getNbIntegrationPoints(q.type, q.ghost_type);
q.global_num = nb_quad * q.element + q.num_point;
}
};
// Change the pairs in new global numbering
for (auto ghost_type : ghost_types) {
auto & pair_list = this->pair_list.at(ghost_type);
for (auto && pair : pair_list) {
if (pair.first.ghost_type == _ghost) {
cleanPoint(pair.first);
}
if (pair.second.ghost_type == _ghost) {
cleanPoint(pair.second);
}
}
}
this->grid_synchronizer->onElementsRemoved(element_list, new_numbering,
event);
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/model/common/non_local_toolbox/neighborhood_base.hh b/src/model/common/non_local_toolbox/neighborhood_base.hh
index 5f1da3859..d4c5f6a2b 100644
--- a/src/model/common/non_local_toolbox/neighborhood_base.hh
+++ b/src/model/common/non_local_toolbox/neighborhood_base.hh
@@ -1,153 +1,152 @@
/**
* @file neighborhood_base.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Generic neighborhood of quadrature points
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NEIGHBORHOOD_BASE_HH_
#define AKANTU_NEIGHBORHOOD_BASE_HH_
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "data_accessor.hh"
#include "integration_point.hh"
#include "synchronizer_registry.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class Model;
template <class T> class SpatialGrid;
class GridSynchronizer;
class RemovedElementsEvent;
} // namespace akantu
namespace akantu {
class NeighborhoodBase : public DataAccessor<Element>,
public SynchronizerRegistry {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NeighborhoodBase(Model & model,
const ElementTypeMapArray<Real> & quad_coordinates,
const ID & id = "neighborhood");
~NeighborhoodBase() override;
using PairList = std::vector<std::pair<IntegrationPoint, IntegrationPoint>>;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// intialize the neighborhood
virtual void initNeighborhood();
// /// create a synchronizer registry
// void createSynchronizerRegistry(DataAccessor * data_accessor);
/// initialize the material computed parameter
inline void insertIntegrationPoint(const IntegrationPoint & quad,
- const Vector<Real> & coords);
+ const Ref<Vector<Real>> & coords);
/// create the pairs of quadrature points
void updatePairList();
/// save the pairs of quadrature points in a file
void savePairs(const std::string & filename) const;
/// save the coordinates of all neighbors of a quad
void saveNeighborCoords(const std::string & filename) const;
/// create grid synchronizer and exchange ghost cells
virtual void createGridSynchronizer() = 0;
virtual void synchronize(DataAccessor<Element> & data_accessor,
const SynchronizationTag & tag) = 0;
/// inherited function from MeshEventHandler
- virtual void
- onElementsRemoved(const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
- const RemovedElementsEvent & event);
+ virtual void onElementsRemoved(const Array<Element> & element_list,
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent & event);
protected:
/// create the grid
void createGrid();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
+ AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, Int);
AKANTU_GET_MACRO(Model, model, const Model &);
/// return the object handling synchronizers
const PairList & getPairLists(GhostType type) {
return pair_list[type == _not_ghost ? 0 : 1];
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ID id;
/// the model to which the neighborhood belongs
Model & model;
/// Radius of impact: to determine if two quadrature points influence each
/// other
Real neighborhood_radius{0.};
/**
* the pairs of quadrature points
* 0: not ghost to not ghost
* 1: not ghost to ghost
*/
std::array<PairList, 2> pair_list;
/// the regular grid to construct/update the pair lists
std::unique_ptr<SpatialGrid<IntegrationPoint>> spatial_grid;
bool is_creating_grid{false};
/// the grid synchronizer for parallel computations
std::unique_ptr<GridSynchronizer> grid_synchronizer;
/// the quadrature point positions
const ElementTypeMapArray<Real> & quad_coordinates;
/// the spatial dimension of the problem
- const UInt spatial_dimension;
+ const Int spatial_dimension;
};
} // namespace akantu
#include "neighborhood_base_inline_impl.hh"
#endif /* AKANTU_NEIGHBORHOOD_BASE_HH_ */
diff --git a/src/model/common/non_local_toolbox/neighborhood_base_inline_impl.hh b/src/model/common/non_local_toolbox/neighborhood_base_inline_impl.hh
index a3e09747e..c84342848 100644
--- a/src/model/common/non_local_toolbox/neighborhood_base_inline_impl.hh
+++ b/src/model/common/non_local_toolbox/neighborhood_base_inline_impl.hh
@@ -1,51 +1,51 @@
/**
* @file neighborhood_base_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Wed Jan 31 2018
*
* @brief Inline implementation of neighborhood base functions
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_grid_dynamic.hh"
#include "neighborhood_base.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NEIGHBORHOOD_BASE_INLINE_IMPL_HH_
#define AKANTU_NEIGHBORHOOD_BASE_INLINE_IMPL_HH_
namespace akantu {
inline void
NeighborhoodBase::insertIntegrationPoint(const IntegrationPoint & quad,
- const Vector<Real> & coords) {
+ const Ref<VectorXr> & coords) {
this->spatial_grid->insert(quad, coords);
}
} // namespace akantu
#endif /* AKANTU_NEIGHBORHOOD_BASE_INLINE_IMPL_HH_ */
diff --git a/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc
index ac2e0d853..c467a3607 100644
--- a/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc
+++ b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc
@@ -1,291 +1,291 @@
/**
* @file neighborhood_max_criterion.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Thu Oct 15 2015
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of class NeighborhoodMaxCriterion
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "neighborhood_max_criterion.hh"
#include "grid_synchronizer.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NeighborhoodMaxCriterion::NeighborhoodMaxCriterion(
Model & model, const ElementTypeMapReal & quad_coordinates,
const ID & criterion_id, const ID & id)
: NeighborhoodBase(model, quad_coordinates, id),
Parsable(ParserType::_non_local, id), is_highest("is_highest", id),
criterion(criterion_id, id) {
AKANTU_DEBUG_IN();
this->registerParam("radius", neighborhood_radius, 100.,
_pat_parsable | _pat_readable, "Non local radius");
- Mesh & mesh = this->model.getMesh();
+ auto & mesh = this->model.getMesh();
/// allocate the element type map arrays for _not_ghosts: One entry per quad
GhostType ghost_type = _not_ghost;
for (auto type : mesh.elementTypes(spatial_dimension, ghost_type)) {
- UInt new_size = this->quad_coordinates(type, ghost_type).size();
+ auto new_size = this->quad_coordinates(type, ghost_type).size();
this->is_highest.alloc(new_size, 1, type, ghost_type, true);
this->criterion.alloc(new_size, 1, type, ghost_type, 1.);
}
/// criterion needs allocation also for ghost
ghost_type = _ghost;
for (auto type : mesh.elementTypes(spatial_dimension, ghost_type)) {
- UInt new_size = this->quad_coordinates(type, ghost_type).size();
- this->criterion.alloc(new_size, 1, type, ghost_type, 1.);
+ auto new_size = this->quad_coordinates(type, ghost_type).size();
+ this->criterion.alloc(new_size, 1, type, ghost_type, true);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
NeighborhoodMaxCriterion::~NeighborhoodMaxCriterion() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NeighborhoodMaxCriterion::initNeighborhood() {
AKANTU_DEBUG_IN();
/// parse the input parameter
- const Parser & parser = getStaticParser();
- const ParserSection & section_neighborhood =
+ const auto & parser = getStaticParser();
+ const auto & section_neighborhood =
*(parser.getSubSections(ParserType::_neighborhood).first);
this->parseSection(section_neighborhood);
AKANTU_DEBUG_INFO("Creating the grid");
this->createGrid();
/// insert the non-ghost quads into the grid
this->insertAllQuads(_not_ghost);
/// store the number of current ghost elements for each type in the mesh
- ElementTypeMap<UInt> nb_ghost_protected;
- Mesh & mesh = this->model.getMesh();
+ ElementTypeMap<Int> nb_ghost_protected;
+ auto & mesh = this->model.getMesh();
for (auto type : mesh.elementTypes(spatial_dimension, _ghost)) {
nb_ghost_protected(mesh.getNbElement(type, _ghost), type, _ghost);
}
/// create the grid synchronizer
this->createGridSynchronizer();
/// insert the ghost quads into the grid
this->insertAllQuads(_ghost);
/// create the pair lists
this->updatePairList();
/// remove the unneccessary ghosts
this->cleanupExtraGhostElements(nb_ghost_protected);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NeighborhoodMaxCriterion::createGridSynchronizer() {
this->is_creating_grid = true;
std::set<SynchronizationTag> tags;
tags.insert(SynchronizationTag::_nh_criterion);
std::stringstream sstr;
sstr << id << ":grid_synchronizer";
this->grid_synchronizer = std::make_unique<GridSynchronizer>(
this->model.getMesh(), *spatial_grid, *this, tags, sstr.str(), false);
this->is_creating_grid = false;
}
/* -------------------------------------------------------------------------- */
void NeighborhoodMaxCriterion::insertAllQuads(GhostType ghost_type) {
IntegrationPoint q;
q.ghost_type = ghost_type;
Mesh & mesh = this->model.getMesh();
for (auto type : mesh.elementTypes(spatial_dimension, ghost_type)) {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- UInt nb_quad =
+ Int nb_element = mesh.getNbElement(type, ghost_type);
+ Int nb_quad =
this->model.getFEEngine().getNbIntegrationPoints(type, ghost_type);
const Array<Real> & quads = this->quad_coordinates(type, ghost_type);
q.type = type;
auto quad = quads.begin(spatial_dimension);
- for (UInt e = 0; e < nb_element; ++e) {
+ for (Int e = 0; e < nb_element; ++e) {
q.element = e;
- for (UInt nq = 0; nq < nb_quad; ++nq) {
+ for (Int nq = 0; nq < nb_quad; ++nq) {
q.num_point = nq;
q.global_num = q.element * nb_quad + nq;
spatial_grid->insert(q, *quad);
++quad;
}
}
}
}
/* -------------------------------------------------------------------------- */
void NeighborhoodMaxCriterion::findMaxQuads(
std::vector<IntegrationPoint> & max_quads) {
AKANTU_DEBUG_IN();
/// clear the element type maps
this->is_highest.zero();
this->criterion.zero();
/// update the values of the criterion
this->model.updateDataForNonLocalCriterion(criterion);
/// start the exchange the value of the criterion on the ghost elements
this->model.asynchronousSynchronize(SynchronizationTag::_nh_criterion);
/// compare to not-ghost neighbors
checkNeighbors(_not_ghost);
/// finish the exchange
this->model.waitEndSynchronize(SynchronizationTag::_nh_criterion);
/// compare to ghost neighbors
checkNeighbors(_ghost);
/// extract the quads with highest criterion in their neighborhood
IntegrationPoint quad;
quad.ghost_type = _not_ghost;
Mesh & mesh = this->model.getMesh();
for (auto type : mesh.elementTypes(spatial_dimension, _not_ghost)) {
quad.type = type;
- UInt nb_quadrature_points =
+ Int nb_quadrature_points =
this->model.getFEEngine().getNbIntegrationPoints(type, _not_ghost);
/// loop over is_highest for the current element type
for (auto data : enumerate(is_highest(type, _not_ghost))) {
const auto & is_highest = std::get<1>(data);
if (is_highest) {
auto q = std::get<0>(data);
/// gauss point has the highest stress in his neighbourhood
quad.element = q / nb_quadrature_points;
quad.global_num = q;
quad.num_point = q % nb_quadrature_points;
max_quads.push_back(quad);
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NeighborhoodMaxCriterion::checkNeighbors(GhostType ghost_type2) {
AKANTU_DEBUG_IN();
// Compute the weights
for (auto & pair : pair_list[ghost_type2]) {
const auto & lq1 = pair.first;
const auto & lq2 = pair.second;
Array<bool> & has_highest_eq_stress_1 =
is_highest(lq1.type, lq1.ghost_type);
const Array<Real> & criterion_1 = this->criterion(lq1.type, lq1.ghost_type);
const Array<Real> & criterion_2 = this->criterion(lq2.type, lq2.ghost_type);
if (criterion_1(lq1.global_num) < criterion_2(lq2.global_num)) {
has_highest_eq_stress_1(lq1.global_num) = false;
} else if (ghost_type2 != _ghost) {
Array<bool> & has_highest_eq_stress_2 =
is_highest(lq2.type, lq2.ghost_type);
has_highest_eq_stress_2(lq2.global_num) = false;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NeighborhoodMaxCriterion::cleanupExtraGhostElements(
- const ElementTypeMap<UInt> & nb_ghost_protected) {
+ const ElementTypeMap<Int> & nb_ghost_protected) {
- Mesh & mesh = this->model.getMesh();
+ auto & mesh = this->model.getMesh();
/// create remove elements event
RemovedElementsEvent remove_elem(mesh);
/// create set of ghosts to keep
std::set<Element> relevant_ghost_elements;
for (auto & pair : pair_list[_ghost]) {
const auto & q2 = pair.second;
relevant_ghost_elements.insert(q2);
}
Array<Element> ghosts_to_erase(0);
Element element;
element.ghost_type = _ghost;
auto end = relevant_ghost_elements.end();
for (const auto & type : mesh.elementTypes(spatial_dimension, _ghost)) {
element.type = type;
- UInt nb_ghost_elem = mesh.getNbElement(type, _ghost);
- UInt nb_ghost_elem_protected = 0;
+ auto nb_ghost_elem = mesh.getNbElement(type, _ghost);
+ decltype(nb_ghost_elem) nb_ghost_elem_protected = 0;
try {
nb_ghost_elem_protected = nb_ghost_protected(type, _ghost);
} catch (...) {
}
if (!remove_elem.getNewNumbering().exists(type, _ghost)) {
remove_elem.getNewNumbering().alloc(nb_ghost_elem, 1, type, _ghost);
} else {
remove_elem.getNewNumbering(type, _ghost).resize(nb_ghost_elem);
}
- Array<UInt> & new_numbering = remove_elem.getNewNumbering(type, _ghost);
- for (UInt g = 0; g < nb_ghost_elem; ++g) {
+ auto & new_numbering = remove_elem.getNewNumbering(type, _ghost);
+ for (Int g = 0; g < nb_ghost_elem; ++g) {
element.element = g;
if (element.element >= nb_ghost_elem_protected &&
relevant_ghost_elements.find(element) == end) {
ghosts_to_erase.push_back(element);
- new_numbering(element.element) = UInt(-1);
+ new_numbering(element.element) = -1;
}
}
/// renumber remaining ghosts
- UInt ng = 0;
- for (UInt g = 0; g < nb_ghost_elem; ++g) {
- if (new_numbering(g) != UInt(-1)) {
+ Int ng = 0;
+ for (Int g = 0; g < nb_ghost_elem; ++g) {
+ if (new_numbering(g) != Int(-1)) {
new_numbering(g) = ng;
++ng;
}
}
}
mesh.sendEvent(remove_elem);
this->onElementsRemoved(ghosts_to_erase, remove_elem.getNewNumbering(),
remove_elem);
}
} // namespace akantu
diff --git a/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh
index 4c7b751d2..7b0ecc268 100644
--- a/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh
+++ b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh
@@ -1,115 +1,115 @@
/**
* @file neighborhood_max_criterion.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Neighborhood to find a maximum value in a neighborhood
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NEIGHBORHOOD_MAX_CRITERION_BASE_HH_
#define AKANTU_NEIGHBORHOOD_MAX_CRITERION_BASE_HH_
/* -------------------------------------------------------------------------- */
#include "neighborhood_base.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class NeighborhoodMaxCriterion : public NeighborhoodBase, public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NeighborhoodMaxCriterion(Model & model,
const ElementTypeMapReal & quad_coordinates,
const ID & criterion_id,
const ID & id = "neighborhood_max_criterion");
~NeighborhoodMaxCriterion() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the neighborhood
void initNeighborhood() override;
/// create grid synchronizer and exchange ghost cells
void createGridSynchronizer() override;
/// find the quads which have the maximum criterion in their neighborhood
void findMaxQuads(std::vector<IntegrationPoint> & max_quads);
protected:
/// remove unneccessary ghost elements
void
- cleanupExtraGhostElements(const ElementTypeMap<UInt> & nb_ghost_protected);
+ cleanupExtraGhostElements(const ElementTypeMap<Int> & nb_ghost_protected);
/// insert the quadrature points in the grid
void insertAllQuads(GhostType ghost_type);
/// compare criterion with neighbors
void checkNeighbors(GhostType ghost_type);
/* --------------------------------------------------------------------------
*/
/* DataAccessor inherited members */
/* --------------------------------------------------------------------------
*/
public:
- virtual inline UInt getNbDataForElements(const Array<Element> & elements,
+ virtual inline Int getNbDataForElements(const Array<Element> & elements,
SynchronizationTag tag) const;
virtual inline void packElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) const;
virtual inline void unpackElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag);
/* -------------------------------------------------------------------------*/
/* Accessors */
/* -------------------------------------------------------------------------*/
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// a boolean to store the information if a quad has the max
/// criterion in the neighborhood
ElementTypeMapArray<bool> is_highest;
/// an element type map to store the flattened internal of the criterion
ElementTypeMapReal criterion;
};
} // namespace akantu
#include "neighborhood_max_criterion_inline_impl.hh"
#endif /* AKANTU_NEIGHBORHOOD_MAX_CRITERION_BASE_HH_ */
diff --git a/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh
index 5cf323a24..a42899cf4 100644
--- a/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh
+++ b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh
@@ -1,83 +1,83 @@
/**
* @file neighborhood_max_criterion_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of inline functions for class NeighborhoodMaxCriterion
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "model.hh"
-#include "neighborhood_max_criterion.hh"
+//#include "neighborhood_max_criterion.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NEIGHBORHOOD_MAX_CRITERION_INLINE_IMPL_HH_
#define AKANTU_NEIGHBORHOOD_MAX_CRITERION_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt
+inline Int
NeighborhoodMaxCriterion::getNbDataForElements(const Array<Element> & elements,
SynchronizationTag tag) const {
- UInt nb_quadrature_points = this->model.getNbIntegrationPoints(elements);
- UInt size = 0;
+ auto nb_quadrature_points = this->model.getNbIntegrationPoints(elements);
+ Int size = 0;
if (tag == SynchronizationTag::_nh_criterion) {
size += sizeof(Real) * nb_quadrature_points;
}
return size;
}
/* -------------------------------------------------------------------------- */
inline void
NeighborhoodMaxCriterion::packElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) const {
if (tag == SynchronizationTag::_nh_criterion) {
NeighborhoodMaxCriterion::packElementalDataHelper(
criterion, buffer, elements, true, this->model.getFEEngine());
}
}
/* -------------------------------------------------------------------------- */
inline void
NeighborhoodMaxCriterion::unpackElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) {
if (tag == SynchronizationTag::_nh_criterion) {
NeighborhoodMaxCriterion::unpackElementalDataHelper(
criterion, buffer, elements, true, this->model.getFEEngine());
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_NEIGHBORHOOD_MAX_CRITERION_INLINE_IMPL_HH_ */
diff --git a/src/model/common/non_local_toolbox/non_local_manager.cc b/src/model/common/non_local_toolbox/non_local_manager.cc
index 6ff6af7b6..629ad3adf 100644
--- a/src/model/common/non_local_toolbox/non_local_manager.cc
+++ b/src/model/common/non_local_toolbox/non_local_manager.cc
@@ -1,655 +1,572 @@
/**
* @file non_local_manager.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Apr 13 2012
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of non-local manager
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_local_manager.hh"
+#include "base_weight_function.hh"
#include "grid_synchronizer.hh"
+#include "integrator.hh"
#include "model.hh"
#include "non_local_neighborhood.hh"
/* -------------------------------------------------------------------------- */
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NonLocalManager::NonLocalManager(Model & model,
NonLocalManagerCallback & callback,
const ID & id)
: Parsable(ParserType::_neighborhoods, id),
spatial_dimension(model.getMesh().getSpatialDimension()), id(id),
model(model),
integration_points_positions("integration_points_positions", id),
volumes("volumes", id), compute_stress_calls(0), dummy_registry(nullptr),
dummy_grid(nullptr) {
/// parse the neighborhood information from the input file
const Parser & parser = getStaticParser();
/// iterate over all the non-local sections and store them in a map
std::pair<Parser::const_section_iterator, Parser::const_section_iterator>
weight_sect = parser.getSubSections(ParserType::_non_local);
Parser::const_section_iterator it = weight_sect.first;
for (; it != weight_sect.second; ++it) {
const ParserSection & section = *it;
ID name = section.getName();
this->weight_function_types[name] = section;
}
this->callback = &callback;
}
/* -------------------------------------------------------------------------- */
NonLocalManager::~NonLocalManager() = default;
/* -------------------------------------------------------------------------- */
void NonLocalManager::initialize() {
volumes.initialize(this->model.getFEEngine(),
_spatial_dimension = spatial_dimension);
AKANTU_DEBUG_ASSERT(this->callback,
"A callback should be registered prior to this call");
this->callback->insertIntegrationPointsInNeighborhoods(_not_ghost);
auto & mesh = this->model.getMesh();
mesh.registerEventHandler(*this, _ehp_non_local_manager);
- /// store the number of current ghost elements for each type in the mesh
- // ElementTypeMap<UInt> nb_ghost_protected;
- // for (auto type : mesh.elementTypes(spatial_dimension, _ghost))
- // nb_ghost_protected(mesh.getNbElement(type, _ghost), type, _ghost);
-
/// exchange the missing ghosts for the non-local neighborhoods
this->createNeighborhoodSynchronizers();
/// insert the ghost quadrature points of the non-local materials into the
/// non-local neighborhoods
this->callback->insertIntegrationPointsInNeighborhoods(_ghost);
FEEngine & fee = this->model.getFEEngine();
this->updatePairLists();
/// cleanup the unneccessary ghost elements
this->cleanupExtraGhostElements(); // nb_ghost_protected);
this->callback->initializeNonLocal();
this->setJacobians(fee, _ek_regular);
this->initNonLocalVariables();
this->computeWeights();
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::setJacobians(const FEEngine & fe_engine,
- ElementKind kind) {
- Mesh & mesh = this->model.getMesh();
- for (auto ghost_type : ghost_types) {
- for (auto type : mesh.elementTypes(spatial_dimension, ghost_type, kind)) {
- jacobians(type, ghost_type) =
- &fe_engine.getIntegratorInterface().getJacobians(type, ghost_type);
- }
- }
+ ElementKind /*kind*/) {
+ jacobians = &(fe_engine.getIntegratorInterface().getJacobians());
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::createNeighborhood(const ID & weight_func,
const ID & neighborhood_id) {
AKANTU_DEBUG_IN();
auto weight_func_it = this->weight_function_types.find(weight_func);
AKANTU_DEBUG_ASSERT(weight_func_it != weight_function_types.end(),
"No info found in the input file for the weight_function "
<< weight_func << " in the neighborhood "
<< neighborhood_id);
const ParserSection & section = weight_func_it->second;
const ID weight_func_type = section.getOption();
+
/// create new neighborhood for given ID
- std::stringstream sstr;
- sstr << id << ":neighborhood:" << neighborhood_id;
-
- if (weight_func_type == "base_wf") {
- neighborhoods[neighborhood_id] =
- std::make_unique<NonLocalNeighborhood<BaseWeightFunction>>(
- *this, this->integration_points_positions, sstr.str());
-#if defined(AKANTU_DAMAGE_NON_LOCAL)
- } else if (weight_func_type == "remove_wf") {
- neighborhoods[neighborhood_id] =
- std::make_unique<NonLocalNeighborhood<RemoveDamagedWeightFunction>>(
- *this, this->integration_points_positions, sstr.str());
- } else if (weight_func_type == "stress_wf") {
- neighborhoods[neighborhood_id] =
- std::make_unique<NonLocalNeighborhood<StressBasedWeightFunction>>(
- *this, this->integration_points_positions, sstr.str());
- } else if (weight_func_type == "damage_wf") {
- neighborhoods[neighborhood_id] =
- std::make_unique<NonLocalNeighborhood<DamagedWeightFunction>>(
- *this, this->integration_points_positions, sstr.str());
-#endif
- } else {
- AKANTU_EXCEPTION("error in weight function type provided in material file");
- }
+ neighborhoods[neighborhood_id] =
+ NonLocalNeighborhoodFactory::getInstance().allocate(
+ weight_func_type, neighborhood_id, *this,
+ this->integration_points_positions,
+ id + ":neighborhood:" + neighborhood_id);
neighborhoods[neighborhood_id]->parseSection(section);
neighborhoods[neighborhood_id]->initNeighborhood();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::createNeighborhoodSynchronizers() {
/// exchange all the neighborhood IDs, so that every proc knows how many
/// neighborhoods exist globally
/// First: Compute locally the maximum ID size
- UInt max_id_size = 0;
- UInt current_size = 0;
+ Int max_id_size = 0;
+ Int current_size = 0;
NeighborhoodMap::const_iterator it;
- for (it = neighborhoods.begin(); it != neighborhoods.end(); ++it) {
- current_size = it->first.size();
+ for (const auto & id : make_keys_adaptor(neighborhoods)) {
+ current_size = id.size();
if (current_size > max_id_size) {
max_id_size = current_size;
}
}
/// get the global maximum ID size on each proc
const Communicator & static_communicator = model.getMesh().getCommunicator();
static_communicator.allReduce(max_id_size, SynchronizerOperation::_max);
/// get the rank for this proc and the total nb proc
- UInt prank = static_communicator.whoAmI();
- UInt psize = static_communicator.getNbProc();
+ Int prank = static_communicator.whoAmI();
+ Int psize = static_communicator.getNbProc();
/// exchange the number of neighborhoods on each proc
Array<Int> nb_neighborhoods_per_proc(psize);
nb_neighborhoods_per_proc(prank) = neighborhoods.size();
static_communicator.allGather(nb_neighborhoods_per_proc);
/// compute the total number of neighborhoods
- UInt nb_neighborhoods_global = std::accumulate(
+ Int nb_neighborhoods_global = std::accumulate(
nb_neighborhoods_per_proc.begin(), nb_neighborhoods_per_proc.end(), 0);
/// allocate an array of chars to store the names of all neighborhoods
Array<char> buffer(nb_neighborhoods_global, max_id_size);
/// starting index on this proc
- UInt starting_index =
+ Int starting_index =
std::accumulate(nb_neighborhoods_per_proc.begin(),
nb_neighborhoods_per_proc.begin() + prank, 0);
- it = neighborhoods.begin();
/// store the names of local neighborhoods in the buffer
- for (UInt i = 0; i < neighborhoods.size(); ++i, ++it) {
- UInt c = 0;
- for (; c < it->first.size(); ++c) {
- buffer(i + starting_index, c) = it->first[c];
+ for (auto && data : enumerate(make_keys_adaptor(neighborhoods))) {
+ Int c = 0;
+ auto i = std::get<0>(data);
+ const auto & id = std::get<1>(data);
+ for (; c < Int(id.size()); ++c) {
+ buffer(i + starting_index, c) = id[c];
}
for (; c < max_id_size; ++c) {
buffer(i + starting_index, c) = char(0);
}
}
/// store the nb of data to send in the all gather
Array<Int> buffer_size(nb_neighborhoods_per_proc);
buffer_size *= max_id_size;
/// exchange the names of all the neighborhoods with all procs
static_communicator.allGatherV(buffer, buffer_size);
- for (UInt i = 0; i < nb_neighborhoods_global; ++i) {
+ for (Int i = 0; i < nb_neighborhoods_global; ++i) {
std::stringstream neighborhood_id;
- for (UInt c = 0; c < max_id_size; ++c) {
+ for (Int c = 0; c < max_id_size; ++c) {
if (buffer(i, c) == char(0)) {
break;
}
neighborhood_id << buffer(i, c);
}
global_neighborhoods.insert(neighborhood_id.str());
}
/// this proc does not know all the neighborhoods -> create dummy
/// grid so that this proc can participate in the all gather for
/// detecting the overlap of neighborhoods this proc doesn't know
- Vector<Real> grid_center(this->spatial_dimension,
- std::numeric_limits<Real>::max());
- Vector<Real> spacing(this->spatial_dimension, 0.);
+ Vector<Real> grid_center(this->spatial_dimension);
+ grid_center.fill(std::numeric_limits<Real>::max());
+ Vector<Real> spacing(this->spatial_dimension);
+ spacing.fill(0.);
dummy_grid = std::make_unique<SpatialGrid<IntegrationPoint>>(
this->spatial_dimension, spacing, grid_center);
for (const auto & neighborhood_id : global_neighborhoods) {
it = neighborhoods.find(neighborhood_id);
if (it != neighborhoods.end()) {
it->second->createGridSynchronizer();
} else {
dummy_synchronizers[neighborhood_id] = std::make_unique<GridSynchronizer>(
this->model.getMesh(), *dummy_grid,
std::string(this->id + ":" + neighborhood_id + ":grid_synchronizer"),
false);
}
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::synchronize(DataAccessor<Element> & data_accessor,
const SynchronizationTag & tag) {
for (const auto & neighborhood_id : global_neighborhoods) {
auto it = neighborhoods.find(neighborhood_id);
if (it != neighborhoods.end()) {
it->second->synchronize(data_accessor, tag);
} else {
auto synchronizer_it = dummy_synchronizers.find(neighborhood_id);
if (synchronizer_it == dummy_synchronizers.end()) {
continue;
}
synchronizer_it->second->synchronizeOnce(data_accessor, tag);
}
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::averageInternals(GhostType ghost_type) {
/// update the weights of the weight function
if (ghost_type == _not_ghost) {
this->computeWeights();
}
/// loop over all neighborhoods and compute the non-local variables
for (auto & neighborhood : neighborhoods) {
/// loop over all the non-local variables of the given neighborhood
for (auto & non_local_variable : non_local_variables) {
NonLocalVariable & non_local_var = *non_local_variable.second;
neighborhood.second->weightedAverageOnNeighbours(
non_local_var.local, non_local_var.non_local,
non_local_var.nb_component, ghost_type);
}
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::computeWeights() {
AKANTU_DEBUG_IN();
this->updateWeightFunctionInternals();
this->volumes.zero();
for (const auto & global_neighborhood : global_neighborhoods) {
auto it = neighborhoods.find(global_neighborhood);
if (it != neighborhoods.end()) {
it->second->updateWeights();
} else {
dummy_synchronizers[global_neighborhood]->synchronize(
dummy_accessor, SynchronizationTag::_mnl_weight);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::updatePairLists() {
AKANTU_DEBUG_IN();
integration_points_positions.initialize(
this->model.getFEEngine(), _nb_component = spatial_dimension,
_spatial_dimension = spatial_dimension);
/// compute the position of the quadrature points
this->model.getFEEngine().computeIntegrationPointsCoordinates(
integration_points_positions);
- for (auto & pair : neighborhoods) {
- pair.second->updatePairList();
+ for (auto & neighborhood : make_values_adaptor(neighborhoods)) {
+ neighborhood->updatePairList();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::registerNonLocalVariable(const ID & variable_name,
const ID & nl_variable_name,
UInt nb_component) {
AKANTU_DEBUG_IN();
auto non_local_variable_it = non_local_variables.find(variable_name);
if (non_local_variable_it == non_local_variables.end()) {
non_local_variables[nl_variable_name] = std::make_unique<NonLocalVariable>(
variable_name, nl_variable_name, this->id, nb_component);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
ElementTypeMapReal &
NonLocalManager::registerWeightFunctionInternal(const ID & field_name) {
AKANTU_DEBUG_IN();
auto it = this->weight_function_internals.find(field_name);
if (it == weight_function_internals.end()) {
weight_function_internals[field_name] =
std::make_unique<ElementTypeMapReal>(field_name, this->id);
}
AKANTU_DEBUG_OUT();
return *(weight_function_internals[field_name]);
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::updateWeightFunctionInternals() {
for (auto & pair : this->weight_function_internals) {
auto & internals = *pair.second;
internals.zero();
for (auto ghost_type : ghost_types) {
this->callback->updateLocalInternal(internals, ghost_type, _ek_regular);
}
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::initNonLocalVariables() {
/// loop over all the non-local variables
for (auto & pair : non_local_variables) {
auto & variable = *pair.second;
variable.non_local.initialize(this->model.getFEEngine(),
_nb_component = variable.nb_component,
_spatial_dimension = spatial_dimension);
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::computeAllNonLocalStresses() {
/// update the flattened version of the internals
for (auto & pair : non_local_variables) {
auto & variable = *pair.second;
variable.local.zero();
variable.non_local.zero();
for (auto ghost_type : ghost_types) {
this->callback->updateLocalInternal(variable.local, ghost_type,
_ek_regular);
}
}
this->volumes.zero();
for (auto & pair : neighborhoods) {
auto & neighborhood = *pair.second;
neighborhood.asynchronousSynchronize(SynchronizationTag::_mnl_for_average);
}
this->averageInternals(_not_ghost);
AKANTU_DEBUG_INFO("Wait distant non local stresses");
for (auto & pair : neighborhoods) {
auto & neighborhood = *pair.second;
neighborhood.waitEndSynchronize(SynchronizationTag::_mnl_for_average);
}
this->averageInternals(_ghost);
/// copy the results in the materials
for (auto & pair : non_local_variables) {
auto & variable = *pair.second;
for (auto ghost_type : ghost_types) {
this->callback->updateNonLocalInternal(variable.non_local, ghost_type,
_ek_regular);
}
}
this->callback->computeNonLocalStresses(_not_ghost);
++this->compute_stress_calls;
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::cleanupExtraGhostElements() {
- // ElementTypeMap<UInt> & nb_ghost_protected) {
-
using ElementSet = std::set<Element>;
ElementSet relevant_ghost_elements;
/// loop over all the neighborhoods and get their protected ghosts
for (auto & pair : neighborhoods) {
auto & neighborhood = *pair.second;
ElementSet to_keep_per_neighborhood;
neighborhood.getRelevantGhostElements(to_keep_per_neighborhood);
relevant_ghost_elements.insert(to_keep_per_neighborhood.begin(),
to_keep_per_neighborhood.end());
}
for (auto & pair : neighborhoods) {
auto & neighborhood = *pair.second;
neighborhood.cleanupExtraGhostElements(relevant_ghost_elements);
}
-
- // /// remove all unneccessary ghosts from the mesh
- // /// Create list of element to remove and new numbering for element to keep
- // Mesh & mesh = this->model.getMesh();
- // ElementSet ghost_to_erase;
-
- // RemovedElementsEvent remove_elem(mesh);
- // auto & new_numberings = remove_elem.getNewNumbering();
- // Element element;
- // element.ghost_type = _ghost;
-
- // for (auto & type : mesh.elementTypes(spatial_dimension, _ghost)) {
- // element.type = type;
- // UInt nb_ghost_elem = mesh.getNbElement(type, _ghost);
- // // UInt nb_ghost_elem_protected = 0;
- // // try {
- // // nb_ghost_elem_protected = nb_ghost_protected(type, _ghost);
- // // } catch (...) {
- // // }
-
- // if (!new_numberings.exists(type, _ghost))
- // new_numberings.alloc(nb_ghost_elem, 1, type, _ghost);
- // else
- // new_numberings(type, _ghost).resize(nb_ghost_elem);
-
- // Array<UInt> & new_numbering = new_numberings(type, _ghost);
- // for (UInt g = 0; g < nb_ghost_elem; ++g) {
- // element.element = g;
- // if (element.element >= nb_ghost_elem_protected &&
- // relevant_ghost_elements.find(element) ==
- // relevant_ghost_elements.end()) {
- // remove_elem.getList().push_back(element);
- // new_numbering(element.element) = UInt(-1);
- // }
- // }
- // /// renumber remaining ghosts
- // UInt ng = 0;
- // for (UInt g = 0; g < nb_ghost_elem; ++g) {
- // if (new_numbering(g) != UInt(-1)) {
- // new_numbering(g) = ng;
- // ++ng;
- // }
- // }
- // }
-
- // for (auto & type : mesh.elementTypes(spatial_dimension, _not_ghost)) {
- // UInt nb_elem = mesh.getNbElement(type, _not_ghost);
- // if (!new_numberings.exists(type, _not_ghost))
- // new_numberings.alloc(nb_elem, 1, type, _not_ghost);
- // Array<UInt> & new_numbering = new_numberings(type, _not_ghost);
- // for (UInt e = 0; e < nb_elem; ++e) {
- // new_numbering(e) = e;
- // }
- // }
- // mesh.sendEvent(remove_elem);
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::onElementsRemoved(
const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
- __attribute__((unused)) const RemovedElementsEvent & event) {
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent & event) {
FEEngine & fee = this->model.getFEEngine();
NonLocalManager::removeIntegrationPointsFromMap(
event.getNewNumbering(), spatial_dimension, integration_points_positions,
fee, _ek_regular);
NonLocalManager::removeIntegrationPointsFromMap(event.getNewNumbering(), 1,
volumes, fee, _ek_regular);
/// loop over all the neighborhoods and call onElementsRemoved
auto global_neighborhood_it = global_neighborhoods.begin();
NeighborhoodMap::iterator it;
for (; global_neighborhood_it != global_neighborhoods.end();
++global_neighborhood_it) {
it = neighborhoods.find(*global_neighborhood_it);
if (it != neighborhoods.end()) {
it->second->onElementsRemoved(element_list, new_numbering, event);
} else {
dummy_synchronizers[*global_neighborhood_it]->onElementsRemoved(
element_list, new_numbering, event);
}
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::onElementsAdded(const Array<Element> & /*unused*/,
const NewElementsEvent & /*unused*/) {
this->resizeElementTypeMap(1, volumes, model.getFEEngine());
this->resizeElementTypeMap(spatial_dimension, integration_points_positions,
model.getFEEngine());
}
/* -------------------------------------------------------------------------- */
-void NonLocalManager::resizeElementTypeMap(UInt nb_component,
+void NonLocalManager::resizeElementTypeMap(Int nb_component,
ElementTypeMapReal & element_map,
const FEEngine & fee,
const ElementKind el_kind) {
- Mesh & mesh = this->model.getMesh();
+ auto & mesh = this->model.getMesh();
for (auto gt : ghost_types) {
for (auto type : mesh.elementTypes(spatial_dimension, gt, el_kind)) {
- UInt nb_element = mesh.getNbElement(type, gt);
- UInt nb_quads = fee.getNbIntegrationPoints(type, gt);
+ auto nb_element = mesh.getNbElement(type, gt);
+ auto nb_quads = fee.getNbIntegrationPoints(type, gt);
if (!element_map.exists(type, gt)) {
element_map.alloc(nb_element * nb_quads, nb_component, type, gt);
} else {
element_map(type, gt).resize(nb_element * nb_quads);
}
}
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::removeIntegrationPointsFromMap(
- const ElementTypeMapArray<UInt> & new_numbering, UInt nb_component,
+ const ElementTypeMapArray<Idx> & new_numbering, Int nb_component,
ElementTypeMapReal & element_map, const FEEngine & fee,
const ElementKind el_kind) {
for (auto gt : ghost_types) {
for (auto type : new_numbering.elementTypes(_all_dimensions, gt, el_kind)) {
if (element_map.exists(type, gt)) {
- const Array<UInt> & renumbering = new_numbering(type, gt);
+ const auto & renumbering = new_numbering(type, gt);
- Array<Real> & vect = element_map(type, gt);
- UInt nb_quad_per_elem = fee.getNbIntegrationPoints(type, gt);
+ auto & vect = element_map(type, gt);
+ auto nb_quad_per_elem = fee.getNbIntegrationPoints(type, gt);
Array<Real> tmp(renumbering.size() * nb_quad_per_elem, nb_component);
AKANTU_DEBUG_ASSERT(
tmp.size() == vect.size(),
"Something strange append some mater was created or disappeared in "
<< vect.getID() << "(" << vect.size() << "!=" << tmp.size()
<< ") "
"!!");
- UInt new_size = 0;
- for (UInt i = 0; i < renumbering.size(); ++i) {
- UInt new_i = renumbering(i);
- if (new_i != UInt(-1)) {
- memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem,
- vect.storage() + i * nb_component * nb_quad_per_elem,
+ Int new_size = 0;
+ for (Int i = 0; i < renumbering.size(); ++i) {
+ auto new_i = renumbering(i);
+ if (new_i != Int(-1)) {
+ memcpy(tmp.data() + new_i * nb_component * nb_quad_per_elem,
+ vect.data() + i * nb_component * nb_quad_per_elem,
nb_component * nb_quad_per_elem * sizeof(Real));
++new_size;
}
}
tmp.resize(new_size * nb_quad_per_elem);
vect.copy(tmp);
}
}
}
}
/* -------------------------------------------------------------------------- */
-UInt NonLocalManager::getNbData(const Array<Element> & elements,
- const ID & id) const {
- UInt size = 0;
- UInt nb_quadrature_points = this->model.getNbIntegrationPoints(elements);
+Int NonLocalManager::getNbData(const Array<Element> & elements,
+ const ID & id) const {
+ Int size = 0;
+ auto nb_quadrature_points = this->model.getNbIntegrationPoints(elements);
auto it = non_local_variables.find(id);
AKANTU_DEBUG_ASSERT(it != non_local_variables.end(),
"The non-local variable " << id << " is not registered");
size += it->second->nb_component * sizeof(Real) * nb_quadrature_points;
return size;
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const ID & id) const {
-
auto it = non_local_variables.find(id);
AKANTU_DEBUG_ASSERT(it != non_local_variables.end(),
"The non-local variable " << id << " is not registered");
DataAccessor<Element>::packElementalDataHelper<Real>(
it->second->local, buffer, elements, true, this->model.getFEEngine());
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const ID & id) const {
auto it = non_local_variables.find(id);
AKANTU_DEBUG_ASSERT(it != non_local_variables.end(),
"The non-local variable " << id << " is not registered");
DataAccessor<Element>::unpackElementalDataHelper<Real>(
it->second->local, buffer, elements, true, this->model.getFEEngine());
}
} // namespace akantu
diff --git a/src/model/common/non_local_toolbox/non_local_manager.hh b/src/model/common/non_local_toolbox/non_local_manager.hh
index e2753908e..b98527347 100644
--- a/src/model/common/non_local_toolbox/non_local_manager.hh
+++ b/src/model/common/non_local_toolbox/non_local_manager.hh
@@ -1,287 +1,283 @@
/**
* @file non_local_manager.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Classes that manages all the non-local neighborhoods
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communication_buffer.hh"
#include "data_accessor.hh"
#include "mesh_events.hh"
#include "non_local_manager_callback.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
#include <map>
#include <set>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LOCAL_MANAGER_HH_
#define AKANTU_NON_LOCAL_MANAGER_HH_
namespace akantu {
class Model;
class NonLocalNeighborhoodBase;
class GridSynchronizer;
class SynchronizerRegistry;
class IntegrationPoint;
template <typename T> class SpatialGrid;
class FEEngine;
} // namespace akantu
namespace akantu {
class NonLocalManager : public MeshEventHandler, public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NonLocalManager(Model & model, NonLocalManagerCallback & callback,
const ID & id = "non_local_manager");
~NonLocalManager() override;
using NeighborhoodMap =
std::map<ID, std::unique_ptr<NonLocalNeighborhoodBase>>;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ----------------------------------------------------------------------- */
public:
/// register a new internal needed for the weight computations
ElementTypeMapReal & registerWeightFunctionInternal(const ID & field_name);
/// register a non-local variable
void registerNonLocalVariable(const ID & variable_name,
const ID & nl_variable_name, UInt nb_component);
/// register non-local neighborhood
inline void registerNeighborhood(const ID & neighborhood,
const ID & weight_func_id);
// void registerNonLocalManagerCallback(NonLocalManagerCallback & callback);
/// average the internals and compute the non-local stresses
virtual void computeAllNonLocalStresses();
/// initialize the non-local manager: compute pair lists and weights for all
/// neighborhoods
virtual void initialize();
/// synchronize once on a given tag using the neighborhoods synchronizer
void synchronize(DataAccessor<Element> & data_accessor,
const SynchronizationTag & /*tag*/);
protected:
/// create the grid synchronizers for each neighborhood
void createNeighborhoodSynchronizers();
/// compute the weights in each neighborhood for non-local averaging
void computeWeights();
/// compute the weights in each neighborhood for non-local averaging
void updatePairLists();
/// average the non-local variables
void averageInternals(GhostType ghost_type = _not_ghost);
/// update the flattened version of the weight function internals
void updateWeightFunctionInternals();
protected:
/// create a new neighborhood for a given domain ID
void createNeighborhood(const ID & weight_func, const ID & neighborhood);
/// set the values of the jacobians
void setJacobians(const FEEngine & fe_engine, ElementKind kind);
- /// allocation of eelment type maps
- // void initElementTypeMap(UInt nb_component,
- // ElementTypeMapReal & element_map,
- // const FEEngine & fe_engine,
- // const ElementKind el_kind = _ek_regular);
-
/// resizing of element type maps
- void resizeElementTypeMap(UInt nb_component, ElementTypeMapReal & element_map,
+ void resizeElementTypeMap(Int nb_component, ElementTypeMapReal & element_map,
const FEEngine & fee,
ElementKind el_kind = _ek_regular);
/// remove integration points from element type maps
- static void removeIntegrationPointsFromMap(
- const ElementTypeMapArray<UInt> & new_numbering, UInt nb_component,
+ void removeIntegrationPointsFromMap(
+ const ElementTypeMapArray<Idx> & new_numbering, Int nb_component,
ElementTypeMapReal & element_map, const FEEngine & fee,
ElementKind el_kind = _ek_regular);
/// allocate the non-local variables
void initNonLocalVariables();
/// cleanup unneccessary ghosts
void
- cleanupExtraGhostElements(); // ElementTypeMap<UInt> & nb_ghost_protected);
+ cleanupExtraGhostElements(); // ElementTypeMap<Int> & nb_ghost_protected);
/* ------------------------------------------------------------------------ */
/* DataAccessor kind of interface */
/* ------------------------------------------------------------------------ */
public:
/// get Nb data for synchronization in parallel
- UInt getNbData(const Array<Element> & elements, const ID & id) const;
+ Int getNbData(const Array<Element> & elements, const ID & id) const;
/// pack data for synchronization in parallel
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const ID & id) const;
/// unpack data for synchronization in parallel
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const ID & id) const;
/* ------------------------------------------------------------------------ */
/* MeshEventHandler inherited members */
/* ------------------------------------------------------------------------ */
public:
void onElementsRemoved(const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) override;
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
- AKANTU_GET_MACRO(Model, model, const Model &);
- AKANTU_GET_MACRO_NOT_CONST(Model, model, Model &);
- AKANTU_GET_MACRO_NOT_CONST(Volumes, volumes, ElementTypeMapReal &)
- AKANTU_GET_MACRO(NbStressCalls, compute_stress_calls, UInt);
+ AKANTU_GET_MACRO_AUTO(SpatialDimension, spatial_dimension);
+ AKANTU_GET_MACRO_AUTO(Model, model);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Model, model);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Volumes, volumes)
+ AKANTU_GET_MACRO_AUTO(NbStressCalls, compute_stress_calls);
/// return the fem object associated with a provided name
inline NonLocalNeighborhoodBase & getNeighborhood(const ID & name) const;
inline const Array<Real> & getJacobians(ElementType type,
GhostType ghost_type) {
- return *jacobians(type, ghost_type);
+ return (*jacobians)(type, ghost_type);
}
+ inline const ElementTypeMapArray<Real> & getJacobians() { return *jacobians; }
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// the spatial dimension
- const UInt spatial_dimension;
+ const Int spatial_dimension;
ID id;
protected:
/// the non-local neighborhoods present
NeighborhoodMap neighborhoods;
/// list of all the non-local materials in the model
// std::vector<ID> non_local_materials;
struct NonLocalVariable {
NonLocalVariable(const ID & variable_name, const ID & nl_variable_name,
- const ID & id, UInt nb_component)
+ const ID & id, Int nb_component)
: local(variable_name, id), non_local(nl_variable_name, id),
nb_component(nb_component) {}
ElementTypeMapReal local;
ElementTypeMapReal non_local;
- UInt nb_component;
+ Int nb_component;
};
/// the non-local variables associated to a certain neighborhood
std::map<ID, std::unique_ptr<NonLocalVariable>> non_local_variables;
/// reference to the model
Model & model;
/// jacobians for all the elements in the mesh
- ElementTypeMap<const Array<Real> *> jacobians;
+ const ElementTypeMapArray<Real> * jacobians{nullptr};
/// store the position of the quadrature points
ElementTypeMapReal integration_points_positions;
/// store the volume of each quadrature point for the non-local weight
/// normalization
ElementTypeMapReal volumes;
/// counter for computeStress calls
- UInt compute_stress_calls;
+ Int compute_stress_calls;
/// map to store weight function types from input file
std::map<ID, ParserSection> weight_function_types;
/// map to store the internals needed by the weight functions
std::map<ID, std::unique_ptr<ElementTypeMapReal>> weight_function_internals;
/* --------------------------------------------------------------------------
*/
/// the following are members needed to make this processor participate in the
/// grid creation of neighborhoods he doesn't own as a member. For details see
/// createGridSynchronizers function
/// synchronizer registry for dummy grid synchronizers
std::unique_ptr<SynchronizerRegistry> dummy_registry;
/// map of dummy synchronizers
std::map<ID, std::unique_ptr<GridSynchronizer>> dummy_synchronizers;
/// dummy spatial grid
std::unique_ptr<SpatialGrid<IntegrationPoint>> dummy_grid;
/// create a set of all neighborhoods present in the simulation
std::set<ID> global_neighborhoods;
class DummyDataAccessor : public DataAccessor<Element> {
public:
- inline UInt getNbData(const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/) const override {
+ inline Int getNbData(const Array<Element> &,
+ const SynchronizationTag &) const override {
return 0;
};
inline void packData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*element*/,
const SynchronizationTag & /*tag*/) const override{};
inline void unpackData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*element*/,
const SynchronizationTag & /*tag*/) override{};
};
DummyDataAccessor dummy_accessor;
/* ------------------------------------------------------------------------ */
NonLocalManagerCallback * callback;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "non_local_manager_inline_impl.hh"
#endif /* AKANTU_NON_LOCAL_MANAGER_HH_ */
diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood.hh b/src/model/common/non_local_toolbox/non_local_neighborhood.hh
index 15dee5b72..90eede849 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood.hh
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood.hh
@@ -1,134 +1,126 @@
/**
* @file non_local_neighborhood.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Non-local neighborhood for non-local averaging based on
* weight function
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_NON_LOCAL_NEIGHBORHOOD_HH_
-#define AKANTU_NON_LOCAL_NEIGHBORHOOD_HH_
-/* -------------------------------------------------------------------------- */
-#include "base_weight_function.hh"
#include "non_local_neighborhood_base.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
+#ifndef AKANTU_NON_LOCAL_NEIGHBORHOOD_HH_
+#define AKANTU_NON_LOCAL_NEIGHBORHOOD_HH_
+
namespace akantu {
-class NonLocalManager;
class BaseWeightFunction;
+class NonLocalManager;
} // namespace akantu
namespace akantu {
template <class WeightFunction = BaseWeightFunction>
class NonLocalNeighborhood : public NonLocalNeighborhoodBase {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NonLocalNeighborhood(NonLocalManager & manager,
const ElementTypeMapReal & quad_coordinates,
const ID & id = "neighborhood");
~NonLocalNeighborhood() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// compute the weights for non-local averaging
void computeWeights() override;
/// save the pair of weights in a file
void saveWeights(const std::string & filename) const override;
/// compute the non-local counter part for a given element type map
// compute the non-local counter part for a given element type map
void weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate,
ElementTypeMapReal & accumulated,
- UInt nb_degree_of_freedom,
+ Int nb_degree_of_freedom,
GhostType ghost_type2) const override;
/// update the weights based on the weight function
void updateWeights() override;
/// register a new non-local variable in the neighborhood
// void registerNonLocalVariable(const ID & id);
protected:
template <class Func>
inline void foreach_weight(GhostType ghost_type, Func && func);
template <class Func>
inline void foreach_weight(GhostType ghost_type, Func && func) const;
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Accessor */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(NonLocalManager, non_local_manager, const NonLocalManager &);
- AKANTU_GET_MACRO_NOT_CONST(NonLocalManager, non_local_manager,
- NonLocalManager &);
+ AKANTU_GET_MACRO_AUTO(NonLocalManager, non_local_manager);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(NonLocalManager, non_local_manager);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// Pointer to non-local manager class
NonLocalManager & non_local_manager;
/// the weights associated to the pairs
std::array<std::unique_ptr<Array<Real>>, 2> pair_weight;
/// weight function
- std::unique_ptr<WeightFunction> weight_function;
+ std::shared_ptr<WeightFunction> weight_function;
};
} // namespace akantu
-/* -------------------------------------------------------------------------- */
-/* Implementation of template functions */
-/* -------------------------------------------------------------------------- */
-#include "non_local_neighborhood_tmpl.hh"
-/* -------------------------------------------------------------------------- */
-/* inline functions */
-/* -------------------------------------------------------------------------- */
#include "non_local_neighborhood_inline_impl.hh"
+#include "non_local_neighborhood_tmpl.hh"
#endif /* AKANTU_NON_LOCAL_NEIGHBORHOOD_HH_ */
diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc b/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc
index f8b78a232..d0db156c0 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood_base.cc
@@ -1,126 +1,121 @@
/**
* @file non_local_neighborhood_base.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Fri Jul 10 2020
*
* @brief Implementation of non-local neighborhood base
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_local_neighborhood_base.hh"
#include "grid_synchronizer.hh"
#include "model.hh"
/* -------------------------------------------------------------------------- */
#include <memory>
namespace akantu {
/* -------------------------------------------------------------------------- */
NonLocalNeighborhoodBase::NonLocalNeighborhoodBase(
Model & model, const ElementTypeMapReal & quad_coordinates, const ID & id)
: NeighborhoodBase(model, quad_coordinates, id),
Parsable(ParserType::_non_local, id) {
- AKANTU_DEBUG_IN();
-
this->registerParam("radius", neighborhood_radius, 100.,
_pat_parsable | _pat_readable, "Non local radius");
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
NonLocalNeighborhoodBase::~NonLocalNeighborhoodBase() = default;
/* -------------------------------------------------------------------------- */
void NonLocalNeighborhoodBase::createGridSynchronizer() {
this->is_creating_grid = true;
this->grid_synchronizer = std::make_unique<GridSynchronizer>(
this->model.getMesh(), *spatial_grid, *this,
std::set<SynchronizationTag>{SynchronizationTag::_mnl_weight,
SynchronizationTag::_mnl_for_average},
std::string(id + ":grid_synchronizer"), false);
this->is_creating_grid = false;
}
/* -------------------------------------------------------------------------- */
void NonLocalNeighborhoodBase::synchronize(
DataAccessor<Element> & data_accessor, const SynchronizationTag & tag) {
if (not grid_synchronizer) {
return;
}
grid_synchronizer->synchronizeOnce(data_accessor, tag);
}
/* -------------------------------------------------------------------------- */
void NonLocalNeighborhoodBase::getRelevantGhostElements(
std::set<Element> & relevant_ghost_elements) {
-
for (auto && ghost_type : ghost_type_t{}) {
auto & pair_list = this->pair_list.at(ghost_type);
for (auto && pair : pair_list) {
if (pair.first.ghost_type == _ghost) {
relevant_ghost_elements.insert(pair.first);
}
if (pair.second.ghost_type == _ghost) {
relevant_ghost_elements.insert(pair.second);
}
}
}
}
/* -------------------------------------------------------------------------- */
void NonLocalNeighborhoodBase::cleanupExtraGhostElements(
std::set<Element> & relevant_ghost_elements) {
Array<Element> ghosts_to_erase;
auto & mesh = this->model.getMesh();
auto end = relevant_ghost_elements.end();
for (const auto & type : mesh.elementTypes(
_spatial_dimension = spatial_dimension, _ghost_type = _ghost)) {
auto nb_ghost_elem = mesh.getNbElement(type, _ghost);
- for (UInt g = 0; g < nb_ghost_elem; ++g) {
+ for (auto g : arange(nb_ghost_elem)) {
Element element{type, g, _ghost};
if (relevant_ghost_elements.find(element) == end) {
ghosts_to_erase.push_back(element);
}
}
}
/// remove the unneccessary ghosts from the synchronizer
mesh.eraseElements(ghosts_to_erase);
}
/* -------------------------------------------------------------------------- */
void NonLocalNeighborhoodBase::registerNonLocalVariable(const ID & id) {
this->non_local_variables.insert(id);
}
} // namespace akantu
diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh
index dce06713b..b7190cbd6 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh
@@ -1,136 +1,136 @@
/**
* @file non_local_neighborhood_base.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Non-local neighborhood base class
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "neighborhood_base.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH_
#define AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH_
namespace akantu {
class Model;
}
/* -------------------------------------------------------------------------- */
namespace akantu {
class NonLocalNeighborhoodBase : public NeighborhoodBase, public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NonLocalNeighborhoodBase(Model & model,
const ElementTypeMapReal & quad_coordinates,
const ID & id = "non_local_neighborhood");
~NonLocalNeighborhoodBase() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// create grid synchronizer and exchange ghost cells
void createGridSynchronizer() override;
void synchronize(DataAccessor<Element> & data_accessor,
const SynchronizationTag & tag) override;
/// compute weights, for instance needed for non-local damage computation
virtual void computeWeights(){};
// compute the non-local counter part for a given element type map
virtual void
weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate,
ElementTypeMapReal & accumulated,
- UInt nb_degree_of_freedom,
+ Int nb_degree_of_freedom,
GhostType ghost_type2) const = 0;
/// update the weights for the non-local averaging
virtual void updateWeights() = 0;
/// update the weights for the non-local averaging
virtual void saveWeights(const std::string & /*unused*/) const {
AKANTU_TO_IMPLEMENT();
}
/// register a new non-local variable in the neighborhood
virtual void registerNonLocalVariable(const ID & id);
/// clean up the unneccessary ghosts
void cleanupExtraGhostElements(std::set<Element> & relevant_ghost_elements);
/// list releveant ghosts
void getRelevantGhostElements(std::set<Element> & relevant_ghost_elements);
protected:
/// create the grid
void createGrid();
/* --------------------------------------------------------------------------
*/
/* DataAccessor inherited members */
/* --------------------------------------------------------------------------
*/
public:
- inline UInt getNbData(const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/) const override {
+ inline Int getNbData(const Array<Element> &,
+ const SynchronizationTag &) const override {
return 0;
}
inline void packData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*element*/,
const SynchronizationTag & /*tag*/) const override {}
inline void unpackData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*element*/,
const SynchronizationTag & /*tag*/) override {}
/* --------------------------------------------------------------------------
*/
/* Accessors */
/* --------------------------------------------------------------------------
*/
public:
AKANTU_GET_MACRO(NonLocalVariables, non_local_variables,
const std::set<ID> &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// list of non-local variables associated to the neighborhood
std::set<ID> non_local_variables;
};
} // namespace akantu
#endif /* AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH_ */
diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.hh
index f4534bdfb..d95e6431b 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.hh
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood_inline_impl.hh
@@ -1,88 +1,89 @@
/**
* @file non_local_neighborhood_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Oct 06 2015
* @date last modification: Sun Dec 30 2018
*
* @brief Implementation of inline functions of non-local neighborhood class
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "non_local_neighborhood.hh"
+//#include "non_local_neighborhood.hh"
+#include "non_local_manager.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LOCAL_NEIGHBORHOOD_INLINE_IMPL_HH_
#define AKANTU_NON_LOCAL_NEIGHBORHOOD_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
-inline UInt NonLocalNeighborhood<WeightFunction>::getNbData(
+inline Int NonLocalNeighborhood<WeightFunction>::getNbData(
const Array<Element> & elements, const SynchronizationTag & tag) const {
- UInt size = 0;
+ Int size = 0;
if (tag == SynchronizationTag::_mnl_for_average) {
- for (auto & variable_id : non_local_variables) {
+ for (auto && variable_id : non_local_variables) {
size += this->non_local_manager.getNbData(elements, variable_id);
}
}
size += this->weight_function->getNbData(elements, tag);
return size;
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
inline void NonLocalNeighborhood<WeightFunction>::packData(
CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const {
if (tag == SynchronizationTag::_mnl_for_average) {
- for (auto & variable_id : non_local_variables) {
+ for (auto && variable_id : non_local_variables) {
this->non_local_manager.packData(buffer, elements, variable_id);
}
}
this->weight_function->packData(buffer, elements, tag);
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
inline void NonLocalNeighborhood<WeightFunction>::unpackData(
CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) {
if (tag == SynchronizationTag::_mnl_for_average) {
for (auto & variable_id : non_local_variables) {
this->non_local_manager.unpackData(buffer, elements, variable_id);
}
}
this->weight_function->unpackData(buffer, elements, tag);
}
} // namespace akantu
#endif /* AKANTU_NON_LOCAL_NEIGHBORHOOD_INLINE_IMPL_HH_ */
diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh
index e07deb731..74b48443f 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh
@@ -1,281 +1,260 @@
/**
* @file non_local_neighborhood_tmpl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Sep 28 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Implementation of class non-local neighborhood
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
+#include "model.hh"
#include "non_local_manager.hh"
-#include "non_local_neighborhood.hh"
+//#include "non_local_neighborhood.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LOCAL_NEIGHBORHOOD_TMPL_HH_
#define AKANTU_NON_LOCAL_NEIGHBORHOOD_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
template <class Func>
inline void
NonLocalNeighborhood<WeightFunction>::foreach_weight(GhostType ghost_type,
Func && func) {
auto weight_it =
pair_weight[ghost_type]->begin(pair_weight[ghost_type]->getNbComponent());
for (auto & pair : pair_list[ghost_type]) {
std::forward<decltype(func)>(func)(pair.first, pair.second, *weight_it);
++weight_it;
}
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
template <class Func>
inline void
NonLocalNeighborhood<WeightFunction>::foreach_weight(GhostType ghost_type,
Func && func) const {
auto weight_it =
pair_weight[ghost_type]->begin(pair_weight[ghost_type]->getNbComponent());
for (auto & pair : pair_list[ghost_type]) {
std::forward<decltype(func)>(func)(pair.first, pair.second, *weight_it);
++weight_it;
}
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
NonLocalNeighborhood<WeightFunction>::NonLocalNeighborhood(
NonLocalManager & manager, const ElementTypeMapReal & quad_coordinates,
const ID & id)
: NonLocalNeighborhoodBase(manager.getModel(), quad_coordinates, id),
non_local_manager(manager) {
AKANTU_DEBUG_IN();
this->weight_function = std::make_unique<WeightFunction>(manager);
this->registerSubSection(ParserType::_weight_function, "weight_parameter",
*weight_function);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
NonLocalNeighborhood<WeightFunction>::~NonLocalNeighborhood() = default;
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
void NonLocalNeighborhood<WeightFunction>::computeWeights() {
AKANTU_DEBUG_IN();
this->weight_function->setRadius(this->neighborhood_radius);
- Vector<Real> q1_coord(this->spatial_dimension);
- Vector<Real> q2_coord(this->spatial_dimension);
- UInt nb_weights_per_pair = 2; /// w1: q1->q2, w2: q2->q1
+ Int nb_weights_per_pair = 2; /// w1: q1->q2, w2: q2->q1
/// get the elementtypemap for the neighborhood volume for each quadrature
/// point
ElementTypeMapReal & quadrature_points_volumes =
this->non_local_manager.getVolumes();
/// update the internals of the weight function if applicable (not
/// all the weight functions have internals and do noting in that
/// case)
weight_function->updateInternals();
for (auto ghost_type : ghost_types) {
/// allocate the array to store the weight, if it doesn't exist already
- if (!(pair_weight[ghost_type])) {
+ if (not pair_weight[ghost_type]) {
pair_weight[ghost_type] =
std::make_unique<Array<Real>>(0, nb_weights_per_pair);
}
- /// resize the array to the correct size
- pair_weight[ghost_type]->resize(pair_list[ghost_type].size());
- /// set entries to zero
- pair_weight[ghost_type]->zero();
+ auto && pair_lists = pair_list[ghost_type];
+ auto && pair_weights = *pair_weight[ghost_type];
+ pair_weights.resize(pair_lists.size());
+ pair_weights.zero();
/// loop over all pairs in the current pair list array and their
/// corresponding weights
- auto first_pair = pair_list[ghost_type].begin();
- auto last_pair = pair_list[ghost_type].end();
- auto weight_it = pair_weight[ghost_type]->begin(nb_weights_per_pair);
-
// Compute the weights
- for (; first_pair != last_pair; ++first_pair, ++weight_it) {
- Vector<Real> & weight = *weight_it;
- const IntegrationPoint & q1 = first_pair->first;
- const IntegrationPoint & q2 = first_pair->second;
+ for (auto && [weight, pairs] :
+ zip(make_view(pair_weights, nb_weights_per_pair), pair_lists)) {
+ const auto & [q1, q2] = pairs;
/// get the coordinates for the given pair of quads
- auto coords_type_1_it = this->quad_coordinates(q1.type, q1.ghost_type)
- .begin(this->spatial_dimension);
- q1_coord = coords_type_1_it[q1.global_num];
- auto coords_type_2_it = this->quad_coordinates(q2.type, q2.ghost_type)
- .begin(this->spatial_dimension);
- q2_coord = coords_type_2_it[q2.global_num];
-
- Array<Real> & quad_volumes_1 =
- quadrature_points_volumes(q1.type, q1.ghost_type);
- const Array<Real> & jacobians_2 =
- this->non_local_manager.getJacobians(q2.type, q2.ghost_type);
- const Real & q2_wJ = jacobians_2(q2.global_num);
+ auto && q1_coord = this->quad_coordinates.get(q1);
+ auto && q2_coord = this->quad_coordinates.get(q2);
+
+ auto && quad_volumes_1 = quadrature_points_volumes(q1);
+ const auto & q2_wJ = this->non_local_manager.getJacobians()(q2);
/// compute distance between the two quadrature points
- Real r = q1_coord.distance(q2_coord);
+ auto r = q1_coord.distance(q2_coord);
/// compute the weight for averaging on q1 based on the distance
- Real w1 = this->weight_function->operator()(r, q1, q2);
- weight(0) = q2_wJ * w1;
+ weight(0) = q2_wJ * (*this->weight_function)(r, q1, q2);
- quad_volumes_1(q1.global_num) += weight(0);
+ quad_volumes_1 += weight(0);
if (q2.ghost_type != _ghost && q1.global_num != q2.global_num) {
- const Array<Real> & jacobians_1 =
- this->non_local_manager.getJacobians(q1.type, q1.ghost_type);
- Array<Real> & quad_volumes_2 =
- quadrature_points_volumes(q2.type, q2.ghost_type);
+ const auto & q1_wJ = this->non_local_manager.getJacobians()(q1);
+ auto && quad_volumes_2 = quadrature_points_volumes(q2);
+
/// compute the weight for averaging on q2
- const Real & q1_wJ = jacobians_1(q1.global_num);
- Real w2 = this->weight_function->operator()(r, q2, q1);
- weight(1) = q1_wJ * w2;
- quad_volumes_2(q2.global_num) += weight(1);
+ weight(1) = q1_wJ * (*this->weight_function)(r, q2, q1);
+ quad_volumes_2 += weight(1);
} else {
weight(1) = 0.;
}
}
}
/// normalize the weights
for (auto ghost_type : ghost_types) {
foreach_weight(ghost_type, [&](const auto & q1, const auto & q2,
auto & weight) {
auto & quad_volumes_1 = quadrature_points_volumes(q1.type, q1.ghost_type);
auto & quad_volumes_2 = quadrature_points_volumes(q2.type, q2.ghost_type);
- Real q1_volume = quad_volumes_1(q1.global_num);
+ auto q1_volume = quad_volumes_1(q1.global_num);
auto ghost_type2 = q2.ghost_type;
weight(0) *= 1. / q1_volume;
if (ghost_type2 != _ghost) {
- Real q2_volume = quad_volumes_2(q2.global_num);
+ auto q2_volume = quad_volumes_2(q2.global_num);
weight(1) *= 1. / q2_volume;
}
});
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
void NonLocalNeighborhood<WeightFunction>::saveWeights(
const std::string & filename) const {
std::ofstream pout;
std::stringstream sstr;
const Communicator & comm = model.getMesh().getCommunicator();
- Int prank = comm.whoAmI();
+ auto prank = comm.whoAmI();
sstr << filename << "." << prank;
pout.open(sstr.str().c_str());
- for (UInt gt = _not_ghost; gt <= _ghost; ++gt) {
- auto ghost_type = (GhostType)gt;
-
+ for (auto ghost_type : ghost_types) {
AKANTU_DEBUG_ASSERT((pair_weight[ghost_type]),
"the weights have not been computed yet");
- Array<Real> & weights = *(pair_weight[ghost_type]);
+ auto & weights = *(pair_weight[ghost_type]);
auto weights_it = weights.begin(2);
- for (UInt i = 0; i < weights.size(); ++i, ++weights_it) {
+ for (Int i = 0; i < weights.size(); ++i, ++weights_it) {
pout << "w1: " << (*weights_it)(0) << " w2: " << (*weights_it)(1)
<< std::endl;
}
}
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
void NonLocalNeighborhood<WeightFunction>::weightedAverageOnNeighbours(
const ElementTypeMapReal & to_accumulate, ElementTypeMapReal & accumulated,
- UInt nb_degree_of_freedom, GhostType ghost_type2) const {
+ Int nb_degree_of_freedom, GhostType ghost_type2) const {
auto it = non_local_variables.find(accumulated.getName());
// do averaging only for variables registered in the neighborhood
if (it == non_local_variables.end()) {
return;
}
foreach_weight(
ghost_type2,
[ghost_type2, nb_degree_of_freedom, &to_accumulate,
&accumulated](const auto & q1, const auto & q2, auto & weight) {
- const Vector<Real> to_acc_1 =
- to_accumulate(q1.type, q1.ghost_type)
- .begin(nb_degree_of_freedom)[q1.global_num];
- const Vector<Real> to_acc_2 =
- to_accumulate(q2.type, q2.ghost_type)
- .begin(nb_degree_of_freedom)[q2.global_num];
- Vector<Real> acc_1 = accumulated(q1.type, q1.ghost_type)
- .begin(nb_degree_of_freedom)[q1.global_num];
- Vector<Real> acc_2 = accumulated(q2.type, q2.ghost_type)
- .begin(nb_degree_of_freedom)[q2.global_num];
+ auto && to_acc_1 = to_accumulate(q1.type, q1.ghost_type)
+ .begin(nb_degree_of_freedom)[q1.global_num];
+ auto && to_acc_2 = to_accumulate(q2.type, q2.ghost_type)
+ .begin(nb_degree_of_freedom)[q2.global_num];
+ auto && acc_1 = accumulated(q1.type, q1.ghost_type)
+ .begin(nb_degree_of_freedom)[q1.global_num];
+ auto && acc_2 = accumulated(q2.type, q2.ghost_type)
+ .begin(nb_degree_of_freedom)[q2.global_num];
acc_1 += weight(0) * to_acc_2;
if (ghost_type2 != _ghost) {
acc_2 += weight(1) * to_acc_1;
}
});
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
void NonLocalNeighborhood<WeightFunction>::updateWeights() {
// Update the weights for the non local variable averaging
if (this->weight_function->getUpdateRate() &&
(this->non_local_manager.getNbStressCalls() %
this->weight_function->getUpdateRate() ==
0)) {
SynchronizerRegistry::synchronize(SynchronizationTag::_mnl_weight);
this->computeWeights();
}
}
} // namespace akantu
#endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_TMPL__ */
diff --git a/src/model/common/time_step_solvers/time_step_solver.hh b/src/model/common/time_step_solvers/time_step_solver.hh
index fa2898595..050e9c275 100644
--- a/src/model/common/time_step_solvers/time_step_solver.hh
+++ b/src/model/common/time_step_solvers/time_step_solver.hh
@@ -1,171 +1,171 @@
/**
* @file time_step_solver.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 08 2020
*
* @brief This corresponding to the time step evolution solver
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "integration_scheme.hh"
#include "parameter_registry.hh"
#include "solver_callback.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TIME_STEP_SOLVER_HH_
#define AKANTU_TIME_STEP_SOLVER_HH_
namespace akantu {
class DOFManager;
class NonLinearSolver;
} // namespace akantu
namespace akantu {
class TimeStepSolver : public ParameterRegistry, public SolverCallback {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
TimeStepSolver(DOFManager & dof_manager, const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver,
SolverCallback & solver_callback, const ID & id);
~TimeStepSolver() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// solves on step
virtual void solveStep(SolverCallback & solver_callback) = 0;
/// register an integration scheme for a given dof
void setIntegrationScheme(const ID & dof_id,
const IntegrationSchemeType & type,
IntegrationScheme::SolutionType solution_type =
IntegrationScheme::_not_defined);
/// register an integration scheme for a given dof
void setIntegrationScheme(const ID & dof_id,
std::unique_ptr<IntegrationScheme> & scheme,
IntegrationScheme::SolutionType solution_type =
IntegrationScheme::_not_defined);
- virtual IntegrationScheme & getIntegrationScheme(const ID & dof_id) {
+ virtual IntegrationScheme & getIntegrationScheme(const ID & /*dof_id*/) {
AKANTU_TO_IMPLEMENT();
}
protected:
/// register an integration scheme for a given dof
virtual std::unique_ptr<IntegrationScheme>
getIntegrationSchemeInternal(const ID & dof_id,
const IntegrationSchemeType & type,
IntegrationScheme::SolutionType solution_type =
IntegrationScheme::_not_defined) = 0;
virtual void
setIntegrationSchemeInternal(const ID & dof_id,
std::unique_ptr<IntegrationScheme> & scheme,
IntegrationScheme::SolutionType solution_type =
IntegrationScheme::_not_defined) = 0;
public:
/// replies if a integration scheme has been set
virtual bool hasIntegrationScheme(const ID & dof_id) const = 0;
/* ------------------------------------------------------------------------ */
/* Solver Callback interface */
/* ------------------------------------------------------------------------ */
public:
/// implementation of the SolverCallback::getMatrixType()
MatrixType getMatrixType(const ID & /*unused*/) const final {
return _mt_not_defined;
}
/// implementation of the SolverCallback::predictor()
void predictor() override;
/// implementation of the SolverCallback::corrector()
void corrector() override;
/// implementation of the SolverCallback::assembleJacobian()
void assembleMatrix(const ID & matrix_id) override;
/// implementation of the SolverCallback::assembleJacobian()
void assembleLumpedMatrix(const ID & matrix_id) override;
/// implementation of the SolverCallback::assembleResidual()
void assembleResidual() override;
/// implementation of the SolverCallback::assembleResidual()
void assembleResidual(const ID & residual_part) override;
void beforeSolveStep() override;
void afterSolveStep(bool converged = true) override;
bool canSplitResidual() const override {
return solver_callback->canSplitResidual();
}
/* ------------------------------------------------------------------------ */
/* Accessor */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(TimeStep, time_step, Real);
AKANTU_SET_MACRO(TimeStep, time_step, Real);
AKANTU_GET_MACRO(NonLinearSolver, non_linear_solver, const NonLinearSolver &);
AKANTU_GET_MACRO_NOT_CONST(NonLinearSolver, non_linear_solver,
NonLinearSolver &);
protected:
MatrixType getCommonMatrixType();
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ID id;
/// Underlying dof manager containing the dof to treat
DOFManager & _dof_manager;
/// Type of solver
TimeStepSolverType type;
/// The time step for this solver
Real time_step;
/// Temporary storage for solver callback
SolverCallback * solver_callback;
/// NonLinearSolver used by this tome step solver
NonLinearSolver & non_linear_solver;
/// List of required matrices
std::map<std::string, MatrixType> needed_matrices;
/// specifies if the solvers gives to full solution or just the increment of
/// solution
bool is_solution_increment{true};
};
} // namespace akantu
#endif /* AKANTU_TIME_STEP_SOLVER_HH_ */
diff --git a/src/model/common/time_step_solvers/time_step_solver_default.cc b/src/model/common/time_step_solvers/time_step_solver_default.cc
index f767800f6..9804c5d70 100644
--- a/src/model/common/time_step_solvers/time_step_solver_default.cc
+++ b/src/model/common/time_step_solvers/time_step_solver_default.cc
@@ -1,344 +1,318 @@
/**
* @file time_step_solver_default.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 15 2015
* @date last modification: Tue Sep 08 2020
*
* @brief Default implementation of the time step solver
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "time_step_solver_default.hh"
#include "dof_manager_default.hh"
#include "integration_scheme_1st_order.hh"
#include "integration_scheme_2nd_order.hh"
#include "mesh.hh"
#include "non_linear_solver.hh"
#include "pseudo_time.hh"
#include "sparse_matrix_aij.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
TimeStepSolverDefault::TimeStepSolverDefault(
DOFManager & dof_manager, const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver, SolverCallback & solver_callback,
const ID & id)
: TimeStepSolver(dof_manager, type, non_linear_solver, solver_callback,
id) {
switch (type) {
case TimeStepSolverType::_dynamic:
break;
case TimeStepSolverType::_dynamic_lumped:
this->is_mass_lumped = true;
break;
case TimeStepSolverType::_static:
/// initialize a static time solver for callback dofs
break;
default:
AKANTU_TO_IMPLEMENT();
}
}
/* -------------------------------------------------------------------------- */
std::unique_ptr<IntegrationScheme>
TimeStepSolverDefault::getIntegrationSchemeInternal(
const ID & dof_id, const IntegrationSchemeType & type,
IntegrationScheme::SolutionType /*solution_type*/) {
std::unique_ptr<IntegrationScheme> integration_scheme;
if (this->is_mass_lumped) {
switch (type) {
case IntegrationSchemeType::_forward_euler: {
integration_scheme = std::make_unique<ForwardEuler>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_central_difference: {
integration_scheme =
std::make_unique<CentralDifference>(_dof_manager, dof_id);
break;
}
default:
AKANTU_EXCEPTION(
"This integration scheme cannot be used in lumped dynamic");
}
} else {
switch (type) {
case IntegrationSchemeType::_pseudo_time: {
integration_scheme = std::make_unique<PseudoTime>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_forward_euler: {
integration_scheme = std::make_unique<ForwardEuler>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_trapezoidal_rule_1: {
integration_scheme =
std::make_unique<TrapezoidalRule1>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_backward_euler: {
integration_scheme =
std::make_unique<BackwardEuler>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_central_difference: {
integration_scheme =
std::make_unique<CentralDifference>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_fox_goodwin: {
integration_scheme = std::make_unique<FoxGoodwin>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_trapezoidal_rule_2: {
integration_scheme =
std::make_unique<TrapezoidalRule2>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_linear_acceleration: {
integration_scheme =
std::make_unique<LinearAceleration>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_generalized_trapezoidal: {
integration_scheme =
std::make_unique<GeneralizedTrapezoidal>(_dof_manager, dof_id);
break;
}
case IntegrationSchemeType::_newmark_beta:
integration_scheme = std::make_unique<NewmarkBeta>(_dof_manager, dof_id);
break;
}
}
AKANTU_DEBUG_ASSERT(integration_scheme,
"No integration scheme was found for the provided types");
return integration_scheme;
}
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::setIntegrationSchemeInternal(
const ID & dof_id, std::unique_ptr<IntegrationScheme> & integration_scheme,
IntegrationScheme::SolutionType solution_type) {
if (this->integration_schemes.find(dof_id) !=
this->integration_schemes.end()) {
AKANTU_EXCEPTION("Their DOFs "
<< dof_id
<< " have already an integration scheme associated");
}
auto && matrices_names = integration_scheme->getNeededMatrixList();
for (auto && name : matrices_names) {
needed_matrices.insert({name, _mt_not_defined});
}
this->integration_schemes[dof_id] = std::move(integration_scheme);
this->solution_types[dof_id] = solution_type;
this->integration_schemes_owner.insert(dof_id);
}
/* -------------------------------------------------------------------------- */
bool TimeStepSolverDefault::hasIntegrationScheme(const ID & dof_id) const {
return this->integration_schemes.find(dof_id) !=
this->integration_schemes.end();
}
/* -------------------------------------------------------------------------- */
TimeStepSolverDefault::~TimeStepSolverDefault() = default;
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::solveStep(SolverCallback & solver_callback) {
this->solver_callback = &solver_callback;
this->non_linear_solver.solve(*this);
this->solver_callback = nullptr;
}
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::predictor() {
TimeStepSolver::predictor();
- for (auto && pair : this->integration_schemes) {
- const auto & dof_id = pair.first;
- auto & integration_scheme = pair.second;
-
+ for (auto && [dof_id, integration_scheme] : this->integration_schemes) {
if (this->_dof_manager.hasPreviousDOFs(dof_id)) {
this->_dof_manager.savePreviousDOFs(dof_id);
}
/// integrator predictor
integration_scheme->predictor(this->time_step);
}
}
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::corrector() {
AKANTU_DEBUG_IN();
- for (auto & pair : this->integration_schemes) {
- const auto & dof_id = pair.first;
- auto & integration_scheme = pair.second;
-
+ for (auto && [dof_id, integration_scheme] : this->integration_schemes) {
const auto & solution_type = this->solution_types[dof_id];
integration_scheme->corrector(solution_type, this->time_step);
/// computing the increment of dof if needed
if (this->_dof_manager.hasDOFsIncrement(dof_id)) {
if (not this->_dof_manager.hasPreviousDOFs(dof_id)) {
AKANTU_DEBUG_WARNING("In order to compute the increment of "
<< dof_id << " a 'previous' has to be registered");
continue;
}
auto & increment = this->_dof_manager.getDOFsIncrement(dof_id);
auto & previous = this->_dof_manager.getPreviousDOFs(dof_id);
auto dof_array_comp = this->_dof_manager.getDOFs(dof_id).getNbComponent();
- increment.copy(this->_dof_manager.getDOFs(dof_id));
+ if (solution_type == IntegrationScheme::_displacement) {
+ increment.copy(this->_dof_manager.getSolution(dof_id), true);
+ } else {
+ increment.copy(this->_dof_manager.getDOFs(dof_id));
- for (auto && data : zip(make_view(increment, dof_array_comp),
- make_view(previous, dof_array_comp))) {
- std::get<0>(data) -= std::get<1>(data);
+ for (auto && data : zip(make_view(increment, dof_array_comp),
+ make_view(previous, dof_array_comp))) {
+ std::get<0>(data) -= std::get<1>(data);
+ }
}
}
}
TimeStepSolver::corrector();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::assembleMatrix(const ID & matrix_id) {
AKANTU_DEBUG_IN();
TimeStepSolver::assembleMatrix(matrix_id);
if (matrix_id != "J") {
return;
}
for_each_integrator([&](auto && dof_id, auto && integration_scheme) {
const auto & solution_type = this->solution_types[dof_id];
integration_scheme.assembleJacobian(solution_type, this->time_step);
});
this->_dof_manager.applyBoundary("J");
AKANTU_DEBUG_OUT();
}
-/* -------------------------------------------------------------------------- */
-// void TimeStepSolverDefault::assembleLumpedMatrix(const ID & matrix_id) {
-// AKANTU_DEBUG_IN();
-
-// TimeStepSolver::assembleLumpedMatrix(matrix_id);
-
-// if (matrix_id != "J")
-// return;
-
-// for (auto & pair : this->integration_schemes) {
-// auto & dof_id = pair.first;
-// auto & integration_scheme = pair.second;
-
-// const auto & solution_type = this->solution_types[dof_id];
-
-// integration_scheme->assembleJacobianLumped(solution_type,
-// this->time_step);
-// }
-
-// this->_dof_manager.applyBoundaryLumped("J");
-
-// AKANTU_DEBUG_OUT();
-// }
-
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::assembleResidual() {
if (this->needed_matrices.find("M") != needed_matrices.end()) {
if (this->is_mass_lumped) {
this->assembleLumpedMatrix("M");
} else {
this->assembleMatrix("M");
}
}
TimeStepSolver::assembleResidual();
for_each_integrator([&](auto && /*unused*/, auto && integration_scheme) {
integration_scheme.assembleResidual(this->is_mass_lumped);
});
}
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::assembleResidual(const ID & residual_part) {
AKANTU_DEBUG_IN();
if (this->needed_matrices.find("M") != needed_matrices.end()) {
if (this->is_mass_lumped) {
this->assembleLumpedMatrix("M");
} else {
this->assembleMatrix("M");
}
}
if (residual_part != "inertial") {
TimeStepSolver::assembleResidual(residual_part);
}
if (residual_part == "inertial") {
for_each_integrator([&](auto && /*unused*/, auto && integration_scheme) {
integration_scheme.assembleResidual(this->is_mass_lumped);
});
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::beforeSolveStep() {
TimeStepSolver::beforeSolveStep();
for_each_integrator([&](auto && /*unused*/, auto && integration_scheme) {
integration_scheme.store();
});
}
/* -------------------------------------------------------------------------- */
void TimeStepSolverDefault::afterSolveStep(bool converged) {
if (not converged) {
for_each_integrator([&](auto && /*unused*/, auto && integration_scheme) {
integration_scheme.restore();
});
}
TimeStepSolver::afterSolveStep(converged);
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/common/time_step_solvers/time_step_solver_default.hh b/src/model/common/time_step_solvers/time_step_solver_default.hh
index a02e96d2a..3e00d41fa 100644
--- a/src/model/common/time_step_solvers/time_step_solver_default.hh
+++ b/src/model/common/time_step_solvers/time_step_solver_default.hh
@@ -1,141 +1,139 @@
/**
* @file time_step_solver_default.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Sep 08 2020
*
* @brief Default implementation for the time stepper
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "integration_scheme.hh"
#include "time_step_solver.hh"
/* -------------------------------------------------------------------------- */
#include <map>
#include <set>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TIME_STEP_SOLVER_DEFAULT_HH_
#define AKANTU_TIME_STEP_SOLVER_DEFAULT_HH_
namespace akantu {
class DOFManager;
}
namespace akantu {
class TimeStepSolverDefault : public TimeStepSolver {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
TimeStepSolverDefault(DOFManager & dof_manager,
const TimeStepSolverType & type,
NonLinearSolver & non_linear_solver,
SolverCallback & solver_callback, const ID & id);
~TimeStepSolverDefault() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// registers an integration scheme for a given dof
std::unique_ptr<IntegrationScheme>
getIntegrationSchemeInternal(const ID & dof_id,
const IntegrationSchemeType & type,
IntegrationScheme::SolutionType solution_type =
IntegrationScheme::_not_defined) override;
void setIntegrationSchemeInternal(
const ID & dof_id,
std::unique_ptr<IntegrationScheme> & integration_scheme,
IntegrationScheme::SolutionType solution_type) override;
public:
bool hasIntegrationScheme(const ID & dof_id) const override;
/// implementation of the TimeStepSolver::predictor()
void predictor() override;
/// implementation of the TimeStepSolver::corrector()
void corrector() override;
/// implementation of the TimeStepSolver::assembleMatrix()
void assembleMatrix(const ID & matrix_id) override;
// void assembleLumpedMatrix(const ID & matrix_id) override;
/// implementation of the TimeStepSolver::assembleResidual()
void assembleResidual() override;
void assembleResidual(const ID & residual_part) override;
void beforeSolveStep() override;
void afterSolveStep(bool converged = true) override;
/// implementation of the generic TimeStepSolver::solveStep()
void solveStep(SolverCallback & solver_callback) override;
IntegrationScheme & getIntegrationScheme(const ID & dof_id) override {
auto it = integration_schemes.find(dof_id);
AKANTU_DEBUG_ASSERT(it != integration_schemes.end(),
"No integration scheme");
return *(it->second);
}
private:
template <class Func> void for_each_integrator(Func && function) {
- for (auto & pair : this->integration_schemes) {
- const auto & dof_id = pair.first;
- auto & integration_scheme = pair.second;
+ for (auto && [dof_id, integration_scheme] : this->integration_schemes) {
function(dof_id, *integration_scheme);
}
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
using DOFsIntegrationSchemes =
std::map<ID, std::unique_ptr<IntegrationScheme>>;
using DOFsIntegrationSchemesSolutionTypes =
std::map<ID, IntegrationScheme::SolutionType>;
using DOFsIntegrationSchemesOwner = std::set<ID>;
/// Underlying integration scheme per dof, \todo check what happens in dynamic
/// in case of coupled equations
DOFsIntegrationSchemes integration_schemes;
/// defines if the solver is owner of the memory or not
DOFsIntegrationSchemesOwner integration_schemes_owner;
/// Type of corrector to use
DOFsIntegrationSchemesSolutionTypes solution_types;
/// define if the mass matrix is lumped or not
bool is_mass_lumped{false};
};
} // namespace akantu
#endif /* AKANTU_TIME_STEP_SOLVER_DEFAULT_HH_ */
diff --git a/src/model/contact_mechanics/contact_detector.cc b/src/model/contact_mechanics/contact_detector.cc
index f5c17d48d..05236daf2 100644
--- a/src/model/contact_mechanics/contact_detector.cc
+++ b/src/model/contact_mechanics/contact_detector.cc
@@ -1,295 +1,279 @@
/**
* @file contact_detector.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed Dec 05 2018
* @date last modification: Thu Jun 24 2021
*
* @brief Mother class for all detection algorithms
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_detector.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
ContactDetector::ContactDetector(Mesh & mesh, const ID & id)
: ContactDetector(mesh, mesh.getNodes(), id) {}
/* -------------------------------------------------------------------------- */
ContactDetector::ContactDetector(Mesh & mesh, Array<Real> positions,
const ID & id)
: Parsable(ParserType::_contact_detector, id), mesh(mesh),
positions(0, mesh.getSpatialDimension()) {
AKANTU_DEBUG_IN();
this->spatial_dimension = mesh.getSpatialDimension();
this->positions.copy(positions);
const Parser & parser = getStaticParser();
const ParserSection & section =
*(parser.getSubSections(ParserType::_contact_detector).first);
this->parseSection(section);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ContactDetector::parseSection(const ParserSection & section) {
auto type = section.getParameterValue<std::string>("type");
if (type == "implicit") {
this->detection_type = _implicit;
} else if (type == "explicit") {
this->detection_type = _explicit;
} else {
AKANTU_ERROR("Unknown detection type : " << type);
}
this->projection_tolerance =
section.getParameterValue<Real>("projection_tolerance");
- this->max_iterations = section.getParameterValue<Real>("max_iterations");
+ this->max_iterations = section.getParameterValue<Int>("max_iterations");
this->extension_tolerance =
section.getParameterValue<Real>("extension_tolerance");
}
/* -------------------------------------------------------------------------- */
void ContactDetector::search(Array<ContactElement> & elements,
Array<Real> & gaps, Array<Real> & normals,
Array<Real> & tangents,
Array<Real> & projections) {
auto surface_dimension = spatial_dimension - 1;
this->mesh.fillNodesToElements(surface_dimension);
this->computeMaximalDetectionDistance();
contact_pairs.clear();
- SpatialGrid<UInt> master_grid(spatial_dimension);
- SpatialGrid<UInt> slave_grid(spatial_dimension);
+ auto && [bbox, master_grid] = this->globalSearch();
- this->globalSearch(slave_grid, master_grid);
-
- this->localSearch(slave_grid, master_grid);
+ this->localSearch(bbox, *master_grid);
this->createContactElements(elements, gaps, normals, tangents, projections);
}
/* -------------------------------------------------------------------------- */
-void ContactDetector::globalSearch(SpatialGrid<UInt> & slave_grid,
- SpatialGrid<UInt> & master_grid) {
+std::pair<BBox, std::unique_ptr<SpatialGrid<Idx>>>
+ContactDetector::globalSearch() const {
auto & master_list = surface_selector->getMasterList();
auto & slave_list = surface_selector->getSlaveList();
BBox bbox_master(spatial_dimension);
this->constructBoundingBox(bbox_master, master_list);
BBox bbox_slave(spatial_dimension);
this->constructBoundingBox(bbox_slave, slave_list);
auto && bbox_intersection = bbox_master.intersection(bbox_slave);
AKANTU_DEBUG_INFO("Intersection BBox " << bbox_intersection);
Vector<Real> center(spatial_dimension);
- bbox_intersection.getCenter(center);
-
Vector<Real> spacing(spatial_dimension);
+
+ bbox_intersection.getCenter(center);
this->computeCellSpacing(spacing);
- master_grid.setCenter(center);
- master_grid.setSpacing(spacing);
- this->constructGrid(master_grid, bbox_intersection, master_list);
+ auto && master_grid =
+ std::make_unique<SpatialGrid<Idx>>(spatial_dimension, spacing, center);
+
+ this->constructGrid(*master_grid, bbox_intersection, master_list);
- slave_grid.setCenter(center);
- slave_grid.setSpacing(spacing);
- this->constructGrid(slave_grid, bbox_intersection, slave_list);
+ // slave_grid.setCenter(center);
+ // slave_grid.setSpacing(spacing);
+ // this->constructGrid(slave_grid, bbox_intersection, slave_list);
- // search slave grid nodes in contactelement array and if they exits
+ return std::make_pair(bbox_intersection, std::move(master_grid));
+ // search slave grid nodes in contact element array and if they exits
// and still have orthogonal projection on its associated master
- // facetremove it from the spatial grid or do not consider it for
+ // facet remove it from the spatial grid or do not consider it for
// local search, maybe better option will be to have spatial grid of
// type node info and one of the variable of node info should be
// facet already exits
// so contact elements will be updated based on the above
// consideration , this means only those contact elements will be
// keep whose slave node is still in intersection bbox and still has
// projection in its master facet
// also if slave node is already exists in contact element and
// orthogonal projection does not exits then search the associated
// master facets with the current master facets within a given
// radius , this is subjected to computational cost as searching
// neighbbor cells can be more effective.
}
/* -------------------------------------------------------------------------- */
-void ContactDetector::localSearch(SpatialGrid<UInt> & slave_grid,
- SpatialGrid<UInt> & master_grid) {
+void ContactDetector::localSearch(const BBox & intersection,
+ const SpatialGrid<Idx> & master_grid) {
// local search
// out of these array check each cell for closet node in that cell
// and neighbouring cells find the actual orthogonally closet
// check the projection of slave node on master facets connected to
// the closet master node, if yes update the contact element with
// slave node and master node and master surfaces connected to the
// master node
// these master surfaces will be needed later to update contact
// elements
+ auto pos_it = make_view(positions, spatial_dimension).begin();
- /// find the closet master node for each slave node
- for (auto && cell_id : slave_grid) {
- /// loop over all the slave nodes of the current cell
- for (auto && slave_node : slave_grid.getCell(cell_id)) {
+ for (auto && slave_node : surface_selector->getSlaveList()) {
+ bool pair_exists = false;
- bool pair_exists = false;
+ auto && pos_slave = pos_it[slave_node];
- Vector<Real> pos(spatial_dimension);
- for (UInt s : arange(spatial_dimension)) {
- pos(s) = this->positions(slave_node, s);
- }
-
- Real closet_distance = std::numeric_limits<Real>::max();
- UInt closet_master_node;
+ if (not intersection.contains(pos_slave)) {
+ continue;
+ }
- /// loop over all the neighboring cells of the current cell
- for (auto && neighbor_cell : cell_id.neighbors()) {
- /// loop over the data of neighboring cells from master grid
- for (auto && master_node : master_grid.getCell(neighbor_cell)) {
+ Real closet_distance = std::numeric_limits<Real>::max();
+ Int closet_master_node{-1};
- /// check for self contact
- if (slave_node == master_node) {
- continue;
- }
+ auto && master_cell_id = master_grid.getCellID(pos_slave);
- bool is_valid = true;
- Array<Element> elements;
- this->mesh.getAssociatedElements(slave_node, elements);
+ /// loop over all the neighboring cells of the current cell
+ for (auto && neighbor_cell : master_cell_id.neighbors()) {
+ /// loop over the data of neighboring cells from master grid
+ for (auto && master_node : master_grid.getCell(neighbor_cell)) {
+ /// check for self contact
+ if (slave_node == master_node) {
+ continue;
+ }
- for (auto & elem : elements) {
- if (elem.kind() != _ek_regular) {
- continue;
- }
+ bool is_valid = true;
- Vector<UInt> connectivity =
- const_cast<const Mesh &>(this->mesh).getConnectivity(elem);
+ auto && elements = this->mesh.getAssociatedElements(slave_node);
- auto node_iter = std::find(connectivity.begin(), connectivity.end(),
- master_node);
- if (node_iter != connectivity.end()) {
- is_valid = false;
- break;
- }
+ for (const auto & elem : elements) {
+ if (elem.kind() != _ek_regular) {
+ continue;
}
- Vector<Real> pos2(spatial_dimension);
- for (UInt s : arange(spatial_dimension)) {
- pos2(s) = this->positions(master_node, s);
+ const auto & connectivity = this->mesh.getConnectivity(elem);
+
+ auto node_iter =
+ std::find(connectivity.begin(), connectivity.end(), master_node);
+ if (node_iter != connectivity.end()) {
+ is_valid = false;
+ break;
}
+ }
- Real distance = pos.distance(pos2);
+ if (not is_valid) {
+ continue;
+ }
- if (distance <= closet_distance and is_valid) {
- closet_master_node = master_node;
- closet_distance = distance;
- pair_exists = true;
- }
+ auto && pos_master = pos_it[master_node];
+
+ Real distance = pos_slave.distance(pos_master);
+
+ if (distance <= closet_distance) {
+ closet_master_node = master_node;
+ closet_distance = distance;
+ pair_exists = true;
}
}
+ }
- if (pair_exists) {
- contact_pairs.emplace_back(
- std::make_pair(slave_node, closet_master_node));
- }
+ if (pair_exists) {
+ contact_pairs.emplace_back(
+ std::make_pair(slave_node, closet_master_node));
}
}
}
/* -------------------------------------------------------------------------- */
void ContactDetector::createContactElements(
Array<ContactElement> & contact_elements, Array<Real> & gaps,
Array<Real> & normals, Array<Real> & tangents, Array<Real> & projections) {
auto surface_dimension = spatial_dimension - 1;
- Real alpha;
- switch (detection_type) {
- case _explicit: {
- alpha = 1.0;
- break;
- }
- case _implicit: {
+ Real alpha{1.0};
+ if (detection_type == _implicit) {
alpha = -1.0;
- break;
}
- default:
- AKANTU_EXCEPTION(detection_type
- << " is not a valid contact detection type");
- break;
- }
-
- for (auto & pairs : contact_pairs) {
- const auto & slave_node = pairs.first;
+ auto gaps_it = gaps.begin();
+ auto normals_it = normals.begin(spatial_dimension);
+ auto tangents_it = tangents.begin(spatial_dimension, surface_dimension);
+ auto projections_it = projections.begin(surface_dimension);
+ auto pos_it = make_view(positions, spatial_dimension).begin();
- Vector<Real> slave(spatial_dimension);
- for (UInt s : arange(spatial_dimension)) {
- slave(s) = this->positions(slave_node, s);
- }
+ for (auto && [slave_node, master_node] : contact_pairs) {
+ const auto & slave = pos_it[slave_node];
+ auto && elements = this->mesh.getAssociatedElements(master_node);
- const auto & master_node = pairs.second;
- Array<Element> elements;
- this->mesh.getAssociatedElements(master_node, elements);
+ auto && gap = gaps_it[slave_node];
+ auto && normal = normals_it[slave_node];
+ auto && tangent = tangents_it[slave_node];
+ auto && projection = projections_it[slave_node];
- auto & gap = gaps.begin()[slave_node];
- Vector<Real> normal(normals.begin(spatial_dimension)[slave_node]);
- Vector<Real> projection(projections.begin(surface_dimension)[slave_node]);
- Matrix<Real> tangent(
- tangents.begin(surface_dimension, spatial_dimension)[slave_node]);
- auto index = GeometryUtils::orthogonalProjection(
+ auto found_element = GeometryUtils::orthogonalProjection(
mesh, positions, slave, elements, gap, projection, normal, tangent,
alpha, this->max_iterations, this->projection_tolerance,
this->extension_tolerance);
// if a valid projection is not found on the patch of elements
// index is -1 or if not a valid self contact, the contact element
// is not created
- if (index == UInt(-1) or !isValidSelfContact(slave_node, gap, normal)) {
- gap *= 0;
- normal *= 0;
- projection *= 0;
- tangent *= 0;
+ if (found_element == ElementNull or
+ !isValidSelfContact(slave_node, gap, normal)) {
+ gap = 0.;
+ normal.zero();
+ projection.zero();
+ tangent.zero();
continue;
}
// create contact element
- contact_elements.push_back(ContactElement(slave_node, elements[index]));
+ contact_elements.push_back(ContactElement(slave_node, found_element));
}
contact_pairs.clear();
}
} // namespace akantu
diff --git a/src/model/contact_mechanics/contact_detector.hh b/src/model/contact_mechanics/contact_detector.hh
index 00f84dd66..3463e8cdf 100644
--- a/src/model/contact_mechanics/contact_detector.hh
+++ b/src/model/contact_mechanics/contact_detector.hh
@@ -1,218 +1,232 @@
/**
* @file contact_detector.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Thu Jun 24 2021
*
* @brief Mother class for all detection algorithms
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_bbox.hh"
#include "aka_common.hh"
#include "aka_grid_dynamic.hh"
#include "contact_element.hh"
#include "element_class.hh"
#include "element_group.hh"
#include "fe_engine.hh"
#include "geometry_utils.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "parsable.hh"
#include "surface_selector.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_CONTACT_DETECTOR_HH__
#define __AKANTU_CONTACT_DETECTOR_HH__
namespace akantu {
enum class Surface { master, slave };
/* -------------------------------------------------------------------------- */
class ContactDetector : public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructor/Destructors */
/* ------------------------------------------------------------------------ */
public:
ContactDetector(Mesh & /*mesh*/, const ID & id = "contact_detector");
ContactDetector(Mesh & /*mesh*/, Array<Real> positions,
const ID & id = "contact_detector");
~ContactDetector() override = default;
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
public:
/// performs all search steps
void search(Array<ContactElement> & elements, Array<Real> & gaps,
Array<Real> & normals, Array<Real> & tangents,
Array<Real> & projections);
/// performs global spatial search to construct spatial grids
- void globalSearch(SpatialGrid<UInt> & /*slave_grid*/,
- SpatialGrid<UInt> & /*master_grid*/);
+ std::pair<BBox, std::unique_ptr<SpatialGrid<Idx>>> globalSearch() const;
/// performs local search to find closet master node to a slave node
- void localSearch(SpatialGrid<UInt> & /*slave_grid*/,
- SpatialGrid<UInt> & /*master_grid*/);
+ void localSearch(const BBox & intersection,
+ const SpatialGrid<Idx> & master_grid);
/// create contact elements
void createContactElements(Array<ContactElement> & elements,
Array<Real> & gaps, Array<Real> & normals,
Array<Real> & tangents, Array<Real> & projections);
private:
/// reads the input file to get contact detection options
void parseSection(const ParserSection & section) override;
/* ------------------------------------------------------------------------ */
/* Inline Methods */
/* ------------------------------------------------------------------------ */
public:
/// checks whether the natural projection is valid or not
- inline bool checkValidityOfProjection(Vector<Real> & projection) const;
+ template <class Derived,
+ std::enable_if_t<aka::is_vector_v<Derived>> * = nullptr>
+ inline bool
+ checkValidityOfProjection(Eigen::MatrixBase<Derived> & projection) const;
/// extracts the coordinates of an element
+ template <class Derived>
inline void coordinatesOfElement(const Element & el,
- Matrix<Real> & coords) const;
+ Eigen::MatrixBase<Derived> & coords) const;
/// computes the optimal cell size for grid
- inline void computeCellSpacing(Vector<Real> & spacing) const;
+ template <class Derived,
+ std::enable_if_t<aka::is_vector_v<Derived>> * = nullptr>
+ inline void computeCellSpacing(Eigen::MatrixBase<Derived> & spacing) const;
/// constructs a grid containing nodes lying within bounding box
- inline void constructGrid(SpatialGrid<UInt> & grid, BBox & bbox,
- const Array<UInt> & nodes_list) const;
+ inline void constructGrid(SpatialGrid<Idx> & grid, BBox & bbox,
+ const Array<Idx> & nodes_list) const;
/// constructs the bounding box based on nodes list
inline void constructBoundingBox(BBox & bbox,
- const Array<UInt> & nodes_list) const;
+ const Array<Idx> & nodes_list) const;
/// computes the maximum in radius for a given mesh
inline void computeMaximalDetectionDistance();
/// constructs the connectivity for a contact element
- inline Vector<UInt> constructConnectivity(UInt & slave,
- const Element & master) const;
+ inline Vector<Idx> constructConnectivity(Idx & slave,
+ const Element & master) const;
/// computes normal on an element
+ template <class Derived,
+ std::enable_if_t<aka::is_vector_v<Derived>> * = nullptr>
inline void computeNormalOnElement(const Element & element,
- Vector<Real> & normal) const;
+ Eigen::MatrixBase<Derived> & normal) const;
/// extracts vectors which forms the plane of element
+ template <class Derived>
inline void vectorsAlongElement(const Element & el,
- Matrix<Real> & vectors) const;
+ Eigen::MatrixBase<Derived> & vectors) const;
/// computes the gap between slave and its projection on master
/// surface
- inline Real computeGap(const Vector<Real> & slave,
- const Vector<Real> & master) const;
+ template <
+ class Derived1, class Derived2,
+ std::enable_if_t<aka::are_vectors<Derived1, Derived2>::value> * = nullptr>
+ inline Real computeGap(const Eigen::MatrixBase<Derived1> & slave,
+ const Eigen::MatrixBase<Derived2> & master) const;
/// filter boundary elements
inline void filterBoundaryElements(const Array<Element> & elements,
Array<Element> & boundary_elements) const;
/// checks whether self contact condition leads to a master element
/// which is closet but not orthogonally opposite to slave surface
- inline bool isValidSelfContact(const UInt & slave_node, const Real & gap,
- const Vector<Real> & normal) const;
+ template <class Derived,
+ std::enable_if_t<aka::is_vector_v<Derived>> * = nullptr>
+ inline bool
+ isValidSelfContact(const Idx & slave_node, const Real & gap,
+ const Eigen::MatrixBase<Derived> & normal) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the mesh
AKANTU_GET_MACRO(Mesh, mesh, Mesh &)
/// returns the maximum detection distance
AKANTU_GET_MACRO(MaximumDetectionDistance, max_dd, Real);
AKANTU_SET_MACRO(MaximumDetectionDistance, max_dd, Real);
/// returns the bounding box extension
AKANTU_GET_MACRO(MaximumBoundingBox, max_bb, Real);
AKANTU_SET_MACRO(MaximumBoundingBox, max_bb, Real);
/// returns the minimum detection distance
AKANTU_GET_MACRO(MinimumDetectionDistance, min_dd, Real);
AKANTU_SET_MACRO(MinimumDetectionDistance, min_dd, Real);
AKANTU_GET_MACRO_NOT_CONST(Positions, positions, Array<Real> &);
AKANTU_SET_MACRO(Positions, positions, Array<Real>);
AKANTU_GET_MACRO_NOT_CONST(SurfaceSelector, *surface_selector,
SurfaceSelector &);
AKANTU_SET_MACRO(SurfaceSelector, surface_selector,
std::shared_ptr<SurfaceSelector>);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// maximal detection distance for grid spacing
Real max_dd;
/// minimal detection distance for grid spacing
Real min_dd;
/// maximal bounding box extension
Real max_bb;
/// tolerance for finding natural projection
Real projection_tolerance;
/// iterations for finding natural projection
- UInt max_iterations;
+ Int max_iterations;
/// tolerance for extending a master elements on all sides
Real extension_tolerance;
/// Mesh
Mesh & mesh;
/// dimension of the model
- UInt spatial_dimension{0};
+ Int spatial_dimension{0};
/// node selector for selecting master and slave nodes
std::shared_ptr<SurfaceSelector> surface_selector;
/// contact pair slave node to closet master node
- std::vector<std::pair<UInt, UInt>> contact_pairs;
+ std::vector<std::pair<Idx, Idx>> contact_pairs;
/// contains the updated positions of the nodes
Array<Real> positions;
/// type of detection explicit/implicit
DetectionType detection_type;
};
} // namespace akantu
#include "contact_detector_inline_impl.cc"
#endif /* __AKANTU_CONTACT_DETECTOR_HH__ */
diff --git a/src/model/contact_mechanics/contact_detector_inline_impl.cc b/src/model/contact_mechanics/contact_detector_inline_impl.cc
index eaed7c983..f6a08392b 100644
--- a/src/model/contact_mechanics/contact_detector_inline_impl.cc
+++ b/src/model/contact_mechanics/contact_detector_inline_impl.cc
@@ -1,316 +1,300 @@
/**
* @file contact_detector_inline_impl.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed May 08 2019
* @date last modification: Thu Jun 24 2021
*
* @brief inine implementation of the contact detector class
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_detector.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_CONTACT_DETECTOR_INLINE_IMPL_CC__
#define __AKANTU_CONTACT_DETECTOR_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline bool
-ContactDetector::checkValidityOfProjection(Vector<Real> & projection) const {
+template <class Derived, std::enable_if_t<aka::is_vector_v<Derived>> *>
+inline bool ContactDetector::checkValidityOfProjection(
+ Eigen::MatrixBase<Derived> & projection) const {
Real tolerance = 1e-3;
return std::all_of(projection.begin(), projection.end(),
[&tolerance](auto && xi) {
return (xi > -1.0 - tolerance) or (xi < 1.0 + tolerance);
});
}
/* -------------------------------------------------------------------------- */
-inline void ContactDetector::coordinatesOfElement(const Element & el,
- Matrix<Real> & coords) const {
-
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type);
- const Vector<UInt> connect = mesh.getConnectivity(el.type, _not_ghost)
- .begin(nb_nodes_per_element)[el.element];
-
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- UInt node = connect[n];
- for (UInt s : arange(spatial_dimension)) {
- coords(s, n) = this->positions(node, s);
- }
- }
+template <class Derived>
+inline void ContactDetector::coordinatesOfElement(
+ const Element & el, Eigen::MatrixBase<Derived> & coords) const {
+ coords = mesh.extractNodalValuesFromElement(positions, el);
}
/* -------------------------------------------------------------------------- */
-inline void ContactDetector::computeCellSpacing(Vector<Real> & spacing) const {
- for (UInt s : arange(spatial_dimension)) {
- spacing(s) = std::sqrt(2.0) * max_dd;
- }
+template <class Derived, std::enable_if_t<aka::is_vector_v<Derived>> *>
+inline void ContactDetector::computeCellSpacing(
+ Eigen::MatrixBase<Derived> & spacing) const {
+ spacing.fill(std::sqrt(2.0) * max_dd);
}
/* -------------------------------------------------------------------------- */
inline void
-ContactDetector::constructGrid(SpatialGrid<UInt> & grid, BBox & bbox,
- const Array<UInt> & nodes_list) const {
- auto to_grid = [&](UInt node) {
- Vector<Real> pos(spatial_dimension);
- for (UInt s : arange(spatial_dimension)) {
- pos(s) = this->positions(node, s);
- }
-
+ContactDetector::constructGrid(SpatialGrid<Idx> & grid, BBox & bbox,
+ const Array<Idx> & nodes_list) const {
+ auto position_it = make_view(this->positions, spatial_dimension).begin();
+ auto to_grid = [&](auto node) {
+ auto && pos = position_it[node];
if (bbox.contains(pos)) {
grid.insert(node, pos);
}
};
std::for_each(nodes_list.begin(), nodes_list.end(), to_grid);
}
/* -------------------------------------------------------------------------- */
inline void
ContactDetector::constructBoundingBox(BBox & bbox,
- const Array<UInt> & nodes_list) const {
- auto to_bbox = [&](UInt node) {
- Vector<Real> pos(spatial_dimension);
- for (UInt s : arange(spatial_dimension)) {
- pos(s) = this->positions(node, s);
- }
+ const Array<Idx> & nodes_list) const {
+ auto to_bbox = [&](auto node) {
+ auto && pos = make_view(this->positions, spatial_dimension).begin()[node];
bbox += pos;
};
std::for_each(nodes_list.begin(), nodes_list.end(), to_bbox);
- auto & lower_bound = bbox.getLowerBounds();
- auto & upper_bound = bbox.getUpperBounds();
+ Vector<Real> lower_bound = bbox.getLowerBounds().array() - max_bb;
+ Vector<Real> upper_bound = bbox.getUpperBounds().array() + max_bb;
- lower_bound -= this->max_bb;
- upper_bound += this->max_bb;
+ bbox.setLowerBounds(lower_bound);
+ bbox.setUpperBounds(upper_bound);
AKANTU_DEBUG_INFO("BBox" << bbox);
}
/* -------------------------------------------------------------------------- */
inline void ContactDetector::computeMaximalDetectionDistance() {
Real elem_size;
Real max_elem_size = std::numeric_limits<Real>::min();
Real min_elem_size = std::numeric_limits<Real>::max();
auto & master_nodes = this->surface_selector->getMasterList();
for (auto & master : master_nodes) {
Array<Element> elements;
this->mesh.getAssociatedElements(master, elements);
for (auto element : elements) {
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element.type);
+ Int nb_nodes_per_element = mesh.getNbNodesPerElement(element.type);
Matrix<Real> elem_coords(spatial_dimension, nb_nodes_per_element);
this->coordinatesOfElement(element, elem_coords);
elem_size = FEEngine::getElementInradius(elem_coords, element.type);
max_elem_size = std::max(max_elem_size, elem_size);
min_elem_size = std::min(min_elem_size, elem_size);
}
}
AKANTU_DEBUG_INFO("The maximum element size : " << max_elem_size);
this->min_dd = min_elem_size;
this->max_dd = max_elem_size;
this->max_bb = max_elem_size;
}
/* -------------------------------------------------------------------------- */
-inline Vector<UInt>
-ContactDetector::constructConnectivity(UInt & slave,
+inline Vector<Idx>
+ContactDetector::constructConnectivity(Idx & slave,
const Element & master) const {
- const Vector<UInt> master_conn = this->mesh.getConnectivity(master);
+ auto && master_conn = this->mesh.getConnectivity(master);
- Vector<UInt> elem_conn(master_conn.size() + 1);
+ Vector<Idx> elem_conn(master_conn.size() + 1);
elem_conn[0] = slave;
- for (UInt i = 1; i < elem_conn.size(); ++i) {
- elem_conn[i] = master_conn[i - 1];
- }
+ elem_conn.block(1, 0, master_conn.size(), 1) = master_conn;
return elem_conn;
}
/* -------------------------------------------------------------------------- */
-inline void
-ContactDetector::computeNormalOnElement(const Element & element,
- Vector<Real> & normal) const {
+template <class Derived, std::enable_if_t<aka::is_vector_v<Derived>> *>
+inline void ContactDetector::computeNormalOnElement(
+ const Element & element, Eigen::MatrixBase<Derived> & normal) const {
Matrix<Real> vectors(spatial_dimension, spatial_dimension - 1);
this->vectorsAlongElement(element, vectors);
switch (this->spatial_dimension) {
case 2: {
- Math::normal2(vectors.storage(), normal.storage());
+ normal = Math::normal(vectors);
break;
}
case 3: {
- Math::normal3(vectors(0).storage(), vectors(1).storage(), normal.storage());
+ normal = Math::normal(vectors.col(0), vectors.col(1));
break;
}
default: {
AKANTU_ERROR("Unknown dimension : " << spatial_dimension);
}
}
// to ensure that normal is always outwards from master surface
const auto & element_to_subelement =
mesh.getElementToSubelement(element.type)(element.element);
- Vector<Real> outside(spatial_dimension);
- mesh.getBarycenter(element, outside);
+ Vector<Real> outside = mesh.getBarycenter(element);
// check if mesh facets exists for cohesive elements contact
- Vector<Real> inside(spatial_dimension);
+ Vector<Real> inside;
if (mesh.isMeshFacets()) {
- mesh.getMeshParent().getBarycenter(element_to_subelement[0], inside);
+ inside = mesh.getMeshParent().getBarycenter(element_to_subelement[0]);
} else {
- mesh.getBarycenter(element_to_subelement[0], inside);
+ inside = mesh.getBarycenter(element_to_subelement[0]);
}
- Vector<Real> inside_to_outside = outside - inside;
- auto projection = inside_to_outside.dot(normal);
+ auto projection = (outside - inside).dot(normal);
if (projection < 0) {
normal *= -1.0;
}
}
/* -------------------------------------------------------------------------- */
-inline void ContactDetector::vectorsAlongElement(const Element & el,
- Matrix<Real> & vectors) const {
+template <class Derived>
+inline void ContactDetector::vectorsAlongElement(
+ const Element & el, Eigen::MatrixBase<Derived> & vectors) const {
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type);
Matrix<Real> coords(spatial_dimension, nb_nodes_per_element);
this->coordinatesOfElement(el, coords);
for (auto i : arange(spatial_dimension - 1)) {
- vectors(i) = Vector<Real>(coords(i + 1)) - Vector<Real>(coords(0));
+ vectors(i) = coords(i + 1) - coords(0);
}
}
/* -------------------------------------------------------------------------- */
-inline Real ContactDetector::computeGap(const Vector<Real> & slave,
- const Vector<Real> & master) const {
+template <class Derived1, class Derived2,
+ std::enable_if_t<aka::are_vectors<Derived1, Derived2>::value> *>
+inline Real
+ContactDetector::computeGap(const Eigen::MatrixBase<Derived1> & slave,
+ const Eigen::MatrixBase<Derived2> & master) const {
auto gap = (master - slave).norm();
return gap;
}
/* -------------------------------------------------------------------------- */
inline void ContactDetector::filterBoundaryElements(
const Array<Element> & elements, Array<Element> & boundary_elements) const {
for (auto elem : elements) {
const auto & element_to_subelement =
mesh.getElementToSubelement(elem.type)(elem.element);
// for regular boundary elements
if (element_to_subelement.size() == 1 and
element_to_subelement[0].kind() == _ek_regular) {
boundary_elements.push_back(elem);
continue;
}
// for cohesive boundary elements
UInt nb_subelements_regular = 0;
for (auto subelem : element_to_subelement) {
if (subelem == ElementNull) {
continue;
}
if (subelem.kind() == _ek_regular) {
++nb_subelements_regular;
}
}
auto nb_subelements = element_to_subelement.size();
if (nb_subelements_regular < nb_subelements) {
boundary_elements.push_back(elem);
}
}
}
/* -------------------------------------------------------------------------- */
-inline bool
-ContactDetector::isValidSelfContact(const UInt & slave_node, const Real & gap,
- const Vector<Real> & normal) const {
- UInt master_node;
+template <class Derived, std::enable_if_t<aka::is_vector_v<Derived>> *>
+inline bool ContactDetector::isValidSelfContact(
+ const Idx & slave_node, const Real & gap,
+ const Eigen::MatrixBase<Derived> & normal) const {
+ Idx master_node{-1};
// finding the master node corresponding to slave node
- for (auto && pair : contact_pairs) {
- if (pair.first == slave_node) {
- master_node = pair.second;
- break;
- }
- }
+ auto it = std::find_if(
+ contact_pairs.begin(), contact_pairs.end(),
+ [slave_node](auto && pair) { return pair.first == slave_node; });
+ master_node = it->second;
- Array<Element> slave_elements;
- this->mesh.getAssociatedElements(slave_node, slave_elements);
+ auto && slave_elements = this->mesh.getAssociatedElements(slave_node);
// Check 1 : master node is not connected to elements connected to
// slave node
Vector<Real> slave_normal(spatial_dimension);
- for (auto & element : slave_elements) {
- if (element.kind() != _ek_regular) {
- continue;
- }
+ for (auto & element : filter_if(slave_elements, [](auto && element) {
+ return element.kind() == _ek_regular;
+ })) {
+
+ auto && connectivity = this->mesh.getConnectivity(element);
- const Vector<UInt> connectivity = this->mesh.getConnectivity(element);
+ auto coords = mesh.extractNodalValuesFromElement(positions, element);
// finding the normal at slave node by averaging of normals
- Vector<Real> normal(spatial_dimension);
- GeometryUtils::normal(mesh, positions, element, normal);
+ auto normal = GeometryUtils::normal(mesh, coords, element);
slave_normal = slave_normal + normal;
auto node_iter =
std::find(connectivity.begin(), connectivity.end(), master_node);
if (node_iter != connectivity.end()) {
return false;
}
}
// Check 2 : if gap is twice the size of smallest element
if (std::abs(gap) > 2.0 * min_dd) {
return false;
}
// Check 3 : check the directions of normal at slave node and at
// master element, should be in opposite directions
auto norm = slave_normal.norm();
if (norm != 0) {
slave_normal /= norm;
}
auto product = slave_normal.dot(normal);
return not(product >= 0);
}
} // namespace akantu
#endif /* __AKANTU_CONTACT_DETECTOR_INLINE_IMPL_CC__ */
diff --git a/src/model/contact_mechanics/contact_element.hh b/src/model/contact_mechanics/contact_element.hh
index b97ae3c7d..f23220f3f 100644
--- a/src/model/contact_mechanics/contact_element.hh
+++ b/src/model/contact_mechanics/contact_element.hh
@@ -1,87 +1,87 @@
/**
* @file contact_element.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Tue Jun 08 2021
*
* @brief Mother class for all detection algorithms
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "element.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_CONTACT_ELEMENT_HH__
#define __AKANTU_CONTACT_ELEMENT_HH__
/* -------------------------------------------------------------------------- */
namespace akantu {
-using SlaveType = UInt;
+using SlaveType = Idx;
using MasterType = Element;
class ContactElement {
/* ------------------------------------------------------------------------ */
/* Constructor/ Destructors */
/* ------------------------------------------------------------------------ */
public:
ContactElement() = default;
ContactElement(const SlaveType & slave, const MasterType & master)
: slave(slave), master(master) {}
~ContactElement() = default;
bool operator==(const ContactElement & other) const {
return slave == other.slave and master == other.master;
}
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
inline UInt getNbNodes() const {
auto nb_master_nodes = Mesh::getNbNodesPerElement(master.type);
return nb_master_nodes + 1;
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
public:
/// slave node
SlaveType slave;
/// master element/node
MasterType master;
};
} // namespace akantu
#endif /* __AKANTU_CONTACT_ELEMENT_HH__ */
diff --git a/src/model/contact_mechanics/contact_mechanics_model.cc b/src/model/contact_mechanics/contact_mechanics_model.cc
index 2f4ffa575..dac3a442e 100644
--- a/src/model/contact_mechanics/contact_mechanics_model.cc
+++ b/src/model/contact_mechanics/contact_mechanics_model.cc
@@ -1,706 +1,675 @@
/**
* @file contact_mechanics_model.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Wed Jul 28 2021
*
* @brief Contact mechanics model
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "boundary_condition_functor.hh"
#include "dumpable_inline_impl.hh"
#include "group_manager_inline_impl.hh"
#include "integrator_gauss.hh"
#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
ContactMechanicsModel::ContactMechanicsModel(
- Mesh & mesh, UInt dim, const ID & id,
+ Mesh & mesh, Int dim, const ID & id,
std::shared_ptr<DOFManager> dof_manager, const ModelType model_type)
: Model(mesh, model_type, dim, id) {
AKANTU_DEBUG_IN();
this->initDOFManager(dof_manager);
this->registerFEEngineObject<MyFEEngineType>("ContactMechanicsModel", mesh,
Model::spatial_dimension);
this->mesh.registerDumper<DumperParaview>("contact_mechanics", id, true);
this->mesh.addDumpMeshToDumper("contact_mechanics", mesh,
Model::spatial_dimension - 1, _not_ghost,
_ek_regular);
this->registerDataAccessor(*this);
this->detector =
std::make_unique<ContactDetector>(this->mesh, id + ":contact_detector");
registerFEEngineObject<MyFEEngineType>("ContactFacetsFEEngine", mesh,
Model::spatial_dimension - 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
ContactMechanicsModel::~ContactMechanicsModel() = default;
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::initFullImpl(const ModelOptions & options) {
Model::initFullImpl(options);
// initalize the resolutions
if (not this->parser.getLastParsedFile().empty()) {
this->instantiateResolutions();
this->initResolutions();
}
this->initBC(*this, *displacement, *displacement_increment, *external_force);
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::instantiateResolutions() {
ParserSection model_section;
bool is_empty;
std::tie(model_section, is_empty) = this->getParserSection();
if (not is_empty) {
auto model_resolutions =
model_section.getSubSections(ParserType::_contact_resolution);
for (const auto & section : model_resolutions) {
this->registerNewResolution(section);
}
}
auto sub_sections =
this->parser.getSubSections(ParserType::_contact_resolution);
for (const auto & section : sub_sections) {
this->registerNewResolution(section);
}
if (resolutions.empty()) {
AKANTU_EXCEPTION("No contact resolutions where instantiated for the model"
<< getID());
}
are_resolutions_instantiated = true;
}
/* -------------------------------------------------------------------------- */
Resolution &
ContactMechanicsModel::registerNewResolution(const ParserSection & section) {
std::string res_name;
std::string res_type = section.getName();
std::string opt_param = section.getOption();
try {
std::string tmp = section.getParameter("name");
res_name = tmp; /** this can seem weird, but there is an ambiguous operator
* overload that i couldn't solve. @todo remove the
* weirdness of this code
*/
} catch (debug::Exception &) {
AKANTU_ERROR("A contact resolution of type \'"
<< res_type
<< "\' in the input file has been defined without a name!");
}
Resolution & res = this->registerNewResolution(res_name, res_type, opt_param);
res.parseSection(section);
return res;
}
/* -------------------------------------------------------------------------- */
Resolution & ContactMechanicsModel::registerNewResolution(
const ID & res_name, const ID & res_type, const ID & opt_param) {
AKANTU_DEBUG_ASSERT(resolutions_names_to_id.find(res_name) ==
resolutions_names_to_id.end(),
"A resolution with this name '"
<< res_name << "' has already been registered. "
<< "Please use unique names for resolutions");
UInt res_count = resolutions.size();
resolutions_names_to_id[res_name] = res_count;
std::stringstream sstr_res;
sstr_res << this->id << ":" << res_count << ":" << res_type;
ID res_id = sstr_res.str();
std::unique_ptr<Resolution> resolution =
ResolutionFactory::getInstance().allocate(res_type, spatial_dimension,
opt_param, *this, res_id);
resolutions.push_back(std::move(resolution));
return *(resolutions.back());
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::initResolutions() {
AKANTU_DEBUG_ASSERT(resolutions.size() != 0,
"No resolutions to initialize !");
if (!are_resolutions_instantiated) {
instantiateResolutions();
}
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::initModel() {
AKANTU_DEBUG_IN();
getFEEngine("ContactMechanicsModel").initShapeFunctions(_not_ghost);
getFEEngine("ContactMechanicsModel").initShapeFunctions(_ghost);
getFEEngine("ContactFacetsFEEngine").initShapeFunctions(_not_ghost);
getFEEngine("ContactFacetsFEEngine").initShapeFunctions(_ghost);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
FEEngine & ContactMechanicsModel::getFEEngineBoundary(const ID & name) {
return dynamic_cast<FEEngine &>(
getFEEngineClassBoundary<MyFEEngineType>(name));
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::initSolver(
TimeStepSolverType /*time_step_solver_type*/,
NonLinearSolverType /*unused*/) {
// for alloc type of solvers
this->allocNodalField(this->displacement, spatial_dimension, "displacement");
this->allocNodalField(this->displacement_increment, spatial_dimension,
"displacement_increment");
this->allocNodalField(this->internal_force, spatial_dimension,
"internal_force");
this->allocNodalField(this->external_force, spatial_dimension,
"external_force");
this->allocNodalField(this->normal_force, spatial_dimension, "normal_force");
this->allocNodalField(this->tangential_force, spatial_dimension,
"tangential_force");
this->allocNodalField(this->gaps, 1, "gaps");
this->allocNodalField(this->nodal_area, 1, "areas");
this->allocNodalField(this->blocked_dofs, 1, "blocked_dofs");
this->allocNodalField(this->contact_state, 1, "contact_state");
this->allocNodalField(this->previous_master_elements, 1,
"previous_master_elements");
this->allocNodalField(this->normals, spatial_dimension, "normals");
auto surface_dimension = spatial_dimension - 1;
this->allocNodalField(this->tangents, surface_dimension * spatial_dimension,
"tangents");
this->allocNodalField(this->projections, surface_dimension, "projections");
this->allocNodalField(this->previous_projections, surface_dimension,
"previous_projections");
this->allocNodalField(this->previous_tangents,
surface_dimension * spatial_dimension,
"previous_tangents");
this->allocNodalField(this->tangential_tractions, surface_dimension,
"tangential_tractions");
this->allocNodalField(this->previous_tangential_tractions, surface_dimension,
"previous_tangential_tractions");
// todo register multipliers as dofs for lagrange multipliers
}
/* -------------------------------------------------------------------------- */
std::tuple<ID, TimeStepSolverType>
ContactMechanicsModel::getDefaultSolverID(const AnalysisMethod & method) {
switch (method) {
case _explicit_lumped_mass: {
return std::make_tuple("explicit_lumped",
TimeStepSolverType::_dynamic_lumped);
}
case _explicit_consistent_mass: {
return std::make_tuple("explicit", TimeStepSolverType::_dynamic);
}
case _static: {
return std::make_tuple("static", TimeStepSolverType::_static);
}
case _implicit_dynamic: {
return std::make_tuple("implicit", TimeStepSolverType::_dynamic);
}
default:
return std::make_tuple("unknown", TimeStepSolverType::_not_defined);
}
}
/* -------------------------------------------------------------------------- */
ModelSolverOptions ContactMechanicsModel::getDefaultSolverOptions(
const TimeStepSolverType & type) const {
ModelSolverOptions options;
switch (type) {
case TimeStepSolverType::_dynamic: {
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
break;
}
case TimeStepSolverType::_dynamic_lumped: {
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
break;
}
case TimeStepSolverType::_static: {
options.non_linear_solver_type =
NonLinearSolverType::_newton_raphson_contact;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_pseudo_time;
options.solution_type["displacement"] = IntegrationScheme::_not_defined;
break;
}
default:
AKANTU_EXCEPTION(type << " is not a valid time step solver type");
break;
}
return options;
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::assembleResidual() {
AKANTU_DEBUG_IN();
/* ------------------------------------------------------------------------ */
// computes the internal forces
this->assembleInternalForces();
/* ------------------------------------------------------------------------ */
this->getDOFManager().assembleToResidual("displacement",
*this->internal_force, 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::assembleInternalForces() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the contact forces");
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
this->internal_force->clear();
this->normal_force->clear();
this->tangential_force->clear();
internal_force->resize(nb_nodes, 0.);
normal_force->resize(nb_nodes, 0.);
tangential_force->resize(nb_nodes, 0.);
// assemble the forces due to contact
auto assemble = [&](auto && ghost_type) {
for (auto & resolution : resolutions) {
resolution->assembleInternalForces(ghost_type);
}
};
AKANTU_DEBUG_INFO("Assemble residual for local elements");
assemble(_not_ghost);
// assemble the stresses due to ghost elements
// AKANTU_DEBUG_INFO("Assemble residual for ghost elements");
// assemble(_ghost);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::search() {
// save the previous state
this->savePreviousState();
contact_elements.clear();
// this needs to be resized if cohesive elements are added
UInt nb_nodes = mesh.getNbNodes();
auto resize_arrays = [&](auto & internal_array) {
internal_array->resize(nb_nodes);
internal_array->zero();
};
resize_arrays(gaps);
resize_arrays(normals);
resize_arrays(tangents);
resize_arrays(projections);
resize_arrays(tangential_tractions);
resize_arrays(contact_state);
resize_arrays(nodal_area);
resize_arrays(external_force);
this->detector->search(contact_elements, *gaps, *normals, *tangents,
*projections);
// interpenetration value must be positive for contact mechanics
// model to work by default the gap value from detector is negative
std::for_each((*gaps).begin(), (*gaps).end(), [](Real & gap) { gap *= -1.; });
- if (!contact_elements.empty()) {
+ if (not contact_elements.empty()) {
this->computeNodalAreas();
}
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::savePreviousState() {
AKANTU_DEBUG_IN();
// saving previous natural projections
(*previous_projections).copy(*projections);
// saving previous tangents
(*previous_tangents).copy(*tangents);
// saving previous tangential traction
(*previous_tangential_tractions).copy(*tangential_tractions);
previous_master_elements->clear();
previous_master_elements->resize(projections->size());
previous_master_elements->set(ElementNull);
for (auto & element : contact_elements) {
(*previous_master_elements)[element.slave] = element.master;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::computeNodalAreas(GhostType ghost_type) {
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
nodal_area->resize(nb_nodes);
nodal_area->zero();
external_force->resize(nb_nodes);
external_force->zero();
auto & fem_boundary =
getFEEngineClassBoundary<MyFEEngineType>("ContactMechanicsModel");
fem_boundary.initShapeFunctions(getPositions(), _not_ghost);
fem_boundary.initShapeFunctions(getPositions(), _ghost);
fem_boundary.computeNormalsOnIntegrationPoints(_not_ghost);
fem_boundary.computeNormalsOnIntegrationPoints(_ghost);
IntegrationPoint quad_point;
quad_point.ghost_type = ghost_type;
auto & group = mesh.getElementGroup("contact_surface");
UInt nb_degree_of_freedom = external_force->getNbComponent();
for (auto && type : group.elementTypes(spatial_dimension - 1, ghost_type)) {
const auto & element_ids = group.getElements(type, ghost_type);
- UInt nb_quad_points = fem_boundary.getNbIntegrationPoints(type, ghost_type);
- UInt nb_elements = element_ids.size();
+ auto nb_quad_points = fem_boundary.getNbIntegrationPoints(type, ghost_type);
+ auto nb_elements = element_ids.size();
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> dual_before_integ(nb_elements * nb_quad_points,
- nb_degree_of_freedom, 0.);
+ nb_degree_of_freedom);
Array<Real> quad_coords(nb_elements * nb_quad_points, spatial_dimension);
const auto & normals_on_quad =
fem_boundary.getNormalsOnIntegrationPoints(type, ghost_type);
auto normals_begin = normals_on_quad.begin(spatial_dimension);
decltype(normals_begin) normals_iter;
auto quad_coords_iter = quad_coords.begin(spatial_dimension);
auto dual_iter = dual_before_integ.begin(nb_degree_of_freedom);
quad_point.type = type;
- Element subelement;
- subelement.type = type;
- subelement.ghost_type = ghost_type;
+ Element subelement{type, 0, ghost_type};
for (auto el : element_ids) {
subelement.element = el;
- const auto & element_to_subelement =
- mesh.getElementToSubelement(type)(el);
-
- Vector<Real> outside(spatial_dimension);
- mesh.getBarycenter(subelement, outside);
-
- Vector<Real> inside(spatial_dimension);
- if (mesh.isMeshFacets()) {
- mesh.getMeshParent().getBarycenter(element_to_subelement[0], inside);
- } else {
- mesh.getBarycenter(element_to_subelement[0], inside);
- }
- Vector<Real> inside_to_outside(spatial_dimension);
- inside_to_outside = outside - inside;
+ auto inside_to_outside =
+ GeometryUtils::outsideDirection(mesh, subelement);
normals_iter = normals_begin + el * nb_quad_points;
quad_point.element = el;
for (auto q : arange(nb_quad_points)) {
quad_point.num_point = q;
- auto ddot = inside_to_outside.dot(*normals_iter);
- Vector<Real> normal(*normals_iter);
+
+ auto & normal = *normals_iter;
+ auto ddot = inside_to_outside.dot(normal);
+
if (ddot < 0) {
normal *= -1.0;
}
- (*dual_iter)
- .mul<false>(Matrix<Real>::eye(spatial_dimension, 1), normal);
+ (*dual_iter) =
+ Matrix<Real>::Identity(spatial_dimension, spatial_dimension) *
+ normal;
+
++dual_iter;
++quad_coords_iter;
++normals_iter;
}
}
Array<Real> dual_by_shapes(nb_elements * nb_quad_points,
nb_degree_of_freedom * nb_nodes_per_element);
fem_boundary.computeNtb(dual_before_integ, dual_by_shapes, type, ghost_type,
element_ids);
Array<Real> dual_by_shapes_integ(nb_elements, nb_degree_of_freedom *
nb_nodes_per_element);
fem_boundary.integrate(dual_by_shapes, dual_by_shapes_integ,
nb_degree_of_freedom * nb_nodes_per_element, type,
ghost_type, element_ids);
this->getDOFManager().assembleElementalArrayLocalArray(
dual_by_shapes_integ, *external_force, type, ghost_type, 1.,
element_ids);
}
for (auto && tuple :
zip(*nodal_area, make_view(*external_force, spatial_dimension))) {
auto & area = std::get<0>(tuple);
- Vector<Real> force(std::get<1>(tuple));
+ auto & force = std::get<1>(tuple);
area = force.norm();
}
this->external_force->clear();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "Contact Mechanics Model [" << std::endl;
stream << space << " + id : " << id << std::endl;
stream << space << " + spatial dimension : " << Model::spatial_dimension
<< std::endl;
stream << space << " + fem [" << std::endl;
getFEEngine().printself(stream, indent + 2);
stream << space << AKANTU_INDENT << "]" << std::endl;
stream << space << " + resolutions [" << std::endl;
for (const auto & resolution : resolutions) {
resolution->printself(stream, indent + 1);
}
stream << space << AKANTU_INDENT << "]" << std::endl;
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
MatrixType ContactMechanicsModel::getMatrixType(const ID & matrix_id) const {
if (matrix_id == "K") {
return _symmetric;
}
return _mt_not_defined;
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::assembleMatrix(const ID & matrix_id) {
if (matrix_id == "K") {
this->assembleStiffnessMatrix();
}
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::assembleStiffnessMatrix() {
AKANTU_DEBUG_INFO("Assemble the new stiffness matrix");
if (!this->getDOFManager().hasMatrix("K")) {
this->getDOFManager().getNewMatrix("K", getMatrixType("K"));
}
for (auto & resolution : resolutions) {
resolution->assembleStiffnessMatrix(_not_ghost);
}
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::assembleLumpedMatrix(const ID & /*matrix_id*/) {
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::beforeSolveStep() {
for (auto & resolution : resolutions) {
resolution->beforeSolveStep();
}
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::afterSolveStep(bool converged) {
for (auto & resolution : resolutions) {
resolution->afterSolveStep(converged);
}
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
ContactMechanicsModel::createNodalFieldBool(const std::string & /*unused*/,
const std::string & /*unused*/,
bool /*unused*/) {
return nullptr;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
ContactMechanicsModel::createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) {
std::map<std::string, Array<Real> *> real_nodal_fields;
real_nodal_fields["contact_force"] = this->internal_force.get();
real_nodal_fields["normal_force"] = this->normal_force.get();
real_nodal_fields["tangential_force"] = this->tangential_force.get();
real_nodal_fields["blocked_dofs"] = this->blocked_dofs.get();
real_nodal_fields["normals"] = this->normals.get();
real_nodal_fields["tangents"] = this->tangents.get();
real_nodal_fields["gaps"] = this->gaps.get();
real_nodal_fields["areas"] = this->nodal_area.get();
real_nodal_fields["tangential_traction"] = this->tangential_tractions.get();
std::shared_ptr<dumpers::Field> field;
if (padding_flag) {
field = this->mesh.createNodalField(real_nodal_fields[field_name],
group_name, 3);
} else {
field =
this->mesh.createNodalField(real_nodal_fields[field_name], group_name);
}
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
-ContactMechanicsModel::createNodalFieldUInt(const std::string & field_name,
- const std::string & group_name,
- bool /*padding_flag*/) {
+ContactMechanicsModel::createNodalFieldInt(const std::string & field_name,
+ const std::string & group_name,
+ bool /*padding_flag*/) {
std::shared_ptr<dumpers::Field> field;
if (field_name == "contact_state") {
auto && func =
- std::make_unique<dumpers::ComputeUIntFromEnum<ContactState>>();
+ std::make_unique<dumpers::ComputeIntFromEnum<ContactState>>();
field = mesh.createNodalField(this->contact_state.get(), group_name);
field =
dumpers::FieldComputeProxy::createFieldCompute(field, std::move(func));
}
return field;
}
/* -------------------------------------------------------------------------- */
-UInt ContactMechanicsModel::getNbData(
- const Array<Element> & elements, const SynchronizationTag & /*tag*/) const {
- AKANTU_DEBUG_IN();
-
- UInt size = 0;
- UInt nb_nodes_per_element = 0;
+Int ContactMechanicsModel::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & /*tag*/) const {
+ Int size = 0;
+ Int nb_nodes_per_element = 0;
for (const Element & el : elements) {
nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
}
- AKANTU_DEBUG_OUT();
- return size;
+ return size * nb_nodes_per_element;
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::packData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
const SynchronizationTag & /*tag*/) const {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::unpackData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
-}
+ const SynchronizationTag & /*tag*/) {}
/* -------------------------------------------------------------------------- */
-UInt ContactMechanicsModel::getNbData(
- const Array<UInt> & dofs, const SynchronizationTag & /*tag*/) const {
- AKANTU_DEBUG_IN();
-
+Int ContactMechanicsModel::getNbData(const Array<Idx> & dofs,
+ const SynchronizationTag & /*tag*/) const {
UInt size = 0;
-
- AKANTU_DEBUG_OUT();
return size * dofs.size();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::packData(CommunicationBuffer & /*buffer*/,
- const Array<UInt> & /*dofs*/,
+ const Array<Idx> & /*dofs*/,
const SynchronizationTag & /*tag*/) const {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::unpackData(CommunicationBuffer & /*buffer*/,
- const Array<UInt> & /*dofs*/,
- const SynchronizationTag & /*tag*/) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
-}
+ const Array<Idx> & /*dofs*/,
+ const SynchronizationTag & /*tag*/) {}
} // namespace akantu
diff --git a/src/model/contact_mechanics/contact_mechanics_model.hh b/src/model/contact_mechanics/contact_mechanics_model.hh
index cddce2919..63784d22a 100644
--- a/src/model/contact_mechanics/contact_mechanics_model.hh
+++ b/src/model/contact_mechanics/contact_mechanics_model.hh
@@ -1,372 +1,372 @@
/**
* @file contact_mechanics_model.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Jun 24 2021
*
* @brief Model of Contact Mechanics
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "boundary_condition.hh"
#include "contact_detector.hh"
#include "data_accessor.hh"
#include "fe_engine.hh"
#include "model.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_CONTACT_MECHANICS_MODEL_HH__
#define __AKANTU_CONTACT_MECHANICS_MODEL_HH__
namespace akantu {
class Resolution;
template <ElementKind kind, class IntegrationOrderFunctor>
class IntegratorGauss;
template <ElementKind kind> class ShapeLagrange;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
class ContactMechanicsModel : public Model,
public DataAccessor<Element>,
- public DataAccessor<UInt>,
+ public DataAccessor<Idx>,
public BoundaryCondition<ContactMechanicsModel> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
public:
ContactMechanicsModel(
- Mesh & mesh, UInt dim = _all_dimensions,
+ Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "contact_mechanics_model",
std::shared_ptr<DOFManager> dof_manager = nullptr,
ModelType model_type = ModelType::_contact_mechanics_model);
~ContactMechanicsModel() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// initialize completely the model
void initFullImpl(const ModelOptions & options) override;
/// allocate all vectors
void initSolver(TimeStepSolverType /*unused*/,
NonLinearSolverType /*unused*/) override;
/// initialize all internal arrays for resolutions
void initResolutions();
/// initialize the modelType
void initModel() override;
/// call back for the solver, computes the force residual
void assembleResidual() override;
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override;
/// callback for the solver, this assembles different matrices
void assembleMatrix(const ID & matrix_id) override;
/// callback for the solver, this assembles the stiffness matrix
void assembleLumpedMatrix(const ID & matrix_id) override;
/// get some default values for derived classes
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
/// callback for the solver, this is called at beginning of solve
void beforeSolveStep() override;
/// callback for the solver, this is called at end of solve
void afterSolveStep(bool converged = true) override;
/// function to print the containt of the class
void printself(std::ostream & stream, int indent = 0) const override;
/* ------------------------------------------------------------------------ */
/* Contact Detection */
/* ------------------------------------------------------------------------ */
public:
void search();
void computeNodalAreas(GhostType ghost_type = _not_ghost);
/* ------------------------------------------------------------------------ */
/* Contact Resolution */
/* ------------------------------------------------------------------------ */
public:
/// register an empty contact resolution of a given type
Resolution & registerNewResolution(const ID & res_name, const ID & res_type,
const ID & opt_param);
protected:
/// register a resolution in the dynamic database
Resolution & registerNewResolution(const ParserSection & res_section);
/// read the resolution files to instantiate all the resolutions
void instantiateResolutions();
/// save the parameters from previous state
void savePreviousState();
/* ------------------------------------------------------------------------ */
/* Solver Interface */
/* ------------------------------------------------------------------------ */
public:
/// assembles the contact stiffness matrix
virtual void assembleStiffnessMatrix();
/// assembles the contant internal forces
virtual void assembleInternalForces();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
FEEngine & getFEEngineBoundary(const ID & name = "") override;
/* ------------------------------------------------------------------------ */
/* Dumpable interface */
/* ------------------------------------------------------------------------ */
public:
std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
- createNodalFieldUInt(const std::string & field_name,
- const std::string & group_name,
- bool padding_flag) override;
+ createNodalFieldInt(const std::string & field_name,
+ const std::string & group_name,
+ bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const override;
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) override;
- UInt getNbData(const Array<UInt> & dofs,
- const SynchronizationTag & tag) const override;
+ Int getNbData(const Array<Idx> & dofs,
+ const SynchronizationTag & tag) const override;
- void packData(CommunicationBuffer & buffer, const Array<UInt> & dofs,
+ void packData(CommunicationBuffer & buffer, const Array<Idx> & dofs,
const SynchronizationTag & tag) const override;
- void unpackData(CommunicationBuffer & buffer, const Array<UInt> & dofs,
+ void unpackData(CommunicationBuffer & buffer, const Array<Idx> & dofs,
const SynchronizationTag & tag) override;
protected:
/// contact detection class
friend class ContactDetector;
/// contact resolution class
friend class Resolution;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the ContactMechanicsModel::displacement vector
AKANTU_GET_MACRO(Displacement, *displacement, Array<Real> &);
/// get the ContactMechanicsModel::increment vector \warn only consistent
/// if ContactMechanicsModel::setIncrementFlagOn has been called before
AKANTU_GET_MACRO(Increment, *displacement_increment, Array<Real> &);
/// get the ContactMechanics::internal_force vector (internal forces)
AKANTU_GET_MACRO(InternalForce, *internal_force, Array<Real> &);
/// get the ContactMechanicsModel::external_force vector (external forces)
AKANTU_GET_MACRO(ExternalForce, *external_force, Array<Real> &);
/// get the ContactMechanics::normal_force vector (normal forces)
AKANTU_GET_MACRO(NormalForce, *normal_force, Array<Real> &);
/// get the ContactMechanics::tangential_force vector (friction forces)
AKANTU_GET_MACRO(TangentialForce, *tangential_force, Array<Real> &);
/// get the ContactMechanics::traction vector (friction traction)
AKANTU_GET_MACRO(TangentialTractions, *tangential_tractions, Array<Real> &);
/// get the ContactMechanics::previous_tangential_tractions vector
AKANTU_GET_MACRO(PreviousTangentialTractions, *previous_tangential_tractions,
Array<Real> &);
/// get the ContactMechanicsModel::force vector (external forces)
Array<Real> & getForce() {
AKANTU_DEBUG_WARNING("getForce was maintained for backward compatibility, "
"use getExternalForce instead");
return *external_force;
}
/// get the ContactMechanics::blocked_dofs vector
AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<Real> &);
/// get the ContactMechanics::gaps (contact gaps)
AKANTU_GET_MACRO(Gaps, *gaps, Array<Real> &);
/// get the ContactMechanics::normals (normals on slave nodes)
AKANTU_GET_MACRO(Normals, *normals, Array<Real> &);
/// get the ContactMechanics::tangents (tangents on slave nodes)
AKANTU_GET_MACRO(Tangents, *tangents, Array<Real> &);
/// get the ContactMechanics::previous_tangents (tangents on slave nodes)
AKANTU_GET_MACRO(PreviousTangents, *previous_tangents, Array<Real> &);
/// get the ContactMechanics::areas (nodal areas)
AKANTU_GET_MACRO(NodalArea, *nodal_area, Array<Real> &);
/// get the ContactMechanics::previous_projections (previous_projections)
AKANTU_GET_MACRO(PreviousProjections, *previous_projections, Array<Real> &);
/// get the ContactMechanics::projections (projections)
AKANTU_GET_MACRO(Projections, *projections, Array<Real> &);
/// get the ContactMechanics::contact_state vector (no_contact/stick/slip
/// state)
AKANTU_GET_MACRO(ContactState, *contact_state, Array<ContactState> &);
/// get the ContactMechanics::previous_master_elements
AKANTU_GET_MACRO(PreviousMasterElements, *previous_master_elements,
Array<Element> &);
/// get contact detector
AKANTU_GET_MACRO_NOT_CONST(ContactDetector, *detector, ContactDetector &);
/// get the contact elements
inline const Array<ContactElement> & getContactElements() const {
return contact_elements;
}
/// get the current positions of the nodes
inline Array<Real> & getPositions() { return detector->getPositions(); }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// tells if the resolutions are instantiated
bool are_resolutions_instantiated;
/// displacements array
std::unique_ptr<Array<Real>> displacement;
/// increment of displacement
std::unique_ptr<Array<Real>> displacement_increment;
/// contact forces array
std::unique_ptr<Array<Real>> internal_force;
/// external forces array
std::unique_ptr<Array<Real>> external_force;
/// normal force array
std::unique_ptr<Array<Real>> normal_force;
/// friction force array
std::unique_ptr<Array<Real>> tangential_force;
/// friction traction array
std::unique_ptr<Array<Real>> tangential_tractions;
/// previous friction traction array
std::unique_ptr<Array<Real>> previous_tangential_tractions;
/// boundary vector
std::unique_ptr<Array<Real>> blocked_dofs;
/// array to store gap between slave and master
std::unique_ptr<Array<Real>> gaps;
/// array to store normals from master to slave
std::unique_ptr<Array<Real>> normals;
/// array to store tangents on the master element
std::unique_ptr<Array<Real>> tangents;
/// array to store previous tangents on the master element
std::unique_ptr<Array<Real>> previous_tangents;
/// array to store nodal areas
std::unique_ptr<Array<Real>> nodal_area;
/// array to store stick/slip state :
std::unique_ptr<Array<ContactState>> contact_state;
/// array to store previous projections in covariant basis
std::unique_ptr<Array<Real>> previous_projections;
// array to store projections in covariant basis
std::unique_ptr<Array<Real>> projections;
/// contact detection
std::unique_ptr<ContactDetector> detector;
/// list of contact resolutions
std::vector<std::unique_ptr<Resolution>> resolutions;
/// mapping between resolution name and resolution internal id
std::map<std::string, UInt> resolutions_names_to_id;
/// array to store contact elements
Array<ContactElement> contact_elements;
/// array to store previous master elements
std::unique_ptr<Array<Element>> previous_master_elements;
};
} // namespace akantu
/* ------------------------------------------------------------------------ */
/* inline functions */
/* ------------------------------------------------------------------------ */
#include "parser.hh"
#include "resolution.hh"
/* ------------------------------------------------------------------------ */
#endif /* __AKANTU_CONTACT_MECHANICS_MODEL_HH__ */
diff --git a/src/model/contact_mechanics/geometry_utils.cc b/src/model/contact_mechanics/geometry_utils.cc
index 4b6683fef..dc5527f9b 100644
--- a/src/model/contact_mechanics/geometry_utils.cc
+++ b/src/model/contact_mechanics/geometry_utils.cc
@@ -1,731 +1,37 @@
/**
* @file geometry_utils.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed Oct 02 2019
* @date last modification: Thu Jun 24 2021
*
* @brief Implementation of various utilities needed for contact geometry
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "geometry_utils.hh"
#include "element_class_helper.hh"
/* -------------------------------------------------------------------------- */
-namespace akantu {
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::normal(const Mesh & mesh, const Array<Real> & positions,
- const Element & element, Vector<Real> & normal,
- bool outward) {
-
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt surface_dimension = spatial_dimension - 1;
-
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
- Matrix<Real> coords(spatial_dimension, nb_nodes_per_element);
-
- UInt * elem_val = mesh.getConnectivity(element.type, _not_ghost).storage();
- mesh.extractNodalValuesFromElement(positions, coords.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- Matrix<Real> vectors(spatial_dimension, surface_dimension);
- switch (spatial_dimension) {
- case 1: {
- normal[0] = 1;
- break;
- }
- case 2: {
- vectors(0) = Vector<Real>(coords(1)) - Vector<Real>(coords(0));
- Math::normal2(vectors.storage(), normal.storage());
- break;
- }
- case 3: {
- vectors(0) = Vector<Real>(coords(1)) - Vector<Real>(coords(0));
- vectors(1) = Vector<Real>(coords(2)) - Vector<Real>(coords(0));
- Math::normal3(vectors(0).storage(), vectors(1).storage(), normal.storage());
- break;
- }
- default: {
- AKANTU_ERROR("Unknown dimension : " << spatial_dimension);
- }
- }
-
- // to ensure that normal is always outwards from master surface
- if (outward) {
-
- const auto & element_to_subelement =
- mesh.getElementToSubelement(element.type)(element.element);
-
- Vector<Real> outside(spatial_dimension);
- mesh.getBarycenter(element, outside);
-
- // check if mesh facets exists for cohesive elements contact
- Vector<Real> inside(spatial_dimension);
- if (mesh.isMeshFacets()) {
- mesh.getMeshParent().getBarycenter(element_to_subelement[0], inside);
- } else {
- mesh.getBarycenter(element_to_subelement[0], inside);
- }
-
- Vector<Real> inside_to_outside = outside - inside;
- auto projection = inside_to_outside.dot(normal);
-
- if (projection < 0) {
- normal *= -1.0;
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::normal(const Mesh & mesh, const Element & element,
- Matrix<Real> & tangents, Vector<Real> & normal,
- bool outward) {
- UInt spatial_dimension = mesh.getSpatialDimension();
-
- // to ensure that normal is always outwards from master surface we
- // compute a direction vector form inside of element attached to the
- // suurface element
-
- Vector<Real> inside_to_outside(spatial_dimension);
- if (outward) {
-
- const auto & element_to_subelement =
- mesh.getElementToSubelement(element.type)(element.element);
-
- Vector<Real> outside(spatial_dimension);
- mesh.getBarycenter(element, outside);
-
- // check if mesh facets exists for cohesive elements contact
- Vector<Real> inside(spatial_dimension);
- if (mesh.isMeshFacets()) {
- mesh.getMeshParent().getBarycenter(element_to_subelement[0], inside);
- } else {
- mesh.getBarycenter(element_to_subelement[0], inside);
- }
-
- inside_to_outside = outside - inside;
- // auto projection = inside_to_outside.dot(normal);
-
- // if (projection < 0) {
- // normal *= -1.0;
- //}
- }
-
- // to ensure that direction of tangents are correct, cross product
- // of tangents should give be in the same direction as of inside to outside
- switch (spatial_dimension) {
- case 2: {
- normal[0] = -tangents(0, 1);
- normal[1] = tangents(0, 0);
-
- auto ddot = inside_to_outside.dot(normal);
- if (ddot < 0) {
- tangents *= -1.0;
- normal *= -1.0;
- }
-
- break;
- }
- case 3: {
- auto tang_trans = tangents.transpose();
- auto tang1 = Vector<Real>(tang_trans(0));
- auto tang2 = Vector<Real>(tang_trans(1));
-
- auto tang1_cross_tang2 = tang1.crossProduct(tang2);
- normal = tang1_cross_tang2 / tang1_cross_tang2.norm();
-
- auto ddot = inside_to_outside.dot(normal);
- if (ddot < 0) {
- tang_trans(1) *= -1.0;
- normal *= -1.0;
- }
-
- tangents = tang_trans.transpose();
-
- break;
- }
- default:
- break;
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::covariantBasis(const Mesh & mesh,
- const Array<Real> & positions,
- const Element & element,
- const Vector<Real> & normal,
- Vector<Real> & natural_coord,
- Matrix<Real> & tangents) {
- UInt spatial_dimension = mesh.getSpatialDimension();
-
- const ElementType type = element.type;
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- UInt * elem_val = mesh.getConnectivity(type, _not_ghost).storage();
- Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
-
- mesh.extractNodalValuesFromElement(positions, nodes_coord.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- auto && dnds = ElementClassHelper<_ek_regular>::getDNDS(natural_coord, type);
- tangents.mul<false, true>(dnds, nodes_coord);
-
- auto temp_tangents = tangents.transpose();
- for (UInt i = 0; i < spatial_dimension - 1; ++i) {
- auto temp = Vector<Real>(temp_tangents(i));
- temp_tangents(i) = temp.normalize();
- }
-
- tangents = temp_tangents.transpose();
-
- // to ensure that direction of tangents are correct, cross product
- // of tangents should give the normal vector computed earlier
- switch (spatial_dimension) {
- case 2: {
- Vector<Real> e_z(3);
- e_z[0] = 0.;
- e_z[1] = 0.;
- e_z[2] = 1.;
-
- Vector<Real> tangent(3);
- tangent[0] = tangents(0, 0);
- tangent[1] = tangents(0, 1);
- tangent[2] = 0.;
-
- auto exp_normal = e_z.crossProduct(tangent);
-
- auto ddot = normal.dot(exp_normal);
- if (ddot < 0) {
- tangents *= -1.0;
- }
- break;
- }
- case 3: {
- auto tang_trans = tangents.transpose();
- auto tang1 = Vector<Real>(tang_trans(0));
- auto tang2 = Vector<Real>(tang_trans(1));
-
- auto tang1_cross_tang2 = tang1.crossProduct(tang2);
- auto exp_normal = tang1_cross_tang2 / tang1_cross_tang2.norm();
-
- auto ddot = normal.dot(exp_normal);
- if (ddot < 0) {
- tang_trans(1) *= -1.0;
- }
-
- tangents = tang_trans.transpose();
- break;
- }
- default:
- break;
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::covariantBasis(const Mesh & mesh,
- const Array<Real> & positions,
- const Element & element,
- Vector<Real> & natural_coord,
- Matrix<Real> & tangents) {
-
- UInt spatial_dimension = mesh.getSpatialDimension();
-
- const ElementType & type = element.type;
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- UInt * elem_val = mesh.getConnectivity(type, _not_ghost).storage();
- Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
-
- mesh.extractNodalValuesFromElement(positions, nodes_coord.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- auto && dnds = ElementClassHelper<_ek_regular>::getDNDS(natural_coord, type);
- tangents.mul<false, true>(dnds, nodes_coord);
-
- auto temp_tangents = tangents.transpose();
- for (UInt i = 0; i < spatial_dimension - 1; ++i) {
- auto temp = Vector<Real>(temp_tangents(i));
- temp_tangents(i) = temp.normalize();
- }
-
- tangents = temp_tangents.transpose();
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::curvature(const Mesh & mesh, const Array<Real> & positions,
- const Element & element,
- const Vector<Real> & natural_coord,
- Matrix<Real> & curvature) {
- UInt spatial_dimension = mesh.getSpatialDimension();
- const ElementType & type = element.type;
-
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- UInt * elem_val = mesh.getConnectivity(type, _not_ghost).storage();
-
- auto && d2nds2 =
- ElementClassHelper<_ek_regular>::getD2NDS2(natural_coord, type);
-
- Matrix<Real> coords(spatial_dimension, nb_nodes_per_element);
- mesh.extractNodalValuesFromElement(positions, coords.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- curvature.mul<false, true>(coords, d2nds2);
-}
-
-/* -------------------------------------------------------------------------- */
-UInt GeometryUtils::orthogonalProjection(
- const Mesh & mesh, const Array<Real> & positions,
- const Vector<Real> & slave, const Array<Element> & elements, Real & gap,
- Vector<Real> & natural_projection, Vector<Real> & normal, Real alpha,
- UInt max_iterations, Real projection_tolerance, Real extension_tolerance) {
-
- UInt index = UInt(-1);
- Real min_gap = std::numeric_limits<Real>::max();
-
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt surface_dimension = spatial_dimension - 1;
-
- UInt nb_same_sides{0};
- UInt nb_boundary_elements{0};
-
- UInt counter{0};
-
- const auto & contact_group = mesh.getElementGroup("contact_surface");
-
- for (const auto & element : elements) {
- // filter out elements which are not there in the element group
- // contact surface created by the surface selector and is stored
- // in the mesh or mesh_facet, if a element is not there it
- // returnas UInt(-1)
-
- const auto & elements_of_type = contact_group.getElements(element.type);
- if (elements_of_type.find(element.element) == UInt(-1)) {
- continue;
- }
-
- nb_boundary_elements++;
-
- // find the natural coordinate corresponding to the minimum gap
- // between slave node and master element
-
- Vector<Real> master(spatial_dimension);
-
- Vector<Real> xi(natural_projection.size());
- GeometryUtils::naturalProjection(mesh, positions, element, slave, master,
- xi, max_iterations, projection_tolerance);
-
- Matrix<Real> tangent_ele(surface_dimension, spatial_dimension);
- GeometryUtils::covariantBasis(mesh, positions, element, xi, tangent_ele);
-
- Vector<Real> normal_ele(spatial_dimension);
- GeometryUtils::normal(mesh, element, tangent_ele, normal_ele);
-
- // if gap between master projection and slave point is zero, then
- // it means that slave point lies on the master element, hence the
- // normal from master to slave cannot be computed in that case
-
- auto master_to_slave = slave - master;
- Real temp_gap = master_to_slave.norm();
-
- if (temp_gap != 0) {
- master_to_slave /= temp_gap;
- }
-
- // also the slave point should lie inside the master surface in
- // case of explicit or outside in case of implicit, one way to
- // check that is by checking the dot product of normal at each
- // master element, if the values of all dot product is same then
- // the slave point lies on the same side of each master element
-
- // A alpha parameter is introduced which is 1 in case of explicit
- // and -1 in case of implicit, therefor the variation (dot product
- // + alpha) should be close to zero (within tolerance) for both
- // cases
-
- Real direction_tolerance = 1e-8;
- auto product = master_to_slave.dot(normal_ele);
- auto variation = std::abs(product + alpha);
-
- if (variation <= direction_tolerance and temp_gap <= min_gap and
- GeometryUtils::isValidProjection(xi, extension_tolerance)) {
-
- gap = -temp_gap;
- min_gap = temp_gap;
- index = counter;
- natural_projection = xi;
- normal = normal_ele;
- }
-
- if (temp_gap == 0 or variation <= direction_tolerance) {
- nb_same_sides++;
- }
-
- counter++;
- }
-
- // if point is not on the same side of all the boundary elements
- // than it is not consider even if the closet master element is
- // found
- if (nb_same_sides != nb_boundary_elements) {
- index = UInt(-1);
- }
-
- return index;
-}
-
-/* -------------------------------------------------------------------------- */
-UInt GeometryUtils::orthogonalProjection(
- const Mesh & mesh, const Array<Real> & positions,
- const Vector<Real> & slave, const Array<Element> & elements, Real & gap,
- Vector<Real> & natural_projection, Vector<Real> & normal,
- Matrix<Real> & tangent, Real /*alpha*/, UInt max_iterations,
- Real projection_tolerance, Real extension_tolerance) {
-
- UInt index = UInt(-1);
- Real min_gap = std::numeric_limits<Real>::max();
-
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt surface_dimension = spatial_dimension - 1;
-
- const auto & contact_group = mesh.getElementGroup("contact_surface");
-
- for (auto && tuple : enumerate(elements)) {
- auto & counter = std::get<0>(tuple);
- const auto & element = std::get<1>(tuple);
- // filter out elements which are not there in the element group
- // contact surface created by the surface selector and is stored
- // in the mesh or mesh_facet, if a element is not there it
- // returnas UInt(-1)
-
- const auto & elements_of_type = contact_group.getElements(element.type);
- if (elements_of_type.find(element.element) == UInt(-1)) {
- continue;
- }
-
- Vector<Real> master(spatial_dimension);
-
- Vector<Real> xi_ele(natural_projection.size());
- GeometryUtils::naturalProjection(mesh, positions, element, slave, master,
- xi_ele, max_iterations,
- projection_tolerance);
-
- Matrix<Real> tangent_ele(surface_dimension, spatial_dimension);
- GeometryUtils::covariantBasis(mesh, positions, element, xi_ele,
- tangent_ele);
-
- Vector<Real> normal_ele(spatial_dimension);
- GeometryUtils::normal(mesh, element, tangent_ele, normal_ele);
-
- // if gap between master projection and slave point is zero, then
- // it means that slave point lies on the master element, hence the
- // normal from master to slave cannot be computed in that case
-
- auto master_to_slave = slave - master;
- Real temp_gap = master_to_slave.norm();
-
- if (temp_gap != 0) {
- master_to_slave /= temp_gap;
- }
-
- // A alpha parameter is introduced which is 1 in case of explicit
- // and -1 in case of implicit, therefor the variation (dot product
- // + alpha) should be close to zero (within tolerance) for both
- // cases
-
- auto product = master_to_slave.dot(normal_ele);
-
- if (product < 0 and temp_gap <= min_gap and
- GeometryUtils::isValidProjection(xi_ele, extension_tolerance)) {
-
- gap = -temp_gap;
- min_gap = temp_gap;
- index = counter;
- natural_projection = xi_ele;
- normal = normal_ele;
- tangent = tangent_ele;
- }
- }
-
- return index;
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::realProjection(const Mesh & mesh,
- const Array<Real> & positions,
- const Vector<Real> & slave,
- const Element & element,
- const Vector<Real> & normal,
- Vector<Real> & projection) {
-
- UInt spatial_dimension = mesh.getSpatialDimension();
-
- const ElementType & type = element.type;
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
-
- UInt * elem_val = mesh.getConnectivity(type, _not_ghost).storage();
- Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
-
- mesh.extractNodalValuesFromElement(positions, nodes_coord.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- Vector<Real> point(nodes_coord(0));
- Real alpha = (slave - point).dot(normal);
-
- projection = slave - alpha * normal;
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::realProjection(const Mesh & mesh,
- const Array<Real> & positions,
- const Element & element,
- const Vector<Real> & natural_coord,
- Vector<Real> & projection) {
-
- auto spatial_dimension = mesh.getSpatialDimension();
-
- const auto & type = element.type;
-
- auto nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
- auto shapes =
- ElementClassHelper<_ek_regular>::getN(natural_coord, element.type);
-
- Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
- UInt * elem_val = mesh.getConnectivity(type, _not_ghost).storage();
- mesh.extractNodalValuesFromElement(positions, nodes_coord.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- projection.mul<false>(nodes_coord, shapes);
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::naturalProjection(
- const Mesh & mesh, const Array<Real> & positions, const Element & element,
- const Vector<Real> & slave_coords, Vector<Real> & master_coords,
- Vector<Real> & natural_projection, UInt max_iterations,
- Real projection_tolerance) {
-
- UInt spatial_dimension = mesh.getSpatialDimension();
- UInt surface_dimension = spatial_dimension - 1;
-
- const ElementType & type = element.type;
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- UInt * elem_val = mesh.getConnectivity(type, _not_ghost).storage();
- Matrix<Real> nodes_coord(spatial_dimension, nb_nodes_per_element);
-
- mesh.extractNodalValuesFromElement(positions, nodes_coord.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- // initial guess
- natural_projection.zero();
-
- // obhjective function computed on the natural_guess
- Matrix<Real> f(surface_dimension, 1);
-
- // jacobian matrix computed on the natural_guess
- Matrix<Real> J(surface_dimension, surface_dimension);
-
- // Jinv = J^{-1}
- Matrix<Real> Jinv(surface_dimension, surface_dimension);
-
- // dxi = \xi_{k+1} - \xi_{k} in the iterative process
- Matrix<Real> dxi(surface_dimension, 1);
-
- // gradient at natural projection
- Matrix<Real> gradient(surface_dimension, spatial_dimension);
-
- // second derivative at natural peojection
- Matrix<Real> double_gradient(surface_dimension, surface_dimension);
-
- // second derivative of shape function at natural projection
- Matrix<Real> d2nds2(surface_dimension * surface_dimension,
- nb_nodes_per_element);
-
- auto compute_double_gradient = [&d2nds2, &nodes_coord, surface_dimension,
- spatial_dimension](UInt & alpha,
- UInt & beta) {
- auto index = alpha * surface_dimension + beta;
- Vector<Real> d_alpha_beta(spatial_dimension);
-
- auto d2nds2_transpose = d2nds2.transpose();
- Vector<Real> d2nds2_alpha_beta(d2nds2_transpose(index));
-
- d_alpha_beta.mul<false>(nodes_coord, d2nds2_alpha_beta);
-
- return d_alpha_beta;
- };
-
- /* --------------------------- */
- /* init before iteration loop */
- /* --------------------------- */
- // do interpolation
- auto update_f = [&f, &master_coords, &natural_projection, &nodes_coord,
- &slave_coords, &gradient, surface_dimension,
- spatial_dimension, type]() {
- // compute real coords on natural projection
- auto && shapes =
- ElementClassHelper<_ek_regular>::getN(natural_projection, type);
-
- master_coords.mul<false>(nodes_coord, shapes);
-
- auto distance = slave_coords - master_coords;
-
- // first derivative of shape function at natural projection
- auto && dnds =
- ElementClassHelper<_ek_regular>::getDNDS(natural_projection, type);
- gradient.mul<false, true>(dnds, nodes_coord);
-
- // gradient transpose at natural projection
- Matrix<Real> gradient_transpose(surface_dimension, spatial_dimension);
-
- gradient_transpose = gradient.transpose();
-
- // loop over surface dimensions
- for (auto alpha : arange(surface_dimension)) {
- Vector<Real> gradient_alpha(gradient_transpose(alpha));
- f(alpha, 0) = -2. * gradient_alpha.dot(distance);
- }
-
- // compute initial error
- auto error = f.norm<L_2>();
- return error;
- };
-
- auto projection_error = update_f();
-
- /* --------------------------- */
- /* iteration loop */
- /* --------------------------- */
- UInt iterations{0};
- while (projection_tolerance < projection_error and
- iterations < max_iterations) {
-
- // compute covariant components of metric tensor
- auto a = GeometryUtils::covariantMetricTensor(gradient);
-
- // computing second derivative at natural projection
- d2nds2 =
- ElementClassHelper<_ek_regular>::getD2NDS2(natural_projection, type);
-
- // real coord - physical guess
- auto distance = slave_coords - master_coords;
-
- // computing Jacobian J
- for (auto alpha : arange(surface_dimension)) {
- for (auto beta : arange(surface_dimension)) {
- auto dgrad_alpha_beta = compute_double_gradient(alpha, beta);
- J(alpha, beta) = 2. * (a(alpha, beta) - dgrad_alpha_beta.dot(distance));
- }
- }
-
- Jinv.inverse(J);
-
- // compute increment
- dxi.mul<false, false>(Jinv, f, -1.0);
-
- // update our guess
- natural_projection += Vector<Real>(dxi(0));
-
- projection_error = update_f();
- iterations++;
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void GeometryUtils::contravariantBasis(const Matrix<Real> & covariant,
- Matrix<Real> & contravariant) {
-
- auto inv_A = GeometryUtils::contravariantMetricTensor(covariant);
- contravariant.mul<false, false>(inv_A, covariant);
-}
-
-/* -------------------------------------------------------------------------- */
-Matrix<Real>
-GeometryUtils::covariantMetricTensor(const Matrix<Real> & covariant_bases) {
- Matrix<Real> A(covariant_bases.rows(), covariant_bases.rows());
- A.mul<false, true>(covariant_bases, covariant_bases);
- return A;
-}
-
-/* -------------------------------------------------------------------------- */
-Matrix<Real>
-GeometryUtils::contravariantMetricTensor(const Matrix<Real> & covariant_bases) {
- auto A = GeometryUtils::covariantMetricTensor(covariant_bases);
- auto inv_A = A.inverse();
- return inv_A;
-}
-
-/* -------------------------------------------------------------------------- */
-Matrix<Real> GeometryUtils::covariantCurvatureTensor(
- const Mesh & mesh, const Array<Real> & positions, const Element & element,
- const Vector<Real> & natural_coord, const Vector<Real> & normal) {
-
- UInt spatial_dimension = mesh.getSpatialDimension();
- auto surface_dimension = spatial_dimension - 1;
-
- const ElementType & type = element.type;
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt * elem_val = mesh.getConnectivity(type, _not_ghost).storage();
-
- auto && d2nds2 =
- ElementClassHelper<_ek_regular>::getD2NDS2(natural_coord, type);
-
- Matrix<Real> coords(spatial_dimension, nb_nodes_per_element);
- mesh.extractNodalValuesFromElement(positions, coords.storage(),
- elem_val +
- element.element * nb_nodes_per_element,
- nb_nodes_per_element, spatial_dimension);
-
- Matrix<Real> curvature(spatial_dimension,
- surface_dimension * surface_dimension);
- curvature.mul<false, true>(coords, d2nds2);
-
- Matrix<Real> H(surface_dimension, surface_dimension);
-
- UInt i = 0;
- for (auto alpha : arange(surface_dimension)) {
- for (auto beta : arange(surface_dimension)) {
- Vector<Real> temp(curvature(i));
- H(alpha, beta) = temp.dot(normal);
- i++;
- }
- }
-
- return H;
-}
-
-} // namespace akantu
+namespace akantu {} // namespace akantu
diff --git a/src/model/contact_mechanics/geometry_utils.hh b/src/model/contact_mechanics/geometry_utils.hh
index a48a38ee9..6d662fe75 100644
--- a/src/model/contact_mechanics/geometry_utils.hh
+++ b/src/model/contact_mechanics/geometry_utils.hh
@@ -1,150 +1,159 @@
/**
* @file geometry_utils.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed Oct 02 2019
* @date last modification: Sat Dec 12 2020
*
* @brief class to compute geometry related quantities
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "fe_engine.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_GEOMETRY_UTILS_HH__
#define __AKANTU_GEOMETRY_UTILS_HH__
namespace akantu {
class GeometryUtils {
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
+ static Vector<Real> outsideDirection(const Mesh & mesh,
+ const Element & element);
+
/// computes the normal on an element (assuming elements is flat)
- static void normal(const Mesh & mesh, const Array<Real> & positions,
- const Element & element, Vector<Real> & normal,
- bool outward = true);
+ template <class Derived>
+ static Vector<Real> normal(const Mesh & mesh,
+ const Eigen::MatrixBase<Derived> & coords,
+ const Element & element, bool outward = true);
// computes normal at given covariant basis
- static void normal(const Mesh & mesh, const Element & element,
- Matrix<Real> & tangents, Vector<Real> & normal,
- bool outward = true);
-
- /// computes the orthogonal projection on a set of elements and
- /// returns natural projection and normal gap and index of element
- static UInt
- orthogonalProjection(const Mesh & mesh, const Array<Real> & positions,
- const Vector<Real> & slave,
- const Array<Element> & elements, Real & gap,
- Vector<Real> & natural_projection, Vector<Real> & normal,
- Real alpha, UInt max_iterations = 100,
- Real tolerance = 1e-10, Real extension_tolerance = 1e-5);
+ template <class Derived>
+ static Vector<Real> normal(const Mesh & mesh, const Element & element,
+ Eigen::MatrixBase<Derived> & tangents,
+ bool outward = true);
/// computes the orthogonal projection on a set of elements and
/// returns natural projection and normal gap and index of element
- static UInt orthogonalProjection(
+ template <class Derived1, class Derived2, class Derived3, class Derived4,
+ class ElementList>
+ static Element orthogonalProjection(
const Mesh & mesh, const Array<Real> & positions,
- const Vector<Real> & slave, const Array<Element> & elements, Real & gap,
- Vector<Real> & natural_projection, Vector<Real> & normal,
- Matrix<Real> & tangent, Real alpha, UInt max_iterations = 100,
- Real tolerance = 1e-10, Real extension_tolerance = 1e-5);
+ const Eigen::MatrixBase<Derived1> & slave, const ElementList & elements,
+ Real & gap, Eigen::MatrixBase<Derived2> & natural_projection,
+ Eigen::MatrixBase<Derived3> & normal,
+ Eigen::MatrixBase<Derived4> & tangent, Real alpha,
+ Int max_iterations = 100, Real projection_tolerance = 1e-10,
+ Real extension_tolerance = 1e-5);
/// computes the natural projection on an element
- static void
- naturalProjection(const Mesh & mesh, const Array<Real> & positions,
- const Element & element, const Vector<Real> & slave_coords,
- Vector<Real> & master_coords,
- Vector<Real> & natural_projection,
- UInt max_iterations = 100, Real tolerance = 1e-10);
+ template <class Derived1, class Derived2>
+ static std::pair<Vector<Real>, Vector<Real>>
+ naturalProjection(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ const Eigen::MatrixBase<Derived2> & slave_coords,
+ Int max_iterations = 100, Real tolerance = 1e-10);
/// computes the real projection on an element
- static void realProjection(const Mesh & mesh, const Array<Real> & positions,
- const Vector<Real> & slave,
- const Element & element,
- const Vector<Real> & normal,
- Vector<Real> & projection);
+ template <class Derived1, class Derived2, class Derived3>
+ static Vector<Real>
+ realProjection(const Eigen::MatrixBase<Derived1> & coords,
+ const Eigen::MatrixBase<Derived2> & slave,
+ const Eigen::MatrixBase<Derived3> & normal);
/// computes the real projection from a natural coordinate
- static void realProjection(const Mesh & mesh, const Array<Real> & positions,
- const Element & element,
- const Vector<Real> & natural_coord,
- Vector<Real> & projection);
+ template <class Derived1, class Derived2>
+ static Vector<Real>
+ realProjection(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ const Eigen::MatrixBase<Derived2> & natural_coord);
/// computes the covariant basis/ local surface basis/ tangents on projection
/// point
- static void covariantBasis(const Mesh & mesh, const Array<Real> & positions,
- const Element & element,
- Vector<Real> & natural_coord,
- Matrix<Real> & tangents);
+ template <class Derived1, class Derived2>
+ static Matrix<Real>
+ covariantBasis(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ Eigen::MatrixBase<Derived2> & natural_coord);
/// computes the covariant basis/ local surface basis/ tangents on projection
/// point
- static void covariantBasis(const Mesh & mesh, const Array<Real> & positions,
- const Element & element,
- const Vector<Real> & normal,
- Vector<Real> & natural_coord,
- Matrix<Real> & tangents);
+ template <class Derived1, class Derived2, class Derived3>
+ static Matrix<Real>
+ covariantBasis(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ const Eigen::MatrixBase<Derived2> & normal,
+ Eigen::MatrixBase<Derived3> & natural_coord);
// computes the curvature on projection
- static void curvature(const Mesh & mesh, const Array<Real> & positions,
- const Element & element,
- const Vector<Real> & natural_coord,
- Matrix<Real> & curvature);
+ template <class Derived1, class Derived2>
+ static Matrix<Real>
+ curvature(const Eigen::MatrixBase<Derived1> & coords, const Element & element,
+ const Eigen::MatrixBase<Derived2> & natural_coord);
/// computes the contravariant basis on projection point
- static void contravariantBasis(const Matrix<Real> & covariant,
- Matrix<Real> & contravariant);
+ template <class Derived>
+ static Matrix<Real>
+ contravariantBasis(const Eigen::MatrixBase<Derived> & covariant);
/// computes metric tesnor with covariant components
+ template <class Derived>
static Matrix<Real>
- covariantMetricTensor(const Matrix<Real> & /*covariant_bases*/);
+ covariantMetricTensor(const Eigen::MatrixBase<Derived> & covariant_bases);
/// computes metric tensor with contravariant components
+ template <class Derived>
static Matrix<Real>
- contravariantMetricTensor(const Matrix<Real> & /*covariant_bases*/);
+ contravariantMetricTensor(const Eigen::MatrixBase<Derived> & covariant_bases);
// computes curvature tensor with convariant components
- static Matrix<Real> covariantCurvatureTensor(
- const Mesh & /*mesh*/, const Array<Real> & /*positions*/,
- const Element & /*element*/, const Vector<Real> & /*natural_coord*/,
- const Vector<Real> & /*normal*/);
+ template <class Derived1, class Derived2, class Derived3>
+ static Matrix<Real>
+ covariantCurvatureTensor(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ const Eigen::MatrixBase<Derived2> & natural_coord,
+ const Eigen::MatrixBase<Derived3> & normal);
/// checks if the element is truly a boundary element or not
inline static bool isBoundaryElement(const Mesh & mesh,
const Element & element);
/// checks if the natural projection is valid for not
- inline static bool isValidProjection(const Vector<Real> & projection,
- Real extension_tolerance = 1e-5);
+ template <class Derived>
+ inline static bool
+ isValidProjection(const Eigen::MatrixBase<Derived> & projection,
+ Real extension_tolerance = 1e-5);
};
} // namespace akantu
#include "geometry_utils_inline_impl.cc"
#endif /* __AKANTU_GEOMETRY_UTILS_HH__ */
diff --git a/src/model/contact_mechanics/geometry_utils_inline_impl.cc b/src/model/contact_mechanics/geometry_utils_inline_impl.cc
index 276f1caef..d366c37f7 100644
--- a/src/model/contact_mechanics/geometry_utils_inline_impl.cc
+++ b/src/model/contact_mechanics/geometry_utils_inline_impl.cc
@@ -1,98 +1,517 @@
/**
* @file geometry_utils_inline_impl.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sun Oct 06 2019
* @date last modification: Wed Sep 16 2020
*
* @brief Geometry utils
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
+/* -------------------------------------------------------------------------- */
+#include "element_class_helper.hh"
#include "geometry_utils.hh"
+/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_GEOMETRY_UTILS_INLINE_IMPL_CC__
#define __AKANTU_GEOMETRY_UTILS_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
inline bool GeometryUtils::isBoundaryElement(const Mesh & mesh,
const Element & subelement) {
-
const auto & element_to_subelement =
mesh.getElementToSubelement(subelement.type)(subelement.element);
- // for regular boundary elements when surfaceselector is set to
+ // for regular boundary elements when akantu::SurfaceSelector is set to
// physical surfaces, the mesh contains only 1 element attached to a
- // boundary subelement
+ // boundary sub-element
if (element_to_subelement.size() == 1 and
element_to_subelement[0].kind() == _ek_regular) {
return true;
}
- // for cohesive interface elements when surfaceSelector is set
+ // for cohesive interface elements when akantu::SurfaceSelector is set
// either cohesive surface selector or all surface selector, in this
// case mesh passed is actually mesh_facet and for boundary or
- // cohesive interface 2 elements are associated to a subelement
- // we want only one regular element attached to the subelement
+ // cohesive interface 2 elements are associated to a sub-element
+ // we want only one regular element attached to the sub-element
- UInt nb_elements_regular = 0;
- UInt nb_elements_cohesive = 0;
+ Int nb_elements_regular{0};
+ // Int nb_elements_cohesive{0};
for (auto elem : element_to_subelement) {
if (elem == ElementNull) {
continue;
}
if (elem.kind() == _ek_regular) {
++nb_elements_regular;
}
- if (elem.kind() == _ek_cohesive) {
- ++nb_elements_cohesive;
- }
+ // if (elem.kind() == _ek_cohesive) {
+ // ++nb_elements_cohesive;
+ // }
}
- auto nb_elements = element_to_subelement.size();
+ Int nb_elements = element_to_subelement.size();
return nb_elements_regular < nb_elements;
}
/* -------------------------------------------------------------------------- */
-inline bool GeometryUtils::isValidProjection(const Vector<Real> & projection,
- Real extension_tolerance) {
-
- UInt nb_xi_inside = 0;
-
+template <class Derived>
+inline bool
+GeometryUtils::isValidProjection(const Eigen::MatrixBase<Derived> & projection,
+ Real extension_tolerance) {
+ Int nb_xi_inside = 0;
for (auto xi : projection) {
if (xi >= -1.0 - extension_tolerance and xi <= 1.0 + extension_tolerance) {
nb_xi_inside++;
}
}
return nb_xi_inside == projection.size();
}
+/* -------------------------------------------------------------------------- */
+inline Vector<Real> GeometryUtils::outsideDirection(const Mesh & mesh,
+ const Element & element) {
+ const auto & element_to_subelement = mesh.getElementToSubelement()(element);
+
+ Vector<Real> outside = mesh.getBarycenter(element);
+
+ // check if mesh facets exists for cohesive elements contact
+ Vector<Real> inside;
+ if (mesh.isMeshFacets()) {
+ inside = mesh.getMeshParent().getBarycenter(element_to_subelement[0]);
+ } else {
+ inside = mesh.getBarycenter(element_to_subelement[0]);
+ }
+
+ return (outside - inside);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived>
+Vector<Real> GeometryUtils::normal(const Mesh & mesh,
+ const Eigen::MatrixBase<Derived> & coords,
+ const Element & element, bool outward) {
+ Int spatial_dimension = coords.rows();
+ Vector<Real> normal(spatial_dimension);
+
+ switch (spatial_dimension) {
+ case 1: {
+ normal[0] = 1;
+ break;
+ }
+ case 2: {
+ normal = Math::normal(coords(1) - coords(0));
+ break;
+ }
+ case 3: {
+ normal = Math::normal(coords(1) - coords(0), coords(2) - coords(0));
+ break;
+ }
+ default: {
+ AKANTU_ERROR("Unknown dimension : " << spatial_dimension);
+ }
+ }
+
+ // to ensure that normal is always outwards from master surface
+ if (outward) {
+ auto projection = outsideDirection(mesh, element).dot(normal);
+ if (projection < 0) {
+ normal *= -1.0;
+ }
+ }
+ return normal;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived>
+Vector<Real> GeometryUtils::normal(const Mesh & mesh, const Element & element,
+ Eigen::MatrixBase<Derived> & tangents,
+ bool outward) {
+ auto spatial_dimension = mesh.getSpatialDimension();
+ // to ensure that normal is always outwards from master surface we
+ // compute a direction vector form inside of element attached to the
+ // suurface element
+
+ Vector<Real> normal(spatial_dimension);
+ // to ensure that direction of tangents are correct, cross product
+ // of tangents should give be in the same direction as of inside to outside
+ switch (spatial_dimension) {
+ case 2: {
+ normal(0) = -tangents(1, 0);
+ normal(1) = tangents(0, 0);
+ break;
+ }
+ case 3: {
+ VectorProxy<Real, 3> tangent1(tangents(0).data());
+ VectorProxy<Real, 3> tangent2(tangents(1).data());
+ normal = (tangent1.cross(tangent2)).normalized();
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (outward) {
+ auto ddot = outsideDirection(mesh, element).dot(normal);
+ if (ddot < 0) {
+ tangents *= -1.0;
+ normal *= -1.0;
+ }
+ }
+ return normal;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2>
+inline Matrix<Real>
+GeometryUtils::covariantBasis(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ Eigen::MatrixBase<Derived2> & natural_coord) {
+ auto && dnds =
+ ElementClassHelper<_ek_regular>::getDNDS(natural_coord, element.type);
+
+ Matrix<Real> tangents_transpose = coords * dnds.transpose();
+ for (auto && vect : tangents_transpose) {
+ vect = vect.normalized();
+ }
+
+ return tangents_transpose;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2, class Derived3>
+inline Matrix<Real>
+GeometryUtils::covariantBasis(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ const Eigen::MatrixBase<Derived2> & normal,
+ Eigen::MatrixBase<Derived3> & natural_coord) {
+ auto tangents = covariantBasis(coords, element, natural_coord);
+
+ // to ensure that direction of tangents are correct, cross product
+ // of tangents should give the normal vector computed earlier
+ Int spatial_dimension = coords.rows();
+ Vector<Real, 3> exp_normal;
+
+ switch (spatial_dimension) {
+ case 2: {
+ Vector<Real, 3> e_z{0., 0., 1.};
+
+ Vector<Real, 3> tangent;
+ tangent[0] = tangents(0, 0);
+ tangent[1] = tangents(1, 0);
+ tangent[2] = 0.;
+
+ exp_normal = e_z.cross(tangent);
+ break;
+ }
+ case 3: {
+ VectorProxy<Real, 3> tangent1(tangents(0).data());
+ VectorProxy<Real, 3> tangent2(tangents(1).data());
+ exp_normal = (tangent1.cross(tangent2)).normalized();
+ break;
+ }
+ default:
+ AKANTU_TO_IMPLEMENT();
+ }
+
+ auto ddot = normal.dot(exp_normal);
+ if (ddot < 0) {
+ tangents(1) *= -1.0;
+ }
+
+ return tangents;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2>
+inline Matrix<Real>
+GeometryUtils::curvature(const Eigen::MatrixBase<Derived1> & coords,
+ const Element & element,
+ const Eigen::MatrixBase<Derived2> & natural_coord) {
+ auto && d2nds2 =
+ ElementClassHelper<_ek_regular>::getD2NDS2(natural_coord, element.type);
+ return coords * d2nds2.transpose();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2, class Derived3, class Derived4,
+ class ElementList>
+Element GeometryUtils::orthogonalProjection(
+ const Mesh & mesh, const Array<Real> & positions,
+ const Eigen::MatrixBase<Derived1> & slave, const ElementList & elements,
+ Real & gap, Eigen::MatrixBase<Derived2> & natural_projection,
+ Eigen::MatrixBase<Derived3> & normal, Eigen::MatrixBase<Derived4> & tangent,
+ Real /*alpha*/, Int max_iterations, Real projection_tolerance,
+ Real extension_tolerance) {
+
+ auto found_element = ElementNull;
+ auto min_gap = std::numeric_limits<Real>::max();
+
+ const auto & contact_group = mesh.getElementGroup("contact_surface");
+
+ for (auto && element : elements) {
+ // filter out elements which are not there in the element group
+ // contact surface created by the surface selector and is stored
+ // in the mesh or mesh_facet, if a element is not there it
+ // returnas UInt(-1)
+
+ const auto & elements_of_type = contact_group.getElements(element.type);
+ if (elements_of_type.find(element.element) == -1) {
+ continue;
+ }
+
+ auto coords = mesh.extractNodalValuesFromElement(positions, element);
+
+ auto && [xi_ele, master] = GeometryUtils::naturalProjection(
+ coords, element, slave, max_iterations, projection_tolerance);
+
+ auto && tangent_ele =
+ GeometryUtils::covariantBasis(coords, element, xi_ele);
+
+ auto && normal_ele = GeometryUtils::normal(mesh, element, tangent_ele);
+
+ // if gap between master projection and slave point is zero, then
+ // it means that slave point lies on the master element, hence the
+ // normal from master to slave cannot be computed in that case
+ auto master_to_slave = (slave - master).eval();
+ auto temp_gap = master_to_slave.norm();
+
+ if (temp_gap != 0) {
+ master_to_slave /= temp_gap;
+ }
+
+ // A alpha parameter is introduced which is 1 in case of explicit
+ // and -1 in case of implicit, therefor the variation (dot product
+ // + alpha) should be close to zero (within tolerance) for both
+ // cases
+ auto product = master_to_slave.dot(normal_ele);
+
+ if (product < 0 and temp_gap <= min_gap and
+ GeometryUtils::isValidProjection(xi_ele, extension_tolerance)) {
+ gap = -temp_gap;
+ min_gap = temp_gap;
+ found_element = element;
+ natural_projection = xi_ele;
+ normal = normal_ele;
+ tangent = tangent_ele;
+ }
+ }
+
+ return found_element;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2, class Derived3>
+Vector<Real>
+GeometryUtils::realProjection(const Eigen::MatrixBase<Derived1> & coords,
+ const Eigen::MatrixBase<Derived2> & slave,
+ const Eigen::MatrixBase<Derived3> & normal) {
+ auto alpha = (slave - coords(0)).dot(normal);
+ return slave - alpha * normal;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2>
+Vector<Real> GeometryUtils::realProjection(
+ const Eigen::MatrixBase<Derived1> & coords, const Element & element,
+ const Eigen::MatrixBase<Derived2> & natural_coord) {
+ auto shapes =
+ ElementClassHelper<_ek_regular>::getN(natural_coord, element.type);
+ return coords * shapes;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2>
+std::pair<Vector<Real>, Vector<Real>> GeometryUtils::naturalProjection(
+ const Eigen::MatrixBase<Derived1> & coords, const Element & element,
+ const Eigen::MatrixBase<Derived2> & slave_coords, Int max_iterations,
+ Real projection_tolerance) {
+
+ auto spatial_dimension = coords.rows();
+ auto surface_dimension = spatial_dimension - 1;
+
+ auto type = element.type;
+
+ Vector<Real> master_coords(spatial_dimension);
+ Vector<Real> natural_projection(surface_dimension);
+
+ // initial guess
+ natural_projection.zero();
+
+ // obhjective function computed on the natural_guess
+ Vector<Real> f(surface_dimension);
+
+ // jacobian matrix computed on the natural_guess
+ Matrix<Real> J(surface_dimension, surface_dimension);
+
+ // dxi = \xi_{k+1} - \xi_{k} in the iterative process
+ Vector<Real> dxi(surface_dimension);
+
+ // gradient at natural projection
+ Matrix<Real> gradient(surface_dimension, spatial_dimension);
+
+ // second derivative at natural peojection
+ Matrix<Real> double_gradient(surface_dimension, surface_dimension);
+
+ // second derivative of shape function at natural projection
+ Matrix<Real> d2nds2(surface_dimension * surface_dimension, coords.cols());
+
+ auto compute_double_gradient = [&d2nds2, &coords, surface_dimension,
+ spatial_dimension](Int & alpha, Int & beta) {
+ auto index = alpha * surface_dimension + beta;
+ Vector<Real> d_alpha_beta(spatial_dimension);
+
+ d_alpha_beta = coords * d2nds2.transpose()(index);
+
+ return d_alpha_beta;
+ };
+
+ /* --------------------------- */
+ /* init before iteration loop */
+ /* --------------------------- */
+ // do interpolation
+ auto update_f = [&f, &master_coords, &natural_projection, &coords,
+ &slave_coords, &gradient, surface_dimension, type]() {
+ // compute real coords on natural projection
+ auto && shapes =
+ ElementClassHelper<_ek_regular>::getN(natural_projection, type);
+
+ master_coords = coords * shapes;
+ auto distance = slave_coords - master_coords;
+
+ // first derivative of shape function at natural projection
+ auto && dnds =
+ ElementClassHelper<_ek_regular>::getDNDS(natural_projection, type);
+ gradient = dnds * coords.transpose();
+
+ // loop over surface dimensions
+ for (auto alpha : arange(surface_dimension)) {
+ f(alpha) = -2. * gradient.transpose()(alpha).dot(distance);
+ }
+
+ // compute initial error
+ return f.norm();
+ };
+
+ auto projection_error = update_f();
+
+ /* --------------------------- */
+ /* iteration loop */
+ /* --------------------------- */
+ Int iterations{0};
+ while (projection_tolerance < projection_error and
+ iterations < max_iterations) {
+
+ // compute covariant components of metric tensor
+ auto a = GeometryUtils::covariantMetricTensor(gradient);
+
+ // computing second derivative at natural projection
+ d2nds2 =
+ ElementClassHelper<_ek_regular>::getD2NDS2(natural_projection, type);
+
+ // real coord - physical guess
+ auto distance = slave_coords - master_coords;
+
+ // computing Jacobian J
+ for (auto alpha : arange(surface_dimension)) {
+ for (auto beta : arange(surface_dimension)) {
+ auto dgrad_alpha_beta = compute_double_gradient(alpha, beta);
+ J(alpha, beta) = 2. * (a(alpha, beta) - dgrad_alpha_beta.dot(distance));
+ }
+ }
+
+ // compute increment
+ dxi = -1 * J.inverse() * f;
+
+ // update our guess
+ natural_projection += dxi;
+
+ projection_error = update_f();
+ iterations++;
+ }
+
+ return std::make_pair(natural_projection, master_coords);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived>
+Matrix<Real> GeometryUtils::contravariantBasis(
+ const Eigen::MatrixBase<Derived> & covariant) {
+ auto && inv_A = GeometryUtils::contravariantMetricTensor(covariant);
+ return inv_A * covariant;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived>
+Matrix<Real> GeometryUtils::covariantMetricTensor(
+ const Eigen::MatrixBase<Derived> & covariant_bases) {
+ auto A = covariant_bases.transpose() * covariant_bases;
+ return A;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived>
+Matrix<Real> GeometryUtils::contravariantMetricTensor(
+ const Eigen::MatrixBase<Derived> & covariant_bases) {
+ Matrix<Real> A_inv = GeometryUtils::covariantMetricTensor(covariant_bases);
+ return A_inv.inverse();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class Derived1, class Derived2, class Derived3>
+Matrix<Real> GeometryUtils::covariantCurvatureTensor(
+ const Eigen::MatrixBase<Derived1> & coords, const Element & element,
+ const Eigen::MatrixBase<Derived2> & natural_coord,
+ const Eigen::MatrixBase<Derived3> & normal) {
+
+ auto spatial_dimension = coords.rows();
+ auto surface_dimension = spatial_dimension - 1;
+
+ auto type = element.type;
+
+ auto && d2nds2 =
+ ElementClassHelper<_ek_regular>::getD2NDS2(natural_coord, type);
+
+ Matrix<Real> curvature = coords * d2nds2.transpose();
+ Matrix<Real> H(surface_dimension, surface_dimension);
+
+ Int i = 0;
+ for (auto alpha : arange(surface_dimension)) {
+ for (auto beta : arange(surface_dimension)) {
+ H(alpha, beta) = curvature(i).dot(normal);
+ i++;
+ }
+ }
+
+ return H;
+}
+
} // namespace akantu
#endif
diff --git a/src/model/contact_mechanics/resolution.cc b/src/model/contact_mechanics/resolution.cc
index 688b4db6e..b1d7bf271 100644
--- a/src/model/contact_mechanics/resolution.cc
+++ b/src/model/contact_mechanics/resolution.cc
@@ -1,222 +1,208 @@
/**
* @file resolution.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Jan 17 2019
* @date last modification: Wed Apr 07 2021
*
* @brief Implementation of common part of the contact resolution class
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "resolution.hh"
#include "contact_mechanics_model.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
Resolution::Resolution(ContactMechanicsModel & model, const ID & id)
: Parsable(ParserType::_contact_resolution, id), id(id),
fem(model.getFEEngine()), model(model) {
AKANTU_DEBUG_IN();
spatial_dimension = model.getMesh().getSpatialDimension();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Resolution::~Resolution() = default;
/* -------------------------------------------------------------------------- */
void Resolution::initialize() {
registerParam("name", name, std::string(), _pat_parsable | _pat_readable);
registerParam("mu", mu, Real(0.), _pat_parsable | _pat_modifiable,
"Friction Coefficient");
registerParam("is_master_deformable", is_master_deformable, bool(false),
_pat_parsable | _pat_readable, "Is master surface deformable");
}
/* -------------------------------------------------------------------------- */
void Resolution::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
std::string type = getID().substr(getID().find_last_of(':') + 1);
stream << space << "Contact Resolution " << type << " [" << std::endl;
Parsable::printself(stream, indent);
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
void Resolution::assembleInternalForces(GhostType /*ghost_type*/) {
AKANTU_DEBUG_IN();
this->assembleInternalForces();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Resolution::assembleInternalForces() {
AKANTU_DEBUG_IN();
for (const auto & element : model.getContactElements()) {
auto nb_nodes = element.getNbNodes();
Vector<Real> local_fn(nb_nodes * spatial_dimension);
computeNormalForce(element, local_fn);
Vector<Real> local_ft(nb_nodes * spatial_dimension);
computeTangentialForce(element, local_ft);
- Vector<Real> local_fc(nb_nodes * spatial_dimension);
- local_fc = local_fn + local_ft;
-
assembleLocalToGlobalArray(element, local_fn, model.getNormalForce());
assembleLocalToGlobalArray(element, local_ft, model.getTangentialForce());
- assembleLocalToGlobalArray(element, local_fc, model.getInternalForce());
+ }
+
+ for (auto && [fc, ft, fn] :
+ zip(make_view(model.getInternalForce(), spatial_dimension),
+ make_view(model.getTangentialForce(), spatial_dimension),
+ make_view(model.getNormalForce(), spatial_dimension))) {
+ fc = ft + fn;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Resolution::assembleLocalToGlobalArray(const ContactElement & element,
Vector<Real> & local,
Array<Real> & global) {
auto get_connectivity = [&](auto & slave, auto & master) {
- Vector<UInt> master_conn =
- const_cast<const Mesh &>(model.getMesh()).getConnectivity(master);
- Vector<UInt> elem_conn(master_conn.size() + 1);
-
+ const auto master_conn = model.getMesh().getConnectivity(master);
+ Vector<Idx> elem_conn(master_conn.size() + 1);
elem_conn[0] = slave;
- for (UInt i = 1; i < elem_conn.size(); ++i) {
- elem_conn[i] = master_conn[i - 1];
- }
+ elem_conn.block(1, 0, master_conn.size(), 1) = master_conn;
return elem_conn;
};
- auto & surface_selector = model.getContactDetector().getSurfaceSelector();
- auto & slave_list = surface_selector.getSlaveList();
- auto & master_list = surface_selector.getMasterList();
-
auto connectivity = get_connectivity(element.slave, element.master);
- UInt nb_dofs = global.getNbComponent();
- UInt nb_nodes = is_master_deformable ? connectivity.size() : 1;
+ auto nb_dofs = global.getNbComponent();
+ auto nb_nodes = is_master_deformable ? connectivity.size() : 1;
Real alpha = is_master_deformable ? 0.5 : 1.;
- for (UInt i : arange(nb_nodes)) {
- UInt n = connectivity[i];
-
- auto slave_result = std::find(slave_list.begin(), slave_list.end(), n);
- auto master_result = std::find(master_list.begin(), master_list.end(), n);
+ MatrixProxy<Real> local_m(local.data(), nb_dofs, connectivity.cols());
+ auto global_it = make_view(global, nb_dofs).begin();
- for (UInt j : arange(nb_dofs)) {
- UInt offset_node = n * nb_dofs + j;
- global[offset_node] += alpha * local[i * nb_dofs + j];
- }
+ for (Int i : arange(nb_nodes)) {
+ global_it[connectivity(i)] = alpha * local_m(i);
}
}
/* -------------------------------------------------------------------------- */
void Resolution::assembleStiffnessMatrix(GhostType /*ghost_type*/) {
AKANTU_DEBUG_IN();
auto & global_stiffness =
const_cast<SparseMatrix &>(model.getDOFManager().getMatrix("K"));
for (const auto & element : model.getContactElements()) {
auto nb_nodes = element.getNbNodes();
Matrix<Real> local_kn(nb_nodes * spatial_dimension,
nb_nodes * spatial_dimension);
computeNormalModuli(element, local_kn);
assembleLocalToGlobalMatrix(element, local_kn, global_stiffness);
Matrix<Real> local_kt(nb_nodes * spatial_dimension,
nb_nodes * spatial_dimension);
computeTangentialModuli(element, local_kt);
assembleLocalToGlobalMatrix(element, local_kt, global_stiffness);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Resolution::assembleLocalToGlobalMatrix(const ContactElement & element,
const Matrix<Real> & local,
SparseMatrix & global) {
auto get_connectivity = [&](auto & slave, auto & master) {
- Vector<UInt> master_conn =
- const_cast<const Mesh &>(model.getMesh()).getConnectivity(master);
- Vector<UInt> elem_conn(master_conn.size() + 1);
-
+ const auto master_conn = model.getMesh().getConnectivity(master);
+ Vector<Idx> elem_conn(master_conn.size() + 1);
elem_conn[0] = slave;
- for (UInt i = 1; i < elem_conn.size(); ++i) {
- elem_conn[i] = master_conn[i - 1];
- }
+ elem_conn.block(1, 0, master_conn.size(), 1) = master_conn;
return elem_conn;
};
auto connectivity = get_connectivity(element.slave, element.master);
auto nb_dofs = spatial_dimension;
UInt nb_nodes = is_master_deformable ? connectivity.size() : 1;
UInt total_nb_dofs = nb_dofs * nb_nodes;
std::vector<UInt> equations;
- for (UInt i : arange(connectivity.size())) {
+ for (Int i : arange(connectivity.size())) {
UInt conn = connectivity[i];
- for (UInt j : arange(nb_dofs)) {
+ for (Int j : arange(nb_dofs)) {
equations.push_back(conn * nb_dofs + j);
}
}
- for (UInt i : arange(total_nb_dofs)) {
+ for (Int i : arange(total_nb_dofs)) {
UInt row = equations[i];
- for (UInt j : arange(total_nb_dofs)) {
+ for (Int j : arange(total_nb_dofs)) {
UInt col = equations[j];
global.add(row, col, local(i, j));
}
}
}
/* -------------------------------------------------------------------------- */
void Resolution::beforeSolveStep() {}
/* -------------------------------------------------------------------------- */
void Resolution::afterSolveStep(__attribute__((unused)) bool converged) {}
} // namespace akantu
diff --git a/src/model/contact_mechanics/resolution.hh b/src/model/contact_mechanics/resolution.hh
index eaef3d209..63809e0d6 100644
--- a/src/model/contact_mechanics/resolution.hh
+++ b/src/model/contact_mechanics/resolution.hh
@@ -1,236 +1,228 @@
/**
* @file resolution.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Apr 07 2021
*
* @brief Mother class for all contact resolutions
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_factory.hh"
#include "contact_element.hh"
#include "fe_engine.hh"
#include "geometry_utils.hh"
#include "parsable.hh"
#include "parser.hh"
#include "resolution_utils.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_RESOLUTION_HH__
#define __AKANTU_RESOLUTION_HH__
/* -------------------------------------------------------------------------- */
namespace akantu {
class Model;
class ContactMechanicsModel;
} // namespace akantu
namespace akantu {
/**
* Interface of all contact resolutions
* Prerequisites for a new resolution
* - inherit from this class
* - implement the following methods:
* \code
*
* virtual void computeNormalForce();
* virtual void computeTangentialForce();
* virtual void computeNormalModuli();
* virtual void computeTangentialModuli();
*
* \endcode
*
*/
class Resolution : public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructor/Destructor */
/* ------------------------------------------------------------------------ */
public:
/// instantiate contact resolution with defaults
Resolution(ContactMechanicsModel & model, const ID & id = "");
/// Destructor
~Resolution() override;
protected:
void initialize();
/// computes coordinates of a given element
void computeCoordinates(const Element &, Matrix<Real> &);
/* ------------------------------------------------------------------------ */
/* Functions that resolutions should reimplement for force */
/* ------------------------------------------------------------------------ */
public:
/// computes the force vector due to normal traction
- virtual void computeNormalForce(__attribute__((unused))
- const ContactElement & /*unused*/,
- __attribute__((unused))
+ virtual void computeNormalForce(const ContactElement & /*unused*/,
Vector<Real> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/// computes the tangential force vector due to frictional traction
- virtual void computeTangentialForce(__attribute__((unused))
- const ContactElement & /*unused*/,
- __attribute__((unused))
+ virtual void computeTangentialForce(const ContactElement & /*unused*/,
Vector<Real> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/* ------------------------------------------------------------------------ */
/* Functions that resolutions should reimplement for stiffness */
/* ------------------------------------------------------------------------ */
public:
/// compute the normal moduli due to normal traction
- virtual void computeNormalModuli(__attribute__((unused))
- const ContactElement & /*unused*/,
- __attribute__((unused))
+ virtual void computeNormalModuli(const ContactElement & /*unused*/,
Matrix<Real> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/// compute the tangent moduli due to tangential traction
- virtual void computeTangentialModuli(__attribute__((unused))
- const ContactElement & /*unused*/,
- __attribute__((unused))
+ virtual void computeTangentialModuli(const ContactElement & /*unused*/,
Matrix<Real> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// assemble the residual for this resolution
void assembleInternalForces(GhostType ghost_type);
/// assemble the stiffness matrix for this resolution
void assembleStiffnessMatrix(GhostType ghost_type);
private:
/// assemble the residual for this resolution
void assembleInternalForces();
/// assemble the local array to global array for a contact element
void assembleLocalToGlobalArray(const ContactElement & /*element*/,
Vector<Real> & /*local*/,
Array<Real> & /*global*/);
/// assemble the local stiffness to global stiffness for a contact element
void assembleLocalToGlobalMatrix(const ContactElement & /*element*/,
const Matrix<Real> & /*local*/,
SparseMatrix & /*global*/);
public:
virtual void beforeSolveStep();
virtual void afterSolveStep(bool converged = true);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(ID, id, const ID &);
public:
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ID id;
/// friction coefficient : mu
Real mu;
/// spatial dimension
- UInt spatial_dimension;
+ Int spatial_dimension;
/// is master surface deformable
bool is_master_deformable;
/// Link to the fe engine object in the model
FEEngine & fem;
/// resolution name
std::string name;
/// model to which the resolution belong
ContactMechanicsModel & model;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const Resolution & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
using ResolutionFactory = Factory<Resolution, ID, UInt, const ID &,
ContactMechanicsModel &, const ID &>;
/// macaulay bracket to convert positive gap to zero
-template <typename T> T macaulay(T var) { return var < 0 ? 0 : var; }
+template <typename T> T macaulay(T var) { return std::max(var, T()); }
template <typename T> T heaviside(T var) { return var < 0 ? 0 : 1.0; }
} // namespace akantu
#define INSTANTIATE_RESOLUTION_ONLY(res_name) class res_name
#define RESOLUTION_DEFAULT_PER_DIM_ALLOCATOR(id, res_name) \
- [](UInt dim, const ID &, ContactMechanicsModel & model, \
+ [](Int dim, const ID &, ContactMechanicsModel & model, \
const ID & id) -> std::unique_ptr<Resolution> { \
switch (dim) { \
case 1: \
return std::make_unique<res_name>(model, id); \
case 2: \
return std::make_unique<res_name>(model, id); \
case 3: \
return std::make_unique<res_name>(model, id); \
default: \
AKANTU_EXCEPTION( \
"The dimension " \
<< dim << "is not a valid dimension for the contact resolution " \
<< #id); \
} \
}
#define INSTANTIATE_RESOLUTION(id, res_name) \
INSTANTIATE_RESOLUTION_ONLY(res_name); \
static bool resolution_is_alocated_##id [[gnu::unused]] = \
ResolutionFactory::getInstance().registerAllocator( \
#id, RESOLUTION_DEFAULT_PER_DIM_ALLOCATOR(id, res_name))
#endif /* __AKANTU_RESOLUTION_HH__ */
diff --git a/src/model/contact_mechanics/resolution_utils.cc b/src/model/contact_mechanics/resolution_utils.cc
index 88a839c9a..89d1aaeed 100644
--- a/src/model/contact_mechanics/resolution_utils.cc
+++ b/src/model/contact_mechanics/resolution_utils.cc
@@ -1,70 +1,41 @@
/**
* @file resolution_utils.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon May 20 2019
* @date last modification: Sun Jun 06 2021
*
* @brief Implementation of various utilities neede for resolution class
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "resolution_utils.hh"
#include "element_class_helper.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-void ResolutionUtils::computeShapeFunctionMatric(
- const ContactElement & element, const Vector<Real> & projection,
- Matrix<Real> & shape_matric) {
-
- shape_matric.zero();
-
- const ElementType & type = element.master.type;
-
- auto surface_dimension = Mesh::getSpatialDimension(type);
- auto spatial_dimension = surface_dimension + 1;
- UInt nb_nodes_per_contact = element.getNbNodes();
-
- AKANTU_DEBUG_ASSERT(spatial_dimension == shape_matric.rows() &&
- spatial_dimension * nb_nodes_per_contact ==
- shape_matric.cols(),
- "Shape Matric dimensions are not correct");
-
- auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
-
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- shape_matric(j, i * spatial_dimension + j) = 1;
- continue;
- }
- shape_matric(j, i * spatial_dimension + j) = -shapes[i - 1];
- }
- }
-}
} // namespace akantu
diff --git a/src/model/contact_mechanics/resolution_utils.hh b/src/model/contact_mechanics/resolution_utils.hh
index d42beacc6..28c36cb3a 100644
--- a/src/model/contact_mechanics/resolution_utils.hh
+++ b/src/model/contact_mechanics/resolution_utils.hh
@@ -1,61 +1,119 @@
/**
* @file resolution_utils.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon May 20 2019
* @date last modification: Sun Jun 06 2021
*
* @brief All resolution utils necessary for various tasks
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "contact_element.hh"
#include "contact_mechanics_model.hh"
#include "fe_engine.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_RESOLUTION_UTILS_HH__
#define __AKANTU_RESOLUTION_UTILS_HH__
/* -------------------------------------------------------------------------- */
namespace akantu {
class ResolutionUtils {
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// computes the shape function matric for the contact element (@f$A
/// @f$) where row is equal to spatial dimension and cols is equal
/// to spatial dimension times number of nodes in contact element
- static void computeShapeFunctionMatric(const ContactElement & /*element*/,
- const Vector<Real> & /*projection*/,
- Matrix<Real> & /*shape_matric*/);
+ template <class Derived>
+ static Matrix<Real>
+ computeShapeFunctionMatrix(const ContactElement & element,
+ const Eigen::MatrixBase<Derived> & projection) {
+ const auto type = element.master.type;
+ const auto surface_dimension = Mesh::getSpatialDimension(type);
+ const auto spatial_dimension = surface_dimension + 1;
+ const auto nb_nodes_per_contact = element.getNbNodes();
+
+ Matrix<Real> shape_matrix(spatial_dimension,
+ spatial_dimension * nb_nodes_per_contact);
+ shape_matrix.zero();
+
+ auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
+
+ for (auto i : arange(nb_nodes_per_contact)) {
+ for (auto j : arange(spatial_dimension)) {
+ if (i == 0) {
+ shape_matrix(j, i * spatial_dimension + j) = 1;
+ continue;
+ }
+ shape_matrix(j, i * spatial_dimension + j) = -shapes[i - 1];
+ }
+ }
+ return shape_matrix;
+ }
+
+ template <class Derived>
+ static Tensor3<Real> computeDerivativeShapeFunctionMatrix(
+ const ContactElement & element,
+ const Eigen::MatrixBase<Derived> & projection) {
+
+ const auto type = element.master.type;
+
+ // computing shape derivatives
+ auto && shape_derivatives =
+ ElementClassHelper<_ek_regular>::getDNDS(projection, type);
+
+ const auto surface_dimension = shape_derivatives.rows();
+ const auto spatial_dimension = shape_derivatives.rows() + 1;
+ const auto nb_nodes_per_contact = shape_derivatives.cols() + 1;
+
+ Tensor3<Real> derivative_shape_matrix(
+ spatial_dimension, spatial_dimension * nb_nodes_per_contact,
+ surface_dimension);
+ derivative_shape_matrix.zero();
+
+ for (auto && [dnds, Aj] :
+ zip(shape_derivatives.transpose(), derivative_shape_matrix)) {
+ for (auto i : arange(nb_nodes_per_contact)) {
+ for (auto j : arange(spatial_dimension)) {
+ if (i == 0) {
+ Aj(j, i * spatial_dimension + j) = 0;
+ continue;
+ }
+ Aj(j, i * spatial_dimension + j) = dnds(i - 1);
+ }
+ }
+ }
+ return derivative_shape_matrix;
+ }
};
} // namespace akantu
#endif /* __AKANTU_RESOLUTION_UTILS_HH__ */
diff --git a/src/model/contact_mechanics/resolutions/resolution_penalty.cc b/src/model/contact_mechanics/resolutions/resolution_penalty.cc
index eb6ee0d98..829a5fedc 100644
--- a/src/model/contact_mechanics/resolutions/resolution_penalty.cc
+++ b/src/model/contact_mechanics/resolutions/resolution_penalty.cc
@@ -1,844 +1,615 @@
/**
* @file resolution_penalty.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Jan 17 2019
* @date last modification: Wed Jun 09 2021
*
* @brief Specialization of the resolution class for the penalty method
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "resolution_penalty.hh"
#include "element_class_helper.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
ResolutionPenalty::ResolutionPenalty(ContactMechanicsModel & model,
const ID & id)
: Resolution(model, id) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::initialize() {
this->registerParam("epsilon_n", epsilon_n, Real(0.),
_pat_parsable | _pat_modifiable,
"Normal penalty parameter");
this->registerParam("epsilon_t", epsilon_t, Real(0.),
_pat_parsable | _pat_modifiable,
"Tangential penalty parameter");
}
/* -------------------------------------------------------------------------- */
-Real ResolutionPenalty::computeNormalTraction(Real & gap) const {
+Real ResolutionPenalty::computeNormalTraction(const Real & gap) const {
return epsilon_n * macaulay(gap);
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeNormalForce(const ContactElement & element,
Vector<Real> & force) {
-
- force.zero();
-
- auto & gaps = model.getGaps();
- auto & projections = model.getProjections();
- auto & normals = model.getNormals();
+ const auto & gaps = model.getGaps();
+ const auto & projections = model.getProjections();
+ const auto & normals = model.getNormals();
+ const auto & nodal_area = model.getNodalArea();
auto surface_dimension = spatial_dimension - 1;
- Real gap(gaps.begin()[element.slave]);
- Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
- Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
-
- auto & nodal_area = const_cast<Array<Real> &>(model.getNodalArea());
+ auto gap = gaps(element.slave);
+ auto && normal = normals.begin(spatial_dimension)[element.slave];
+ auto && projection = projections.begin(surface_dimension)[element.slave];
// compute normal traction
- Real p_n = computeNormalTraction(gap);
- p_n *= nodal_area[element.slave];
+ auto p_n = computeNormalTraction(gap) * nodal_area[element.slave];
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> shape_matric(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- ResolutionUtils::computeShapeFunctionMatric(element, projection,
- shape_matric);
+ auto shape_matrix =
+ ResolutionUtils::computeShapeFunctionMatrix(element, projection);
- force.mul<true>(shape_matric, normal, p_n);
+ force = p_n * shape_matrix.transpose() * normal;
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeTangentialForce(const ContactElement & element,
Vector<Real> & force) {
-
+ force.zero();
if (mu == 0) {
return;
}
- force.zero();
-
- UInt surface_dimension = spatial_dimension - 1;
+ auto surface_dimension = spatial_dimension - 1;
// compute covariant basis
- auto & projections = model.getProjections();
- Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
+ auto && projection =
+ model.getProjections().begin(surface_dimension)[element.slave];
- auto & normals = model.getNormals();
- Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
-
- auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
+ auto && covariant_basis = model.getTangents().begin(
+ spatial_dimension, surface_dimension)[element.slave];
// check for no-contact to contact condition
// need a better way to check if new node added is not presnt in the
// previous master elemets
auto & previous_master_elements = model.getPreviousMasterElements();
if (element.slave >= previous_master_elements.size()) {
return;
}
auto & previous_element = previous_master_elements[element.slave];
if (previous_element.type == _not_defined) {
return;
}
// compute tangential traction using return map algorithm
auto & tangential_tractions = model.getTangentialTractions();
- Vector<Real> tangential_traction(
- tangential_tractions.begin(surface_dimension)[element.slave]);
+ auto && tangential_traction =
+ tangential_tractions.begin(surface_dimension)[element.slave];
this->computeTangentialTraction(element, covariant_basis,
tangential_traction);
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> shape_matric(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- ResolutionUtils::computeShapeFunctionMatric(element, projection,
- shape_matric);
+ auto shape_matrix =
+ ResolutionUtils::computeShapeFunctionMatrix(element, projection);
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
- auto & nodal_area = const_cast<Array<Real> &>(model.getNodalArea());
-
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent_alpha = std::get<1>(values1);
- for (auto && values2 : enumerate(tangential_traction)) {
- auto & beta = std::get<0>(values2);
- auto & traction_beta = std::get<1>(values2);
- Vector<Real> tmp(force.size());
- tmp.mul<true>(shape_matric, tangent_alpha, traction_beta);
- tmp *=
- contravariant_metric_tensor(alpha, beta) * nodal_area[element.slave];
- force += tmp;
+ const auto & nodal_area = model.getNodalArea();
+
+ for (auto && [alpha, tangent_alpha] : enumerate(covariant_basis)) {
+ for (auto && [beta, traction_beta] : enumerate(tangential_traction)) {
+ force += (traction_beta * shape_matrix.transpose() * tangent_alpha) *
+ contravariant_metric_tensor(alpha, beta) *
+ nodal_area[element.slave];
}
}
}
/* -------------------------------------------------------------------------- */
+template <typename D>
void ResolutionPenalty::computeTangentialTraction(
const ContactElement & element, const Matrix<Real> & covariant_basis,
- Vector<Real> & traction_tangential) {
+ Eigen::MatrixBase<D> & traction_tangential) {
- UInt surface_dimension = spatial_dimension - 1;
+ Int surface_dimension = spatial_dimension - 1;
- auto & gaps = model.getGaps();
- auto & gap = gaps.begin()[element.slave];
+ const auto & gap = model.getGaps()(element.slave);
// Return map algorithm is employed
// compute trial traction
Vector<Real> traction_trial(surface_dimension);
this->computeTrialTangentialTraction(element, covariant_basis,
traction_trial);
// compute norm of trial traction
Real traction_trial_norm = 0;
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
for (auto i : arange(surface_dimension)) {
for (auto j : arange(surface_dimension)) {
traction_trial_norm += traction_trial[i] * traction_trial[j] *
contravariant_metric_tensor(i, j);
}
}
- traction_trial_norm = sqrt(traction_trial_norm);
+ traction_trial_norm = std::sqrt(traction_trial_norm);
// check stick or slip condition
auto & contact_state = model.getContactState();
auto & state = contact_state.begin()[element.slave];
Real p_n = computeNormalTraction(gap);
bool stick = (traction_trial_norm <= mu * p_n);
if (stick) {
state = ContactState::_stick;
computeStickTangentialTraction(element, traction_trial,
traction_tangential);
} else {
state = ContactState::_slip;
computeSlipTangentialTraction(element, covariant_basis, traction_trial,
traction_tangential);
}
}
/* -------------------------------------------------------------------------- */
+template <typename D>
void ResolutionPenalty::computeTrialTangentialTraction(
- const ContactElement & element, const Matrix<Real> & covariant_basis,
- Vector<Real> & traction) {
+ const ContactElement & element, const Matrix<Real> & current_tangent,
+ Eigen::MatrixBase<D> & traction) {
UInt surface_dimension = spatial_dimension - 1;
auto & projections = model.getProjections();
Vector<Real> current_projection(
projections.begin(surface_dimension)[element.slave]);
auto & previous_projections = model.getPreviousProjections();
Vector<Real> previous_projection(
previous_projections.begin(surface_dimension)[element.slave]);
// method from Laursen et. al.
/*auto covariant_metric_tensor =
GeometryUtils::covariantMetricTensor(covariant_basis); auto
increment_projection = current_projection - previous_projection;
traction.mul<false>(covariant_metric_tensor, increment_projection, epsilon_t);
auto & previous_tangential_tractions = model.getPreviousTangentialTractions();
Vector<Real>
previous_traction(previous_tangential_tractions.begin(surface_dimension)[element.slave]);
traction = previous_traction + traction;*/
// method from Schweizerhof
auto covariant_metric_tensor =
- GeometryUtils::covariantMetricTensor(covariant_basis);
+ GeometryUtils::covariantMetricTensor(current_tangent);
auto & previous_tangential_tractions = model.getPreviousTangentialTractions();
- Vector<Real> previous_traction(
+ auto && previous_traction(
previous_tangential_tractions.begin(surface_dimension)[element.slave]);
auto & previous_tangents = model.getPreviousTangents();
- Matrix<Real> previous_covariant_basis(previous_tangents.begin(
- surface_dimension, spatial_dimension)[element.slave]);
+ auto && previous_tangent = previous_tangents.begin(
+ spatial_dimension, surface_dimension)[element.slave];
auto previous_contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(previous_covariant_basis);
-
- auto current_tangent = covariant_basis.transpose();
- auto previous_tangent = previous_covariant_basis.transpose();
+ GeometryUtils::contravariantMetricTensor(previous_tangent);
for (auto alpha : arange(surface_dimension)) {
- Vector<Real> tangent_alpha(current_tangent(alpha));
for (auto gamma : arange(surface_dimension)) {
for (auto beta : arange(surface_dimension)) {
- Vector<Real> tangent_beta(previous_tangent(beta));
- auto t_alpha_t_beta = tangent_beta.dot(tangent_alpha);
+ auto t_alpha_t_beta =
+ previous_tangent(beta).dot(current_tangent(alpha));
traction[alpha] += previous_traction[gamma] *
previous_contravariant_metric_tensor(gamma, beta) *
t_alpha_t_beta;
}
}
}
auto & previous_master_elements = model.getPreviousMasterElements();
auto & previous_element = previous_master_elements[element.slave];
- Vector<Real> previous_real_projection(spatial_dimension);
- GeometryUtils::realProjection(
- model.getMesh(), model.getContactDetector().getPositions(),
- previous_element, previous_projection, previous_real_projection);
+ auto coords = model.getMesh().extractNodalValuesFromElement(
+ model.getContactDetector().getPositions(), previous_element);
+
+ auto previous_real_projection = GeometryUtils::realProjection(
+ coords, previous_element, previous_projection);
- Vector<Real> current_real_projection(spatial_dimension);
- GeometryUtils::realProjection(
- model.getMesh(), model.getContactDetector().getPositions(),
- element.master, current_projection, current_real_projection);
+ auto current_real_projection =
+ GeometryUtils::realProjection(coords, element.master, current_projection);
auto increment_real = current_real_projection - previous_real_projection;
Vector<Real> increment_xi(surface_dimension);
auto contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(covariant_basis);
+ GeometryUtils::contravariantMetricTensor(current_tangent);
// increment in natural coordinate
for (auto beta : arange(surface_dimension)) {
for (auto gamma : arange(surface_dimension)) {
auto temp = increment_real.dot(current_tangent(gamma));
temp *= contravariant_metric_tensor(beta, gamma);
increment_xi[beta] += temp;
}
}
- Vector<Real> temp(surface_dimension);
- temp.mul<false>(covariant_metric_tensor, increment_xi, epsilon_t);
-
- traction -= temp;
+ traction -= epsilon_t * covariant_metric_tensor * increment_xi;
}
/* -------------------------------------------------------------------------- */
+template <typename D1, typename D2>
void ResolutionPenalty::computeStickTangentialTraction(
- const ContactElement & /*element*/, Vector<Real> & traction_trial,
- Vector<Real> & traction_tangential) {
+ const ContactElement & /*element*/, Eigen::MatrixBase<D1> & traction_trial,
+ Eigen::MatrixBase<D2> & traction_tangential) {
traction_tangential = traction_trial;
}
/* -------------------------------------------------------------------------- */
+template <typename D1, typename D2>
void ResolutionPenalty::computeSlipTangentialTraction(
const ContactElement & element, const Matrix<Real> & covariant_basis,
- Vector<Real> & traction_trial, Vector<Real> & traction_tangential) {
+ Eigen::MatrixBase<D1> & traction_trial,
+ Eigen::MatrixBase<D2> & traction_tangential) {
UInt surface_dimension = spatial_dimension - 1;
- auto & gaps = model.getGaps();
- auto & gap = gaps.begin()[element.slave];
+ auto & gap = model.getGaps()(element.slave);
// compute norm of trial traction
Real traction_trial_norm = 0;
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
for (auto alpha : arange(surface_dimension)) {
for (auto beta : arange(surface_dimension)) {
traction_trial_norm += traction_trial[alpha] * traction_trial[beta] *
contravariant_metric_tensor(alpha, beta);
}
}
traction_trial_norm = sqrt(traction_trial_norm);
- auto slip_direction = traction_trial;
- slip_direction /= traction_trial_norm;
-
Real p_n = computeNormalTraction(gap);
- traction_tangential = slip_direction;
- traction_tangential *= mu * p_n;
+ traction_tangential = traction_trial / traction_trial_norm * mu * p_n;
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeNormalModuli(const ContactElement & element,
Matrix<Real> & stiffness) {
auto surface_dimension = spatial_dimension - 1;
auto & gaps = model.getGaps();
Real gap(gaps.begin()[element.slave]);
auto & projections = model.getProjections();
Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
auto & nodal_areas = model.getNodalArea();
auto & nodal_area = nodal_areas.begin()[element.slave];
auto & normals = model.getNormals();
Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
// method from Schweizerhof and A. Konyukhov, K. Schweizerhof
// DOI 10.1007/s00466-004-0616-7 and DOI 10.1007/s00466-003-0515-3
// construct A matrix
- const ElementType & type = element.master.type;
- auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> A(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- A(j, i * spatial_dimension + j) = 1;
- continue;
- }
- A(j, i * spatial_dimension + j) = -shapes[i - 1];
- }
- }
+ auto A = ResolutionUtils::computeShapeFunctionMatrix(element, projection);
// construct the main part of normal matrix
- Matrix<Real> k_main(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
+ Matrix<Real> k_main(A.cols(), A.cols());
Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_n(normal.storage(), normal.size(), 1.);
- n_outer_n.mul<false, true>(mat_n, mat_n);
-
- Matrix<Real> tmp(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(n_outer_n, A);
+ n_outer_n = normal * normal.transpose();
- k_main.mul<true, false>(A, tmp);
- k_main *= epsilon_n * heaviside(gap) * nodal_area;
+ k_main =
+ (A.transpose() * n_outer_n * A) * epsilon_n * heaviside(gap) * nodal_area;
// construct the rotational part of the normal matrix
- auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
+ const auto & tangents = model.getTangents();
+ auto && covariant_basis(
+ tangents.begin(spatial_dimension, surface_dimension)[element.slave]);
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
- // computing shape derivatives
- auto && shape_derivatives =
- ElementClassHelper<_ek_regular>::getDNDS(projection, type);
-
// consists of 2 rotational parts
- Matrix<Real> k_rot1(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_rot2(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> Aj(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- auto construct_Aj = [&](auto && dnds) {
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- Aj(j, i * spatial_dimension + j) = 0;
- continue;
- }
- Aj(j, i * spatial_dimension + j) = dnds(i - 1);
- }
- }
- };
+ Matrix<Real> k_rot1(A.cols(), A.cols());
+ Matrix<Real> k_rot2(A.cols(), A.cols());
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent = std::get<1>(values1);
+ k_rot1.zero();
+ k_rot2.zero();
- Matrix<Real> n_outer_t(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_t(tangent.storage(), tangent.size(), 1.);
- n_outer_t.mul<false, true>(mat_n, mat_t);
+ auto Ajs = ResolutionUtils::computeDerivativeShapeFunctionMatrix(element,
+ projection);
- Matrix<Real> t_outer_n(spatial_dimension, spatial_dimension);
- t_outer_n.mul<false, true>(mat_t, mat_n);
+ for (auto && [alpha, tangent] : enumerate(covariant_basis)) {
+ auto n_outer_t = normal * tangent.transpose();
+ // auto t_outer_n = tangent * normal.transpose();
- for (auto && values2 : enumerate(shape_derivatives.transpose())) {
- auto & beta = std::get<0>(values2);
- auto & dnds = std::get<1>(values2);
+ for (auto && [beta, Aj] : enumerate(Ajs)) {
// construct Aj from shape function wrt to jth natural
// coordinate
- construct_Aj(dnds);
-
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(n_outer_t, A);
- tmp1.mul<true, false>(Aj, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, beta);
- k_rot1 += tmp1;
-
- tmp.mul<false, false>(t_outer_n, Aj);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, beta);
- k_rot2 += tmp1;
+ k_rot1 += (Aj.transpose() * n_outer_t * A) *
+ contravariant_metric_tensor(alpha, beta);
+
+ k_rot2 += (A.transpose() * n_outer_t * Aj) *
+ contravariant_metric_tensor(alpha, beta);
}
}
k_rot1 *= -epsilon_n * heaviside(gap) * gap * nodal_area;
k_rot2 *= -epsilon_n * heaviside(gap) * gap * nodal_area;
stiffness += k_main + k_rot1 + k_rot2;
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeTangentialModuli(const ContactElement & element,
Matrix<Real> & stiffness) {
if (mu == 0) {
return;
}
stiffness.zero();
auto & contact_state = model.getContactState();
auto state = contact_state.begin()[element.slave];
switch (state) {
case ContactState::_stick: {
computeStickModuli(element, stiffness);
break;
}
case ContactState::_slip: {
computeSlipModuli(element, stiffness);
break;
}
default:
break;
}
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeStickModuli(const ContactElement & element,
Matrix<Real> & stiffness) {
auto surface_dimension = spatial_dimension - 1;
auto & projections = model.getProjections();
Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
auto & nodal_areas = model.getNodalArea();
auto & nodal_area = nodal_areas.begin()[element.slave];
// method from Schweizerhof and A. Konyukhov, K. Schweizerhof
// DOI 10.1007/s00466-004-0616-7 and DOI 10.1007/s00466-003-0515-3
// construct A matrix
- const ElementType & type = element.master.type;
- auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> A(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- A(j, i * spatial_dimension + j) = 1;
- continue;
- }
- A(j, i * spatial_dimension + j) = -shapes[i - 1];
- }
- }
+ auto A = ResolutionUtils::computeShapeFunctionMatrix(element, projection);
// computing shape derivatives
- auto && shape_derivatives =
- ElementClassHelper<_ek_regular>::getDNDS(projection, type);
-
- Matrix<Real> Aj(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- auto construct_Aj = [&](auto && dnds) {
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- Aj(j, i * spatial_dimension + j) = 0;
- continue;
- }
- Aj(j, i * spatial_dimension + j) = dnds(i - 1);
- }
- }
- };
+ auto Ajs = ResolutionUtils::computeDerivativeShapeFunctionMatrix(element,
+ projection);
// tangents should have been calculated in normal modulii
auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
+ auto && covariant_basis(
+ tangents.begin(spatial_dimension, surface_dimension)[element.slave]);
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
// construct 1st part of the stick modulii
- Matrix<Real> k_main(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
-
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent_alpha = std::get<1>(values1);
-
- Matrix<Real> t_outer_t(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_t_alpha(tangent_alpha.storage(), tangent_alpha.size(), 1.);
-
- for (auto && values2 : enumerate(covariant_basis.transpose())) {
- auto & beta = std::get<0>(values2);
- auto & tangent_beta = std::get<1>(values2);
-
- Matrix<Real> mat_t_beta(tangent_beta.storage(), tangent_beta.size(), 1.);
- t_outer_t.mul<false, true>(mat_t_alpha, mat_t_beta);
-
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(t_outer_t, A);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, beta);
- k_main += tmp1;
+ Matrix<Real> k_main(A.cols(), A.cols());
+ k_main.zero();
+
+ for (auto && [alpha, tangent_alpha] : enumerate(covariant_basis)) {
+ for (auto && [beta, tangent_beta] : enumerate(covariant_basis)) {
+ auto t_outer_t = tangent_alpha * tangent_beta.transpose();
+
+ k_main += (A.transpose() * t_outer_t * A) *
+ contravariant_metric_tensor(alpha, beta);
}
}
k_main *= -epsilon_t;
// construct 2nd part of the stick modulii
auto & tangential_tractions = model.getTangentialTractions();
- Vector<Real> tangential_traction(
- tangential_tractions.begin(surface_dimension)[element.slave]);
+ auto && tangential_traction =
+ tangential_tractions.begin(surface_dimension)[element.slave];
- Matrix<Real> k_second(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
+ Matrix<Real> k_second(A.cols(), A.cols());
+ k_second.zero();
+
+ Matrix<Real> k_sum(A.cols(), A.cols());
for (auto alpha : arange(surface_dimension)) {
- Matrix<Real> k_sum(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
-
- for (auto && values1 : enumerate(shape_derivatives.transpose())) {
- auto & beta = std::get<0>(values1);
- auto & dnds = std::get<1>(values1);
- // construct Aj from shape function wrt to jth natural
- // coordinate
- construct_Aj(dnds);
- for (auto && values2 : enumerate(covariant_basis.transpose())) {
- auto & gamma = std::get<0>(values2);
- auto & tangent_gamma = std::get<1>(values2);
+ k_sum.zero();
+ for (auto && [beta, Aj] : enumerate(Ajs)) {
+ for (auto && [gamma, tangent_gamma] : enumerate(covariant_basis)) {
Matrix<Real> t_outer_t(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_t_gamma(tangent_gamma.storage(), tangent_gamma.size(),
- 1.);
for (auto && values3 : enumerate(covariant_basis.transpose())) {
auto & theta = std::get<0>(values3);
auto & tangent_theta = std::get<1>(values3);
- Matrix<Real> mat_t_theta(tangent_theta.storage(),
- tangent_theta.size(), 1.);
- t_outer_t.mul<false, true>(mat_t_gamma, mat_t_theta);
-
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(t_outer_t, Aj);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, theta) *
- contravariant_metric_tensor(beta, gamma);
-
- Matrix<Real> tmp2(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp3(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp2.mul<false, false>(t_outer_t, A);
- tmp3.mul<true, false>(Aj, tmp2);
- tmp3 *= contravariant_metric_tensor(alpha, gamma) *
- contravariant_metric_tensor(beta, theta);
-
- k_sum += tmp1 + tmp3;
+ t_outer_t = tangent_gamma * tangent_theta.transpose();
+
+ k_sum += (A.transpose() * t_outer_t * Aj) *
+ contravariant_metric_tensor(alpha, theta) *
+ contravariant_metric_tensor(beta, gamma) +
+ (Aj.transpose() * t_outer_t * A) *
+ contravariant_metric_tensor(alpha, gamma) *
+ contravariant_metric_tensor(beta, theta);
}
}
}
k_second += tangential_traction[alpha] * k_sum;
}
stiffness += k_main * nodal_area - k_second * nodal_area;
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeSlipModuli(const ContactElement & element,
Matrix<Real> & stiffness) {
auto surface_dimension = spatial_dimension - 1;
auto & gaps = model.getGaps();
Real gap(gaps.begin()[element.slave]);
auto & nodal_areas = model.getNodalArea();
auto & nodal_area = nodal_areas.begin()[element.slave];
// compute normal traction
Real p_n = computeNormalTraction(gap);
auto & projections = model.getProjections();
Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
auto & normals = model.getNormals();
Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
- // restructure normal as a matrix for an outer product
- Matrix<Real> mat_n(normal.storage(), normal.size(), 1.);
-
// method from Schweizerhof and A. Konyukhov, K. Schweizerhof
// DOI 10.1007/s00466-004-0616-7 and DOI 10.1007/s00466-003-0515-3
// construct A matrix
- const ElementType & type = element.master.type;
- auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> A(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- A(j, i * spatial_dimension + j) = 1;
- continue;
- }
- A(j, i * spatial_dimension + j) = -shapes[i - 1];
- }
- }
+ auto A = ResolutionUtils::computeShapeFunctionMatrix(element, projection);
// computing shape derivatives
- auto && shape_derivatives =
- ElementClassHelper<_ek_regular>::getDNDS(projection, type);
-
- Matrix<Real> Aj(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- auto construct_Aj = [&](auto && dnds) {
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- Aj(j, i * spatial_dimension + j) = 0;
- continue;
- }
- Aj(j, i * spatial_dimension + j) = dnds(i - 1);
- }
- }
- };
+ auto Ajs = ResolutionUtils::computeDerivativeShapeFunctionMatrix(element,
+ projection);
// tangents should have been calculated in normal modulii
- auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
+ auto && covariant_basis = model.getTangents().begin(
+ spatial_dimension, surface_dimension)[element.slave];
auto & tangential_tractions = model.getTangentialTractions();
Vector<Real> tangential_traction(
tangential_tractions.begin(surface_dimension)[element.slave]);
// compute norm of trial traction
Real traction_norm = 0;
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
for (auto i : arange(surface_dimension)) {
for (auto j : arange(surface_dimension)) {
traction_norm += tangential_traction[i] * tangential_traction[j] *
contravariant_metric_tensor(i, j);
}
}
traction_norm = sqrt(traction_norm);
// construct four parts of stick modulii (eq 107,107a-c)
- Matrix<Real> k_first(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_second(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_third(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_fourth(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
-
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent_alpha = std::get<1>(values1);
-
- Matrix<Real> mat_t_alpha(tangent_alpha.storage(), tangent_alpha.size(), 1.);
-
- Matrix<Real> t_outer_n(spatial_dimension, spatial_dimension);
- Matrix<Real> t_outer_t(spatial_dimension, spatial_dimension);
-
- for (auto && values2 :
- zip(arange(surface_dimension), covariant_basis.transpose(),
- shape_derivatives.transpose())) {
- auto & beta = std::get<0>(values2);
- auto & tangent_beta = std::get<1>(values2);
- auto & dnds = std::get<2>(values2);
- // construct Aj from shape function wrt to jth natural
- // coordinate
- construct_Aj(dnds);
-
+ Matrix<Real> k_first(A.cols(), A.cols());
+ Matrix<Real> k_second(A.cols(), A.cols());
+ Matrix<Real> k_third(A.cols(), A.cols());
+ Matrix<Real> k_fourth(A.cols(), A.cols());
+
+ k_first.zero();
+ k_second.zero();
+ k_first.zero();
+ k_fourth.zero();
+
+ Matrix<Real> t_outer_n(spatial_dimension, spatial_dimension);
+ Matrix<Real> t_outer_t(spatial_dimension, spatial_dimension);
+
+ for (auto && [alpha, tangent_alpha] : enumerate(covariant_basis)) {
+ for (auto && [beta, tangent_beta, Aj] :
+ zip(arange(surface_dimension), covariant_basis, Ajs)) {
// eq 107
- Matrix<Real> mat_t_beta(tangent_beta.storage(), tangent_beta.size(), 1.);
- t_outer_n.mul<false, true>(mat_t_beta, mat_n);
-
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(t_outer_n, A);
- tmp1.mul<true, false>(A, tmp);
-
- tmp1 *= epsilon_n * mu * tangential_traction[alpha] *
- contravariant_metric_tensor(alpha, beta);
- tmp1 /= traction_norm;
+ t_outer_n = tangent_beta * normal.transpose();
- k_first += tmp1 * nodal_area;
+ k_first += (A.transpose() * t_outer_n * A) * epsilon_n * mu *
+ tangential_traction[alpha] *
+ contravariant_metric_tensor(alpha, beta) / traction_norm *
+ nodal_area;
// eq 107a
- t_outer_t.mul<false, true>(mat_t_alpha, mat_t_beta);
+ t_outer_t = tangent_alpha * tangent_beta.transpose();
- tmp.mul<false, false>(t_outer_t, A);
- tmp1.mul<true, false>(A, tmp);
+ k_second += (A.transpose() * t_outer_t * A) * epsilon_t * mu * p_n *
+ contravariant_metric_tensor(alpha, beta) / traction_norm *
+ nodal_area;
- tmp1 *= epsilon_t * mu * p_n * contravariant_metric_tensor(alpha, beta);
- tmp1 /= traction_norm;
-
- k_second += tmp1 * nodal_area;
-
- for (auto && values3 : enumerate(covariant_basis.transpose())) {
+ for (auto && values3 : enumerate(covariant_basis)) {
auto & gamma = std::get<0>(values3);
auto & tangent_gamma = std::get<1>(values3);
- Matrix<Real> mat_t_gamma(tangent_gamma.storage(), tangent_gamma.size(),
- 1.);
-
- for (auto && values4 : enumerate(covariant_basis.transpose())) {
+ for (auto && values4 : enumerate(covariant_basis)) {
auto & theta = std::get<0>(values4);
auto & tangent_theta = std::get<1>(values4);
- Matrix<Real> mat_t_theta(tangent_theta.storage(),
- tangent_theta.size(), 1.);
- t_outer_t.mul<false, true>(mat_t_gamma, mat_t_theta);
+ t_outer_t = tangent_gamma * tangent_theta.transpose();
// eq 107b
- tmp.mul<false, false>(t_outer_t, A);
- tmp1.mul<true, false>(A, tmp);
-
- tmp1 *= epsilon_t * mu * p_n * tangential_traction[alpha] *
- tangential_traction[beta];
- tmp1 *= contravariant_metric_tensor(alpha, gamma) *
- contravariant_metric_tensor(beta, theta);
- tmp1 /= pow(traction_norm, 3);
-
- k_third += tmp1 * nodal_area;
+ k_third += (A.transpose() * t_outer_t * A) * epsilon_t * mu * p_n *
+ tangential_traction[alpha] * tangential_traction[beta] *
+ contravariant_metric_tensor(alpha, gamma) *
+ contravariant_metric_tensor(beta, theta) /
+ pow(traction_norm, 3) * nodal_area;
// eq 107c
- tmp.mul<false, false>(t_outer_t, Aj);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, theta) *
- contravariant_metric_tensor(beta, gamma);
- tmp1 *= mu * p_n * tangential_traction[alpha];
- tmp1 /= traction_norm;
-
- Matrix<Real> tmp2(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp3(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp2.mul<false, false>(t_outer_t, A);
- tmp3.mul<true, false>(Aj, tmp2);
- tmp3 *= contravariant_metric_tensor(alpha, gamma) *
- contravariant_metric_tensor(beta, theta);
- tmp3 *= mu * p_n * tangential_traction[alpha];
- tmp3 /= traction_norm;
-
- k_fourth += (tmp1 + tmp3) * nodal_area;
+ k_fourth += ((A.transpose() * t_outer_t * Aj) *
+ contravariant_metric_tensor(alpha, theta) *
+ contravariant_metric_tensor(beta, gamma) +
+ (Aj.transpose() * t_outer_t * A) *
+ contravariant_metric_tensor(alpha, gamma) *
+ contravariant_metric_tensor(beta, theta)) *
+ nodal_area * mu * p_n * tangential_traction[alpha] /
+ traction_norm;
}
}
}
}
stiffness += k_third + k_fourth - k_first - k_second;
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::beforeSolveStep() {}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::afterSolveStep(__attribute__((unused)) bool converged) {
}
INSTANTIATE_RESOLUTION(penalty_linear, ResolutionPenalty);
} // namespace akantu
diff --git a/src/model/contact_mechanics/resolutions/resolution_penalty.hh b/src/model/contact_mechanics/resolutions/resolution_penalty.hh
index 3242f0567..626a1470d 100644
--- a/src/model/contact_mechanics/resolutions/resolution_penalty.hh
+++ b/src/model/contact_mechanics/resolutions/resolution_penalty.hh
@@ -1,133 +1,139 @@
/**
* @file resolution_penalty.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Jun 09 2021
*
* @brief Linear Penalty Resolution for Contact Mechanics Model
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "resolution.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_RESOLUTION_PENALTY_HH__
#define __AKANTU_RESOLUTION_PENALTY_HH__
namespace akantu {
class ResolutionPenalty : public Resolution {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
ResolutionPenalty(ContactMechanicsModel & model, const ID & id = "");
~ResolutionPenalty() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// initialize the resolution
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods for stiffness computation */
/* ------------------------------------------------------------------------ */
protected:
/// local computaion of stiffness matrix due to stick state
- void computeStickModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/);
+ void computeStickModuli(const ContactElement & element,
+ Matrix<Real> & stiffness);
/// local computation of stiffness matrix due to slip state
- void computeSlipModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/);
+ void computeSlipModuli(const ContactElement & element,
+ Matrix<Real> & stiffness);
public:
/// local computation of tangent moduli due to normal traction
- void computeNormalModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/) override;
+ void computeNormalModuli(const ContactElement & element,
+ Matrix<Real> & stiffness) override;
/// local computation of tangent moduli due to tangential traction
- void computeTangentialModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/) override;
+ void computeTangentialModuli(const ContactElement & element,
+ Matrix<Real> & stiffness) override;
/* ------------------------------------------------------------------------ */
/* Methods for force computation */
/* ------------------------------------------------------------------------ */
public:
/// local computation of normal force due to normal contact
- void computeNormalForce(const ContactElement & /*element*/,
- Vector<Real> & /*force*/) override;
+ void computeNormalForce(const ContactElement & element,
+ Vector<Real> & force) override;
/// local computation of tangential force due to frictional traction
- void computeTangentialForce(const ContactElement & /*element*/,
- Vector<Real> & /*force*/) override;
+ void computeTangentialForce(const ContactElement & element,
+ Vector<Real> & force) override;
protected:
/// local computation of normal traction due to penetration
- Real computeNormalTraction(Real & /*gap*/) const;
+ virtual Real computeNormalTraction(const Real & gap) const;
/// local computation of trial tangential traction due to friction
- void computeTrialTangentialTraction(const ContactElement & /*element*/,
- const Matrix<Real> & /*covariant_basis*/,
- Vector<Real> & /*traction*/);
+ template <typename D>
+ void computeTrialTangentialTraction(const ContactElement & element,
+ const Matrix<Real> & covariant_basis,
+ Eigen::MatrixBase<D> & traction);
/// local computation of tangential traction due to stick
- void computeStickTangentialTraction(const ContactElement & /*unused*/,
- Vector<Real> & /*traction_trial*/,
- Vector<Real> & /*traction_tangential*/);
+ template <typename D1, typename D2>
+ void
+ computeStickTangentialTraction(const ContactElement & unused,
+ Eigen::MatrixBase<D1> & traction_trial,
+ Eigen::MatrixBase<D2> & traction_tangential);
/// local computation of tangential traction due to slip
- void computeSlipTangentialTraction(const ContactElement & /*element*/,
- const Matrix<Real> & /*covariant_basis*/,
- Vector<Real> & /*traction_trial*/,
- Vector<Real> & /*traction_tangential*/);
+ template <typename D1, typename D2>
+ void
+ computeSlipTangentialTraction(const ContactElement & element,
+ const Matrix<Real> & covariant_basis,
+ Eigen::MatrixBase<D1> & traction_trial,
+ Eigen::MatrixBase<D2> & traction_tangential);
/// local computation of tangential traction due to friction
- void computeTangentialTraction(const ContactElement & /*element*/,
- const Matrix<Real> & /*covariant_basis*/,
- Vector<Real> & /*traction_tangential*/);
+ template <typename D>
+ void computeTangentialTraction(const ContactElement & element,
+ const Matrix<Real> & covariant_basis,
+ Eigen::MatrixBase<D> & traction_tangential);
public:
void beforeSolveStep() override;
void afterSolveStep(bool converged = true) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// penalty parameter for normal traction
Real epsilon_n;
/// penalty parameter for tangential traction
Real epsilon_t;
};
} // namespace akantu
#endif /* __AKANTU_RESOLUTION_PENALTY_HH__ */
diff --git a/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.cc b/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.cc
index 0849b48a6..49dedbffe 100644
--- a/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.cc
+++ b/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.cc
@@ -1,836 +1,128 @@
/**
* @file resolution_penalty_quadratic.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Jan 17 2019
* @date last modification: Wed Jun 09 2021
*
* @brief Specialization of the resolution class for the quadratic penalty
* method
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "resolution_penalty_quadratic.hh"
#include "element_class_helper.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
ResolutionPenaltyQuadratic::ResolutionPenaltyQuadratic(
ContactMechanicsModel & model, const ID & id)
: Parent(model, id) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::initialize() {}
-
-/* -------------------------------------------------------------------------- */
-Real ResolutionPenaltyQuadratic::computeNormalTraction(Real & gap) {
+Real ResolutionPenaltyQuadratic::computeNormalTraction(const Real & gap) const {
return epsilon_n * (macaulay(gap) * macaulay(gap) + macaulay(gap));
}
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeNormalForce(
- const ContactElement & element, Vector<Real> & force) {
- force.zero();
-
- auto & gaps = model.getGaps();
- auto & projections = model.getProjections();
- auto & normals = model.getNormals();
-
- auto surface_dimension = spatial_dimension - 1;
-
- Real gap(gaps.begin()[element.slave]);
- Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
- Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
-
- auto & nodal_area = const_cast<Array<Real> &>(model.getNodalArea());
-
- // compute normal traction
- Real p_n = computeNormalTraction(gap);
- p_n *= nodal_area[element.slave];
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> shape_matric(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- ResolutionUtils::computeShapeFunctionMatric(element, projection,
- shape_matric);
-
- force.mul<true>(shape_matric, normal, p_n);
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeTangentialForce(
- const ContactElement & element, Vector<Real> & force) {
-
- if (mu == 0) {
- return;
- }
-
- force.zero();
-
- UInt surface_dimension = spatial_dimension - 1;
-
- // compute tangents
- auto & projections = model.getProjections();
- Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
-
- auto & normals = model.getNormals();
- Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
-
- auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
-
- // check for no-contact to contact condition
- // need a better way to check if new node added is not presnt in the
- // previous master elemets
- auto & previous_master_elements = model.getPreviousMasterElements();
- if (element.slave >= previous_master_elements.size()) {
- return;
- }
-
- auto & previous_element = previous_master_elements[element.slave];
- if (previous_element.type == _not_defined) {
- return;
- }
-
- // compute tangential traction using return map algorithm
- auto & tangential_tractions = model.getTangentialTractions();
- Vector<Real> tangential_traction(
- tangential_tractions.begin(surface_dimension)[element.slave]);
- this->computeTangentialTraction(element, covariant_basis,
- tangential_traction);
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> shape_matric(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- ResolutionUtils::computeShapeFunctionMatric(element, projection,
- shape_matric);
-
- auto contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(covariant_basis);
-
- auto & nodal_area = const_cast<Array<Real> &>(model.getNodalArea());
-
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent_alpha = std::get<1>(values1);
- for (auto && values2 : enumerate(tangential_traction)) {
- auto & beta = std::get<0>(values2);
- auto & traction_beta = std::get<1>(values2);
- Vector<Real> tmp(force.size());
- tmp.mul<true>(shape_matric, tangent_alpha, traction_beta);
- tmp *=
- contravariant_metric_tensor(alpha, beta) * nodal_area[element.slave];
- force += tmp;
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeTangentialTraction(
- const ContactElement & element, const Matrix<Real> & covariant_basis,
- Vector<Real> & traction_tangential) {
-
- UInt surface_dimension = spatial_dimension - 1;
-
- auto & gaps = model.getGaps();
- auto & gap = gaps.begin()[element.slave];
-
- // Return map algorithm is employed
- // compute trial traction
- Vector<Real> traction_trial(surface_dimension);
- this->computeTrialTangentialTraction(element, covariant_basis,
- traction_trial);
-
- // compute norm of trial traction
- Real traction_trial_norm = 0;
- auto contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(covariant_basis);
- for (auto i : arange(surface_dimension)) {
- for (auto j : arange(surface_dimension)) {
- traction_trial_norm += traction_trial[i] * traction_trial[j] *
- contravariant_metric_tensor(i, j);
- }
- }
- traction_trial_norm = sqrt(traction_trial_norm);
-
- // check stick or slip condition
- auto & contact_state = model.getContactState();
- auto & state = contact_state.begin()[element.slave];
-
- Real p_n = computeNormalTraction(gap);
- bool stick = traction_trial_norm <= mu * p_n;
-
- if (stick) {
- state = ContactState::_stick;
- computeStickTangentialTraction(element, traction_trial,
- traction_tangential);
- } else {
- state = ContactState::_slip;
- computeSlipTangentialTraction(element, covariant_basis, traction_trial,
- traction_tangential);
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeTrialTangentialTraction(
- const ContactElement & element, const Matrix<Real> & covariant_basis,
- Vector<Real> & traction) {
-
- UInt surface_dimension = spatial_dimension - 1;
-
- auto & projections = model.getProjections();
- Vector<Real> current_projection(
- projections.begin(surface_dimension)[element.slave]);
-
- auto & previous_projections = model.getPreviousProjections();
- Vector<Real> previous_projection(
- previous_projections.begin(surface_dimension)[element.slave]);
-
- // method from Laursen et. al.
- /*auto covariant_metric_tensor =
- GeometryUtils::covariantMetricTensor(covariant_basis); auto
- increment_projection = current_projection - previous_projection;
-
- traction.mul<false>(covariant_metric_tensor, increment_projection, epsilon_t);
-
- auto & previous_tangential_tractions = model.getPreviousTangentialTractions();
- Vector<Real>
- previous_traction(previous_tangential_tractions.begin(surface_dimension)[element.slave]);
- traction = previous_traction + traction;*/
-
- // method from Schweizerhof
- auto covariant_metric_tensor =
- GeometryUtils::covariantMetricTensor(covariant_basis);
-
- auto & previous_tangential_tractions = model.getPreviousTangentialTractions();
- Vector<Real> previous_traction(
- previous_tangential_tractions.begin(surface_dimension)[element.slave]);
-
- auto & previous_tangents = model.getPreviousTangents();
- Matrix<Real> previous_covariant_basis(previous_tangents.begin(
- surface_dimension, spatial_dimension)[element.slave]);
- auto previous_contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(previous_covariant_basis);
-
- auto current_tangent = covariant_basis.transpose();
- auto previous_tangent = previous_covariant_basis.transpose();
-
- for (auto alpha : arange(surface_dimension)) {
- Vector<Real> tangent_alpha(current_tangent(alpha));
- for (auto gamma : arange(surface_dimension)) {
- for (auto beta : arange(surface_dimension)) {
- Vector<Real> tangent_beta(previous_tangent(beta));
- auto t_alpha_t_beta = tangent_beta.dot(tangent_alpha);
- traction[alpha] += previous_traction[gamma] *
- previous_contravariant_metric_tensor(gamma, beta) *
- t_alpha_t_beta;
- }
- }
- }
-
- auto & previous_master_elements = model.getPreviousMasterElements();
- auto & previous_element = previous_master_elements[element.slave];
-
- Vector<Real> previous_real_projection(spatial_dimension);
- GeometryUtils::realProjection(
- model.getMesh(), model.getContactDetector().getPositions(),
- previous_element, previous_projection, previous_real_projection);
-
- Vector<Real> current_real_projection(spatial_dimension);
- GeometryUtils::realProjection(
- model.getMesh(), model.getContactDetector().getPositions(),
- element.master, current_projection, current_real_projection);
-
- auto increment_real = current_real_projection - previous_real_projection;
- Vector<Real> increment_xi(surface_dimension);
-
- auto contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(covariant_basis);
-
- // increment in natural coordinate
- for (auto beta : arange(surface_dimension)) {
- for (auto gamma : arange(surface_dimension)) {
- auto temp = increment_real.dot(current_tangent(gamma));
- temp *= contravariant_metric_tensor(beta, gamma);
- increment_xi[beta] += temp;
- }
- }
-
- Vector<Real> temp(surface_dimension);
- temp.mul<false>(covariant_metric_tensor, increment_xi, epsilon_t);
-
- traction -= temp;
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeStickTangentialTraction(
- const ContactElement & /*element*/, Vector<Real> & traction_trial,
- Vector<Real> & traction_tangential) {
- traction_tangential = traction_trial;
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeSlipTangentialTraction(
- const ContactElement & element, const Matrix<Real> & covariant_basis,
- Vector<Real> & traction_trial, Vector<Real> & traction_tangential) {
- UInt surface_dimension = spatial_dimension - 1;
-
- auto & gaps = model.getGaps();
- auto & gap = gaps.begin()[element.slave];
-
- // compute norm of trial traction
- Real traction_trial_norm = 0;
- auto contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(covariant_basis);
- for (auto i : arange(surface_dimension)) {
- for (auto j : arange(surface_dimension)) {
- traction_trial_norm += traction_trial[i] * traction_trial[j] *
- contravariant_metric_tensor(i, j);
- }
- }
- traction_trial_norm = sqrt(traction_trial_norm);
-
- auto slip_direction = traction_trial;
- slip_direction /= traction_trial_norm;
-
- Real p_n = computeNormalTraction(gap);
- traction_tangential = slip_direction;
- traction_tangential *= mu * p_n;
-}
-
/* -------------------------------------------------------------------------- */
void ResolutionPenaltyQuadratic::computeNormalModuli(
const ContactElement & element, Matrix<Real> & stiffness) {
auto surface_dimension = spatial_dimension - 1;
auto & gaps = model.getGaps();
Real gap(gaps.begin()[element.slave]);
auto & projections = model.getProjections();
Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
auto & nodal_areas = model.getNodalArea();
auto & nodal_area = nodal_areas.begin()[element.slave];
auto & normals = model.getNormals();
Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
// method from Schweizerhof and A. Konyukhov, K. Schweizerhof
// DOI 10.1007/s00466-004-0616-7 and DOI 10.1007/s00466-003-0515-3
// construct A matrix
- const ElementType & type = element.master.type;
- auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> A(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- A(j, i * spatial_dimension + j) = 1;
- continue;
- }
- A(j, i * spatial_dimension + j) = -shapes[i - 1];
- }
- }
+ auto A = ResolutionUtils::computeShapeFunctionMatrix(element, projection);
// construct the main part of normal matrix
- Matrix<Real> k_main(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
+ Matrix<Real> k_main(A.cols(), A.cols());
Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_n(normal.storage(), normal.size(), 1.);
- n_outer_n.mul<false, true>(mat_n, mat_n);
+ n_outer_n = normal * normal.transpose();
- Matrix<Real> tmp(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(n_outer_n, A);
-
- k_main.mul<true, false>(A, tmp);
- k_main *= epsilon_n * heaviside(gap) * (2 * gap + 1) * nodal_area;
+ k_main = (A.transpose() * n_outer_n * A) * epsilon_n * heaviside(gap) *
+ (2 * gap + 1) * nodal_area;
// construct the rotational part of the normal matrix
auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
+ auto && covariant_basis =
+ tangents.begin(spatial_dimension, surface_dimension)[element.slave];
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
- // computing shape derivatives
- auto && shape_derivatives =
- ElementClassHelper<_ek_regular>::getDNDS(projection, type);
-
// consists of 2 rotational parts
- Matrix<Real> k_rot1(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_rot2(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> Aj(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
+ Matrix<Real> k_rot1(A.cols(), A.cols());
+ Matrix<Real> k_rot2(A.cols(), A.cols());
- auto construct_Aj = [&](auto && dnds) {
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- Aj(j, i * spatial_dimension + j) = 0;
- continue;
- }
- Aj(j, i * spatial_dimension + j) = dnds(i - 1);
- }
- }
- };
-
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent = std::get<1>(values1);
+ k_rot1.zero();
+ k_rot2.zero();
- Matrix<Real> n_outer_t(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_t(tangent.storage(), tangent.size(), 1.);
- n_outer_t.mul<false, true>(mat_n, mat_t);
+ auto Ajs = ResolutionUtils::computeDerivativeShapeFunctionMatrix(element,
+ projection);
- Matrix<Real> t_outer_n(spatial_dimension, spatial_dimension);
- t_outer_n.mul<false, true>(mat_t, mat_n);
+ for (auto && [alpha, tangent] : enumerate(covariant_basis)) {
+ auto n_outer_t = normal * tangent.transpose();
+ // auto t_outer_n = tangent * normal.transpose();
- for (auto && values2 : enumerate(shape_derivatives.transpose())) {
- auto & beta = std::get<0>(values2);
- auto & dnds = std::get<1>(values2);
+ for (auto && [beta, Aj] : enumerate(Ajs)) {
// construct Aj from shape function wrt to jth natural
// coordinate
- construct_Aj(dnds);
+ k_rot1 += (Aj.transpose() * n_outer_t * A) *
+ contravariant_metric_tensor(alpha, beta);
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(n_outer_t, A);
- tmp1.mul<true, false>(Aj, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, beta);
- k_rot1 += tmp1;
-
- tmp.mul<false, false>(t_outer_n, Aj);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, beta);
- k_rot2 += tmp1;
+ k_rot2 += (A.transpose() * n_outer_t * Aj) *
+ contravariant_metric_tensor(alpha, beta);
}
}
k_rot1 *= -epsilon_n * heaviside(gap) * (gap * gap + gap) * nodal_area;
k_rot2 *= -epsilon_n * heaviside(gap) * (gap * gap + gap) * nodal_area;
stiffness += k_main + k_rot1 + k_rot2;
}
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeTangentialModuli(
- const ContactElement & element, Matrix<Real> & stiffness) {
- if (mu == 0) {
- return;
- }
-
- stiffness.zero();
-
- auto & contact_state = model.getContactState();
- auto state = contact_state.begin()[element.slave];
-
- switch (state) {
- case ContactState::_stick: {
- computeStickModuli(element, stiffness);
- break;
- }
- case ContactState::_slip: {
- computeSlipModuli(element, stiffness);
- break;
- }
- default:
- break;
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeStickModuli(
- const ContactElement & element, Matrix<Real> & stiffness) {
-
- auto surface_dimension = spatial_dimension - 1;
-
- auto & projections = model.getProjections();
- Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
-
- auto & nodal_areas = model.getNodalArea();
- auto & nodal_area = nodal_areas.begin()[element.slave];
-
- // method from Schweizerhof and A. Konyukhov, K. Schweizerhof
- // DOI 10.1007/s00466-004-0616-7 and DOI 10.1007/s00466-003-0515-3
-
- // construct A matrix
- const ElementType & type = element.master.type;
- auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> A(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- A(j, i * spatial_dimension + j) = 1;
- continue;
- }
- A(j, i * spatial_dimension + j) = -shapes[i - 1];
- }
- }
-
- // computing shape derivatives
- auto && shape_derivatives =
- ElementClassHelper<_ek_regular>::getDNDS(projection, type);
-
- Matrix<Real> Aj(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- auto construct_Aj = [&](auto && dnds) {
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- Aj(j, i * spatial_dimension + j) = 0;
- continue;
- }
- Aj(j, i * spatial_dimension + j) = dnds(i - 1);
- }
- }
- };
-
- // tangents should have been calculated in normal modulii
- auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
-
- auto contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(covariant_basis);
-
- // construct 1st part of the stick modulii
- Matrix<Real> k_main(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
-
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent_alpha = std::get<1>(values1);
-
- Matrix<Real> t_outer_t(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_t_alpha(tangent_alpha.storage(), tangent_alpha.size(), 1.);
-
- for (auto && values2 : enumerate(covariant_basis.transpose())) {
- auto & beta = std::get<0>(values2);
- auto & tangent_beta = std::get<1>(values2);
-
- Matrix<Real> mat_t_beta(tangent_beta.storage(), tangent_beta.size(), 1.);
- t_outer_t.mul<false, true>(mat_t_alpha, mat_t_beta);
-
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(t_outer_t, A);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, beta);
- k_main += tmp1;
- }
- }
-
- k_main *= -epsilon_t;
-
- // construct 2nd part of the stick modulii
- auto & tangential_tractions = model.getTangentialTractions();
- Vector<Real> tangential_traction(
- tangential_tractions.begin(surface_dimension)[element.slave]);
-
- Matrix<Real> k_second(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
-
- for (auto alpha : arange(surface_dimension)) {
-
- Matrix<Real> k_sum(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
-
- for (auto && values1 : enumerate(shape_derivatives.transpose())) {
- auto & beta = std::get<0>(values1);
- auto & dnds = std::get<1>(values1);
- // construct Aj from shape function wrt to jth natural
- // coordinate
- construct_Aj(dnds);
- for (auto && values2 : enumerate(covariant_basis.transpose())) {
- auto & gamma = std::get<0>(values2);
- auto & tangent_gamma = std::get<1>(values2);
-
- Matrix<Real> t_outer_t(spatial_dimension, spatial_dimension);
- Matrix<Real> mat_t_gamma(tangent_gamma.storage(), tangent_gamma.size(),
- 1.);
-
- for (auto && values3 : enumerate(covariant_basis.transpose())) {
- auto & theta = std::get<0>(values3);
- auto & tangent_theta = std::get<1>(values3);
-
- Matrix<Real> mat_t_theta(tangent_theta.storage(),
- tangent_theta.size(), 1.);
- t_outer_t.mul<false, true>(mat_t_gamma, mat_t_theta);
-
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(t_outer_t, Aj);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, theta) *
- contravariant_metric_tensor(beta, gamma);
-
- Matrix<Real> tmp2(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp3(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp2.mul<false, false>(t_outer_t, A);
- tmp3.mul<true, false>(Aj, tmp2);
- tmp3 *= contravariant_metric_tensor(alpha, gamma) *
- contravariant_metric_tensor(beta, theta);
-
- k_sum += tmp1 + tmp3;
- }
- }
- }
-
- k_second += tangential_traction[alpha] * k_sum;
- }
-
- stiffness += k_main * nodal_area - k_second * nodal_area;
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::computeSlipModuli(
- const ContactElement & element, Matrix<Real> & stiffness) {
-
- auto surface_dimension = spatial_dimension - 1;
-
- auto & gaps = model.getGaps();
- Real gap(gaps.begin()[element.slave]);
-
- auto & nodal_areas = model.getNodalArea();
- auto & nodal_area = nodal_areas.begin()[element.slave];
-
- // compute normal traction
- Real p_n = computeNormalTraction(gap);
-
- auto & projections = model.getProjections();
- Vector<Real> projection(projections.begin(surface_dimension)[element.slave]);
-
- auto & normals = model.getNormals();
- Vector<Real> normal(normals.begin(spatial_dimension)[element.slave]);
-
- // restructure normal as a matrix for an outer product
- Matrix<Real> mat_n(normal.storage(), normal.size(), 1.);
-
- // method from Schweizerhof and A. Konyukhov, K. Schweizerhof
- // DOI 10.1007/s00466-004-0616-7 and DOI 10.1007/s00466-003-0515-3
-
- // construct A matrix
- const ElementType & type = element.master.type;
- auto && shapes = ElementClassHelper<_ek_regular>::getN(projection, type);
-
- UInt nb_nodes_per_contact = element.getNbNodes();
- Matrix<Real> A(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- A(j, i * spatial_dimension + j) = 1;
- continue;
- }
- A(j, i * spatial_dimension + j) = -shapes[i - 1];
- }
- }
-
- // computing shape derivatives
- auto && shape_derivatives =
- ElementClassHelper<_ek_regular>::getDNDS(projection, type);
-
- Matrix<Real> Aj(spatial_dimension, spatial_dimension * nb_nodes_per_contact);
-
- auto construct_Aj = [&](auto && dnds) {
- for (auto i : arange(nb_nodes_per_contact)) {
- for (auto j : arange(spatial_dimension)) {
- if (i == 0) {
- Aj(j, i * spatial_dimension + j) = 0;
- continue;
- }
- Aj(j, i * spatial_dimension + j) = dnds(i - 1);
- }
- }
- };
-
- // tangents should have been calculated in normal modulii
- auto & tangents = model.getTangents();
- Matrix<Real> covariant_basis(
- tangents.begin(surface_dimension, spatial_dimension)[element.slave]);
-
- auto & tangential_tractions = model.getTangentialTractions();
- Vector<Real> tangential_traction(
- tangential_tractions.begin(surface_dimension)[element.slave]);
-
- // compute norm of trial traction
- Real traction_norm = 0;
- auto contravariant_metric_tensor =
- GeometryUtils::contravariantMetricTensor(covariant_basis);
-
- for (auto i : arange(surface_dimension)) {
- for (auto j : arange(surface_dimension)) {
- traction_norm += tangential_traction[i] * tangential_traction[j] *
- contravariant_metric_tensor(i, j);
- }
- }
- traction_norm = sqrt(traction_norm);
-
- // construct four parts of stick modulii (eq 107,107a-c)
- Matrix<Real> k_first(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_second(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_third(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
- Matrix<Real> k_fourth(nb_nodes_per_contact * spatial_dimension,
- nb_nodes_per_contact * spatial_dimension);
-
- for (auto && values1 : enumerate(covariant_basis.transpose())) {
- auto & alpha = std::get<0>(values1);
- auto & tangent_alpha = std::get<1>(values1);
-
- Matrix<Real> mat_t_alpha(tangent_alpha.storage(), tangent_alpha.size(), 1.);
-
- Matrix<Real> t_outer_n(spatial_dimension, spatial_dimension);
- Matrix<Real> t_outer_t(spatial_dimension, spatial_dimension);
-
- for (auto && values2 :
- zip(arange(surface_dimension), covariant_basis.transpose(),
- shape_derivatives.transpose())) {
- auto & beta = std::get<0>(values2);
- auto & tangent_beta = std::get<1>(values2);
- auto & dnds = std::get<2>(values2);
- // construct Aj from shape function wrt to jth natural
- // coordinate
- construct_Aj(dnds);
-
- // eq 107
- Matrix<Real> mat_t_beta(tangent_beta.storage(), tangent_beta.size(), 1.);
- t_outer_n.mul<false, true>(mat_t_beta, mat_n);
-
- Matrix<Real> tmp(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp1(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp.mul<false, false>(t_outer_n, A);
- tmp1.mul<true, false>(A, tmp);
-
- tmp1 *= epsilon_n * mu * tangential_traction[alpha] *
- contravariant_metric_tensor(alpha, beta);
- tmp1 /= traction_norm;
-
- k_first += tmp1 * nodal_area;
-
- // eq 107a
- t_outer_t.mul<false, true>(mat_t_alpha, mat_t_beta);
-
- tmp.mul<false, false>(t_outer_t, A);
- tmp1.mul<true, false>(A, tmp);
-
- tmp1 *= epsilon_t * mu * p_n * contravariant_metric_tensor(alpha, beta);
- tmp1 /= traction_norm;
-
- k_second += tmp1 * nodal_area;
-
- for (auto && values3 : enumerate(covariant_basis.transpose())) {
- auto & gamma = std::get<0>(values3);
- auto & tangent_gamma = std::get<1>(values3);
-
- Matrix<Real> mat_t_gamma(tangent_gamma.storage(), tangent_gamma.size(),
- 1.);
-
- for (auto && values4 : enumerate(covariant_basis.transpose())) {
- auto & theta = std::get<0>(values4);
- auto & tangent_theta = std::get<1>(values4);
-
- Matrix<Real> mat_t_theta(tangent_theta.storage(),
- tangent_theta.size(), 1.);
- t_outer_t.mul<false, true>(mat_t_gamma, mat_t_theta);
-
- // eq 107b
- tmp.mul<false, false>(t_outer_t, A);
- tmp1.mul<true, false>(A, tmp);
-
- tmp1 *= epsilon_t * mu * p_n * tangential_traction[alpha] *
- tangential_traction[beta];
- tmp1 *= contravariant_metric_tensor(alpha, gamma) *
- contravariant_metric_tensor(beta, theta);
- tmp1 /= pow(traction_norm, 3);
-
- k_third += tmp1 * nodal_area;
-
- // eq 107c
- tmp.mul<false, false>(t_outer_t, Aj);
- tmp1.mul<true, false>(A, tmp);
- tmp1 *= contravariant_metric_tensor(alpha, theta) *
- contravariant_metric_tensor(beta, gamma);
- tmp1 *= mu * p_n * tangential_traction[alpha];
- tmp1 /= traction_norm;
-
- Matrix<Real> tmp2(spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- Matrix<Real> tmp3(nb_nodes_per_contact * spatial_dimension,
- spatial_dimension * nb_nodes_per_contact);
- tmp2.mul<false, false>(t_outer_t, A);
- tmp3.mul<true, false>(Aj, tmp2);
- tmp3 *= contravariant_metric_tensor(alpha, gamma) *
- contravariant_metric_tensor(beta, theta);
- tmp3 *= mu * p_n * tangential_traction[alpha];
- tmp3 /= traction_norm;
-
- k_fourth += (tmp1 + tmp3) * nodal_area;
- }
- }
- }
- }
-
- stiffness += k_third + k_fourth - k_first - k_second;
-}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::beforeSolveStep() {}
-
-/* -------------------------------------------------------------------------- */
-void ResolutionPenaltyQuadratic::afterSolveStep(
- __attribute__((unused)) bool converged) {}
-
INSTANTIATE_RESOLUTION(penalty_quadratic, ResolutionPenaltyQuadratic);
} // namespace akantu
diff --git a/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh b/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh
index 363bade8a..5372029fd 100644
--- a/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh
+++ b/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh
@@ -1,130 +1,66 @@
/**
* @file resolution_penalty_quadratic.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Mon Aug 10 2020
*
* @brief Quadratic Penalty Resolution for Contact Mechanics Model
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "resolution_penalty.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_RESOLUTION_PENALTY_QUADRATIC_HH__
#define __AKANTU_RESOLUTION_PENALTY_QUADRATIC_HH__
namespace akantu {
class ResolutionPenaltyQuadratic : public ResolutionPenalty {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
private:
using Parent = ResolutionPenalty;
public:
ResolutionPenaltyQuadratic(ContactMechanicsModel & model, const ID & id = "");
~ResolutionPenaltyQuadratic() override = default;
- /* ------------------------------------------------------------------------ */
- /* Methods */
- /* ------------------------------------------------------------------------ */
-protected:
- /// initialize the resolution
- void initialize();
-
- /* ------------------------------------------------------------------------ */
- /* Methods for stiffness computation */
- /* ------------------------------------------------------------------------ */
-protected:
- /// local computaion of stiffness matrix due to stick state
- void computeStickModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/);
-
- /// local computation of stiffness matrix due to slip state
- void computeSlipModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/);
-
- /* ------------------------------------------------------------------------ */
- /* Methods for stiffness computation */
- /* ------------------------------------------------------------------------ */
public:
/// local computation of tangent moduli due to normal traction
- void computeNormalModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/) override;
-
- /// local computation of tangent moduli due to tangential traction
- void computeTangentialModuli(const ContactElement & /*element*/,
- Matrix<Real> & /*stiffness*/) override;
-
- /* ------------------------------------------------------------------------ */
- /* Methods for force computation */
- /* ------------------------------------------------------------------------ */
-public:
- /// local computation of normal force due to normal contact
- void computeNormalForce(const ContactElement & /*element*/,
- Vector<Real> & /*force*/) override;
-
- /// local computation of tangential force due to frictional traction
- void computeTangentialForce(const ContactElement & /*element*/,
- Vector<Real> & /*force*/) override;
+ void computeNormalModuli(const ContactElement & element,
+ Matrix<Real> & stiffness) override;
protected:
/// local computation of normal traction due to penetration
- Real computeNormalTraction(Real & /*gap*/);
-
- /// local computation of trial tangential traction due to friction
- void computeTrialTangentialTraction(const ContactElement & /*element*/,
- const Matrix<Real> & /*covariant_basis*/,
- Vector<Real> & /*traction*/);
-
- /// local computation of tangential traction due to stick
- void computeStickTangentialTraction(const ContactElement & /*unused*/,
- Vector<Real> & /*traction_trial*/,
- Vector<Real> & /*traction_tangential*/);
-
- /// local computation of tangential traction due to slip
- void computeSlipTangentialTraction(const ContactElement & /*element*/,
- const Matrix<Real> & /*covariant_basis*/,
- Vector<Real> & /*traction_trial*/,
- Vector<Real> & /*traction_tangential*/);
-
- /// local computation of tangential traction due to friction
- void computeTangentialTraction(const ContactElement & /*element*/,
- const Matrix<Real> & /*covariant_basis*/,
- Vector<Real> & /*traction_tangential*/);
-
-public:
- void beforeSolveStep() override;
-
- void afterSolveStep(bool converged = true) override;
+ Real computeNormalTraction(const Real & gap) const override;
};
} // namespace akantu
#endif /* __AKANTU_RESOLUTION_PENALTY_QUADRATIC_HH__ */
diff --git a/src/model/contact_mechanics/surface_selector.cc b/src/model/contact_mechanics/surface_selector.cc
index ec709e97b..8019b3869 100644
--- a/src/model/contact_mechanics/surface_selector.cc
+++ b/src/model/contact_mechanics/surface_selector.cc
@@ -1,223 +1,217 @@
/**
* @file surface_selector.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sun Jun 30 2019
* @date last modification: Fri Sep 18 2020
*
* @brief Surface selector for contact detector
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "surface_selector.hh"
#include "geometry_utils.hh"
#include "model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
SurfaceSelector::SurfaceSelector(Mesh & mesh)
: Parsable(ParserType::_contact_detector), mesh(mesh) {}
/* -------------------------------------------------------------------------- */
/**
* class that selects contact surface from physical names
*/
PhysicalSurfaceSelector::PhysicalSurfaceSelector(Mesh & mesh)
: SurfaceSelector(mesh) {
const Parser & parser = getStaticParser();
const ParserSection & section =
*(parser.getSubSections(ParserType::_contact_detector).first);
master = section.getParameterValue<std::string>("master");
slave = section.getParameterValue<std::string>("slave");
UInt surface_dimension = mesh.getSpatialDimension() - 1;
auto & group = mesh.createElementGroup("contact_surface", surface_dimension);
group.append(mesh.getElementGroup(master));
group.append(mesh.getElementGroup(slave));
group.optimize();
}
/* -------------------------------------------------------------------------- */
-Array<UInt> & PhysicalSurfaceSelector::getMasterList() {
+Array<Idx> & PhysicalSurfaceSelector::getMasterList() {
return mesh.getElementGroup(master).getNodeGroup().getNodes();
}
/* -------------------------------------------------------------------------- */
-Array<UInt> & PhysicalSurfaceSelector::getSlaveList() {
+Array<Idx> & PhysicalSurfaceSelector::getSlaveList() {
return mesh.getElementGroup(slave).getNodeGroup().getNodes();
}
/* -------------------------------------------------------------------------- */
/**
* class that selects contact surface from cohesive elements
*/
#if defined(AKANTU_COHESIVE_ELEMENT)
/* -------------------------------------------------------------------------- */
CohesiveSurfaceSelector::CohesiveSurfaceSelector(Mesh & mesh)
: SurfaceSelector(mesh), mesh_facets(mesh.getMeshFacets()) {
this->mesh.registerEventHandler(*this, _ehp_lowest);
- UInt surface_dimension = mesh.getSpatialDimension() - 1;
+ auto surface_dimension = mesh.getSpatialDimension() - 1;
mesh_facets.createElementGroup("contact_surface", surface_dimension, true);
}
/* -------------------------------------------------------------------------- */
void CohesiveSurfaceSelector::onElementsAdded(
- const Array<Element> & element_list,
- __attribute__((unused)) const NewElementsEvent & event) {
+ const Array<Element> & element_list, const NewElementsEvent & /*event*/) {
auto & group = mesh_facets.getElementGroup("contact_surface");
for (auto elem : element_list) {
if (elem.kind() != _ek_cohesive) {
continue;
}
const auto & subelement_to_element =
mesh_facets.getSubelementToElement(elem.type);
auto && facets = Vector<Element>(
make_view(subelement_to_element, subelement_to_element.getNbComponent())
.begin()[elem.element]);
for (auto facet : facets) {
group.add(facet, true);
}
}
group.optimize();
}
/* -------------------------------------------------------------------------- */
-void CohesiveSurfaceSelector::onNodesAdded(const Array<UInt> & /*nodes_list*/,
+void CohesiveSurfaceSelector::onNodesAdded(const Array<Idx> & /*nodes_list*/,
const NewNodesEvent & event) {
-
if (not aka::is_of_type<CohesiveNewNodesEvent>(event)) {
return;
}
mesh_facets.fillNodesToElements(mesh.getSpatialDimension() - 1);
}
/* -------------------------------------------------------------------------- */
-Array<UInt> & CohesiveSurfaceSelector::getMasterList() {
+Array<Idx> & CohesiveSurfaceSelector::getMasterList() {
return mesh_facets.getElementGroup("contact_surface")
.getNodeGroup()
.getNodes();
}
/* -------------------------------------------------------------------------- */
-Array<UInt> & CohesiveSurfaceSelector::getSlaveList() {
+Array<Idx> & CohesiveSurfaceSelector::getSlaveList() {
return mesh_facets.getElementGroup("contact_surface")
.getNodeGroup()
.getNodes();
}
/* -------------------------------------------------------------------------- */
/**
* class that selects contact surface from both cohesive elements and
* physical names
*/
AllSurfaceSelector::AllSurfaceSelector(Mesh & mesh)
: SurfaceSelector(mesh), mesh_facets(mesh.getMeshFacets()) {
this->mesh.registerEventHandler(*this, _ehp_lowest);
const Parser & parser = getStaticParser();
-
const ParserSection & section =
*(parser.getSubSections(ParserType::_contact_detector).first);
master = section.getParameterValue<std::string>("master");
slave = section.getParameterValue<std::string>("slave");
- UInt surface_dimension = this->mesh.getSpatialDimension() - 1;
+ auto surface_dimension = this->mesh.getSpatialDimension() - 1;
auto & group =
mesh_facets.createElementGroup("contact_surface", surface_dimension);
group.append(mesh_facets.getElementGroup(master));
group.append(mesh_facets.getElementGroup(slave));
group.optimize();
}
/* -------------------------------------------------------------------------- */
void AllSurfaceSelector::onElementsAdded(const Array<Element> & element_list,
- __attribute__((unused))
- const NewElementsEvent & event) {
-
+ const NewElementsEvent & /*event*/) {
auto & group = mesh_facets.getElementGroup("contact_surface");
for (auto elem : element_list) {
if (elem.kind() != _ek_cohesive) {
continue;
}
const auto & subelement_to_element =
mesh_facets.getSubelementToElement(elem.type);
auto && facets = Vector<Element>(
make_view(subelement_to_element, subelement_to_element.getNbComponent())
.begin()[elem.element]);
for (auto facet : facets) {
group.add(facet, true);
}
}
group.optimize();
}
/* -------------------------------------------------------------------------- */
-void AllSurfaceSelector::onNodesAdded(const Array<UInt> & /* nodes_list */,
+void AllSurfaceSelector::onNodesAdded(const Array<Idx> & /* nodes_list */,
const NewNodesEvent & event) {
-
if (not aka::is_of_type<CohesiveNewNodesEvent>(event)) {
return;
}
mesh_facets.fillNodesToElements(mesh.getSpatialDimension() - 1);
}
/* -------------------------------------------------------------------------- */
-Array<UInt> & AllSurfaceSelector::getMasterList() {
+Array<Idx> & AllSurfaceSelector::getMasterList() {
return mesh_facets.getElementGroup("contact_surface")
.getNodeGroup()
.getNodes();
}
/* -------------------------------------------------------------------------- */
-Array<UInt> & AllSurfaceSelector::getSlaveList() {
+Array<Idx> & AllSurfaceSelector::getSlaveList() {
return mesh_facets.getElementGroup("contact_surface")
.getNodeGroup()
.getNodes();
}
#endif
} // namespace akantu
diff --git a/src/model/contact_mechanics/surface_selector.hh b/src/model/contact_mechanics/surface_selector.hh
index cef245726..4de2395a8 100644
--- a/src/model/contact_mechanics/surface_selector.hh
+++ b/src/model/contact_mechanics/surface_selector.hh
@@ -1,150 +1,150 @@
/**
* @file surface_selector.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sun Jun 30 2019
* @date last modification: Sun Jun 06 2021
*
* @brief Node selectors for contact detection
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh.hh"
#include "mesh_utils.hh"
#include "parsable.hh"
#if defined(AKANTU_COHESIVE_ELEMENT)
#include "cohesive_element_inserter.hh"
#endif
/* -------------------------------------------------------------------------- */
#include <memory>
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_SURFACE_SELECTOR_HH__
#define __AKANTU_SURFACE_SELECTOR_HH__
namespace akantu {
class Model;
class GlobalIdsUpdater;
} // namespace akantu
namespace akantu {
/**
* main class to assign surfaces for contact detection
*/
class SurfaceSelector : public MeshEventHandler, public Parsable {
public:
SurfaceSelector(Mesh & mesh);
~SurfaceSelector() override = default;
public:
- virtual Array<UInt> & getMasterList() { AKANTU_TO_IMPLEMENT(); }
- virtual Array<UInt> & getSlaveList() { AKANTU_TO_IMPLEMENT(); }
+ virtual Array<Idx> & getMasterList() { AKANTU_TO_IMPLEMENT(); }
+ virtual Array<Idx> & getSlaveList() { AKANTU_TO_IMPLEMENT(); }
protected:
Mesh & mesh;
};
/* -------------------------------------------------------------------------- */
/**
* class that selects contact surface from physical names
*/
class PhysicalSurfaceSelector : public SurfaceSelector {
public:
PhysicalSurfaceSelector(Mesh & mesh);
public:
- Array<UInt> & getMasterList() override;
- Array<UInt> & getSlaveList() override;
+ Array<Idx> & getMasterList() override;
+ Array<Idx> & getSlaveList() override;
protected:
std::string master;
std::string slave;
};
/* -------------------------------------------------------------------------- */
/**
* class that selects contact surface from cohesive elements
*/
#if defined(AKANTU_COHESIVE_ELEMENT)
class CohesiveSurfaceSelector : public SurfaceSelector {
public:
CohesiveSurfaceSelector(Mesh & mesh);
protected:
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
- void onNodesAdded(const Array<UInt> & nodes_list,
+ void onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) override;
public:
- Array<UInt> & getMasterList() override;
- Array<UInt> & getSlaveList() override;
+ Array<Idx> & getMasterList() override;
+ Array<Idx> & getSlaveList() override;
- AKANTU_GET_MACRO_NOT_CONST(NewNodesList, new_nodes_list, Array<UInt> &);
- AKANTU_GET_MACRO(NewNodesList, new_nodes_list, const Array<UInt> &);
+ AKANTU_GET_MACRO_NOT_CONST(NewNodesList, new_nodes_list, Array<Idx> &);
+ AKANTU_GET_MACRO(NewNodesList, new_nodes_list, const Array<Idx> &);
protected:
Mesh & mesh_facets;
- Array<UInt> new_nodes_list;
+ Array<Idx> new_nodes_list;
};
/* -------------------------------------------------------------------------- */
/**
* class that selects contact surface from both cohesive elements and
* physical names
*/
class AllSurfaceSelector : public SurfaceSelector {
public:
AllSurfaceSelector(Mesh & mesh);
protected:
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
- void onNodesAdded(const Array<UInt> & nodes_list,
+ void onNodesAdded(const Array<Int> & nodes_list,
const NewNodesEvent & event) override;
public:
- Array<UInt> & getMasterList() override;
+ Array<Idx> & getMasterList() override;
- Array<UInt> & getSlaveList() override;
+ Array<Idx> & getSlaveList() override;
- AKANTU_GET_MACRO_NOT_CONST(NewNodesList, new_nodes_list, Array<UInt> &);
- AKANTU_GET_MACRO(NewNodesList, new_nodes_list, const Array<UInt> &);
+ AKANTU_GET_MACRO_NOT_CONST(NewNodesList, new_nodes_list, Array<Idx> &);
+ AKANTU_GET_MACRO(NewNodesList, new_nodes_list, const Array<Idx> &);
protected:
std::string master;
std::string slave;
Mesh & mesh_facets;
- Array<UInt> new_nodes_list;
+ Array<Idx> new_nodes_list;
};
#endif
} // namespace akantu
#endif /* __AKANTU_SURFACE_SELECTOR_HH__ */
diff --git a/src/model/heat_transfer/heat_transfer_model.cc b/src/model/heat_transfer/heat_transfer_model.cc
index fcf8b2032..9ffe7a364 100644
--- a/src/model/heat_transfer/heat_transfer_model.cc
+++ b/src/model/heat_transfer/heat_transfer_model.cc
@@ -1,886 +1,883 @@
/**
* @file heat_transfer_model.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Srinivasa Babu Ramisetti <srinivasa.ramisetti@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Rui Wang <rui.wang@epfl.ch>
*
* @date creation: Sun May 01 2011
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of HeatTransferModel class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "heat_transfer_model.hh"
#include "dumpable_inline_impl.hh"
#include "element_synchronizer.hh"
#include "fe_engine_template.hh"
#include "generalized_trapezoidal.hh"
#include "group_manager_inline_impl.hh"
#include "integrator_gauss.hh"
#include "mesh.hh"
#include "parser.hh"
#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_element_partition.hh"
#include "dumper_elemental_field.hh"
#include "dumper_internal_material_field.hh"
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace heat_transfer {
namespace details {
class ComputeRhoFunctor {
public:
ComputeRhoFunctor(const HeatTransferModel & model) : model(model){};
void operator()(Matrix<Real> & rho, const Element & /*unused*/) {
rho.set(model.getCapacity() * model.getDensity());
}
private:
const HeatTransferModel & model;
};
} // namespace details
} // namespace heat_transfer
/* -------------------------------------------------------------------------- */
-HeatTransferModel::HeatTransferModel(Mesh & mesh, UInt dim, const ID & id,
+HeatTransferModel::HeatTransferModel(Mesh & mesh, Int dim, const ID & id,
std::shared_ptr<DOFManager> dof_manager)
: Model(mesh, ModelType::_heat_transfer_model, dim, id),
temperature_gradient("temperature_gradient", id),
temperature_on_qpoints("temperature_on_qpoints", id),
conductivity_on_qpoints("conductivity_on_qpoints", id),
k_gradt_on_qpoints("k_gradt_on_qpoints", id) {
AKANTU_DEBUG_IN();
this->initDOFManager(dof_manager);
conductivity = Matrix<Real>(this->spatial_dimension, this->spatial_dimension);
this->registerDataAccessor(*this);
if (this->mesh.isDistributed()) {
auto & synchronizer = this->mesh.getElementSynchronizer();
this->registerSynchronizer(synchronizer,
SynchronizationTag::_htm_temperature);
this->registerSynchronizer(synchronizer,
SynchronizationTag::_htm_gradient_temperature);
}
registerFEEngineObject<FEEngineType>(id + ":fem", mesh, spatial_dimension);
this->mesh.registerDumper<DumperParaview>("heat_transfer", id, true);
this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular);
this->registerParam("conductivity", conductivity, _pat_parsmod);
this->registerParam("conductivity_variation", conductivity_variation, 0.,
_pat_parsmod);
this->registerParam("temperature_reference", T_ref, 0., _pat_parsmod);
this->registerParam("capacity", capacity, _pat_parsmod);
this->registerParam("density", density, _pat_parsmod);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::initModel() {
auto & fem = this->getFEEngine();
fem.initShapeFunctions(_not_ghost);
fem.initShapeFunctions(_ghost);
temperature_on_qpoints.initialize(fem, _nb_component = 1);
temperature_gradient.initialize(fem, _nb_component = spatial_dimension);
conductivity_on_qpoints.initialize(fem, _nb_component = spatial_dimension *
spatial_dimension);
k_gradt_on_qpoints.initialize(fem, _nb_component = spatial_dimension);
}
/* -------------------------------------------------------------------------- */
FEEngine & HeatTransferModel::getFEEngineBoundary(const ID & name) {
return aka::as_type<FEEngine>(getFEEngineClassBoundary<FEEngineType>(name));
}
/* -------------------------------------------------------------------------- */
HeatTransferModel::~HeatTransferModel() = default;
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleCapacityLumped(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & fem = getFEEngineClass<FEEngineType>();
heat_transfer::details::ComputeRhoFunctor compute_rho(*this);
for (auto && type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) {
fem.assembleFieldLumped(compute_rho, "M", "temperature",
this->getDOFManager(), type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
MatrixType HeatTransferModel::getMatrixType(const ID & matrix_id) const {
if (matrix_id == "K" or matrix_id == "M") {
return _symmetric;
}
return _mt_not_defined;
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleMatrix(const ID & matrix_id) {
if (matrix_id == "K") {
this->assembleConductivityMatrix();
} else if (matrix_id == "M" and need_to_reassemble_capacity) {
this->assembleCapacity();
}
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleLumpedMatrix(const ID & matrix_id) {
if (matrix_id == "M" and need_to_reassemble_capacity) {
this->assembleCapacityLumped();
}
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleResidual() {
AKANTU_DEBUG_IN();
this->assembleInternalHeatRate();
this->getDOFManager().assembleToResidual("temperature",
*this->external_heat_rate, 1);
this->getDOFManager().assembleToResidual("temperature",
*this->internal_heat_rate, 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::predictor() { ++temperature_release; }
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleCapacityLumped() {
AKANTU_DEBUG_IN();
if (!this->getDOFManager().hasLumpedMatrix("M")) {
this->getDOFManager().getNewLumpedMatrix("M");
}
this->getDOFManager().zeroLumpedMatrix("M");
assembleCapacityLumped(_not_ghost);
assembleCapacityLumped(_ghost);
need_to_reassemble_capacity_lumped = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::initSolver(TimeStepSolverType time_step_solver_type,
NonLinearSolverType /*unused*/) {
DOFManager & dof_manager = this->getDOFManager();
this->allocNodalField(this->temperature, 1, "temperature");
this->allocNodalField(this->external_heat_rate, 1, "external_heat_rate");
this->allocNodalField(this->internal_heat_rate, 1, "internal_heat_rate");
this->allocNodalField(this->blocked_dofs, 1, "blocked_dofs");
if (!dof_manager.hasDOFs("temperature")) {
dof_manager.registerDOFs("temperature", *this->temperature, _dst_nodal);
dof_manager.registerBlockedDOFs("temperature", *this->blocked_dofs);
}
if (time_step_solver_type == TimeStepSolverType::_dynamic ||
time_step_solver_type == TimeStepSolverType::_dynamic_lumped) {
this->allocNodalField(this->temperature_rate, 1, "temperature_rate");
if (!dof_manager.hasDOFsDerivatives("temperature", 1)) {
dof_manager.registerDOFsDerivative("temperature", 1,
*this->temperature_rate);
}
}
}
/* -------------------------------------------------------------------------- */
std::tuple<ID, TimeStepSolverType>
HeatTransferModel::getDefaultSolverID(const AnalysisMethod & method) {
switch (method) {
case _explicit_lumped_mass: {
return std::make_tuple("explicit_lumped",
TimeStepSolverType::_dynamic_lumped);
}
case _static: {
return std::make_tuple("static", TimeStepSolverType::_static);
}
case _implicit_dynamic: {
return std::make_tuple("implicit", TimeStepSolverType::_dynamic);
}
default:
return std::make_tuple("unknown", TimeStepSolverType::_not_defined);
}
}
/* -------------------------------------------------------------------------- */
ModelSolverOptions HeatTransferModel::getDefaultSolverOptions(
const TimeStepSolverType & type) const {
ModelSolverOptions options;
switch (type) {
case TimeStepSolverType::_dynamic_lumped: {
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["temperature"] =
IntegrationSchemeType::_forward_euler;
options.solution_type["temperature"] = IntegrationScheme::_temperature_rate;
break;
}
case TimeStepSolverType::_static: {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["temperature"] =
IntegrationSchemeType::_pseudo_time;
options.solution_type["temperature"] = IntegrationScheme::_not_defined;
break;
}
case TimeStepSolverType::_dynamic: {
if (this->method == _explicit_consistent_mass) {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["temperature"] =
IntegrationSchemeType::_forward_euler;
options.solution_type["temperature"] =
IntegrationScheme::_temperature_rate;
} else {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["temperature"] =
IntegrationSchemeType::_backward_euler;
options.solution_type["temperature"] = IntegrationScheme::_temperature;
}
break;
}
default:
AKANTU_EXCEPTION(type << " is not a valid time step solver type");
}
return options;
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleConductivityMatrix() {
AKANTU_DEBUG_IN();
this->computeConductivityOnQuadPoints(_not_ghost);
if (conductivity_release[_not_ghost] == conductivity_matrix_release) {
return;
}
AKANTU_DEBUG_ASSERT(this->getDOFManager().hasMatrix("K"),
"The K matrix has not been initialized yet.");
this->getDOFManager().zeroMatrix("K");
auto & fem = this->getFEEngine();
for (auto && type : mesh.elementTypes(spatial_dimension)) {
auto nb_element = mesh.getNbElement(type);
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto nb_quadrature_points = fem.getNbIntegrationPoints(type);
auto bt_d_b = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points,
nb_nodes_per_element * nb_nodes_per_element, "B^t*D*B");
fem.computeBtDB(conductivity_on_qpoints(type), *bt_d_b, 2, type);
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
auto K_e = std::make_unique<Array<Real>>(
nb_element, nb_nodes_per_element * nb_nodes_per_element, "K_e");
fem.integrate(*bt_d_b, *K_e, nb_nodes_per_element * nb_nodes_per_element,
type);
this->getDOFManager().assembleElementalMatricesToMatrix(
"K", "temperature", *K_e, type, _not_ghost, _symmetric);
}
conductivity_matrix_release = conductivity_release[_not_ghost];
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::computeConductivityOnQuadPoints(GhostType ghost_type) {
// if already computed once check if need to compute
if (not initial_conductivity[ghost_type]) {
// if temperature did not change, conductivity will not vary
if (temperature_release == conductivity_release[ghost_type]) {
return;
}
// if conductivity_variation is 0 no need to recompute
if (conductivity_variation == 0.) {
return;
}
}
for (auto && type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) {
auto & temperature_interpolated = temperature_on_qpoints(type, ghost_type);
// compute the temperature on quadrature points
this->getFEEngine().interpolateOnIntegrationPoints(
*temperature, temperature_interpolated, 1, type, ghost_type);
auto & cond = conductivity_on_qpoints(type, ghost_type);
for (auto && tuple :
zip(make_view(cond, spatial_dimension, spatial_dimension),
temperature_interpolated)) {
auto & C = std::get<0>(tuple);
auto & T = std::get<1>(tuple);
C = conductivity;
- Matrix<Real> variation(spatial_dimension, spatial_dimension,
- conductivity_variation * (T - T_ref));
+ Matrix<Real> variation(spatial_dimension, spatial_dimension);
+ variation.fill(conductivity_variation * (T - T_ref));
// @TODO: Guillaume are you sure ? why due you compute variation then ?
- C += conductivity_variation;
+ C.array() += conductivity_variation;
}
}
conductivity_release[ghost_type] = temperature_release;
initial_conductivity[ghost_type] = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::computeKgradT(GhostType ghost_type) {
computeConductivityOnQuadPoints(ghost_type);
for (auto && type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) {
auto & gradient = temperature_gradient(type, ghost_type);
this->getFEEngine().gradientOnIntegrationPoints(*temperature, gradient, 1,
type, ghost_type);
for (auto && values :
zip(make_view(conductivity_on_qpoints(type, ghost_type),
spatial_dimension, spatial_dimension),
make_view(gradient, spatial_dimension),
make_view(k_gradt_on_qpoints(type, ghost_type),
spatial_dimension))) {
const auto & C = std::get<0>(values);
const auto & BT = std::get<1>(values);
auto & k_BT = std::get<2>(values);
- k_BT.mul<false>(C, BT);
+ k_BT = C * BT;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleInternalHeatRate() {
AKANTU_DEBUG_IN();
this->internal_heat_rate->zero();
this->synchronize(SynchronizationTag::_htm_temperature);
auto & fem = this->getFEEngine();
for (auto ghost_type : ghost_types) {
// compute k \grad T
computeKgradT(ghost_type);
for (auto type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) {
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto & k_gradt_on_qpoints_vect = k_gradt_on_qpoints(type, ghost_type);
- UInt nb_quad_points = k_gradt_on_qpoints_vect.size();
+ auto nb_quad_points = k_gradt_on_qpoints_vect.size();
Array<Real> bt_k_gT(nb_quad_points, nb_nodes_per_element);
fem.computeBtD(k_gradt_on_qpoints_vect, bt_k_gT, type, ghost_type);
- UInt nb_elements = mesh.getNbElement(type, ghost_type);
+ auto nb_elements = mesh.getNbElement(type, ghost_type);
Array<Real> int_bt_k_gT(nb_elements, nb_nodes_per_element);
fem.integrate(bt_k_gT, int_bt_k_gT, nb_nodes_per_element, type,
ghost_type);
this->getDOFManager().assembleElementalArrayLocalArray(
int_bt_k_gT, *this->internal_heat_rate, type, ghost_type, -1);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Real HeatTransferModel::getStableTimeStep() {
+auto HeatTransferModel::getStableTimeStep() -> Real {
AKANTU_DEBUG_IN();
Real el_size;
Real min_el_size = std::numeric_limits<Real>::max();
Real conductivitymax = conductivity(0, 0);
// get the biggest parameter from k11 until k33//
- for (UInt i = 0; i < spatial_dimension; i++) {
- for (UInt j = 0; j < spatial_dimension; j++) {
+ for (Int i = 0; i < spatial_dimension; i++) {
+ for (Int j = 0; j < spatial_dimension; j++) {
conductivitymax = std::max(conductivity(i, j), conductivitymax);
}
}
for (auto && type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_regular)) {
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> coord(0, nb_nodes_per_element * spatial_dimension);
FEEngine::extractNodalToElementField(mesh, mesh.getNodes(), coord, type,
_not_ghost);
auto el_coord = coord.begin(spatial_dimension, nb_nodes_per_element);
- UInt nb_element = mesh.getNbElement(type);
+ auto nb_element = mesh.getNbElement(type);
- for (UInt el = 0; el < nb_element; ++el, ++el_coord) {
+ for (Int el = 0; el < nb_element; ++el, ++el_coord) {
el_size = getFEEngine().getElementInradius(*el_coord, type);
min_el_size = std::min(min_el_size, el_size);
}
AKANTU_DEBUG_INFO("The minimum element size : "
<< min_el_size
<< " and the max conductivity is : " << conductivitymax);
}
Real min_dt = 2. * min_el_size * min_el_size / 4. * density * capacity /
conductivitymax;
mesh.getCommunicator().allReduce(min_dt, SynchronizerOperation::_min);
AKANTU_DEBUG_OUT();
return min_dt;
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::setTimeStep(Real time_step, const ID & solver_id) {
Model::setTimeStep(time_step, solver_id);
this->mesh.getDumper("heat_transfer").setTimeStep(time_step);
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::readMaterials() {
auto sect = this->getParserSection();
if (not std::get<1>(sect)) {
const auto & section = std::get<0>(sect);
this->parseSection(section);
}
conductivity_on_qpoints.set(conductivity);
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::initFullImpl(const ModelOptions & options) {
Model::initFullImpl(options);
readMaterials();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::assembleCapacity() {
AKANTU_DEBUG_IN();
auto ghost_type = _not_ghost;
this->getDOFManager().zeroMatrix("M");
auto & fem = getFEEngineClass<FEEngineType>();
heat_transfer::details::ComputeRhoFunctor rho_functor(*this);
for (auto && type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) {
fem.assembleFieldMatrix(rho_functor, "M", "temperature",
this->getDOFManager(), type, ghost_type);
}
need_to_reassemble_capacity = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void HeatTransferModel::computeRho(Array<Real> & rho, ElementType type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
FEEngine & fem = this->getFEEngine();
- UInt nb_element = mesh.getNbElement(type, ghost_type);
- UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
rho.resize(nb_element * nb_quadrature_points);
rho.set(this->capacity);
- // Real * rho_1_val = rho.storage();
+ // Real * rho_1_val = rho.data();
// /// compute @f$ rho @f$ for each nodes of each element
- // for (UInt el = 0; el < nb_element; ++el) {
- // for (UInt n = 0; n < nb_quadrature_points; ++n) {
+ // for (auto el = 0; el < nb_element; ++el) {
+ // for (auto n = 0; n < nb_quadrature_points; ++n) {
// *rho_1_val++ = this->capacity;
// }
// }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Real HeatTransferModel::computeThermalEnergyByNode() {
+auto HeatTransferModel::computeThermalEnergyByNode() -> Real {
AKANTU_DEBUG_IN();
Real ethermal = 0.;
for (auto && pair : enumerate(make_view(
*internal_heat_rate, internal_heat_rate->getNbComponent()))) {
auto n = std::get<0>(pair);
auto & heat_rate = std::get<1>(pair);
Real heat = 0.;
bool is_local_node = mesh.isLocalOrMasterNode(n);
bool count_node = is_local_node;
- for (UInt i = 0; i < heat_rate.size(); ++i) {
+ for (Int i = 0; i < heat_rate.size(); ++i) {
if (count_node) {
heat += heat_rate[i] * time_step;
}
}
ethermal += heat;
}
mesh.getCommunicator().allReduce(ethermal, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
return ethermal;
}
/* -------------------------------------------------------------------------- */
-template <class iterator>
-void HeatTransferModel::getThermalEnergy(
- iterator Eth, Array<Real>::const_iterator<Real> T_it,
- const Array<Real>::const_iterator<Real> & T_end) const {
+template <class iterator, class t_iterator>
+void HeatTransferModel::getThermalEnergy(iterator Eth, t_iterator T_it,
+ t_iterator T_end) const {
for (; T_it != T_end; ++T_it, ++Eth) {
*Eth = capacity * density * *T_it;
}
}
/* -------------------------------------------------------------------------- */
-Real HeatTransferModel::getThermalEnergy(ElementType type, UInt index) {
+auto HeatTransferModel::getThermalEnergy(ElementType type, Idx index) -> Real {
AKANTU_DEBUG_IN();
- UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
+ auto nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
Vector<Real> Eth_on_quarature_points(nb_quadrature_points);
auto T_it = this->temperature_on_qpoints(type).begin();
T_it += index * nb_quadrature_points;
auto T_end = T_it + nb_quadrature_points;
- getThermalEnergy(Eth_on_quarature_points.storage(), T_it, T_end);
+ getThermalEnergy(Eth_on_quarature_points.data(), T_it, T_end);
- return getFEEngine().integrate(Eth_on_quarature_points, type, index);
+ return getFEEngine().integrate(Eth_on_quarature_points,
+ Element{type, index, _not_ghost});
}
/* -------------------------------------------------------------------------- */
-Real HeatTransferModel::getThermalEnergy() {
+auto HeatTransferModel::getThermalEnergy() -> Real {
Real Eth = 0;
auto & fem = getFEEngine();
for (auto && type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_regular)) {
auto nb_element = mesh.getNbElement(type, _not_ghost);
auto nb_quadrature_points = fem.getNbIntegrationPoints(type, _not_ghost);
Array<Real> Eth_per_quad(nb_element * nb_quadrature_points, 1);
auto & temperature_interpolated = temperature_on_qpoints(type);
// compute the temperature on quadrature points
this->getFEEngine().interpolateOnIntegrationPoints(
*temperature, temperature_interpolated, 1, type);
auto T_it = temperature_interpolated.begin();
auto T_end = temperature_interpolated.end();
getThermalEnergy(Eth_per_quad.begin(), T_it, T_end);
Eth += fem.integrate(Eth_per_quad, type);
}
return Eth;
}
/* -------------------------------------------------------------------------- */
-Real HeatTransferModel::getEnergy(const std::string & id) {
+auto HeatTransferModel::getEnergy(const std::string & id) -> Real {
AKANTU_DEBUG_IN();
Real energy = 0;
if (id == "thermal") {
energy = getThermalEnergy();
}
// reduction sum over all processors
mesh.getCommunicator().allReduce(energy, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
return energy;
}
/* -------------------------------------------------------------------------- */
-Real HeatTransferModel::getEnergy(const std::string & id, ElementType type,
- UInt index) {
+auto HeatTransferModel::getEnergy(const std::string & id, ElementType type,
+ Int index) -> Real {
AKANTU_DEBUG_IN();
Real energy = 0.;
if (id == "thermal") {
energy = getThermalEnergy(type, index);
}
AKANTU_DEBUG_OUT();
return energy;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> HeatTransferModel::createNodalFieldBool(
const std::string & field_name, const std::string & group_name,
__attribute__((unused)) bool padding_flag) {
std::map<std::string, Array<bool> *> uint_nodal_fields;
uint_nodal_fields["blocked_dofs"] = blocked_dofs.get();
auto field = mesh.createNodalField(uint_nodal_fields[field_name], group_name);
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> HeatTransferModel::createNodalFieldReal(
const std::string & field_name, const std::string & group_name,
__attribute__((unused)) bool padding_flag) {
if (field_name == "capacity_lumped") {
AKANTU_EXCEPTION(
"Capacity lumped is a nodal field now stored in the DOF manager."
"Therefore it cannot be used by a dumper anymore");
}
std::map<std::string, Array<Real> *> real_nodal_fields;
real_nodal_fields["temperature"] = temperature.get();
real_nodal_fields["temperature_rate"] = temperature_rate.get();
real_nodal_fields["external_heat_rate"] = external_heat_rate.get();
real_nodal_fields["internal_heat_rate"] = internal_heat_rate.get();
real_nodal_fields["increment"] = increment.get();
std::shared_ptr<dumpers::Field> field =
mesh.createNodalField(real_nodal_fields[field_name], group_name);
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> HeatTransferModel::createElementalField(
const std::string & field_name, const std::string & group_name,
- bool /*padding_flag*/, UInt /*spatial_dimension*/,
+ bool /*padding_flag*/, Int /*spatial_dimension*/,
ElementKind element_kind) {
std::shared_ptr<dumpers::Field> field;
if (field_name == "partitions") {
- field = mesh.createElementalField<UInt, dumpers::ElementPartitionField>(
+ field = mesh.createElementalField<Int, dumpers::ElementPartitionField>(
mesh.getConnectivities(), group_name, this->spatial_dimension,
element_kind);
} else if (field_name == "temperature_gradient") {
- ElementTypeMap<UInt> nb_data_per_elem =
- this->mesh.getNbDataPerElem(temperature_gradient);
+ auto nb_data_per_elem = this->mesh.getNbDataPerElem(temperature_gradient);
field = mesh.createElementalField<Real, dumpers::InternalMaterialField>(
temperature_gradient, group_name, this->spatial_dimension, element_kind,
nb_data_per_elem);
} else if (field_name == "conductivity") {
- ElementTypeMap<UInt> nb_data_per_elem =
+ auto nb_data_per_elem =
this->mesh.getNbDataPerElem(conductivity_on_qpoints);
field = mesh.createElementalField<Real, dumpers::InternalMaterialField>(
conductivity_on_qpoints, group_name, this->spatial_dimension,
element_kind, nb_data_per_elem);
}
return field;
}
/* -------------------------------------------------------------------------- */
-inline UInt HeatTransferModel::getNbData(const Array<UInt> & indexes,
- const SynchronizationTag & tag) const {
+inline Int HeatTransferModel::getNbData(const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
- UInt size = 0;
- UInt nb_nodes = indexes.size();
+ Int size = 0;
+ auto nb_nodes = indexes.size();
switch (tag) {
case SynchronizationTag::_htm_temperature: {
size += nb_nodes * sizeof(Real);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
inline void HeatTransferModel::packData(CommunicationBuffer & buffer,
- const Array<UInt> & indexes,
+ const Array<Idx> & indexes,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
for (auto index : indexes) {
switch (tag) {
case SynchronizationTag::_htm_temperature: {
buffer << (*temperature)(index);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
inline void HeatTransferModel::unpackData(CommunicationBuffer & buffer,
- const Array<UInt> & indexes,
+ const Array<Idx> & indexes,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
for (auto index : indexes) {
switch (tag) {
case SynchronizationTag::_htm_temperature: {
buffer >> (*temperature)(index);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-inline UInt HeatTransferModel::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+inline Int HeatTransferModel::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
- UInt size = 0;
- UInt nb_nodes_per_element = 0;
- Array<Element>::const_iterator<Element> it = elements.begin();
- Array<Element>::const_iterator<Element> end = elements.end();
- for (; it != end; ++it) {
- const Element & el = *it;
+ Int size = 0;
+ auto nb_nodes_per_element = 0;
+
+ for (auto && el : elements) {
nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
}
switch (tag) {
case SynchronizationTag::_htm_temperature: {
size += nb_nodes_per_element * sizeof(Real); // temperature
break;
}
case SynchronizationTag::_htm_gradient_temperature: {
// temperature gradient
size += getNbIntegrationPoints(elements) * spatial_dimension * sizeof(Real);
size += nb_nodes_per_element * sizeof(Real); // nodal temperatures
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
inline void HeatTransferModel::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
switch (tag) {
case SynchronizationTag::_htm_temperature: {
packNodalDataHelper(*temperature, buffer, elements, mesh);
break;
}
case SynchronizationTag::_htm_gradient_temperature: {
packElementalDataHelper(temperature_gradient, buffer, elements, true,
getFEEngine());
packNodalDataHelper(*temperature, buffer, elements, mesh);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
/* -------------------------------------------------------------------------- */
inline void HeatTransferModel::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
switch (tag) {
case SynchronizationTag::_htm_temperature: {
unpackNodalDataHelper(*temperature, buffer, elements, mesh);
break;
}
case SynchronizationTag::_htm_gradient_temperature: {
unpackElementalDataHelper(temperature_gradient, buffer, elements, true,
getFEEngine());
unpackNodalDataHelper(*temperature, buffer, elements, mesh);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/heat_transfer/heat_transfer_model.hh b/src/model/heat_transfer/heat_transfer_model.hh
index af4f77627..858af7e7f 100644
--- a/src/model/heat_transfer/heat_transfer_model.hh
+++ b/src/model/heat_transfer/heat_transfer_model.hh
@@ -1,316 +1,312 @@
/**
* @file heat_transfer_model.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Srinivasa Babu Ramisetti <srinivasa.ramisetti@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Rui Wang <rui.wang@epfl.ch>
*
* @date creation: Sun May 01 2011
* @date last modification: Mon Mar 15 2021
*
* @brief Model of Heat Transfer
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "data_accessor.hh"
#include "fe_engine.hh"
#include "model.hh"
/* -------------------------------------------------------------------------- */
#include <array>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_HEAT_TRANSFER_MODEL_HH_
#define AKANTU_HEAT_TRANSFER_MODEL_HH_
namespace akantu {
template <ElementKind kind, class IntegrationOrderFunctor>
class IntegratorGauss;
template <ElementKind kind> class ShapeLagrange;
} // namespace akantu
namespace akantu {
class HeatTransferModel : public Model,
public DataAccessor<Element>,
- public DataAccessor<UInt> {
+ public DataAccessor<Idx> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using FEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
- HeatTransferModel(Mesh & mesh, UInt dim = _all_dimensions,
+ HeatTransferModel(Mesh & mesh, Int spatial_dimension = _all_dimensions,
const ID & id = "heat_transfer_model",
std::shared_ptr<DOFManager> dof_manager = nullptr);
~HeatTransferModel() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// generic function to initialize everything ready for explicit dynamics
void initFullImpl(const ModelOptions & options) override;
/// read one material file to instantiate all the materials
void readMaterials();
/// allocate all vectors
void initSolver(TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type) override;
/// initialize the model
void initModel() override;
void predictor() override;
/// compute the heat flux
void assembleResidual() override;
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override;
/// callback to assemble a Matrix
void assembleMatrix(const ID & matrix_id) override;
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & matrix_id) override;
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
/* ------------------------------------------------------------------------ */
/* Methods for explicit */
/* ------------------------------------------------------------------------ */
public:
/// compute and get the stable time step
Real getStableTimeStep();
/// set the stable timestep
void setTimeStep(Real time_step, const ID & solver_id = "") override;
// temporary protection to prevent bad usage: should check for bug
protected:
/// compute the internal heat flux \todo Need code review: currently not
/// public method
void assembleInternalHeatRate();
public:
/// calculate the lumped capacity vector for heat transfer problem
void assembleCapacityLumped();
public:
/// assemble the conductivity matrix
void assembleConductivityMatrix();
/// assemble the conductivity matrix
void assembleCapacity();
/// compute the capacity on quadrature points
void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type);
private:
/// calculate the lumped capacity vector for heat transfer problem (w
/// ghost type)
void assembleCapacityLumped(GhostType ghost_type);
/// compute the conductivity tensor for each quadrature point in an array
void computeConductivityOnQuadPoints(GhostType ghost_type);
/// compute vector \f[k \grad T\f] for each quadrature point
void computeKgradT(GhostType ghost_type);
/// compute the thermal energy
Real computeThermalEnergyByNode();
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
- inline UInt getNbData(const Array<UInt> & indexes,
- const SynchronizationTag & tag) const override;
- inline void packData(CommunicationBuffer & buffer,
- const Array<UInt> & indexes,
+ inline Int getNbData(const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const override;
+ inline void packData(CommunicationBuffer & buffer, const Array<Idx> & indexes,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
- const Array<UInt> & indexes,
+ const Array<Idx> & indexes,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Dumpable interface */
/* ------------------------------------------------------------------------ */
public:
std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createElementalField(const std::string & field_name,
const std::string & group_name, bool padding_flag,
- UInt spatial_dimension, ElementKind kind) override;
+ Int spatial_dimension, ElementKind kind) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(Density, density, Real);
- AKANTU_GET_MACRO(Capacity, capacity, Real);
+ AKANTU_GET_MACRO_AUTO(Density, density);
+ AKANTU_GET_MACRO_AUTO(Capacity, capacity);
+ /// get the dimension of the system space
+ AKANTU_GET_MACRO_AUTO(SpatialDimension, spatial_dimension);
/// get the current value of the time step
- AKANTU_GET_MACRO(TimeStep, time_step, Real);
+ AKANTU_GET_MACRO_AUTO(TimeStep, time_step);
/// get the assembled heat flux
- AKANTU_GET_MACRO(InternalHeatRate, *internal_heat_rate, Array<Real> &);
+ AKANTU_GET_MACRO_DEREF_PTR(InternalHeatRate, internal_heat_rate);
/// get the boundary vector
- AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool> &);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(BlockedDOFs, blocked_dofs);
/// get the external heat rate vector
- AKANTU_GET_MACRO(ExternalHeatRate, *external_heat_rate, Array<Real> &);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(ExternalHeatRate, external_heat_rate);
/// get the temperature gradient
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(TemperatureGradient,
temperature_gradient, Real);
/// get the conductivity on q points
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ConductivityOnQpoints,
conductivity_on_qpoints, Real);
/// get the conductivity on q points
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(TemperatureOnQpoints,
temperature_on_qpoints, Real);
/// internal variables
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(KgradT, k_gradt_on_qpoints, Real);
/// get the temperature
- AKANTU_GET_MACRO(Temperature, *temperature, Array<Real> &);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Temperature, temperature);
/// get the temperature derivative
- AKANTU_GET_MACRO(TemperatureRate, *temperature_rate, Array<Real> &);
+ AKANTU_GET_MACRO_DEREF_PTR(TemperatureRate, temperature_rate);
/// get the energy denominated by thermal
- Real getEnergy(const std::string & energy_id, ElementType type, UInt index);
+ Real getEnergy(const std::string & energy_id, ElementType type, Idx index);
/// get the energy denominated by thermal
Real getEnergy(const std::string & energy_id);
/// get the thermal energy for a given element
- Real getThermalEnergy(ElementType type, UInt index);
+ Real getThermalEnergy(ElementType type, Idx index);
/// get the thermal energy for a given element
Real getThermalEnergy();
protected:
/* ------------------------------------------------------------------------ */
FEEngine & getFEEngineBoundary(const ID & name = "") override;
/* ----------------------------------------------------------------------- */
- template <class iterator>
- void getThermalEnergy(iterator Eth, Array<Real>::const_iterator<Real> T_it,
- const Array<Real>::const_iterator<Real> & T_end) const;
+ template <class iterator, class const_iterator>
+ void getThermalEnergy(iterator Eth, const_iterator T_it,
+ const_iterator T_end) const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// time step
Real time_step;
/// temperatures array
std::unique_ptr<Array<Real>> temperature;
/// temperatures derivatives array
std::unique_ptr<Array<Real>> temperature_rate;
/// increment array (@f$\delta \dot T@f$ or @f$\delta T@f$)
std::unique_ptr<Array<Real>> increment;
/// the density
Real density;
/// the speed of the changing temperature
ElementTypeMapArray<Real> temperature_gradient;
/// temperature field on quadrature points
ElementTypeMapArray<Real> temperature_on_qpoints;
/// conductivity tensor on quadrature points
ElementTypeMapArray<Real> conductivity_on_qpoints;
/// vector \f[k \grad T\f] on quad points
ElementTypeMapArray<Real> k_gradt_on_qpoints;
/// external flux vector
std::unique_ptr<Array<Real>> external_heat_rate;
/// residuals array
std::unique_ptr<Array<Real>> internal_heat_rate;
/// boundary vector
std::unique_ptr<Array<bool>> blocked_dofs;
// realtime
// Real time;
/// capacity
Real capacity;
// conductivity matrix
Matrix<Real> conductivity;
// linear variation of the conductivity (for temperature dependent
// conductivity)
Real conductivity_variation;
// reference temperature for the interpretation of temperature variation
Real T_ref;
// the biggest parameter of conductivity matrix
// Real conductivitymax;
bool need_to_reassemble_capacity{true};
bool need_to_reassemble_capacity_lumped{true};
- UInt temperature_release{0};
- UInt conductivity_matrix_release{UInt(-1)};
+ Int temperature_release{0};
+ Int conductivity_matrix_release{-1};
std::unordered_map<GhostType, bool> initial_conductivity{{_not_ghost, true},
{_ghost, true}};
- std::unordered_map<GhostType, UInt> conductivity_release{{_not_ghost, 0},
- {_ghost, 0}};
+ std::unordered_map<GhostType, Int> conductivity_release{{_not_ghost, 0},
+ {_ghost, 0}};
};
} // namespace akantu
-/* -------------------------------------------------------------------------- */
-/* inline functions */
-/* -------------------------------------------------------------------------- */
-#include "heat_transfer_model_inline_impl.hh"
-
#endif /* AKANTU_HEAT_TRANSFER_MODEL_HH_ */
diff --git a/src/model/heat_transfer/heat_transfer_model_inline_impl.hh b/src/model/heat_transfer/heat_transfer_model_inline_impl.hh
deleted file mode 100644
index 6c6a2cc24..000000000
--- a/src/model/heat_transfer/heat_transfer_model_inline_impl.hh
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * @file heat_transfer_model_inline_impl.hh
- *
- * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
- * @author Srinivasa Babu Ramisetti <srinivasa.ramisetti@epfl.ch>
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
- *
- * @date creation: Fri Aug 20 2010
- * @date last modification: Wed Jan 31 2018
- *
- * @brief Implementation of the inline functions of the HeatTransferModel class
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef AKANTU_HEAT_TRANSFER_MODEL_INLINE_IMPL_HH_
-#define AKANTU_HEAT_TRANSFER_MODEL_INLINE_IMPL_HH_
-
-namespace akantu {
-
-/* -------------------------------------------------------------------------- */
-
-} // namespace akantu
-
-#endif /* AKANTU_HEAT_TRANSFER_MODEL_INLINE_IMPL_HH_ */
diff --git a/src/model/model.cc b/src/model/model.cc
index 9f84d962b..b9dc0302f 100644
--- a/src/model/model.cc
+++ b/src/model/model.cc
@@ -1,352 +1,352 @@
/**
* @file model.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Oct 03 2011
* @date last modification: Fri Apr 09 2021
*
* @brief implementation of model common parts
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "model.hh"
#include "communicator.hh"
#include "data_accessor.hh"
#include "element_group.hh"
#include "element_synchronizer.hh"
#include "synchronizer_registry.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-Model::Model(Mesh & mesh, const ModelType & type, UInt dim, const ID & id)
+Model::Model(Mesh & mesh, const ModelType & type, Int dim, const ID & id)
: ModelSolver(mesh, type, id), mesh(mesh),
spatial_dimension(dim == _all_dimensions ? mesh.getSpatialDimension()
: dim),
parser(getStaticParser()) {
this->mesh.registerEventHandler(*this, _ehp_model);
}
/* -------------------------------------------------------------------------- */
Model::~Model() = default;
/* -------------------------------------------------------------------------- */
void Model::initFullImpl(const ModelOptions & options) {
AKANTU_DEBUG_IN();
method = options.analysis_method;
if (!this->hasDefaultSolver()) {
this->initNewSolver(this->method);
}
initModel();
initFEEngineBoundary();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Model::initNewSolver(const AnalysisMethod & method) {
ID solver_name;
TimeStepSolverType tss_type;
std::tie(solver_name, tss_type) = this->getDefaultSolverID(method);
if (not this->hasSolver(solver_name)) {
ModelSolverOptions options = this->getDefaultSolverOptions(tss_type);
this->getNewSolver(solver_name, tss_type, options.non_linear_solver_type);
for (auto && is_type : options.integration_scheme_type) {
if (!this->hasIntegrationScheme(solver_name, is_type.first)) {
this->setIntegrationScheme(solver_name, is_type.first, is_type.second,
options.solution_type[is_type.first]);
}
}
}
this->method = method;
this->setDefaultSolver(solver_name);
}
/* -------------------------------------------------------------------------- */
void Model::initFEEngineBoundary() {
try {
FEEngine & fem_boundary = getFEEngineBoundary();
fem_boundary.initShapeFunctions(_not_ghost);
fem_boundary.initShapeFunctions(_ghost);
fem_boundary.computeNormalsOnIntegrationPoints(_not_ghost);
fem_boundary.computeNormalsOnIntegrationPoints(_ghost);
} catch (debug::Exception & /*e*/) {
}
}
/* -------------------------------------------------------------------------- */
void Model::dumpGroup(const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
group.dump();
}
/* -------------------------------------------------------------------------- */
void Model::dumpGroup(const std::string & group_name,
const std::string & dumper_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
group.dump(dumper_name);
}
/* -------------------------------------------------------------------------- */
void Model::dumpGroup() {
for (auto & group : mesh.iterateElementGroups()) {
group.dump();
}
}
/* -------------------------------------------------------------------------- */
void Model::setGroupDirectory(const std::string & directory) {
for (auto & group : mesh.iterateElementGroups()) {
group.setDirectory(directory);
}
}
/* -------------------------------------------------------------------------- */
void Model::setGroupDirectory(const std::string & directory,
const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
group.setDirectory(directory);
}
/* -------------------------------------------------------------------------- */
void Model::setGroupBaseName(const std::string & basename,
const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
group.setBaseName(basename);
}
/* -------------------------------------------------------------------------- */
DumperIOHelper & Model::getGroupDumper(const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
return group.getDumper();
}
/* -------------------------------------------------------------------------- */
// DUMPER stuff
/* -------------------------------------------------------------------------- */
void Model::addDumpGroupFieldToDumper(const std::string & field_id,
std::shared_ptr<dumpers::Field> field,
DumperIOHelper & dumper) {
dumper.registerField(field_id, std::move(field));
}
/* -------------------------------------------------------------------------- */
void Model::addDumpField(const std::string & field_id) {
this->addDumpFieldToDumper(mesh.getDefaultDumperName(), field_id);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpFieldVector(const std::string & field_id) {
this->addDumpFieldVectorToDumper(mesh.getDefaultDumperName(), field_id);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpFieldTensor(const std::string & field_id) {
this->addDumpFieldTensorToDumper(mesh.getDefaultDumperName(), field_id);
}
/* -------------------------------------------------------------------------- */
void Model::setBaseName(const std::string & field_id) {
mesh.setBaseName(field_id);
}
/* -------------------------------------------------------------------------- */
void Model::setBaseNameToDumper(const std::string & dumper_name,
const std::string & basename) {
mesh.setBaseNameToDumper(dumper_name, basename);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id) {
this->addDumpGroupFieldToDumper(dumper_name, field_id, "all",
dumper_default_element_kind, false);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpGroupField(const std::string & field_id,
const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
this->addDumpGroupFieldToDumper(group.getDefaultDumperName(), field_id,
group_name, dumper_default_element_kind,
false);
}
/* -------------------------------------------------------------------------- */
void Model::removeDumpGroupField(const std::string & field_id,
const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
this->removeDumpGroupFieldFromDumper(group.getDefaultDumperName(), field_id,
group_name);
}
/* -------------------------------------------------------------------------- */
void Model::removeDumpGroupFieldFromDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
group.removeDumpFieldFromDumper(dumper_name, field_id);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpFieldVectorToDumper(const std::string & dumper_name,
const std::string & field_id) {
this->addDumpGroupFieldToDumper(dumper_name, field_id, "all",
dumper_default_element_kind, true);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpGroupFieldVector(const std::string & field_id,
const std::string & group_name) {
ElementGroup & group = mesh.getElementGroup(group_name);
this->addDumpGroupFieldVectorToDumper(group.getDefaultDumperName(), field_id,
group_name);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpGroupFieldVectorToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name) {
this->addDumpGroupFieldToDumper(dumper_name, field_id, group_name,
dumper_default_element_kind, true);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpFieldTensorToDumper(const std::string & dumper_name,
const std::string & field_id) {
this->addDumpGroupFieldToDumper(dumper_name, field_id, "all",
dumper_default_element_kind, true);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpGroupFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name,
ElementKind element_kind,
bool padding_flag) {
this->addDumpGroupFieldToDumper(dumper_name, field_id, group_name,
this->spatial_dimension, element_kind,
padding_flag);
}
/* -------------------------------------------------------------------------- */
void Model::addDumpGroupFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name,
- UInt spatial_dimension,
+ Int spatial_dimension,
ElementKind element_kind,
bool padding_flag) {
std::shared_ptr<dumpers::Field> field;
if (!field) {
field = this->createNodalFieldReal(field_id, group_name, padding_flag);
}
if (!field) {
- field = this->createNodalFieldUInt(field_id, group_name, padding_flag);
+ field = this->createNodalFieldInt(field_id, group_name, padding_flag);
}
if (!field) {
field = this->createNodalFieldBool(field_id, group_name, padding_flag);
}
if (!field) {
field = this->createElementalField(field_id, group_name, padding_flag,
spatial_dimension, element_kind);
}
if (!field) {
- field = this->mesh.createFieldFromAttachedData<UInt>(field_id, group_name,
- element_kind);
+ field = this->mesh.createFieldFromAttachedData<Int>(field_id, group_name,
+ element_kind);
}
if (!field) {
field = this->mesh.createFieldFromAttachedData<Real>(field_id, group_name,
element_kind);
}
#ifndef AKANTU_NDEBUG
if (!field) {
AKANTU_DEBUG_WARNING("No field could be found based on name: " << field_id);
}
#endif
if (field) {
DumperIOHelper & dumper = mesh.getGroupDumper(dumper_name, group_name);
this->addDumpGroupFieldToDumper(field_id, field, dumper);
}
}
/* -------------------------------------------------------------------------- */
void Model::dump(const std::string & dumper_name) { mesh.dump(dumper_name); }
/* -------------------------------------------------------------------------- */
-void Model::dump(const std::string & dumper_name, UInt step) {
+void Model::dump(const std::string & dumper_name, Int step) {
mesh.dump(dumper_name, step);
}
/* ------------------------------------------------------------------------- */
-void Model::dump(const std::string & dumper_name, Real time, UInt step) {
+void Model::dump(const std::string & dumper_name, Real time, Int step) {
mesh.dump(dumper_name, time, step);
}
/* -------------------------------------------------------------------------- */
void Model::dump() {
auto default_dumper = mesh.getDefaultDumperName();
this->dump(default_dumper);
}
/* -------------------------------------------------------------------------- */
-void Model::dump(UInt step) {
+void Model::dump(Int step) {
auto default_dumper = mesh.getDefaultDumperName();
this->dump(default_dumper, step);
}
/* -------------------------------------------------------------------------- */
-void Model::dump(Real time, UInt step) {
+void Model::dump(Real time, Int step) {
auto default_dumper = mesh.getDefaultDumperName();
this->dump(default_dumper, time, step);
}
/* -------------------------------------------------------------------------- */
void Model::setDirectory(const std::string & directory) {
mesh.setDirectory(directory);
}
/* -------------------------------------------------------------------------- */
void Model::setDirectoryToDumper(const std::string & dumper_name,
const std::string & directory) {
mesh.setDirectoryToDumper(dumper_name, directory);
}
/* -------------------------------------------------------------------------- */
void Model::setTextModeToDumper() { mesh.setTextModeToDumper(); }
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/model.hh b/src/model/model.hh
index b19da1d7a..523760b72 100644
--- a/src/model/model.hh
+++ b/src/model/model.hh
@@ -1,384 +1,384 @@
/**
* @file model.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Interface of a model
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_named_argument.hh"
#include "fe_engine.hh"
#include "mesh.hh"
#include "model_options.hh"
#include "model_solver.hh"
/* -------------------------------------------------------------------------- */
#include <typeindex>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MODEL_HH_
#define AKANTU_MODEL_HH_
namespace akantu {
class SynchronizerRegistry;
class Parser;
class DumperIOHelper;
class DOFManager;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
class Model : public ModelSolver, public MeshEventHandler {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
/// Normal constructor where the DOFManager is created internally
- Model(Mesh & mesh, const ModelType & type, UInt dim = _all_dimensions,
+ Model(Mesh & mesh, const ModelType & type, Int dim = _all_dimensions,
const ID & id = "model");
~Model() override;
using FEEngineMap = std::map<std::string, std::unique_ptr<FEEngine>>;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
virtual void initFullImpl(const ModelOptions & options);
public:
template <typename... pack>
std::enable_if_t<are_named_argument<pack...>::value>
initFull(pack &&... _pack) {
switch (this->model_type) {
#ifdef AKANTU_SOLID_MECHANICS
case ModelType::_solid_mechanics_model:
this->initFullImpl(SolidMechanicsModelOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
#endif
#ifdef AKANTU_COHESIVE_ELEMENT
case ModelType::_solid_mechanics_model_cohesive:
this->initFullImpl(SolidMechanicsModelCohesiveOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
#endif
#ifdef AKANTU_HEAT_TRANSFER
case ModelType::_heat_transfer_model:
this->initFullImpl(HeatTransferModelOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
#endif
#ifdef AKANTU_PHASE_FIELD
case ModelType::_phase_field_model:
this->initFullImpl(PhaseFieldModelOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
#endif
#ifdef AKANTU_EMBEDDED
case ModelType::_embedded_model:
this->initFullImpl(EmbeddedInterfaceModelOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
#endif
#ifdef AKANTU_CONTACT_MECHANICS
case ModelType::_contact_mechanics_model:
this->initFullImpl(ContactMechanicsModelOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
#endif
#ifdef AKANTU_MODEL_COUPLERS
case ModelType::_coupler_solid_contact:
this->initFullImpl(CouplerSolidContactOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
case ModelType::_coupler_solid_cohesive_contact:
this->initFullImpl(CouplerSolidCohesiveContactOptions{
use_named_args, std::forward<decltype(_pack)>(_pack)...});
break;
#endif
default:
this->initFullImpl(ModelOptions{use_named_args,
std::forward<decltype(_pack)>(_pack)...});
}
}
template <typename... pack>
std::enable_if_t<not are_named_argument<pack...>::value>
initFull(pack &&... _pack) {
this->initFullImpl(std::forward<decltype(_pack)>(_pack)...);
}
/// initialize a new solver if needed
void initNewSolver(const AnalysisMethod & method);
protected:
/// get some default values for derived classes
virtual std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) = 0;
virtual void initModel(){};
virtual void initFEEngineBoundary();
/// function to print the containt of the class
void printself(std::ostream & /*stream*/,
int /*indent*/ = 0) const override{};
public:
/* ------------------------------------------------------------------------ */
/* Access to the dumpable interface of the boundaries */
/* ------------------------------------------------------------------------ */
/// Dump the data for a given group
void dumpGroup(const std::string & group_name);
void dumpGroup(const std::string & group_name,
const std::string & dumper_name);
/// Dump the data for all boundaries
void dumpGroup();
/// Set the directory for a given group
void setGroupDirectory(const std::string & directory,
const std::string & group_name);
/// Set the directory for all boundaries
void setGroupDirectory(const std::string & directory);
/// Set the base name for a given group
void setGroupBaseName(const std::string & basename,
const std::string & group_name);
/// Get the internal dumper of a given group
DumperIOHelper & getGroupDumper(const std::string & group_name);
/* ------------------------------------------------------------------------ */
/* Function for non local capabilities */
/* ------------------------------------------------------------------------ */
virtual void updateDataForNonLocalCriterion(__attribute__((unused))
ElementTypeMapReal & criterion) {
AKANTU_TO_IMPLEMENT();
}
protected:
template <typename T>
- void allocNodalField(std::unique_ptr<Array<T>> & array, UInt nb_component,
+ void allocNodalField(std::unique_ptr<Array<T>> & array, Int nb_component,
const ID & name) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get id of model
AKANTU_GET_MACRO(ID, id, const ID &)
/// get the number of surfaces
AKANTU_GET_MACRO(Mesh, mesh, Mesh &)
/// synchronize the boundary in case of parallel run
virtual void synchronizeBoundaries(){};
/// return the fem object associated with a provided name
inline FEEngine & getFEEngine(const ID & name = "") const;
/// return the fem boundary object associated with a provided name
virtual FEEngine & getFEEngineBoundary(const ID & name = "");
inline bool hasFEEngineBoundary(const ID & name = "");
/// register a fem object associated with name
template <typename FEEngineClass>
inline void registerFEEngineObject(const std::string & name, Mesh & mesh,
- UInt spatial_dimension);
+ Int spatial_dimension);
/// unregister a fem object associated with name
inline void unRegisterFEEngineObject(const std::string & name);
/// return the synchronizer registry
SynchronizerRegistry & getSynchronizerRegistry();
/// return the fem object associated with a provided name
template <typename FEEngineClass>
inline FEEngineClass & getFEEngineClass(std::string name = "") const;
/// return the fem boundary object associated with a provided name
template <typename FEEngineClass>
inline FEEngineClass & getFEEngineClassBoundary(std::string name = "");
/// Get the type of analysis method used
AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod);
/// return the dimension of the system space
- AKANTU_GET_MACRO(SpatialDimension, Model::spatial_dimension, UInt);
+ AKANTU_GET_MACRO(SpatialDimension, Model::spatial_dimension, Int);
/* ------------------------------------------------------------------------ */
/* Pack and unpack hexlper functions */
/* ------------------------------------------------------------------------ */
public:
- inline UInt getNbIntegrationPoints(const Array<Element> & elements,
- const ID & fem_id = ID()) const;
+ inline Int getNbIntegrationPoints(const Array<Element> & elements,
+ const ID & fem_id = ID()) const;
/* ------------------------------------------------------------------------ */
/* Dumpable interface (kept for convenience) and dumper relative functions */
/* ------------------------------------------------------------------------ */
void setTextModeToDumper();
virtual void addDumpGroupFieldToDumper(const std::string & field_id,
std::shared_ptr<dumpers::Field> field,
DumperIOHelper & dumper);
virtual void addDumpField(const std::string & field_id);
virtual void addDumpFieldVector(const std::string & field_id);
virtual void addDumpFieldToDumper(const std::string & dumper_name,
const std::string & field_id);
virtual void addDumpFieldVectorToDumper(const std::string & dumper_name,
const std::string & field_id);
virtual void addDumpFieldTensorToDumper(const std::string & dumper_name,
const std::string & field_id);
virtual void addDumpFieldTensor(const std::string & field_id);
virtual void setBaseName(const std::string & field_id);
virtual void setBaseNameToDumper(const std::string & dumper_name,
const std::string & basename);
virtual void addDumpGroupField(const std::string & field_id,
const std::string & group_name);
virtual void addDumpGroupFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name,
ElementKind element_kind,
bool padding_flag);
virtual void addDumpGroupFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name,
- UInt spatial_dimension,
+ Int spatial_dimension,
ElementKind element_kind,
bool padding_flag);
virtual void removeDumpGroupField(const std::string & field_id,
const std::string & group_name);
virtual void removeDumpGroupFieldFromDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name);
virtual void addDumpGroupFieldVector(const std::string & field_id,
const std::string & group_name);
virtual void addDumpGroupFieldVectorToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name);
virtual std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & /*field_name*/,
const std::string & /*group_name*/,
bool /*padding_flag*/) {
return nullptr;
}
virtual std::shared_ptr<dumpers::Field>
- createNodalFieldUInt(const std::string & /*field_name*/,
- const std::string & /*group_name*/,
- bool /*padding_flag*/) {
+ createNodalFieldInt(const std::string & /*field_name*/,
+ const std::string & /*group_name*/,
+ bool /*padding_flag*/) {
return nullptr;
}
virtual std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & /*field_name*/,
const std::string & /*group_name*/,
bool /*padding_flag*/) {
return nullptr;
}
virtual std::shared_ptr<dumpers::Field> createElementalField(
const std::string & /*field_name*/, const std::string & /*group_name*/,
- bool /*padding_flag*/, UInt /*spatial_dimension*/, ElementKind /*kind*/) {
+ bool /*padding_flag*/, Int /*spatial_dimension*/, ElementKind /*kind*/) {
return nullptr;
}
void setDirectory(const std::string & directory);
void setDirectoryToDumper(const std::string & dumper_name,
const std::string & directory);
/* ------------------------------------------------------------------------ */
virtual void dump(const std::string & dumper_name);
- virtual void dump(const std::string & dumper_name, UInt step);
- virtual void dump(const std::string & dumper_name, Real time, UInt step);
+ virtual void dump(const std::string & dumper_name, Int step);
+ virtual void dump(const std::string & dumper_name, Real time, Int step);
/* ------------------------------------------------------------------------ */
virtual void dump();
- virtual void dump(UInt step);
- virtual void dump(Real time, UInt step);
+ virtual void dump(Int step);
+ virtual void dump(Real time, Int step);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
friend std::ostream & operator<<(std::ostream & /*stream*/,
const Model & /*_this*/);
ID id;
/// analysis method check the list in akantu::AnalysisMethod
AnalysisMethod method;
/// Mesh
Mesh & mesh;
/// Spatial dimension of the problem
- UInt spatial_dimension;
+ Int spatial_dimension;
/// the main fem object present in all models
FEEngineMap fems;
/// the fem object present in all models for boundaries
FEEngineMap fems_boundary;
/// default fem object
std::string default_fem;
/// parser to the pointer to use
Parser & parser;
/// default ElementKind for dumper
ElementKind dumper_default_element_kind{_ek_regular};
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream, const Model & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "model_inline_impl.hh"
#endif /* AKANTU_MODEL_HH_ */
diff --git a/src/model/model_couplers/coupler_solid_cohesive_contact.cc b/src/model/model_couplers/coupler_solid_cohesive_contact.cc
index c5e6ced73..2e275b80f 100644
--- a/src/model/model_couplers/coupler_solid_cohesive_contact.cc
+++ b/src/model/model_couplers/coupler_solid_cohesive_contact.cc
@@ -1,77 +1,77 @@
/**
* @file coupler_solid_cohesive_contact.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jan 21 2019
* @date last modification: Wed Jun 23 2021
*
* @brief class for coupling of solid mechanics cohesive and conatct mechanics
* model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_cohesive_contact.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
template <>
CouplerSolidContactTemplate<SolidMechanicsModelCohesive>::
- CouplerSolidContactTemplate(Mesh & mesh, UInt dim, const ID & id,
+ CouplerSolidContactTemplate(Mesh & mesh, Int dim, const ID & id,
std::shared_ptr<DOFManager> dof_manager)
: Model(mesh, ModelType::_coupler_solid_cohesive_contact, dim, id) {
this->initDOFManager(dof_manager);
this->mesh.registerDumper<DumperParaview>("coupler_solid_cohesive_contact",
id, true);
this->mesh.addDumpMeshToDumper("coupler_solid_cohesive_contact", mesh,
Model::spatial_dimension, _not_ghost,
_ek_cohesive);
this->registerDataAccessor(*this);
solid = std::make_unique<SolidMechanicsModelCohesive>(
mesh, Model::spatial_dimension, "solid_mechanics_model_cohesive",
this->dof_manager);
contact = std::make_unique<ContactMechanicsModel>(mesh.getMeshFacets(),
Model::spatial_dimension,
"contact_mechanics_model");
}
/* -------------------------------------------------------------------------- */
template <>
void CouplerSolidContactTemplate<SolidMechanicsModelCohesive>::initFullImpl(
const ModelOptions & options) {
Model::initFullImpl(options);
const auto & cscc_options =
aka::as_type<CouplerSolidCohesiveContactOptions>(options);
solid->initFull(_analysis_method = cscc_options.analysis_method,
_is_extrinsic = cscc_options.is_extrinsic);
contact->initFull(_analysis_method = cscc_options.analysis_method);
}
} // namespace akantu
diff --git a/src/model/model_couplers/coupler_solid_contact.cc b/src/model/model_couplers/coupler_solid_contact.cc
index 9f6b0961f..ed95a9d12 100644
--- a/src/model/model_couplers/coupler_solid_contact.cc
+++ b/src/model/model_couplers/coupler_solid_contact.cc
@@ -1,72 +1,72 @@
/**
* @file coupler_solid_contact.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jan 21 2019
* @date last modification: Wed Jun 23 2021
*
* @brief class for coupling of solid mechanics and conatct mechanics
* model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_contact.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
template <>
CouplerSolidContactTemplate<SolidMechanicsModel>::CouplerSolidContactTemplate(
- Mesh & mesh, UInt dim, const ID & id,
+ Mesh & mesh, Int dim, const ID & id,
std::shared_ptr<DOFManager> dof_manager)
: Model(mesh, ModelType::_coupler_solid_contact, dim, id) {
this->initDOFManager(dof_manager);
this->mesh.registerDumper<DumperParaview>("coupler_solid_contact", id, true);
this->mesh.addDumpMeshToDumper("coupler_solid_contact", mesh,
Model::spatial_dimension, _not_ghost,
_ek_regular);
this->registerDataAccessor(*this);
solid = std::make_unique<SolidMechanicsModel>(mesh, Model::spatial_dimension,
"solid_mechanics_model",
this->dof_manager);
contact = std::make_unique<ContactMechanicsModel>(
mesh, Model::spatial_dimension, "contact_mechanics_model",
this->dof_manager);
}
/* -------------------------------------------------------------------------- */
template <>
void CouplerSolidContactTemplate<SolidMechanicsModel>::initFullImpl(
const ModelOptions & options) {
Model::initFullImpl(options);
solid->initFull(_analysis_method = this->method);
contact->initFull(_analysis_method = this->method);
}
} // namespace akantu
diff --git a/src/model/model_couplers/coupler_solid_contact.hh b/src/model/model_couplers/coupler_solid_contact.hh
index 6c04b4770..7e92c480c 100644
--- a/src/model/model_couplers/coupler_solid_contact.hh
+++ b/src/model/model_couplers/coupler_solid_contact.hh
@@ -1,276 +1,276 @@
/**
* @file coupler_solid_contact.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Sat Jun 26 2021
*
* @brief class for coupling of solid mechanics and conatct mechanics
* model in explicit
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "solid_mechanics_model.hh"
#if defined(AKANTU_COHESIVE_ELEMENT)
#include "solid_mechanics_model_cohesive.hh"
#endif
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_COUPLER_SOLID_CONTACT_HH__
#define __AKANTU_COUPLER_SOLID_CONTACT_HH__
/* ------------------------------------------------------------------------ */
/* Coupling : Solid Mechanics / Contact Mechanics */
/* ------------------------------------------------------------------------ */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
class CouplerSolidContactTemplate : public Model,
public DataAccessor<Element>,
- public DataAccessor<UInt> {
+ public DataAccessor<Idx> {
static_assert(
std::is_base_of<SolidMechanicsModel, SolidMechanicsModelType>::value,
"SolidMechanicsModelType should be derived from SolidMechanicsModel");
/* ------------------------------------------------------------------------ */
/* Constructor/Destructor */
/* ------------------------------------------------------------------------ */
public:
CouplerSolidContactTemplate(
- Mesh & mesh, UInt dim = _all_dimensions,
+ Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "coupler_solid_contact",
std::shared_ptr<DOFManager> dof_manager = nullptr);
~CouplerSolidContactTemplate() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// initialize completely the model
void initFullImpl(const ModelOptions & options) override;
/// get some default values for derived classes
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
/* ------------------------------------------------------------------------ */
/* Solver Interface */
/* ------------------------------------------------------------------------ */
public:
/// assembles the contact stiffness matrix
virtual void assembleStiffnessMatrix();
/// assembles the contant internal forces
virtual void assembleInternalForces();
#if defined(AKANTU_COHESIVE_ELEMENT)
template <class Model_ = SolidMechanicsModelType,
std::enable_if_t<std::is_same<
Model_, SolidMechanicsModelCohesive>::value> * = nullptr>
UInt checkCohesiveStress() {
return solid->checkCohesiveStress();
}
#endif
template <typename FunctorType>
inline void applyBC(const FunctorType & func) {
solid->applyBC(func);
}
template <class FunctorType>
inline void applyBC(const FunctorType & func,
const std::string & group_name) {
solid->applyBC(func, group_name);
}
template <class FunctorType>
inline void applyBC(const FunctorType & func,
const ElementGroup & element_group) {
solid->applyBC(func, element_group);
}
protected:
/// callback for the solver, this adds f_{ext} - f_{int} to the residual
void assembleResidual() override;
/// callback for the solver, this adds f_{ext} or f_{int} to the residual
void assembleResidual(const ID & residual_part) override;
bool canSplitResidual() const override { return true; }
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override;
/// callback for the solver, this assembles different matrices
void assembleMatrix(const ID & matrix_id) override;
/// callback for the solver, this assembles the stiffness matrix
void assembleLumpedMatrix(const ID & matrix_id) override;
/// callback for the solver, this is called at beginning of solve
void predictor() override;
/// callback for the solver, this is called at end of solve
void corrector() override;
/// callback for the solver, this is called at beginning of solve
void beforeSolveStep() override;
/// callback for the solver, this is called at end of solve
void afterSolveStep(bool converged = true) override;
/// callback for the model to instantiate the matricess when needed
void initSolver(TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type) override;
/* ------------------------------------------------------------------------ */
/* Mass matrix for solid mechanics model */
/* ------------------------------------------------------------------------ */
public:
/// assemble the lumped mass matrix
void assembleMassLumped();
/// assemble the mass matrix for consistent mass resolutions
void assembleMass();
protected:
/// assemble the lumped mass matrix for local and ghost elements
void assembleMassLumped(GhostType ghost_type);
/// assemble the mass matrix for either _ghost or _not_ghost elements
void assembleMass(GhostType ghost_type);
protected:
/* ------------------------------------------------------------------------ */
TimeStepSolverType getDefaultSolverType() const override;
/* ------------------------------------------------------------------------ */
ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
public:
bool isDefaultSolverExplicit() { return method == _explicit_lumped_mass; }
/* ------------------------------------------------------------------------ */
public:
// DataAccessor<Element>
- UInt getNbData(const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/) const override {
+ Int getNbData(const Array<Element> & /*elements*/,
+ const SynchronizationTag & /*tag*/) const override {
return 0;
}
void packData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
const SynchronizationTag & /*tag*/) const override {}
void unpackData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
const SynchronizationTag & /*tag*/) override {}
// DataAccessor<UInt> nodes
- UInt getNbData(const Array<UInt> & /*nodes*/,
- const SynchronizationTag & /*tag*/) const override {
+ Int getNbData(const Array<Idx> & /*nodes*/,
+ const SynchronizationTag & /*tag*/) const override {
return 0;
}
- void packData(CommunicationBuffer & /*buffer*/, const Array<UInt> & /*nodes*/,
+ void packData(CommunicationBuffer & /*buffer*/, const Array<Idx> & /*nodes*/,
const SynchronizationTag & /*tag*/) const override {}
void unpackData(CommunicationBuffer & /*buffer*/,
- const Array<UInt> & /*nodes*/,
+ const Array<Idx> & /*nodes*/,
const SynchronizationTag & /*tag*/) override {}
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the solid mechanics model
#if defined(AKANTU_COHESIVE_ELEMENT)
template <class Model_ = SolidMechanicsModelType,
std::enable_if_t<std::is_same<
Model_, SolidMechanicsModelCohesive>::value> * = nullptr>
SolidMechanicsModelCohesive & getSolidMechanicsModelCohesive() {
return *solid;
}
#endif
template <class Model_ = SolidMechanicsModelType,
std::enable_if_t<
std::is_same<Model_, SolidMechanicsModel>::value> * = nullptr>
SolidMechanicsModelType & getSolidMechanicsModel() {
return *solid;
}
/// get the contact mechanics model
AKANTU_GET_MACRO(ContactMechanicsModel, *contact, ContactMechanicsModel &)
/* ------------------------------------------------------------------------ */
/* Dumpable interface */
/* ------------------------------------------------------------------------ */
public:
std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
- createNodalFieldUInt(const std::string & field_name,
- const std::string & group_name,
- bool padding_flag) override;
+ createNodalFieldInt(const std::string & field_name,
+ const std::string & group_name,
+ bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createElementalField(const std::string & field_name,
const std::string & group_name, bool padding_flag,
- UInt spatial_dimension, ElementKind kind) override;
+ Int spatial_dimension, ElementKind kind) override;
void dump(const std::string & dumper_name) override;
- void dump(const std::string & dumper_name, UInt step) override;
- void dump(const std::string & dumper_name, Real time, UInt step) override;
+ void dump(const std::string & dumper_name, Int step) override;
+ void dump(const std::string & dumper_name, Real time, Int step) override;
void dump() override;
- void dump(UInt step) override;
- void dump(Real time, UInt step) override;
+ void dump(Int step) override;
+ void dump(Real time, Int step) override;
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
private:
/// solid mechanics model
std::unique_ptr<SolidMechanicsModelType> solid;
/// contact mechanics model
std::unique_ptr<ContactMechanicsModel> contact;
UInt step;
};
using CouplerSolidContact = CouplerSolidContactTemplate<SolidMechanicsModel>;
} // namespace akantu
#include "coupler_solid_contact_tmpl.hh"
#endif /* __COUPLER_SOLID_CONTACT_HH__ */
diff --git a/src/model/model_couplers/coupler_solid_contact_tmpl.hh b/src/model/model_couplers/coupler_solid_contact_tmpl.hh
index 5bfe1a59f..6d7c806ca 100644
--- a/src/model/model_couplers/coupler_solid_contact_tmpl.hh
+++ b/src/model/model_couplers/coupler_solid_contact_tmpl.hh
@@ -1,396 +1,396 @@
/**
* @file coupler_solid_contact_tmpl.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jan 21 2019
* @date last modification: Wed Jun 23 2021
*
* @brief class for coupling of solid mechanics and conatct mechanics
* model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_contact.hh"
#include "dumpable_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
CouplerSolidContactTemplate<
SolidMechanicsModelType>::~CouplerSolidContactTemplate() = default;
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::initSolver(
TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type) {
auto & solid_model_solver = aka::as_type<ModelSolver>(*solid);
solid_model_solver.initSolver(time_step_solver_type, non_linear_solver_type);
auto & contact_model_solver = aka::as_type<ModelSolver>(*contact);
contact_model_solver.initSolver(time_step_solver_type,
non_linear_solver_type);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
std::tuple<ID, TimeStepSolverType>
CouplerSolidContactTemplate<SolidMechanicsModelType>::getDefaultSolverID(
const AnalysisMethod & method) {
return solid->getDefaultSolverID(method);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
TimeStepSolverType
CouplerSolidContactTemplate<SolidMechanicsModelType>::getDefaultSolverType()
const {
return solid->getDefaultSolverType();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
ModelSolverOptions
CouplerSolidContactTemplate<SolidMechanicsModelType>::getDefaultSolverOptions(
const TimeStepSolverType & type) const {
return solid->getDefaultSolverOptions(type);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::assembleResidual() {
// computes the internal forces
switch (method) {
case _explicit_lumped_mass: {
auto & current_positions = contact->getContactDetector().getPositions();
current_positions.copy(solid->getCurrentPosition());
contact->search();
break;
}
default:
break;
}
this->assembleInternalForces();
auto & internal_force = solid->getInternalForce();
auto & external_force = solid->getExternalForce();
auto & contact_force = contact->getInternalForce();
/* ------------------------------------------------------------------------ */
this->getDOFManager().assembleToResidual("displacement", external_force, 1);
this->getDOFManager().assembleToResidual("displacement", internal_force, 1);
this->getDOFManager().assembleToResidual("displacement", contact_force, 1);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::assembleResidual(
const ID & residual_part) {
AKANTU_DEBUG_IN();
// contact->assembleInternalForces();
auto & internal_force = solid->getInternalForce();
auto & external_force = solid->getExternalForce();
auto & contact_force = contact->getInternalForce();
if ("external" == residual_part) {
this->getDOFManager().assembleToResidual("displacement", external_force, 1);
this->getDOFManager().assembleToResidual("displacement", contact_force, 1);
AKANTU_DEBUG_OUT();
return;
}
if ("internal" == residual_part) {
this->getDOFManager().assembleToResidual("displacement", internal_force, 1);
AKANTU_DEBUG_OUT();
return;
}
AKANTU_CUSTOM_EXCEPTION(
debug::SolverCallbackResidualPartUnknown(residual_part));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::predictor() {
auto & solid_model_solver = aka::as_type<ModelSolver>(*solid);
solid_model_solver.predictor();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::corrector() {
auto & solid_model_solver = aka::as_type<ModelSolver>(*solid);
solid_model_solver.corrector();
switch (method) {
case _static:
case _implicit_dynamic: {
auto & current_positions = contact->getContactDetector().getPositions();
current_positions.copy(solid->getCurrentPosition());
contact->search();
break;
}
default:
break;
}
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
MatrixType CouplerSolidContactTemplate<SolidMechanicsModelType>::getMatrixType(
const ID & matrix_id) const {
if (matrix_id == "K") {
return _symmetric;
}
if (matrix_id == "M") {
return _symmetric;
}
return _mt_not_defined;
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::assembleMatrix(
const ID & matrix_id) {
if (matrix_id == "K") {
this->assembleStiffnessMatrix();
} else if (matrix_id == "M") {
solid->assembleMass();
}
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::assembleLumpedMatrix(
const ID & matrix_id) {
if (matrix_id == "M") {
solid->assembleMassLumped();
}
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::beforeSolveStep() {
auto & solid_solver_callback = aka::as_type<SolverCallback>(*solid);
solid_solver_callback.beforeSolveStep();
auto & contact_solver_callback = aka::as_type<SolverCallback>(*contact);
contact_solver_callback.beforeSolveStep();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::afterSolveStep(
bool converged) {
auto & solid_solver_callback = aka::as_type<SolverCallback>(*solid);
solid_solver_callback.afterSolveStep(converged);
auto & contact_solver_callback = aka::as_type<SolverCallback>(*contact);
contact_solver_callback.afterSolveStep(converged);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<
SolidMechanicsModelType>::assembleInternalForces() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the internal forces");
solid->assembleInternalForces();
contact->assembleInternalForces();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<
SolidMechanicsModelType>::assembleStiffnessMatrix() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the new stiffness matrix");
solid->assembleStiffnessMatrix(true);
switch (method) {
case _static:
case _implicit_dynamic: {
contact->assembleStiffnessMatrix();
break;
}
default:
break;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<
SolidMechanicsModelType>::assembleMassLumped() {
solid->assembleMassLumped();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::assembleMass() {
solid->assembleMass();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::assembleMassLumped(
GhostType ghost_type) {
solid->assembleMassLumped(ghost_type);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::assembleMass(
GhostType ghost_type) {
solid->assembleMass(ghost_type);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
std::shared_ptr<dumpers::Field>
CouplerSolidContactTemplate<SolidMechanicsModelType>::createElementalField(
const std::string & field_name, const std::string & group_name,
- bool padding_flag, UInt spatial_dimension, ElementKind kind) {
+ bool padding_flag, Int spatial_dimension, ElementKind kind) {
std::shared_ptr<dumpers::Field> field;
field = contact->createElementalField(field_name, group_name, padding_flag,
spatial_dimension, kind);
if (not field) {
field = solid->createElementalField(field_name, group_name, padding_flag,
spatial_dimension, kind);
}
return field;
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
std::shared_ptr<dumpers::Field>
CouplerSolidContactTemplate<SolidMechanicsModelType>::createNodalFieldReal(
const std::string & field_name, const std::string & group_name,
bool padding_flag) {
std::shared_ptr<dumpers::Field> field;
field = contact->createNodalFieldReal(field_name, group_name, padding_flag);
if (not field) {
field = solid->createNodalFieldReal(field_name, group_name, padding_flag);
}
return field;
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
std::shared_ptr<dumpers::Field>
-CouplerSolidContactTemplate<SolidMechanicsModelType>::createNodalFieldUInt(
+CouplerSolidContactTemplate<SolidMechanicsModelType>::createNodalFieldInt(
const std::string & field_name, const std::string & group_name,
bool padding_flag) {
std::shared_ptr<dumpers::Field> field;
- field = contact->createNodalFieldUInt(field_name, group_name, padding_flag);
+ field = contact->createNodalFieldInt(field_name, group_name, padding_flag);
if (not field) {
- field = solid->createNodalFieldUInt(field_name, group_name, padding_flag);
+ field = solid->createNodalFieldInt(field_name, group_name, padding_flag);
}
return field;
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
std::shared_ptr<dumpers::Field>
CouplerSolidContactTemplate<SolidMechanicsModelType>::createNodalFieldBool(
const std::string & field_name, const std::string & group_name,
bool padding_flag) {
std::shared_ptr<dumpers::Field> field;
field = contact->createNodalFieldBool(field_name, group_name, padding_flag);
if (not field) {
field = solid->createNodalFieldBool(field_name, group_name, padding_flag);
}
return field;
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(
const std::string & dumper_name) {
solid->onDump();
Model::dump(dumper_name);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(
- const std::string & dumper_name, UInt step) {
+ const std::string & dumper_name, Int step) {
solid->onDump();
Model::dump(dumper_name, step);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(
- const std::string & dumper_name, Real time, UInt step) {
+ const std::string & dumper_name, Real time, Int step) {
solid->onDump();
Model::dump(dumper_name, time, step);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump() {
solid->onDump();
Model::dump();
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
-void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(UInt step) {
+void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(Int step) {
solid->onDump();
Model::dump(step);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(Real time,
- UInt step) {
+ Int step) {
solid->onDump();
Model::dump(time, step);
}
} // namespace akantu
diff --git a/src/model/model_couplers/coupler_solid_phasefield.cc b/src/model/model_couplers/coupler_solid_phasefield.cc
index 7efe6a986..4223f1f05 100644
--- a/src/model/model_couplers/coupler_solid_phasefield.cc
+++ b/src/model/model_couplers/coupler_solid_phasefield.cc
@@ -1,599 +1,578 @@
/**
* @file coupler_solid_phasefield.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Jun 24 2019
* @date last modification: Fri Apr 02 2021
*
* @brief class for coupling of solid mechancis and phase model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_phasefield.hh"
#include "dumpable_inline_impl.hh"
#include "element_synchronizer.hh"
#include "integrator_gauss.hh"
#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
-CouplerSolidPhaseField::CouplerSolidPhaseField(Mesh & mesh, UInt dim,
+CouplerSolidPhaseField::CouplerSolidPhaseField(Mesh & mesh, Int dim,
const ID & id,
const ModelType model_type)
: Model(mesh, model_type, dim, id) {
-
- AKANTU_DEBUG_IN();
-
this->registerFEEngineObject<MyFEEngineType>("CouplerSolidPhaseField", mesh,
Model::spatial_dimension);
this->mesh.registerDumper<DumperParaview>("coupler_solid_phasefield", id,
true);
this->mesh.addDumpMeshToDumper("coupler_solid_phasefield", mesh,
Model::spatial_dimension, _not_ghost,
_ek_regular);
this->registerDataAccessor(*this);
solid = new SolidMechanicsModel(mesh, Model::spatial_dimension,
"solid_mechanics_model");
phase =
new PhaseFieldModel(mesh, Model::spatial_dimension, "phase_field_model");
if (this->mesh.isDistributed()) {
auto & synchronizer = this->mesh.getElementSynchronizer();
this->registerSynchronizer(synchronizer, SynchronizationTag::_csp_damage);
this->registerSynchronizer(synchronizer, SynchronizationTag::_csp_strain);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
CouplerSolidPhaseField::~CouplerSolidPhaseField() = default;
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::initFullImpl(const ModelOptions & options) {
-
Model::initFullImpl(options);
this->initBC(*this, *displacement, *displacement_increment, *external_force);
solid->initFull(_analysis_method = this->method);
phase->initFull(_analysis_method = this->method);
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::initModel() {
-
getFEEngine().initShapeFunctions(_not_ghost);
getFEEngine().initShapeFunctions(_ghost);
}
/* -------------------------------------------------------------------------- */
FEEngine & CouplerSolidPhaseField::getFEEngineBoundary(const ID & name) {
return dynamic_cast<FEEngine &>(
getFEEngineClassBoundary<MyFEEngineType>(name));
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::initSolver(
TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type) {
auto & solid_model_solver = aka::as_type<ModelSolver>(*solid);
solid_model_solver.initSolver(time_step_solver_type, non_linear_solver_type);
auto & phase_model_solver = aka::as_type<ModelSolver>(*phase);
phase_model_solver.initSolver(time_step_solver_type, non_linear_solver_type);
}
/* -------------------------------------------------------------------------- */
std::tuple<ID, TimeStepSolverType>
CouplerSolidPhaseField::getDefaultSolverID(const AnalysisMethod & method) {
-
switch (method) {
case _explicit_lumped_mass: {
return std::make_tuple("explicit_lumped",
TimeStepSolverType::_dynamic_lumped);
}
case _explicit_consistent_mass: {
return std::make_tuple("explicit", TimeStepSolverType::_dynamic);
}
case _static: {
return std::make_tuple("static", TimeStepSolverType::_static);
}
case _implicit_dynamic: {
return std::make_tuple("implicit", TimeStepSolverType::_dynamic);
}
default:
return std::make_tuple("unknown", TimeStepSolverType::_not_defined);
}
}
/* -------------------------------------------------------------------------- */
TimeStepSolverType CouplerSolidPhaseField::getDefaultSolverType() const {
return TimeStepSolverType::_dynamic_lumped;
}
/* -------------------------------------------------------------------------- */
ModelSolverOptions CouplerSolidPhaseField::getDefaultSolverOptions(
const TimeStepSolverType & type) const {
ModelSolverOptions options;
switch (type) {
case TimeStepSolverType::_dynamic_lumped: {
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
break;
}
case TimeStepSolverType::_dynamic: {
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
break;
}
case TimeStepSolverType::_static: {
options.non_linear_solver_type = NonLinearSolverType::_linear;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_pseudo_time;
options.solution_type["displacement"] = IntegrationScheme::_not_defined;
break;
}
default:
AKANTU_EXCEPTION(type << " is not a valid time step solver type");
break;
}
return options;
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleResidual() {
// computes the internal forces
this->assembleInternalForces();
auto & solid_internal_force = solid->getInternalForce();
auto & solid_external_force = solid->getExternalForce();
auto & phasefield_internal_force = phase->getInternalForce();
auto & phasefield_external_force = phase->getExternalForce();
/* ------------------------------------------------------------------------ */
this->getDOFManager().assembleToResidual("displacement", solid_external_force,
1);
this->getDOFManager().assembleToResidual("displacement", solid_internal_force,
1);
this->getDOFManager().assembleToResidual("damage", phasefield_external_force,
1);
this->getDOFManager().assembleToResidual("damage", phasefield_internal_force,
1);
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleResidual(const ID & residual_part) {
AKANTU_DEBUG_IN();
auto & solid_internal_force = solid->getInternalForce();
auto & solid_external_force = solid->getExternalForce();
auto & phasefield_internal_force = phase->getInternalForce();
auto & phasefield_external_force = phase->getExternalForce();
if ("external" == residual_part) {
this->getDOFManager().assembleToResidual("displacement",
solid_external_force, 1);
this->getDOFManager().assembleToResidual("displacement",
solid_internal_force, 1);
AKANTU_DEBUG_OUT();
return;
}
if ("internal" == residual_part) {
this->getDOFManager().assembleToResidual("damage",
phasefield_external_force, 1);
this->getDOFManager().assembleToResidual("damage",
phasefield_internal_force, 1);
AKANTU_DEBUG_OUT();
return;
}
AKANTU_CUSTOM_EXCEPTION(
debug::SolverCallbackResidualPartUnknown(residual_part));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::predictor() {
auto & solid_model_solver = aka::as_type<ModelSolver>(*solid);
solid_model_solver.predictor();
auto & phase_model_solver = aka::as_type<ModelSolver>(*phase);
phase_model_solver.predictor();
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::corrector() {
auto & solid_model_solver = aka::as_type<ModelSolver>(*solid);
solid_model_solver.corrector();
auto & phase_model_solver = aka::as_type<ModelSolver>(*phase);
phase_model_solver.corrector();
}
/* -------------------------------------------------------------------------- */
MatrixType CouplerSolidPhaseField::getMatrixType(const ID & matrix_id) const {
if (matrix_id == "K") {
return _symmetric;
}
if (matrix_id == "M") {
return _symmetric;
}
return _mt_not_defined;
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleMatrix(const ID & matrix_id) {
if (matrix_id == "K") {
this->assembleStiffnessMatrix();
} else if (matrix_id == "M") {
solid->assembleMass();
}
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleLumpedMatrix(const ID & matrix_id) {
if (matrix_id == "M") {
solid->assembleMassLumped();
}
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::beforeSolveStep() {
auto & solid_solver_callback = aka::as_type<SolverCallback>(*solid);
solid_solver_callback.beforeSolveStep();
auto & phase_solver_callback = aka::as_type<SolverCallback>(*phase);
phase_solver_callback.beforeSolveStep();
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::afterSolveStep(bool converged) {
auto & solid_solver_callback = aka::as_type<SolverCallback>(*solid);
solid_solver_callback.afterSolveStep(converged);
auto & phase_solver_callback = aka::as_type<SolverCallback>(*phase);
phase_solver_callback.afterSolveStep(converged);
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleInternalForces() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the internal forces");
solid->assembleInternalForces();
phase->assembleInternalForces();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleStiffnessMatrix() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the new stiffness matrix");
solid->assembleStiffnessMatrix();
phase->assembleStiffnessMatrix();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleMassLumped() {
solid->assembleMassLumped();
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleMass() { solid->assembleMass(); }
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleMassLumped(GhostType ghost_type) {
solid->assembleMassLumped(ghost_type);
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::assembleMass(GhostType ghost_type) {
solid->assembleMass(ghost_type);
}
/* ------------------------------------------------------------------------- */
-void CouplerSolidPhaseField::computeDamageOnQuadPoints(
- const GhostType & ghost_type) {
+void CouplerSolidPhaseField::computeDamageOnQuadPoints(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & fem = phase->getFEEngine();
auto & mesh = phase->getMesh();
auto nb_materials = solid->getNbMaterials();
auto nb_phasefields = phase->getNbPhaseFields();
AKANTU_DEBUG_ASSERT(
nb_phasefields == nb_materials,
"The number of phasefields and materials should be equal");
for (auto index : arange(nb_materials)) {
auto & material = solid->getMaterial(index);
for (auto index2 : arange(nb_phasefields)) {
auto & phasefield = phase->getPhaseField(index2);
if (phasefield.getName() == material.getName()) {
switch (spatial_dimension) {
case 1: {
auto & mat = static_cast<MaterialPhaseField<1> &>(material);
auto & damage = mat.getDamage();
for (const auto & type :
mesh.elementTypes(Model::spatial_dimension, ghost_type)) {
auto & damage_on_qpoints_vect = damage(type, ghost_type);
fem.interpolateOnIntegrationPoints(phase->getDamage(),
damage_on_qpoints_vect, 1, type,
ghost_type);
}
break;
}
case 2: {
auto & mat = static_cast<MaterialPhaseField<2> &>(material);
auto & damage = mat.getDamage();
for (const auto & type :
mesh.elementTypes(Model::spatial_dimension, ghost_type)) {
auto & damage_on_qpoints_vect = damage(type, ghost_type);
fem.interpolateOnIntegrationPoints(phase->getDamage(),
damage_on_qpoints_vect, 1, type,
ghost_type);
}
break;
}
default:
auto & mat = static_cast<MaterialPhaseField<3> &>(material);
auto & damage = mat.getDamage();
for (const auto & type :
mesh.elementTypes(Model::spatial_dimension, ghost_type)) {
auto & damage_on_qpoints_vect = damage(type, ghost_type);
fem.interpolateOnIntegrationPoints(phase->getDamage(),
damage_on_qpoints_vect, 1, type,
ghost_type);
}
break;
}
}
}
}
AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------- */
-void CouplerSolidPhaseField::computeStrainOnQuadPoints(
- const GhostType & ghost_type) {
+void CouplerSolidPhaseField::computeStrainOnQuadPoints(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & mesh = solid->getMesh();
auto nb_materials = solid->getNbMaterials();
auto nb_phasefields = phase->getNbPhaseFields();
AKANTU_DEBUG_ASSERT(
nb_phasefields == nb_materials,
"The number of phasefields and materials should be equal");
for (auto index : arange(nb_materials)) {
auto & material = solid->getMaterial(index);
for (auto index2 : arange(nb_phasefields)) {
auto & phasefield = phase->getPhaseField(index2);
if (phasefield.getName() == material.getName()) {
auto & strain_on_qpoints = phasefield.getStrain();
const auto & gradu_on_qpoints = material.getGradU();
for (const auto & type :
mesh.elementTypes(spatial_dimension, ghost_type)) {
auto & strain_on_qpoints_vect = strain_on_qpoints(type, ghost_type);
const auto & gradu_on_qpoints_vect =
gradu_on_qpoints(type, ghost_type);
for (auto && values :
zip(make_view(strain_on_qpoints_vect, spatial_dimension,
spatial_dimension),
make_view(gradu_on_qpoints_vect, spatial_dimension,
spatial_dimension))) {
auto & strain = std::get<0>(values);
const auto & grad_u = std::get<1>(values);
- gradUToEpsilon(grad_u, strain);
+ strain = (grad_u + grad_u.transpose()) / 2.;
}
}
break;
}
}
}
AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------- */
void CouplerSolidPhaseField::solve(const ID & solid_solver_id,
const ID & phase_solver_id) {
solid->solveStep(solid_solver_id);
this->computeStrainOnQuadPoints(_not_ghost);
phase->solveStep(phase_solver_id);
this->computeDamageOnQuadPoints(_not_ghost);
solid->assembleInternalForces();
}
-/* ------------------------------------------------------------------------- */
-void CouplerSolidPhaseField::gradUToEpsilon(const Matrix<Real> & grad_u,
- Matrix<Real> & epsilon) {
- for (UInt i = 0; i < Model::spatial_dimension; ++i) {
- for (UInt j = 0; j < Model::spatial_dimension; ++j) {
- epsilon(i, j) = 0.5 * (grad_u(i, j) + grad_u(j, i));
- }
- }
-}
-
/* ------------------------------------------------------------------------- */
bool CouplerSolidPhaseField::checkConvergence(Array<Real> & u_new,
Array<Real> & u_old,
Array<Real> & d_new,
Array<Real> & d_old) {
const Array<bool> & blocked_dofs = solid->getBlockedDOFs();
- UInt nb_degree_of_freedom = u_new.size();
+ Int nb_degree_of_freedom = u_new.size();
auto u_n_it = u_new.begin();
auto u_o_it = u_old.begin();
auto bld_it = blocked_dofs.begin();
Real norm = 0;
- for (UInt n = 0; n < nb_degree_of_freedom;
- ++n, ++u_n_it, ++u_o_it, ++bld_it) {
+ for (Int n = 0; n < nb_degree_of_freedom; ++n, ++u_n_it, ++u_o_it, ++bld_it) {
if ((!*bld_it)) {
norm += (*u_n_it - *u_o_it) * (*u_n_it - *u_o_it);
}
}
norm = std::sqrt(norm);
auto d_n_it = d_new.begin();
auto d_o_it = d_old.begin();
nb_degree_of_freedom = d_new.size();
Real norm2 = 0;
- for (UInt i = 0; i < nb_degree_of_freedom; ++i) {
+ for (Int i = 0; i < nb_degree_of_freedom; ++i) {
norm2 += (*d_n_it - *d_o_it);
}
norm2 = std::sqrt(norm2);
Real error = std::max(norm, norm2);
Real tolerance = 1e-8;
return error < tolerance;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> CouplerSolidPhaseField::createElementalField(
const std::string & field_name, const std::string & group_name,
- bool padding_flag, UInt spatial_dimension, ElementKind kind) {
+ bool padding_flag, Idx spatial_dimension, ElementKind kind) {
return solid->createElementalField(field_name, group_name, padding_flag,
spatial_dimension, kind);
std::shared_ptr<dumpers::Field> field;
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
CouplerSolidPhaseField::createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) {
return solid->createNodalFieldReal(field_name, group_name, padding_flag);
std::shared_ptr<dumpers::Field> field;
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
CouplerSolidPhaseField::createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) {
return solid->createNodalFieldBool(field_name, group_name, padding_flag);
std::shared_ptr<dumpers::Field> field;
return field;
}
/* -----------------------------------------------------------------------*/
void CouplerSolidPhaseField::dump(const std::string & dumper_name) {
solid->onDump();
mesh.dump(dumper_name);
}
/* ------------------------------------------------------------------------*/
-void CouplerSolidPhaseField::dump(const std::string & dumper_name, UInt step) {
+void CouplerSolidPhaseField::dump(const std::string & dumper_name, Int step) {
solid->onDump();
mesh.dump(dumper_name, step);
}
/* ----------------------------------------------------------------------- */
void CouplerSolidPhaseField::dump(const std::string & dumper_name, Real time,
- UInt step) {
+ Int step) {
solid->onDump();
mesh.dump(dumper_name, time, step);
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::dump() {
solid->onDump();
mesh.dump();
}
/* -------------------------------------------------------------------------- */
-void CouplerSolidPhaseField::dump(UInt step) {
+void CouplerSolidPhaseField::dump(Int step) {
solid->onDump();
mesh.dump(step);
}
/* -------------------------------------------------------------------------- */
-void CouplerSolidPhaseField::dump(Real time, UInt step) {
+void CouplerSolidPhaseField::dump(Real time, Int step) {
solid->onDump();
mesh.dump(time, step);
}
} // namespace akantu
diff --git a/src/model/model_couplers/coupler_solid_phasefield.hh b/src/model/model_couplers/coupler_solid_phasefield.hh
index fa64644dd..39a6d9db6 100644
--- a/src/model/model_couplers/coupler_solid_phasefield.hh
+++ b/src/model/model_couplers/coupler_solid_phasefield.hh
@@ -1,294 +1,257 @@
/**
* @file coupler_solid_phasefield.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Jun 24 2019
* @date last modification: Wed Jun 23 2021
*
* @brief class for coupling of solid mechancis and phasefield model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "boundary_condition.hh"
#include "data_accessor.hh"
#include "fe_engine.hh"
#include "material.hh"
#include "material_phasefield.hh"
#include "model.hh"
#include "phase_field_model.hh"
#include "solid_mechanics_model.hh"
#include "sparse_matrix.hh"
#include "time_step_solver.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_COUPLER_SOLID_PHASEFIELD_HH__
#define __AKANTU_COUPLER_SOLID_PHASEFIELD_HH__
/* ------------------------------------------------------------------------ */
/* Coupling : Solid Mechanics / PhaseField */
/* ------------------------------------------------------------------------ */
namespace akantu {
template <ElementKind kind, class IntegrationOrderFunctor>
class IntegratorGauss;
template <ElementKind kind> class ShapeLagrange;
class DOFManager;
} // namespace akantu
namespace akantu {
class CouplerSolidPhaseField
: public Model,
public DataAccessor<Element>,
- public DataAccessor<UInt>,
+ public DataAccessor<Idx>,
public BoundaryCondition<CouplerSolidPhaseField> {
/* ------------------------------------------------------------------------ */
/* Constructor/Destructors */
/* ------------------------------------------------------------------------ */
using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
public:
CouplerSolidPhaseField(
- Mesh & mesh, UInt dim = _all_dimensions,
+ Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "coupler_solid_phasefield",
ModelType model_type = ModelType::_coupler_solid_phasefield);
~CouplerSolidPhaseField() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// initialize the complete model
void initFullImpl(const ModelOptions & options) override;
/// initialize the modelType
void initModel() override;
/// get some default values for derived classes
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
/* ------------------------------------------------------------------------ */
/* Solver Interface */
/* ------------------------------------------------------------------------ */
public:
/// assembles the contact stiffness matrix
virtual void assembleStiffnessMatrix();
/// assembles the contant internal forces
virtual void assembleInternalForces();
public:
/// computes damage on quad points for solid mechanics model from
/// damage array from phasefield model
- void computeDamageOnQuadPoints(const GhostType & /*ghost_type*/);
+ void computeDamageOnQuadPoints(GhostType ghost_type);
/// computes strain on quadrature points for phasefield model from
/// displacement gradient from solid mechanics model
- void computeStrainOnQuadPoints(const GhostType & ghost_type);
+ void computeStrainOnQuadPoints(GhostType ghost_type);
/// solve the coupled model
void solve(const ID & solid_solver_id = "", const ID & phase_solver_id = "");
private:
- /// computes small strain from displacement gradient
- void gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon);
-
/// test the convergence criteria
bool checkConvergence(Array<Real> & /*u_new*/, Array<Real> & /*u_old*/,
Array<Real> & /*d_new*/, Array<Real> & /*d_old*/);
protected:
/// callback for the solver, this adds f_{ext} - f_{int} to the residual
void assembleResidual() override;
/// callback for the solver, this adds f_{ext} or f_{int} to the residual
void assembleResidual(const ID & residual_part) override;
bool canSplitResidual() const override { return true; }
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override;
/// callback for the solver, this assembles different matrices
void assembleMatrix(const ID & matrix_id) override;
/// callback for the solver, this assembles the stiffness matrix
void assembleLumpedMatrix(const ID & matrix_id) override;
/// callback for the model to instantiate the matricess when needed
void initSolver(TimeStepSolverType /*time_step_solver_type*/,
- NonLinearSolverType /*non_linear_solver_type*/) override;
+ NonLinearSolverType /*non_linear_solver_type*/)
+ override;
/// callback for the solver, this is called at beginning of solve
void predictor() override;
/// callback for the solver, this is called at end of solve
void corrector() override;
/// callback for the solver, this is called at beginning of solve
void beforeSolveStep() override;
/// callback for the solver, this is called at end of solve
void afterSolveStep(bool converged = true) override;
/// solve the coupled model
// void solveStep(const ID & solver_id = "") override;
/// solve a step using a given pre instantiated time step solver and
/// non linear solver with a user defined callback instead of the
/// model itself /!\ This can mess up everything
// void solveStep(SolverCallback & callback, const ID & solver_id = "")
// override;
/* ------------------------------------------------------------------------ */
/* Mass matrix for solid mechanics model */
/* ------------------------------------------------------------------------ */
public:
/// assemble the lumped mass matrix
void assembleMassLumped();
/// assemble the mass matrix for consistent mass resolutions
void assembleMass();
protected:
/// assemble the lumped mass matrix for local and ghost elements
void assembleMassLumped(GhostType ghost_type);
/// assemble the mass matrix for either _ghost or _not_ghost elements
void assembleMass(GhostType ghost_type);
protected:
/* --------------------------------------------------------------------------
*/
TimeStepSolverType getDefaultSolverType() const override;
/* --------------------------------------------------------------------------
*/
ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
public:
bool isDefaultSolverExplicit() { return method == _explicit_lumped_mass; }
- /* ------------------------------------------------------------------------ */
-public:
- // DataAccessor<Element>
-
- UInt getNbData(const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/) const override {
- return 0;
- }
- void packData(CommunicationBuffer & /*buffer*/,
- const Array<Element> & /*element*/,
- const SynchronizationTag & /*tag*/) const override {}
- void unpackData(CommunicationBuffer & /*buffer*/,
- const Array<Element> & /*element*/,
- const SynchronizationTag & /*tag*/) override {}
-
- UInt getNbData(__attribute__((unused)) const Array<UInt> & indexes,
- __attribute__((unused))
- const SynchronizationTag & tag) const override {
- return 0;
- }
-
- void packData(__attribute__((unused)) CommunicationBuffer & buffer,
- __attribute__((unused)) const Array<UInt> & dofs,
- __attribute__((unused))
- const SynchronizationTag & tag) const override {}
-
- void unpackData(__attribute__((unused)) CommunicationBuffer & buffer,
- __attribute__((unused)) const Array<UInt> & dofs,
- __attribute__((unused))
- const SynchronizationTag & tag) override {}
-
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
FEEngine & getFEEngineBoundary(const ID & name = "") override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the solid mechanics model
AKANTU_GET_MACRO(SolidMechanicsModel, *solid, SolidMechanicsModel &);
/// get the contact mechanics model
AKANTU_GET_MACRO(PhaseFieldModel, *phase, PhaseFieldModel &);
/* ------------------------------------------------------------------------ */
/* Dumpable interface */
/* ------------------------------------------------------------------------ */
public:
std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createElementalField(const std::string & field_name,
const std::string & group_name, bool padding_flag,
- UInt spatial_dimension, ElementKind kind) override;
+ Int spatial_dimension, ElementKind kind) override;
void dump(const std::string & dumper_name) override;
-
- void dump(const std::string & dumper_name, UInt step) override;
-
- void dump(const std::string & dumper_name, Real time, UInt step) override;
+ void dump(const std::string & dumper_name, Int step) override;
+ void dump(const std::string & dumper_name, Real time, Int step) override;
void dump() override;
-
- void dump(UInt step) override;
-
- void dump(Real time, UInt step) override;
+ void dump(Int step) override;
+ void dump(Real time, Int step) override;
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
private:
/// solid mechanics model
SolidMechanicsModel * solid{nullptr};
/// phasefield model
PhaseFieldModel * phase{nullptr};
Array<Real> * displacement{nullptr};
///
Array<Real> * displacement_increment{nullptr};
/// external forces array
Array<Real> * external_force{nullptr};
};
} // namespace akantu
#endif /* __AKANTU_COUPLER_SOLID_PHASEFIELD_HH__ */
diff --git a/src/model/model_inline_impl.hh b/src/model/model_inline_impl.hh
index 1f1e8572c..52131adb0 100644
--- a/src/model/model_inline_impl.hh
+++ b/src/model/model_inline_impl.hh
@@ -1,177 +1,177 @@
/**
* @file model_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 25 2010
* @date last modification: Wed Mar 10 2021
*
* @brief inline implementation of the model class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MODEL_INLINE_IMPL_HH_
#define AKANTU_MODEL_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename FEEngineClass>
inline FEEngineClass & Model::getFEEngineClassBoundary(std::string name) {
if (name.empty()) {
name = default_fem;
}
auto it_boun = fems_boundary.find(name);
if (it_boun == fems_boundary.end()) {
AKANTU_DEBUG_INFO("Creating FEEngine boundary " << name);
auto it = fems.find(name);
if (it == fems.end()) {
AKANTU_EXCEPTION("The FEEngine " << name << " is not registered");
}
auto spatial_dimension = it->second->getElementDimension();
fems_boundary[name] = std::make_unique<FEEngineClass>(
it->second->getMesh(), spatial_dimension - 1,
id + ":fem_boundary:" + name);
}
return aka::as_type<FEEngineClass>(*fems_boundary[name]);
}
/* -------------------------------------------------------------------------- */
template <typename FEEngineClass>
inline FEEngineClass & Model::getFEEngineClass(std::string name) const {
if (name.empty()) {
name = default_fem;
}
auto it = fems.find(name);
if (it == fems.end()) {
AKANTU_EXCEPTION("The FEEngine " << name << " is not registered");
}
return aka::as_type<FEEngineClass>(*(it->second));
}
/* -------------------------------------------------------------------------- */
inline void Model::unRegisterFEEngineObject(const std::string & name) {
auto it = fems.find(name);
if (it == fems.end()) {
AKANTU_EXCEPTION("FEEngine object with name " << name << " was not found");
}
fems.erase(it);
if (not fems.empty() and default_fem == name) {
default_fem = (*fems.begin()).first;
}
}
/* -------------------------------------------------------------------------- */
template <typename FEEngineClass>
inline void Model::registerFEEngineObject(const std::string & name, Mesh & mesh,
- UInt spatial_dimension) {
+ Int spatial_dimension) {
if (fems.empty()) {
default_fem = name;
}
auto it = fems.find(name);
if (it != fems.end()) {
AKANTU_EXCEPTION("FEEngine object with name " << name
<< " was already created");
}
fems[name] = std::make_unique<FEEngineClass>(mesh, spatial_dimension,
id + ":fem:" + name);
}
/* -------------------------------------------------------------------------- */
inline FEEngine & Model::getFEEngine(const ID & name) const {
ID tmp_name = (name.empty()) ? default_fem : name;
auto it = fems.find(tmp_name);
if (it == fems.end()) {
AKANTU_EXCEPTION("The FEEngine " << tmp_name << " is not registered");
}
return *(it->second);
}
/* -------------------------------------------------------------------------- */
inline FEEngine & Model::getFEEngineBoundary(const ID & name) {
ID tmp_name = (name.empty()) ? default_fem : name;
auto it = fems_boundary.find(tmp_name);
if (it == fems_boundary.end()) {
AKANTU_EXCEPTION("The FEEngine boundary " << tmp_name
<< " is not registered");
}
AKANTU_DEBUG_ASSERT(it->second != nullptr, "The FEEngine boundary "
<< tmp_name
<< " was not created");
return *(it->second);
}
/* -------------------------------------------------------------------------- */
inline bool Model::hasFEEngineBoundary(const ID & name) {
ID tmp_name = (name.empty()) ? default_fem : name;
auto it = fems_boundary.find(tmp_name);
return (it != fems_boundary.end());
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Model::allocNodalField(std::unique_ptr<Array<T>> & array,
- UInt nb_component, const ID & name) const {
+ Int nb_component, const ID & name) const {
if (array) {
return;
}
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
array =
std::make_unique<Array<T>>(nb_nodes, nb_component, T(), id + ":" + name);
}
/* -------------------------------------------------------------------------- */
-inline UInt Model::getNbIntegrationPoints(const Array<Element> & elements,
+inline Int Model::getNbIntegrationPoints(const Array<Element> & elements,
const ID & fem_id) const {
- UInt nb_quad = 0;
+ Int nb_quad = 0;
for (auto && el : elements) {
nb_quad +=
getFEEngine(fem_id).getNbIntegrationPoints(el.type, el.ghost_type);
}
return nb_quad;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_MODEL_INLINE_IMPL_HH_ */
diff --git a/src/model/phase_field/phase_field_model.cc b/src/model/phase_field/phase_field_model.cc
index ae8ec98d6..26541d0b8 100644
--- a/src/model/phase_field/phase_field_model.cc
+++ b/src/model/phase_field/phase_field_model.cc
@@ -1,602 +1,594 @@
/**
* @file phase_field_model.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Tue Sep 04 2018
* @date last modification: Wed Jun 23 2021
*
* @brief Implementation of PhaseFieldModel class
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "phase_field_model.hh"
#include "dumpable_inline_impl.hh"
#include "element_synchronizer.hh"
#include "fe_engine_template.hh"
#include "generalized_trapezoidal.hh"
#include "group_manager_inline_impl.hh"
#include "integrator_gauss.hh"
#include "mesh.hh"
#include "parser.hh"
#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_element_partition.hh"
#include "dumper_elemental_field.hh"
#include "dumper_internal_material_field.hh"
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-PhaseFieldModel::PhaseFieldModel(Mesh & mesh, UInt dim, const ID & id,
+PhaseFieldModel::PhaseFieldModel(Mesh & mesh, Int dim, const ID & id,
ModelType model_type)
: Model(mesh, model_type, dim, id),
phasefield_index("phasefield index", id),
phasefield_local_numbering("phasefield local numbering", id) {
AKANTU_DEBUG_IN();
this->registerFEEngineObject<FEEngineType>("PhaseFieldFEEngine", mesh,
Model::spatial_dimension);
this->mesh.registerDumper<DumperParaview>("phase_field", id, true);
this->mesh.addDumpMesh(mesh, Model::spatial_dimension, _not_ghost,
_ek_regular);
phasefield_selector =
std::make_shared<DefaultPhaseFieldSelector>(phasefield_index);
this->initDOFManager();
this->registerDataAccessor(*this);
if (this->mesh.isDistributed()) {
auto & synchronizer = this->mesh.getElementSynchronizer();
this->registerSynchronizer(synchronizer, SynchronizationTag::_pfm_damage);
this->registerSynchronizer(synchronizer, SynchronizationTag::_pfm_driving);
this->registerSynchronizer(synchronizer, SynchronizationTag::_pfm_history);
this->registerSynchronizer(synchronizer, SynchronizationTag::_pfm_energy);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
PhaseFieldModel::~PhaseFieldModel() = default;
/* -------------------------------------------------------------------------- */
MatrixType PhaseFieldModel::getMatrixType(const ID & matrix_id) const {
if (matrix_id == "K") {
return _symmetric;
}
return _mt_not_defined;
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::initModel() {
auto & fem = this->getFEEngine();
fem.initShapeFunctions(_not_ghost);
fem.initShapeFunctions(_ghost);
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::initFullImpl(const ModelOptions & options) {
phasefield_index.initialize(mesh, _element_kind = _ek_not_defined,
_default_value = UInt(-1),
_with_nb_element = true);
phasefield_local_numbering.initialize(mesh, _element_kind = _ek_not_defined,
_with_nb_element = true);
Model::initFullImpl(options);
// initialize the phasefields
if (!this->parser.getLastParsedFile().empty()) {
this->instantiatePhaseFields();
this->initPhaseFields();
}
this->initBC(*this, *damage, *external_force);
}
/* -------------------------------------------------------------------------- */
PhaseField &
PhaseFieldModel::registerNewPhaseField(const ParserSection & section) {
std::string phase_name;
std::string phase_type = section.getName();
std::string opt_param = section.getOption();
try {
std::string tmp = section.getParameter("name");
phase_name = tmp; /** this can seam weird, but there is an ambiguous
* operator overload that i couldn't solve. @todo remove
* the weirdness of this code
*/
} catch (debug::Exception &) {
AKANTU_ERROR("A phasefield of type \'"
<< phase_type
<< "\' in the input file has been defined without a name!");
}
PhaseField & phase =
this->registerNewPhaseField(phase_name, phase_type, opt_param);
phase.parseSection(section);
return phase;
}
/* -------------------------------------------------------------------------- */
PhaseField & PhaseFieldModel::registerNewPhaseField(const ID & phase_name,
const ID & phase_type,
const ID & opt_param) {
AKANTU_DEBUG_ASSERT(phasefields_names_to_id.find(phase_name) ==
phasefields_names_to_id.end(),
"A phasefield with this name '"
<< phase_name << "' has already been registered. "
<< "Please use unique names for phasefields");
UInt phase_count = phasefields.size();
phasefields_names_to_id[phase_name] = phase_count;
std::stringstream sstr_phase;
sstr_phase << this->id << ":" << phase_count << ":" << phase_type;
ID mat_id = sstr_phase.str();
std::unique_ptr<PhaseField> phase = PhaseFieldFactory::getInstance().allocate(
phase_type, opt_param, *this, mat_id);
phasefields.push_back(std::move(phase));
return *(phasefields.back());
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::instantiatePhaseFields() {
ParserSection model_section;
bool is_empty;
std::tie(model_section, is_empty) = this->getParserSection();
if (not is_empty) {
auto model_phasefields =
model_section.getSubSections(ParserType::_phasefield);
for (const auto & section : model_phasefields) {
this->registerNewPhaseField(section);
}
}
auto sub_sections = this->parser.getSubSections(ParserType::_phasefield);
for (const auto & section : sub_sections) {
this->registerNewPhaseField(section);
}
if (phasefields.empty()) {
AKANTU_EXCEPTION("No phasefields where instantiated for the model"
<< getID());
}
are_phasefields_instantiated = true;
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::initPhaseFields() {
AKANTU_DEBUG_ASSERT(phasefields.size() != 0, "No phasefield to initialize !");
if (!are_phasefields_instantiated) {
instantiatePhaseFields();
}
this->assignPhaseFieldToElements();
for (auto & phasefield : phasefields) {
/// init internals properties
phasefield->initPhaseField();
}
this->synchronize(SynchronizationTag::_smm_init_mat);
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::assignPhaseFieldToElements(
- const ElementTypeMapArray<UInt> * filter) {
+ const ElementTypeMapArray<Idx> * filter) {
for_each_element(
mesh,
[&](auto && element) {
- UInt phase_index = (*phasefield_selector)(element);
+ Int phase_index = (*phasefield_selector)(element);
AKANTU_DEBUG_ASSERT(
- phase_index < phasefields.size(),
+ phase_index < Int(phasefields.size()),
"The phasefield selector returned an index that does not exists");
phasefield_index(element) = phase_index;
},
_element_filter = filter, _ghost_type = _not_ghost);
for_each_element(
mesh,
[&](auto && element) {
auto phase_index = phasefield_index(element);
auto index = phasefields[phase_index]->addElement(element);
phasefield_local_numbering(element) = index;
},
_element_filter = filter, _ghost_type = _not_ghost);
// synchronize the element phasefield arrays
this->synchronize(SynchronizationTag::_material_id);
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::assembleMatrix(const ID & matrix_id) {
if (matrix_id == "K") {
this->assembleStiffnessMatrix();
} else {
AKANTU_ERROR("Unknown Matrix ID for PhaseFieldModel : " << matrix_id);
}
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::predictor() {
// AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::corrector() {
// AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::initSolver(TimeStepSolverType time_step_solver_type,
NonLinearSolverType /*unused*/) {
DOFManager & dof_manager = this->getDOFManager();
this->allocNodalField(this->damage, 1, "damage");
this->allocNodalField(this->external_force, 1, "external_force");
this->allocNodalField(this->internal_force, 1, "internal_force");
this->allocNodalField(this->blocked_dofs, 1, "blocked_dofs");
this->allocNodalField(this->previous_damage, 1, "previous_damage");
if (!dof_manager.hasDOFs("damage")) {
dof_manager.registerDOFs("damage", *this->damage, _dst_nodal);
dof_manager.registerBlockedDOFs("damage", *this->blocked_dofs);
dof_manager.registerDOFsPrevious("damage", *this->previous_damage);
}
if (time_step_solver_type == TimeStepSolverType::_dynamic) {
AKANTU_TO_IMPLEMENT();
}
}
/* -------------------------------------------------------------------------- */
FEEngine & PhaseFieldModel::getFEEngineBoundary(const ID & name) {
return dynamic_cast<FEEngine &>(getFEEngineClassBoundary<FEEngineType>(name));
}
/* -------------------------------------------------------------------------- */
std::tuple<ID, TimeStepSolverType>
PhaseFieldModel::getDefaultSolverID(const AnalysisMethod & method) {
switch (method) {
case _explicit_lumped_mass: {
return std::make_tuple("explicit_lumped",
TimeStepSolverType::_dynamic_lumped);
}
case _explicit_consistent_mass: {
return std::make_tuple("explicit", TimeStepSolverType::_dynamic);
}
case _static: {
return std::make_tuple("static", TimeStepSolverType::_static);
}
case _implicit_dynamic: {
return std::make_tuple("implicit", TimeStepSolverType::_dynamic);
}
default:
return std::make_tuple("unknown", TimeStepSolverType::_not_defined);
}
}
/* -------------------------------------------------------------------------- */
ModelSolverOptions PhaseFieldModel::getDefaultSolverOptions(
const TimeStepSolverType & type) const {
ModelSolverOptions options;
switch (type) {
case TimeStepSolverType::_dynamic_lumped: {
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["damage"] =
IntegrationSchemeType::_central_difference;
options.solution_type["damage"] = IntegrationScheme::_acceleration;
break;
}
case TimeStepSolverType::_static: {
options.non_linear_solver_type = NonLinearSolverType::_linear;
options.integration_scheme_type["damage"] =
IntegrationSchemeType::_pseudo_time;
options.solution_type["damage"] = IntegrationScheme::_not_defined;
break;
}
case TimeStepSolverType::_dynamic: {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["damage"] =
IntegrationSchemeType::_backward_euler;
options.solution_type["damage"] = IntegrationScheme::_damage;
break;
}
default:
AKANTU_EXCEPTION(type << " is not a valid time step solver type");
}
return options;
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::beforeSolveStep() {
for (auto & phasefield : phasefields) {
phasefield->beforeSolveStep();
}
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::afterSolveStep(bool converged) {
if (not converged) {
return;
}
for (auto && values : zip(*damage, *previous_damage)) {
auto & dam = std::get<0>(values);
auto & prev_dam = std::get<1>(values);
dam -= prev_dam;
prev_dam = dam;
}
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::assembleStiffnessMatrix() {
AKANTU_DEBUG_INFO("Assemble the new stiffness matrix");
if (!this->getDOFManager().hasMatrix("K")) {
this->getDOFManager().getNewMatrix("K", getMatrixType("K"));
}
this->getDOFManager().zeroMatrix("K");
for (auto & phasefield : phasefields) {
phasefield->assembleStiffnessMatrix(_not_ghost);
}
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::assembleResidual() {
this->assembleInternalForces();
this->getDOFManager().assembleToResidual("damage", *this->external_force, 1);
this->getDOFManager().assembleToResidual("damage", *this->internal_force, 1);
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::assembleInternalForces() {
AKANTU_DEBUG_INFO("Assemble the internal forces");
this->internal_force->zero();
// communicate the driving forces
AKANTU_DEBUG_INFO("Send data for residual assembly");
this->asynchronousSynchronize(SynchronizationTag::_pfm_driving);
// assemble the forces due to local driving forces
AKANTU_DEBUG_INFO("Assemble residual for local elements");
for (auto & phasefield : phasefields) {
phasefield->assembleInternalForces(_not_ghost);
}
// finalize communications
AKANTU_DEBUG_INFO("Wait distant driving forces");
this->waitEndSynchronize(SynchronizationTag::_pfm_driving);
// assemble the residual due to ghost elements
AKANTU_DEBUG_INFO("Assemble residual for ghost elements");
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::assembleLumpedMatrix(const ID & /*matrix_id*/) {}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::setTimeStep(Real time_step, const ID & solver_id) {
Model::setTimeStep(time_step, solver_id);
this->mesh.getDumper("phase_field").setTimeStep(time_step);
}
/* -------------------------------------------------------------------------- */
-UInt PhaseFieldModel::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
- UInt size = 0;
- UInt nb_nodes_per_element = 0;
+Int PhaseFieldModel::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
+ Int size = 0;
+ Int nb_nodes_per_element = 0;
for (const Element & el : elements) {
nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
}
switch (tag) {
case SynchronizationTag::_pfm_damage: {
size += nb_nodes_per_element * sizeof(Real); // damage
break;
}
case SynchronizationTag::_pfm_driving: {
size += getNbIntegrationPoints(elements) * sizeof(Real);
break;
}
case SynchronizationTag::_pfm_history: {
size += getNbIntegrationPoints(elements) * sizeof(Real);
break;
}
case SynchronizationTag::_pfm_energy: {
size += getNbIntegrationPoints(elements) * sizeof(Real);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
return size;
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldModel::packData(__attribute__((unused))
- CommunicationBuffer & buffer,
- __attribute__((unused))
- const Array<Element> & elements,
- __attribute__((unused))
- const SynchronizationTag & tag) const {}
+void PhaseFieldModel::packData(CommunicationBuffer & /*buffer*/,
+ const Array<Element> & /*elements*/,
+ const SynchronizationTag & /*tag*/) const {}
/* -------------------------------------------------------------------------- */
-void PhaseFieldModel::unpackData(__attribute__((unused))
- CommunicationBuffer & buffer,
- __attribute__((unused))
- const Array<Element> & elements,
- __attribute__((unused))
- const SynchronizationTag & tag) {}
+void PhaseFieldModel::unpackData(CommunicationBuffer & /*buffer*/,
+ const Array<Element> & /*elements*/,
+ const SynchronizationTag & /*tag*/) {}
/* -------------------------------------------------------------------------- */
-UInt PhaseFieldModel::getNbData(const Array<UInt> & indexes,
- const SynchronizationTag & tag) const {
+Int PhaseFieldModel::getNbData(const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const {
UInt size = 0;
UInt nb_nodes = indexes.size();
switch (tag) {
case SynchronizationTag::_pfm_damage: {
size += nb_nodes * sizeof(Real);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
return size;
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::packData(CommunicationBuffer & buffer,
- const Array<UInt> & indexes,
+ const Array<Idx> & indexes,
const SynchronizationTag & tag) const {
for (auto index : indexes) {
switch (tag) {
case SynchronizationTag::_pfm_damage: {
buffer << (*damage)(index);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::unpackData(CommunicationBuffer & buffer,
- const Array<UInt> & indexes,
+ const Array<Idx> & indexes,
const SynchronizationTag & tag) {
for (auto index : indexes) {
switch (tag) {
case SynchronizationTag::_pfm_damage: {
buffer >> (*damage)(index);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
PhaseFieldModel::createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool /*unused*/) {
-
std::map<std::string, Array<bool> *> uint_nodal_fields;
uint_nodal_fields["blocked_dofs"] = blocked_dofs.get();
return mesh.createNodalField(uint_nodal_fields[field_name], group_name);
std::shared_ptr<dumpers::Field> field;
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
PhaseFieldModel::createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool /*unused*/) {
-
std::map<std::string, Array<Real> *> real_nodal_fields;
real_nodal_fields["damage"] = damage.get();
real_nodal_fields["external_force"] = external_force.get();
real_nodal_fields["internal_force"] = internal_force.get();
return mesh.createNodalField(real_nodal_fields[field_name], group_name);
std::shared_ptr<dumpers::Field> field;
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> PhaseFieldModel::createElementalField(
const std::string & field_name, const std::string & group_name,
- bool /*unused*/, UInt /*unused*/, ElementKind element_kind) {
+ bool /*unused*/, Int /*unused*/, ElementKind element_kind) {
if (field_name == "partitions") {
- return mesh.createElementalField<UInt, dumpers::ElementPartitionField>(
+ return mesh.createElementalField<Int, dumpers::ElementPartitionField>(
mesh.getConnectivities(), group_name, this->spatial_dimension,
element_kind);
}
std::shared_ptr<dumpers::Field> field;
return field;
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "Phase Field Model [" << std::endl;
stream << space << " + id : " << id << std::endl;
stream << space << " + spatial dimension : " << Model::spatial_dimension
<< std::endl;
stream << space << " + fem [" << std::endl;
getFEEngine().printself(stream, indent + 2);
stream << space << AKANTU_INDENT << "]" << std::endl;
stream << space << " + nodals information [" << std::endl;
damage->printself(stream, indent + 2);
external_force->printself(stream, indent + 2);
internal_force->printself(stream, indent + 2);
blocked_dofs->printself(stream, indent + 2);
stream << space << AKANTU_INDENT << "]" << std::endl;
stream << space << " + phasefield information [" << std::endl;
stream << space << AKANTU_INDENT << "]" << std::endl;
stream << space << "]" << std::endl;
}
} // namespace akantu
diff --git a/src/model/phase_field/phase_field_model.hh b/src/model/phase_field/phase_field_model.hh
index f14f7eeb4..03803b0aa 100644
--- a/src/model/phase_field/phase_field_model.hh
+++ b/src/model/phase_field/phase_field_model.hh
@@ -1,338 +1,338 @@
/**
* @file phase_field_model.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Tue Sep 04 2018
* @date last modification: Wed Jun 23 2021
*
* @brief Model class for Phase Field problem
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "boundary_condition.hh"
#include "data_accessor.hh"
#include "fe_engine.hh"
#include "model.hh"
/* -------------------------------------------------------------------------- */
#include <array>
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASE_FIELD_MODEL_HH__
#define __AKANTU_PHASE_FIELD_MODEL_HH__
namespace akantu {
class PhaseField;
class PhaseFieldSelector;
template <ElementKind kind, class IntegrationOrderFuntor> class IntegratorGauss;
template <ElementKind kind> class ShapeLagrange;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
class PhaseFieldModel : public Model,
public DataAccessor<Element>,
- public DataAccessor<UInt>,
+ public DataAccessor<Idx>,
public BoundaryCondition<PhaseFieldModel> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using FEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
- PhaseFieldModel(Mesh & mesh, UInt dim = _all_dimensions,
+ PhaseFieldModel(Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "phase_field_model",
ModelType model_type = ModelType::_phase_field_model);
~PhaseFieldModel() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// generic function to initialize everything ready for explicit dynamics
void initFullImpl(const ModelOptions & options) override;
/// initialize all internal array for phasefields
void initPhaseFields();
/// allocate all vectors
void initSolver(TimeStepSolverType /*unused*/,
NonLinearSolverType /*unused*/) override;
/// initialize the model
void initModel() override;
/// predictor
void predictor() override;
/// corrector
void corrector() override;
/// compute the heat flux
void assembleResidual() override;
/// get the type of matrix needed
MatrixType getMatrixType(const ID & /*unused*/) const override;
/// callback to assemble a Matrix
void assembleMatrix(const ID & /*unused*/) override;
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & /*unused*/) override;
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
/// function to print the containt of the class
void printself(std::ostream & stream, int indent = 0) const override;
/* ------------------------------------------------------------------------ */
/* Materials (phase_field_model.cc) */
/* ------------------------------------------------------------------------ */
public:
/// register an empty phasefield of a given type
PhaseField & registerNewPhaseField(const ID & phase_name,
const ID & phase_type,
const ID & opt_param);
/// reassigns phasefields depending on the phasefield selector
void reassignPhaseField();
protected:
/// register a phasefield in the dynamic database
PhaseField & registerNewPhaseField(const ParserSection & phase_section);
/// read the phasefield files to instantiate all the phasefields
void instantiatePhaseFields();
/// set the element_id_by_phasefield and add the elements to the good
/// phasefields
- void assignPhaseFieldToElements(
- const ElementTypeMapArray<UInt> * filter = nullptr);
+ void
+ assignPhaseFieldToElements(const ElementTypeMapArray<Idx> * filter = nullptr);
/* ------------------------------------------------------------------------ */
/* Methods for static */
/* ------------------------------------------------------------------------ */
public:
/// assembles the phasefield stiffness matrix
virtual void assembleStiffnessMatrix();
/// compute the internal forces
virtual void assembleInternalForces();
// compute the internal forces
- void assembleInternalForces(const GhostType & ghost_type);
+ void assembleInternalForces(GhostType ghost_type);
/* ------------------------------------------------------------------------ */
/* Methods for dynamic */
/* ------------------------------------------------------------------------ */
public:
/// set the stable timestep
void setTimeStep(Real time_step, const ID & solver_id = "") override;
protected:
/// callback for the solver, this is called at beginning of solve
void beforeSolveStep() override;
/// callback for the solver, this is called at end of solve
void afterSolveStep(bool converged = true) override;
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const override;
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) override;
- UInt getNbData(const Array<UInt> & indexes,
- const SynchronizationTag & tag) const override;
+ Int getNbData(const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const override;
- void packData(CommunicationBuffer & buffer, const Array<UInt> & indexes,
+ void packData(CommunicationBuffer & buffer, const Array<Idx> & indexes,
const SynchronizationTag & tag) const override;
- void unpackData(CommunicationBuffer & buffer, const Array<UInt> & indexes,
+ void unpackData(CommunicationBuffer & buffer, const Array<Idx> & indexes,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// return the damage array
AKANTU_GET_MACRO_DEREF_PTR(Damage, damage);
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Damage, damage);
/// get the PhaseFieldModel::internal_force vector (internal forces)
AKANTU_GET_MACRO_DEREF_PTR(InternalForce, internal_force);
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(InternalForce, internal_force);
/// get the PhaseFieldModel::external_force vector (external forces)
AKANTU_GET_MACRO_DEREF_PTR(ExternalForce, external_force);
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(ExternalForce, external_force);
/// get the PhaseFieldModel::force vector (external forces)
Array<Real> & getForce() {
AKANTU_DEBUG_WARNING("getForce was maintained for backward compatibility, "
"use getExternalForce instead");
return *external_force;
}
/// get the PhaseFieldModel::blocked_dofs vector
AKANTU_GET_MACRO_DEREF_PTR(BlockedDOFs, blocked_dofs);
/// get an iterable on the phasefields
inline decltype(auto) getPhaseFields();
/// get an iterable on the phasefields
inline decltype(auto) getPhaseFields() const;
/// get a particular phasefield (by phasefield index)
inline PhaseField & getPhaseField(UInt mat_index);
/// get a particular phasefield (by phasefield index)
inline const PhaseField & getPhaseField(UInt mat_index) const;
/// get a particular phasefield (by phasefield name)
inline PhaseField & getPhaseField(const std::string & name);
/// get a particular phasefield (by phasefield name)
inline const PhaseField & getPhaseField(const std::string & name) const;
/// get a particular phasefield id from is name
- inline UInt getPhaseFieldIndex(const std::string & name) const;
+ inline Int getPhaseFieldIndex(const std::string & name) const;
/// give the number of phasefields
- inline UInt getNbPhaseFields() const { return phasefields.size(); }
+ inline Int getNbPhaseFields() const { return phasefields.size(); }
/// give the phasefield internal index from its id
Int getInternalIndexFromID(const ID & id) const;
AKANTU_GET_MACRO(PhaseFieldByElement, phasefield_index,
- const ElementTypeMapArray<UInt> &);
+ const ElementTypeMapArray<Idx> &);
AKANTU_GET_MACRO(PhaseFieldLocalNumbering, phasefield_local_numbering,
- const ElementTypeMapArray<UInt> &);
+ const ElementTypeMapArray<Idx> &);
/// vectors containing local material element index for each global element
/// index
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PhaseFieldByElement, phasefield_index,
- UInt);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(PhaseFieldByElement, phasefield_index, UInt);
+ Idx);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE(PhaseFieldByElement, phasefield_index, Idx);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PhaseFieldLocalNumbering,
- phasefield_local_numbering, UInt);
+ phasefield_local_numbering, Idx);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE(PhaseFieldLocalNumbering,
- phasefield_local_numbering, UInt);
+ phasefield_local_numbering, Idx);
AKANTU_GET_MACRO_NOT_CONST(PhaseFieldSelector, *phasefield_selector,
PhaseFieldSelector &);
AKANTU_SET_MACRO(PhaseFieldSelector, phasefield_selector,
std::shared_ptr<PhaseFieldSelector>);
FEEngine & getFEEngineBoundary(const ID & name = "") override;
/* ------------------------------------------------------------------------ */
/* Dumpable Interface */
/* ------------------------------------------------------------------------ */
public:
std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createElementalField(const std::string & field_name,
const std::string & group_name, bool padding_flag,
- UInt spatial_dimension, ElementKind kind) override;
+ Int spatial_dimension, ElementKind kind) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// number of iterations
- UInt n_iter;
+ Int n_iter;
/// damage array
std::unique_ptr<Array<Real>> damage;
/// damage array at the previous time step
std::unique_ptr<Array<Real>> previous_damage;
/// boundary vector
std::unique_ptr<Array<bool>> blocked_dofs;
/// external force vector
std::unique_ptr<Array<Real>> external_force;
/// residuals array
std::unique_ptr<Array<Real>> internal_force;
/// Arrays containing the phasefield index for each element
- ElementTypeMapArray<UInt> phasefield_index;
+ ElementTypeMapArray<Idx> phasefield_index;
/// Arrays containing the position in the element filter of the phasefield
/// (phasefield's local numbering)
- ElementTypeMapArray<UInt> phasefield_local_numbering;
+ ElementTypeMapArray<Idx> phasefield_local_numbering;
/// class defining of to choose a phasefield
std::shared_ptr<PhaseFieldSelector> phasefield_selector;
/// mapping between phasefield name and phasefield internal id
- std::map<std::string, UInt> phasefields_names_to_id;
+ std::map<std::string, Idx> phasefields_names_to_id;
/// list of used phasefields
std::vector<std::unique_ptr<PhaseField>> phasefields;
/// tells if the phasefield are instantiated
bool are_phasefields_instantiated{false};
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "parser.hh"
#include "phasefield.hh"
#include "phase_field_model_inline_impl.cc"
/* -------------------------------------------------------------------------- */
#endif
diff --git a/src/model/phase_field/phase_field_model_inline_impl.cc b/src/model/phase_field/phase_field_model_inline_impl.cc
index 8d9288c1e..7a837123d 100644
--- a/src/model/phase_field/phase_field_model_inline_impl.cc
+++ b/src/model/phase_field/phase_field_model_inline_impl.cc
@@ -1,103 +1,101 @@
/**
* @file phase_field_model_inline_impl.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Fri Jun 19 2020
*
* @brief Phase field implementation of inline functions
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_named_argument.hh"
#include "phasefield_selector.hh"
#include "phasefield_selector_tmpl.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASE_FIELD_MODEL_INLINE_IMPL_CC__
#define __AKANTU_PHASE_FIELD_MODEL_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
inline decltype(auto) PhaseFieldModel::getPhaseFields() {
return make_dereference_adaptor(phasefields);
}
/* -------------------------------------------------------------------------- */
inline decltype(auto) PhaseFieldModel::getPhaseFields() const {
return make_dereference_adaptor(phasefields);
}
/* -------------------------------------------------------------------------- */
inline PhaseField & PhaseFieldModel::getPhaseField(UInt mat_index) {
AKANTU_DEBUG_ASSERT(mat_index < phasefields.size(),
"The model " << id << " has no phasefield no "
<< mat_index);
return *phasefields[mat_index];
}
/* -------------------------------------------------------------------------- */
inline const PhaseField & PhaseFieldModel::getPhaseField(UInt mat_index) const {
AKANTU_DEBUG_ASSERT(mat_index < phasefields.size(),
"The model " << id << " has no phasefield no "
<< mat_index);
return *phasefields[mat_index];
}
/* -------------------------------------------------------------------------- */
inline PhaseField & PhaseFieldModel::getPhaseField(const std::string & name) {
- std::map<std::string, UInt>::const_iterator it =
- phasefields_names_to_id.find(name);
+ auto it = phasefields_names_to_id.find(name);
AKANTU_DEBUG_ASSERT(it != phasefields_names_to_id.end(),
"The model " << id << " has no phasefield named "
<< name);
return *phasefields[it->second];
}
/* -------------------------------------------------------------------------- */
-inline UInt
-PhaseFieldModel::getPhaseFieldIndex(const std::string & name) const {
+inline Int PhaseFieldModel::getPhaseFieldIndex(const std::string & name) const {
auto it = phasefields_names_to_id.find(name);
AKANTU_DEBUG_ASSERT(it != phasefields_names_to_id.end(),
"The model " << id << " has no phasefield named "
<< name);
return it->second;
}
/* -------------------------------------------------------------------------- */
inline const PhaseField &
PhaseFieldModel::getPhaseField(const std::string & name) const {
auto it = phasefields_names_to_id.find(name);
AKANTU_DEBUG_ASSERT(it != phasefields_names_to_id.end(),
"The model " << id << " has no phasefield named "
<< name);
return *phasefields[it->second];
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* __AKANTU_PHASE_FIELD_MODEL_INLINE_IMPL_CC__ */
diff --git a/src/model/phase_field/phasefield.cc b/src/model/phase_field/phasefield.cc
index 30bb8005e..61302178f 100644
--- a/src/model/phase_field/phasefield.cc
+++ b/src/model/phase_field/phasefield.cc
@@ -1,301 +1,285 @@
/**
* @file phasefield.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 19 2020
* @date last modification: Fri May 14 2021
*
* @brief Implementation of the common part of the phasefield class
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "phasefield.hh"
#include "phase_field_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-PhaseField::PhaseField(PhaseFieldModel & model, const ID & id)
- : Parsable(ParserType::_phasefield, id), id(id), fem(model.getFEEngine()),
- model(model), spatial_dimension(this->model.getSpatialDimension()),
- g_c("g_c", *this), element_filter("element_filter", id),
- damage("damage", *this), phi("phi", *this), strain("strain", *this),
- driving_force("driving_force", *this),
- damage_energy("damage_energy", *this),
- damage_energy_density("damage_energy_density", *this) {
-
- AKANTU_DEBUG_IN();
-
- /// for each connectivity types allocate the element filer array of the
- /// material
- element_filter.initialize(model.getMesh(),
- _spatial_dimension = spatial_dimension,
- _element_kind = _ek_regular);
- this->initialize();
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-PhaseField::PhaseField(PhaseFieldModel & model, UInt dim, const Mesh & mesh,
+PhaseField::PhaseField(PhaseFieldModel & model, Int dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id)
: Parsable(ParserType::_phasefield, id), id(id), fem(fe_engine),
- model(model), spatial_dimension(this->model.getSpatialDimension()),
- g_c("g_c", *this), element_filter("element_filter", id),
+ model(model), g_c("g_c", *this),
+ spatial_dimension(this->model.getSpatialDimension()),
+ element_filter("element_filter", id),
damage("damage", *this, dim, fe_engine, this->element_filter),
phi("phi", *this, dim, fe_engine, this->element_filter),
strain("strain", *this, dim, fe_engine, this->element_filter),
driving_force("driving_force", *this, dim, fe_engine,
this->element_filter),
damage_energy("damage_energy", *this, dim, fe_engine,
this->element_filter),
damage_energy_density("damage_energy_density", *this, dim, fe_engine,
this->element_filter) {
AKANTU_DEBUG_IN();
/// for each connectivity types allocate the element filer array of the
/// material
element_filter.initialize(mesh, _spatial_dimension = spatial_dimension,
_element_kind = _ek_regular);
this->initialize();
AKANTU_DEBUG_OUT();
}
+/* -------------------------------------------------------------------------- */
+PhaseField::PhaseField(PhaseFieldModel & model, const ID & id)
+ : PhaseField(model, model.getSpatialDimension(), model.getMesh(),
+ model.getFEEngine(), id) {}
+
/* -------------------------------------------------------------------------- */
PhaseField::~PhaseField() = default;
/* -------------------------------------------------------------------------- */
void PhaseField::initialize() {
registerParam("name", name, std::string(), _pat_parsable | _pat_readable);
registerParam("l0", l0, Real(0.), _pat_parsable | _pat_readable,
"length scale parameter");
registerParam("gc", g_c, _pat_parsable | _pat_readable,
"critical local fracture energy density");
registerParam("E", E, _pat_parsable | _pat_readable, "Young's modulus");
registerParam("nu", nu, _pat_parsable | _pat_readable, "Poisson ratio");
damage.initialize(1);
phi.initialize(1);
driving_force.initialize(1);
g_c.initialize(1);
strain.initialize(spatial_dimension * spatial_dimension);
damage_energy_density.initialize(1);
damage_energy.initialize(spatial_dimension * spatial_dimension);
}
/* -------------------------------------------------------------------------- */
void PhaseField::initPhaseField() {
AKANTU_DEBUG_IN();
this->phi.initializeHistory();
this->resizeInternals();
updateInternalParameters();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::resizeInternals() {
AKANTU_DEBUG_IN();
for (auto it = internal_vectors_real.begin();
it != internal_vectors_real.end(); ++it) {
it->second->resize();
}
- for (auto it = internal_vectors_uint.begin();
- it != internal_vectors_uint.end(); ++it) {
+ for (auto it = internal_vectors_int.begin(); it != internal_vectors_int.end();
+ ++it) {
it->second->resize();
}
for (auto it = internal_vectors_bool.begin();
it != internal_vectors_bool.end(); ++it) {
it->second->resize();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::updateInternalParameters() {
this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
this->mu = this->E / (2 * (1 + this->nu));
}
/* -------------------------------------------------------------------------- */
void PhaseField::computeAllDrivingForces(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
for (const auto & type :
element_filter.elementTypes(spatial_dimension, ghost_type)) {
auto & elem_filter = element_filter(type, ghost_type);
if (elem_filter.empty()) {
continue;
}
computeDrivingForce(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::assembleInternalForces(GhostType ghost_type) {
AKANTU_DEBUG_IN();
Array<Real> & internal_force = model.getInternalForce();
for (auto type : element_filter.elementTypes(_ghost_type = ghost_type)) {
auto & elem_filter = element_filter(type, ghost_type);
if (elem_filter.empty()) {
continue;
}
auto nb_element = elem_filter.size();
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
Array<Real> nt_driving_force(nb_quadrature_points, nb_nodes_per_element);
fem.computeNtb(driving_force(type, ghost_type), nt_driving_force, type,
ghost_type, elem_filter);
Array<Real> int_nt_driving_force(nb_element, nb_nodes_per_element);
fem.integrate(nt_driving_force, int_nt_driving_force, nb_nodes_per_element,
type, ghost_type, elem_filter);
model.getDOFManager().assembleElementalArrayLocalArray(
int_nt_driving_force, internal_force, type, ghost_type, 1, elem_filter);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::assembleStiffnessMatrix(GhostType ghost_type) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the new stiffness matrix");
for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
auto & elem_filter = element_filter(type, ghost_type);
if (elem_filter.empty()) {
AKANTU_DEBUG_OUT();
return;
}
auto nb_element = elem_filter.size();
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
auto nt_b_n = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points,
nb_nodes_per_element * nb_nodes_per_element, "N^t*b*N");
auto bt_d_b = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points,
nb_nodes_per_element * nb_nodes_per_element, "B^t*D*B");
// damage_energy_density_on_qpoints = gc/l0 + phi = scalar
auto & damage_energy_density_vect = damage_energy_density(type, ghost_type);
// damage_energy_on_qpoints = gc*l0 = scalar
auto & damage_energy_vect = damage_energy(type, ghost_type);
fem.computeBtDB(damage_energy_vect, *bt_d_b, 2, type, ghost_type,
elem_filter);
fem.computeNtbN(damage_energy_density_vect, *nt_b_n, type, ghost_type,
elem_filter);
/// compute @f$ K_{\grad d} = \int_e \mathbf{N}^t * \mathbf{w} *
/// \mathbf{N}@f$
auto K_n = std::make_unique<Array<Real>>(
nb_element, nb_nodes_per_element * nb_nodes_per_element, "K_n");
fem.integrate(*nt_b_n, *K_n, nb_nodes_per_element * nb_nodes_per_element,
type, ghost_type, elem_filter);
model.getDOFManager().assembleElementalMatricesToMatrix(
"K", "damage", *K_n, type, _not_ghost, _symmetric, elem_filter);
/// compute @f$ K_{\grad d} = \int_e \mathbf{B}^t * \mathbf{W} *
/// \mathbf{B}@f$
auto K_b = std::make_unique<Array<Real>>(
nb_element, nb_nodes_per_element * nb_nodes_per_element, "K_b");
fem.integrate(*bt_d_b, *K_b, nb_nodes_per_element * nb_nodes_per_element,
type, ghost_type, elem_filter);
model.getDOFManager().assembleElementalMatricesToMatrix(
"K", "damage", *K_b, type, _not_ghost, _symmetric, elem_filter);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::beforeSolveStep() {
this->savePreviousState();
this->computeAllDrivingForces(_not_ghost);
}
/* -------------------------------------------------------------------------- */
void PhaseField::afterSolveStep() {}
/* -------------------------------------------------------------------------- */
void PhaseField::savePreviousState() {
AKANTU_DEBUG_IN();
for (auto pair : internal_vectors_real) {
if (pair.second->hasHistory()) {
pair.second->saveCurrentValues();
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
std::string type = getID().substr(getID().find_last_of(':') + 1);
stream << space << "PhaseField Material " << type << " [" << std::endl;
Parsable::printself(stream, indent);
stream << space << "]" << std::endl;
}
} // namespace akantu
diff --git a/src/model/phase_field/phasefield.hh b/src/model/phase_field/phasefield.hh
index e492e9c64..e4922c661 100644
--- a/src/model/phase_field/phasefield.hh
+++ b/src/model/phase_field/phasefield.hh
@@ -1,310 +1,309 @@
/**
* @file phasefield.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 19 2020
* @date last modification: Wed Jun 23 2021
*
* @brief Mother class for all phasefield laws
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_factory.hh"
#include "data_accessor.hh"
#include "parsable.hh"
#include "parser.hh"
/* -------------------------------------------------------------------------- */
#include "internal_field.hh"
#include "random_internal_field.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASEFIELD_HH__
#define __AKANTU_PHASEFIELD_HH__
/* -------------------------------------------------------------------------- */
namespace akantu {
class Model;
class PhaseFieldModel;
class PhaseField;
} // namespace akantu
namespace akantu {
template <typename T>
using InternalPhaseField = InternalFieldTmpl<PhaseField, T>;
template <>
inline void
ParameterTyped<RandomInternalField<Real, InternalPhaseField>>::setAuto(
const ParserParameter & in_param) {
Parameter::setAuto(in_param);
RandomParameter<Real> random_param = in_param;
param.setRandomDistribution(random_param);
}
using PhaseFieldFactory =
Factory<PhaseField, ID, const ID &, PhaseFieldModel &, const ID &>;
class PhaseField : public DataAccessor<Element>, public Parsable {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
PhaseField(const PhaseField & phase) = delete;
PhaseField & operator=(const PhaseField & phase) = delete;
/// Initialize phasefield with defaults
PhaseField(PhaseFieldModel & model, const ID & id = "");
/// Initialize phasefield with custom mesh & fe_engine
- PhaseField(PhaseFieldModel & model, UInt dim, const Mesh & mesh,
+ PhaseField(PhaseFieldModel & model, Int dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id = "");
/// Destructor
~PhaseField() override;
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
template <typename T>
void registerInternal(InternalPhaseField<T> & /*vect*/) {
AKANTU_TO_IMPLEMENT();
}
template <typename T>
void unregisterInternal(InternalPhaseField<T> & /*vect*/) {
AKANTU_TO_IMPLEMENT();
}
/// initialize the phasefield computed parameter
virtual void initPhaseField();
///
virtual void beforeSolveStep();
///
virtual void afterSolveStep();
/// assemble the residual for this phasefield
virtual void assembleInternalForces(GhostType ghost_type);
/// assemble the stiffness matrix for this phasefield
virtual void assembleStiffnessMatrix(GhostType ghost_type);
/// compute the driving force for this phasefield
virtual void computeAllDrivingForces(GhostType ghost_type = _not_ghost);
/// save the phi in the phi internal field if needed
virtual void savePreviousState();
/// add an element to the local mesh filter
- inline UInt addElement(const ElementType & type, UInt element,
- const GhostType & ghost_type);
+ inline UInt addElement(ElementType type, UInt element, GhostType ghost_type);
inline UInt addElement(const Element & element);
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override;
protected:
/// resize the internals arrrays
virtual void resizeInternals();
/// function called to updatet the internal parameters when the
/// modifiable parameters are modified
virtual void updateInternalParameters();
// constitutive law for driving force
- virtual void computeDrivingForce(const ElementType & /* el_type */,
+ virtual void computeDrivingForce(ElementType /* el_type */,
GhostType /* ghost_type */ = _not_ghost) {
AKANTU_TO_IMPLEMENT();
}
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
template <typename T>
inline void packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack,
CommunicationBuffer & buffer,
const Array<Element> & elements,
const ID & fem_id = ID()) const;
template <typename T>
inline void unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack,
CommunicationBuffer & buffer,
const Array<Element> & elements,
const ID & fem_id = ID());
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(Name, name, const std::string &);
AKANTU_GET_MACRO(Model, model, const PhaseFieldModel &)
AKANTU_GET_MACRO(ID, id, const ID &);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Strain, strain, Real);
AKANTU_GET_MACRO(Strain, strain, const ElementTypeMapArray<Real> &);
AKANTU_GET_MACRO_NOT_CONST(Strain, strain, ElementTypeMapArray<Real> &);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real);
AKANTU_GET_MACRO_NOT_CONST(Damage, damage, ElementTypeMapArray<Real> &);
AKANTU_GET_MACRO(Damage, damage, const ElementTypeMapArray<Real> &);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, Idx);
AKANTU_GET_MACRO(ElementFilter, element_filter,
- const ElementTypeMapArray<UInt> &);
+ const ElementTypeMapArray<Idx> &);
template <typename T>
const InternalPhaseField<T> & getInternal(const ID & id) const;
template <typename T> InternalPhaseField<T> & getInternal(const ID & id);
template <typename T>
- inline bool isInternal(const ID & id, const ElementKind & element_kind) const;
+ inline bool isInternal(const ID & id, ElementKind element_kind) const;
template <typename T> inline void setParam(const ID & param, T value);
inline const Parameter & getParam(const ID & param) const;
template <typename T>
void flattenInternal(const std::string & field_id,
ElementTypeMapArray<T> & internal_flat,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined) const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// boolean to know if the material has been initialized
bool is_init;
std::map<ID, InternalPhaseField<Real> *> internal_vectors_real;
- std::map<ID, InternalPhaseField<UInt> *> internal_vectors_uint;
+ std::map<ID, InternalPhaseField<UInt> *> internal_vectors_int;
std::map<ID, InternalPhaseField<bool> *> internal_vectors_bool;
protected:
ID id;
/// Link to the fem object in the model
FEEngine & fem;
/// phasefield name
std::string name;
/// The model to whch the phasefield belong
PhaseFieldModel & model;
/// length scale parameter
Real l0;
/// critical energy release rate
// Real g_c;
RandomInternalField<Real, InternalPhaseField> g_c;
/// Young's modulus
Real E;
/// Poisson ratio
Real nu;
/// Lame's first parameter
Real lambda;
/// Lame's second paramter
Real mu;
/// spatial dimension
- UInt spatial_dimension;
+ Int spatial_dimension;
/// list of element handled by the phasefield
- ElementTypeMapArray<UInt> element_filter;
+ ElementTypeMapArray<Idx> element_filter;
/// damage arrays ordered by element types
InternalPhaseField<Real> damage;
/// phi arrays ordered by element types
InternalPhaseField<Real> phi;
/// strain arrays ordered by element types
InternalPhaseField<Real> strain;
/// driving force ordered by element types
InternalPhaseField<Real> driving_force;
/// damage energy ordered by element types
InternalPhaseField<Real> damage_energy;
/// damage energy density ordered by element types
InternalPhaseField<Real> damage_energy_density;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const PhaseField & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "phasefield_inline_impl.cc"
#include "internal_field_tmpl.hh"
#include "random_internal_field_tmpl.hh"
/* -------------------------------------------------------------------------- */
#define PHASEFIELD_DEFAULT_ALLOCATOR(id, phase_name) \
[](const ID &, PhaseFieldModel & model, \
const ID & id) -> std::unique_ptr<PhaseField> { \
return std::make_unique<phase_name>(model, id); \
}
#define INSTANTIATE_PHASEFIELD(id, phase_name) \
- static bool phasefield_is_alocated_##id [[gnu::unused]] = \
+ static bool phasefield_is_allocated_##id [[gnu::unused]] = \
PhaseFieldFactory::getInstance().registerAllocator( \
#id, PHASEFIELD_DEFAULT_ALLOCATOR(id, phase_name))
#endif
diff --git a/src/model/phase_field/phasefield_inline_impl.cc b/src/model/phase_field/phasefield_inline_impl.cc
index f87db2f0d..7e8b4569e 100644
--- a/src/model/phase_field/phasefield_inline_impl.cc
+++ b/src/model/phase_field/phasefield_inline_impl.cc
@@ -1,163 +1,162 @@
/**
* @file phasefield_inline_impl.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 19 2020
* @date last modification: Fri Apr 02 2021
*
* @brief Phase field implementation of inline functions
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "phase_field_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASEFIELD_INLINE_IMPL_CC__
#define __AKANTU_PHASEFIELD_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt PhaseField::addElement(const ElementType & type, UInt element,
- const GhostType & ghost_type) {
- Array<UInt> & el_filter = this->element_filter(type, ghost_type);
+inline UInt PhaseField::addElement(ElementType type, UInt element,
+ GhostType ghost_type) {
+ auto & el_filter = this->element_filter(type, ghost_type);
el_filter.push_back(element);
return el_filter.size() - 1;
}
/* -------------------------------------------------------------------------- */
inline UInt PhaseField::addElement(const Element & element) {
return this->addElement(element.type, element.element, element.ghost_type);
}
/* -------------------------------------------------------------------------- */
template <>
inline void
PhaseField::registerInternal<Real>(InternalPhaseField<Real> & vect) {
internal_vectors_real[vect.getID()] = &vect;
}
template <>
inline void
PhaseField::registerInternal<UInt>(InternalPhaseField<UInt> & vect) {
- internal_vectors_uint[vect.getID()] = &vect;
+ internal_vectors_int[vect.getID()] = &vect;
}
template <>
inline void
PhaseField::registerInternal<bool>(InternalPhaseField<bool> & vect) {
internal_vectors_bool[vect.getID()] = &vect;
}
/* -------------------------------------------------------------------------- */
template <>
inline void
PhaseField::unregisterInternal<Real>(InternalPhaseField<Real> & vect) {
internal_vectors_real.erase(vect.getID());
}
template <>
inline void
PhaseField::unregisterInternal<UInt>(InternalPhaseField<UInt> & vect) {
- internal_vectors_uint.erase(vect.getID());
+ internal_vectors_int.erase(vect.getID());
}
template <>
inline void
PhaseField::unregisterInternal<bool>(InternalPhaseField<bool> & vect) {
internal_vectors_bool.erase(vect.getID());
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline bool PhaseField::isInternal(__attribute__((unused)) const ID & id,
__attribute__((unused))
- const ElementKind & element_kind) const {
+ ElementKind element_kind) const {
AKANTU_TO_IMPLEMENT();
}
template <>
-inline bool
-PhaseField::isInternal<Real>(const ID & id,
- const ElementKind & element_kind) const {
+inline bool PhaseField::isInternal<Real>(const ID & id,
+ ElementKind element_kind) const {
auto internal_array = internal_vectors_real.find(this->getID() + ":" + id);
return !(internal_array == internal_vectors_real.end() ||
internal_array->second->getElementKind() != element_kind);
}
/* -------------------------------------------------------------------------- */
-inline UInt PhaseField::getNbData(__attribute__((unused))
- const Array<Element> & elements,
- __attribute__((unused))
- const SynchronizationTag & tag) const {
+inline Int PhaseField::getNbData(__attribute__((unused))
+ const Array<Element> & elements,
+ __attribute__((unused))
+ const SynchronizationTag & tag) const {
return 0;
}
/* -------------------------------------------------------------------------- */
inline void PhaseField::packData(__attribute__((unused))
CommunicationBuffer & buffer,
__attribute__((unused))
const Array<Element> & elements,
__attribute__((unused))
const SynchronizationTag & tag) const {}
/* -------------------------------------------------------------------------- */
inline void
PhaseField::unpackData(__attribute__((unused)) CommunicationBuffer & buffer,
__attribute__((unused)) const Array<Element> & elements,
__attribute__((unused)) const SynchronizationTag & tag) {
}
/* -------------------------------------------------------------------------- */
inline const Parameter & PhaseField::getParam(const ID & param) const {
try {
return get(param);
} catch (...) {
AKANTU_EXCEPTION("No parameter " << param << " in the material "
<< getID());
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void PhaseField::packElementDataHelper(
const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
const Array<Element> & elements, const ID & fem_id) const {
DataAccessor::packElementalDataHelper<T>(data_to_pack, buffer, elements, true,
model.getFEEngine(fem_id));
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void PhaseField::unpackElementDataHelper(
ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer,
const Array<Element> & elements, const ID & fem_id) {
DataAccessor::unpackElementalDataHelper<T>(data_to_unpack, buffer, elements,
true, model.getFEEngine(fem_id));
}
} // namespace akantu
#endif
diff --git a/src/model/phase_field/phasefield_selector.hh b/src/model/phase_field/phasefield_selector.hh
index a681b72d4..85632fb79 100644
--- a/src/model/phase_field/phasefield_selector.hh
+++ b/src/model/phase_field/phasefield_selector.hh
@@ -1,169 +1,169 @@
/**
* @file phasefield_selector.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri May 14 2021
*
* @brief class describing how to choose a phasefield variable
* function for a given element
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <memory>
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASEFIELD_SELECTOR_HH__
#define __AKANTU_PHASEFIELD_SELECTOR_HH__
namespace akantu {
class PhaseFieldModel;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* main class to assign same or different phasefield constitutive laws to
* different elements
*/
class PhaseFieldSelector
: public std::enable_shared_from_this<PhaseFieldSelector> {
public:
PhaseFieldSelector() = default;
virtual ~PhaseFieldSelector() = default;
- virtual inline UInt operator()(const Element & element) {
+ virtual inline Idx operator()(const Element & element) {
if (fallback_selector) {
return (*fallback_selector)(element);
}
return fallback_value;
}
- inline void setFallback(UInt f) { fallback_value = f; }
+ inline void setFallback(Idx f) { fallback_value = f; }
inline void
setFallback(const std::shared_ptr<PhaseFieldSelector> & fallback_selector) {
this->fallback_selector = fallback_selector;
}
inline void setFallback(PhaseFieldSelector & fallback_selector) {
this->fallback_selector = fallback_selector.shared_from_this();
}
inline std::shared_ptr<PhaseFieldSelector> & getFallbackSelector() {
return this->fallback_selector;
}
- inline UInt getFallbackValue() const { return this->fallback_value; }
+ inline Idx getFallbackValue() const { return this->fallback_value; }
protected:
UInt fallback_value{0};
std::shared_ptr<PhaseFieldSelector> fallback_selector;
};
/* -------------------------------------------------------------------------- */
/**
* class that assigns the first phasefield to regular elements by default
*/
class DefaultPhaseFieldSelector : public PhaseFieldSelector {
public:
explicit DefaultPhaseFieldSelector(
- const ElementTypeMapArray<UInt> & phasefield_index)
+ const ElementTypeMapArray<Idx> & phasefield_index)
: phasefield_index(phasefield_index) {}
- UInt operator()(const Element & element) override {
+ Idx operator()(const Element & element) override {
if (not phasefield_index.exists(element.type, element.ghost_type)) {
return PhaseFieldSelector::operator()(element);
}
const auto & phase_indexes =
phasefield_index(element.type, element.ghost_type);
if (element.element < phase_indexes.size()) {
auto && tmp_phase = phase_indexes(element.element);
- if (tmp_phase != UInt(-1)) {
+ if (tmp_phase != -1) {
return tmp_phase;
}
}
return PhaseFieldSelector::operator()(element);
}
private:
- const ElementTypeMapArray<UInt> & phasefield_index;
+ const ElementTypeMapArray<Idx> & phasefield_index;
};
/* -------------------------------------------------------------------------- */
/**
* Use elemental data to assign phasefields
*/
template <typename T>
class ElementDataPhaseFieldSelector : public PhaseFieldSelector {
public:
ElementDataPhaseFieldSelector(const ElementTypeMapArray<T> & element_data,
const PhaseFieldModel & model,
- UInt first_index = 1)
+ Idx first_index = 1)
: element_data(element_data), model(model), first_index(first_index) {}
inline T elementData(const Element & element) {
DebugLevel dbl = debug::getDebugLevel();
debug::setDebugLevel(dblError);
T data = element_data(element.type, element.ghost_type)(element.element);
debug::setDebugLevel(dbl);
return data;
}
- inline UInt operator()(const Element & element) override {
+ inline Idx operator()(const Element & element) override {
return PhaseFieldSelector::operator()(element);
}
protected:
/// list of element with the specified data (i.e. tag value)
const ElementTypeMapArray<T> & element_data;
/// the model that the materials belong
const PhaseFieldModel & model;
/// first phasefield index: equal to 1 if none specified
UInt first_index;
};
/* -------------------------------------------------------------------------- */
/**
* class to use mesh data information to assign different phasefields
* where name is the tag value: tag_0, tag_1
*/
template <typename T>
class MeshDataPhaseFieldSelector : public ElementDataPhaseFieldSelector<T> {
public:
MeshDataPhaseFieldSelector(const std::string & name,
const PhaseFieldModel & model,
- UInt first_index = 1);
+ Idx first_index = 1);
};
} // namespace akantu
#endif /* __AKANTU_PHASEFIELD_SELECTOR_HH__ */
diff --git a/src/model/phase_field/phasefield_selector_tmpl.hh b/src/model/phase_field/phasefield_selector_tmpl.hh
index 116d2a192..a3d6397d5 100644
--- a/src/model/phase_field/phasefield_selector_tmpl.hh
+++ b/src/model/phase_field/phasefield_selector_tmpl.hh
@@ -1,73 +1,73 @@
/**
* @file phasefield_selector_tmpl.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri Jun 19 2020
*
* @brief Implementation of the template PhaseFieldSelector
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "phasefield_selector.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASEFIELD_SELECTOR_TMPL_HH__
#define __AKANTU_PHASEFIELD_SELECTOR_TMPL_HH__
namespace akantu {
/* -------------------------------------------------------------------------- */
template <>
-inline UInt ElementDataPhaseFieldSelector<std::string>::operator()(
+inline Idx ElementDataPhaseFieldSelector<std::string>::operator()(
const Element & element) {
try {
std::string material_name = this->elementData(element);
return model.getPhaseFieldIndex(material_name);
} catch (...) {
return PhaseFieldSelector::operator()(element);
}
}
/* -------------------------------------------------------------------------- */
template <>
-inline UInt
-ElementDataPhaseFieldSelector<UInt>::operator()(const Element & element) {
+inline Idx
+ElementDataPhaseFieldSelector<Idx>::operator()(const Element & element) {
try {
return this->elementData(element) - first_index;
} catch (...) {
return PhaseFieldSelector::operator()(element);
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
MeshDataPhaseFieldSelector<T>::MeshDataPhaseFieldSelector(
- const std::string & name, const PhaseFieldModel & model, UInt first_index)
+ const std::string & name, const PhaseFieldModel & model, Idx first_index)
: ElementDataPhaseFieldSelector<T>(model.getMesh().getData<T>(name), model,
first_index) {}
} // namespace akantu
#endif /* __AKANTU_PHASEFIELD_SELECTOR_TMPL_HH__ */
diff --git a/src/model/phase_field/phasefields/phasefield_exponential.cc b/src/model/phase_field/phasefields/phasefield_exponential.cc
index 11f3a62eb..5d428cc66 100644
--- a/src/model/phase_field/phasefields/phasefield_exponential.cc
+++ b/src/model/phase_field/phasefields/phasefield_exponential.cc
@@ -1,82 +1,82 @@
/**
* @file phasefield_exponential.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 19 2020
* @date last modification: Wed Jun 23 2021
*
* @brief Specialization of the phasefield law class for exponential type
* law
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "phasefield_exponential.hh"
#include "aka_common.hh"
#include <tuple>
namespace akantu {
/* -------------------------------------------------------------------------- */
PhaseFieldExponential::PhaseFieldExponential(PhaseFieldModel & model,
const ID & id)
: PhaseField(model, id) {}
/* -------------------------------------------------------------------------- */
void PhaseFieldExponential::updateInternalParameters() {
PhaseField::updateInternalParameters();
for (const auto & type :
element_filter.elementTypes(spatial_dimension, _not_ghost)) {
for (auto && tuple : zip(make_view(this->damage_energy(type, _not_ghost),
spatial_dimension, spatial_dimension),
this->g_c(type, _not_ghost))) {
- Matrix<Real> d(spatial_dimension, spatial_dimension);
- // eye g_c * l0
- d.eye(std::get<1>(tuple) * this->l0);
+ Matrix<Real> d =
+ Matrix<Real>::Identity(spatial_dimension, spatial_dimension) *
+ std::get<1>(tuple) * this->l0;
std::get<0>(tuple) = d;
}
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldExponential::computeDrivingForce(const ElementType & el_type,
+void PhaseFieldExponential::computeDrivingForce(ElementType el_type,
GhostType ghost_type) {
for (auto && tuple : zip(this->phi(el_type, ghost_type),
this->phi.previous(el_type, ghost_type),
this->driving_force(el_type, ghost_type),
this->damage_energy_density(el_type, ghost_type),
make_view(this->strain(el_type, ghost_type),
spatial_dimension, spatial_dimension),
this->g_c(el_type, ghost_type))) {
computePhiOnQuad(std::get<4>(tuple), std::get<0>(tuple),
std::get<1>(tuple));
computeDamageEnergyDensityOnQuad(std::get<0>(tuple), std::get<3>(tuple),
std::get<5>(tuple));
computeDrivingForceOnQuad(std::get<0>(tuple), std::get<2>(tuple));
}
}
INSTANTIATE_PHASEFIELD(exponential, PhaseFieldExponential);
} // namespace akantu
diff --git a/src/model/phase_field/phasefields/phasefield_exponential.hh b/src/model/phase_field/phasefields/phasefield_exponential.hh
index 3c6f8eac7..99cef22c4 100644
--- a/src/model/phase_field/phasefields/phasefield_exponential.hh
+++ b/src/model/phase_field/phasefields/phasefield_exponential.hh
@@ -1,75 +1,76 @@
/**
* @file phasefield_exponential.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 19 2020
* @date last modification: Wed Jun 23 2021
*
* @brief Phasefield law for approximating discrete crack as an exponential
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "phasefield.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASEFIELD_EXPONENTIAL_HH__
#define __AKANTU_PHASEFIELD_EXPONENTIAL_HH__
namespace akantu {
class PhaseFieldExponential : public PhaseField {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
PhaseFieldExponential(PhaseFieldModel & model, const ID & id = "");
~PhaseFieldExponential() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
void computePhiOnQuad(const Matrix<Real> & /*strain_quad*/,
Real & /*phi_quad*/, Real & /*phi_hist_quad*/);
- void computeDrivingForce(const ElementType & /*el_type*/,
+ void computeDrivingForce(ElementType /*el_type*/,
GhostType /*ghost_type*/) override;
inline void computeDrivingForceOnQuad(const Real & /*phi_quad*/,
Real & /*driving_force_quad*/);
inline void computeDamageEnergyDensityOnQuad(const Real & /*phi_quad*/,
- Real & /*dam_energy_quad*/, const Real & /*g_c_quad*/);
+ Real & /*dam_energy_quad*/,
+ const Real & /*g_c_quad*/);
public:
void updateInternalParameters() override;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "phasefield_exponential_inline_impl.hh"
#endif
diff --git a/src/model/phase_field/phasefields/phasefield_exponential_inline_impl.hh b/src/model/phase_field/phasefields/phasefield_exponential_inline_impl.hh
index 3287929f8..2187170fc 100644
--- a/src/model/phase_field/phasefields/phasefield_exponential_inline_impl.hh
+++ b/src/model/phase_field/phasefields/phasefield_exponential_inline_impl.hh
@@ -1,74 +1,71 @@
#include "phasefield_exponential.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
inline void
PhaseFieldExponential::computeDrivingForceOnQuad(const Real & phi_quad,
Real & driving_force_quad) {
driving_force_quad = 2.0 * phi_quad;
}
/* -------------------------------------------------------------------------- */
inline void PhaseFieldExponential::computeDamageEnergyDensityOnQuad(
const Real & phi_quad, Real & dam_energy_quad, const Real & g_c_quad) {
dam_energy_quad = 2.0 * phi_quad + g_c_quad / this->l0;
}
/* -------------------------------------------------------------------------- */
inline void
PhaseFieldExponential::computePhiOnQuad(const Matrix<Real> & strain_quad,
Real & phi_quad, Real & phi_hist_quad) {
-
Matrix<Real> strain_plus(spatial_dimension, spatial_dimension);
Matrix<Real> strain_minus(spatial_dimension, spatial_dimension);
Matrix<Real> strain_dir(spatial_dimension, spatial_dimension);
Matrix<Real> strain_diag_plus(spatial_dimension, spatial_dimension);
Matrix<Real> strain_diag_minus(spatial_dimension, spatial_dimension);
Vector<Real> strain_values(spatial_dimension);
Real trace_plus, trace_minus;
strain_plus.zero();
strain_minus.zero();
strain_dir.zero();
strain_values.zero();
strain_diag_plus.zero();
strain_diag_minus.zero();
strain_quad.eig(strain_values, strain_dir);
- for (UInt i = 0; i < spatial_dimension; i++) {
+ for (Int i = 0; i < spatial_dimension; i++) {
strain_diag_plus(i, i) = std::max(Real(0.), strain_values(i));
strain_diag_minus(i, i) = std::min(Real(0.), strain_values(i));
}
Matrix<Real> mat_tmp(spatial_dimension, spatial_dimension);
Matrix<Real> sigma_plus(spatial_dimension, spatial_dimension);
Matrix<Real> sigma_minus(spatial_dimension, spatial_dimension);
- mat_tmp.mul<false, true>(strain_diag_plus, strain_dir);
- strain_plus.mul<false, false>(strain_dir, mat_tmp);
- mat_tmp.mul<false, true>(strain_diag_minus, strain_dir);
- strain_minus.mul<false, true>(strain_dir, mat_tmp);
+ strain_plus = strain_dir * strain_diag_plus * strain_dir.transpose();
+ strain_minus = strain_dir * strain_diag_minus * strain_dir.transpose();
trace_plus = std::max(Real(0.), strain_quad.trace());
trace_minus = std::min(Real(0.), strain_quad.trace());
- for (UInt i = 0; i < spatial_dimension; i++) {
- for (UInt j = 0; j < spatial_dimension; j++) {
- sigma_plus(i, j) = static_cast<double>(i == j) * lambda * trace_plus +
+ for (Int i = 0; i < spatial_dimension; i++) {
+ for (Int j = 0; j < spatial_dimension; j++) {
+ sigma_plus(i, j) = static_cast<Real>(i == j) * lambda * trace_plus +
2 * mu * strain_plus(i, j);
- sigma_minus(i, j) = static_cast<double>(i == j) * lambda * trace_minus +
+ sigma_minus(i, j) = static_cast<Real>(i == j) * lambda * trace_minus +
2 * mu * strain_minus(i, j);
}
}
- phi_quad = 0.5 * sigma_plus.doubleDot(strain_plus);
+ phi_quad = sigma_plus.doubleDot(strain_plus) / 2.;
if (phi_quad < phi_hist_quad) {
phi_quad = phi_hist_quad;
}
}
-} //namespace akantu
+} // namespace akantu
diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc
index 24fba5e36..22a6d65b8 100644
--- a/src/model/solid_mechanics/material.cc
+++ b/src/model/solid_mechanics/material.cc
@@ -1,1219 +1,1147 @@
/**
* @file material.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Jul 27 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of the common part of the material class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material.hh"
#include "mesh_iterators.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
Material::Material(SolidMechanicsModel & model, const ID & id)
: Parsable(ParserType::_material, id), id(id), fem(model.getFEEngine()),
model(model), spatial_dimension(this->model.getSpatialDimension()),
element_filter("element_filter", id), stress("stress", *this),
eigengradu("eigen_grad_u", *this), gradu("grad_u", *this),
green_strain("green_strain", *this),
piola_kirchhoff_2("piola_kirchhoff_2", *this),
potential_energy("potential_energy", *this),
interpolation_inverse_coordinates("interpolation inverse coordinates",
*this),
interpolation_points_matrices("interpolation points matrices", *this),
- eigen_grad_u(model.getSpatialDimension(), model.getSpatialDimension(),
- 0.) {
- AKANTU_DEBUG_IN();
+ eigen_grad_u(model.getSpatialDimension(), model.getSpatialDimension()) {
+ eigen_grad_u.fill(0.);
this->registerParam("eigen_grad_u", eigen_grad_u, _pat_parsable,
"EigenGradU");
/// for each connectivity types allocate the element filer array of the
/// material
element_filter.initialize(model.getMesh(),
_spatial_dimension = spatial_dimension,
_element_kind = _ek_regular);
this->initialize();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Material::Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
+Material::Material(SolidMechanicsModel & model, Int dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id)
: Parsable(ParserType::_material, id), id(id), fem(fe_engine), model(model),
spatial_dimension(dim), element_filter("element_filter", id),
stress("stress", *this, dim, fe_engine, this->element_filter),
eigengradu("eigen_grad_u", *this, dim, fe_engine, this->element_filter),
gradu("gradu", *this, dim, fe_engine, this->element_filter),
green_strain("green_strain", *this, dim, fe_engine, this->element_filter),
piola_kirchhoff_2("piola_kirchhoff_2", *this, dim, fe_engine,
this->element_filter),
potential_energy("potential_energy", *this, dim, fe_engine,
this->element_filter),
interpolation_inverse_coordinates("interpolation inverse_coordinates",
*this, dim, fe_engine,
this->element_filter),
interpolation_points_matrices("interpolation points matrices", *this, dim,
fe_engine, this->element_filter),
- eigen_grad_u(dim, dim, 0.) {
-
- AKANTU_DEBUG_IN();
+ eigen_grad_u(dim, dim) {
+ eigen_grad_u.fill(0.);
element_filter.initialize(mesh, _spatial_dimension = spatial_dimension,
_element_kind = _ek_regular);
this->initialize();
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Material::~Material() = default;
/* -------------------------------------------------------------------------- */
void Material::initialize() {
registerParam("rho", rho, Real(0.), _pat_parsable | _pat_modifiable,
"Density");
registerParam("name", name, std::string(), _pat_parsable | _pat_readable);
registerParam("finite_deformation", finite_deformation, false,
_pat_parsable | _pat_readable, "Is finite deformation");
registerParam("inelastic_deformation", inelastic_deformation, false,
_pat_internal, "Is inelastic deformation");
/// allocate gradu stress for local elements
eigengradu.initialize(spatial_dimension * spatial_dimension);
gradu.initialize(spatial_dimension * spatial_dimension);
stress.initialize(spatial_dimension * spatial_dimension);
potential_energy.initialize(1);
this->model.registerEventHandler(*this);
}
/* -------------------------------------------------------------------------- */
void Material::initMaterial() {
AKANTU_DEBUG_IN();
if (finite_deformation) {
this->piola_kirchhoff_2.initialize(spatial_dimension * spatial_dimension);
- if (use_previous_stress) {
- this->piola_kirchhoff_2.initializeHistory();
- }
+ this->piola_kirchhoff_2.initializeHistory();
this->green_strain.initialize(spatial_dimension * spatial_dimension);
}
- if (use_previous_stress) {
- this->stress.initializeHistory();
- }
- if (use_previous_gradu) {
- this->gradu.initializeHistory();
- }
+ this->stress.initializeHistory();
+ this->gradu.initializeHistory();
this->resizeInternals();
auto dim = spatial_dimension;
for (const auto & type :
element_filter.elementTypes(_element_kind = _ek_regular)) {
for (auto & eigen_gradu : make_view(eigengradu(type), dim, dim)) {
eigen_gradu = eigen_grad_u;
}
}
is_init = true;
updateInternalParameters();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::savePreviousState() {
AKANTU_DEBUG_IN();
for (auto pair : internal_vectors_real) {
if (pair.second->hasHistory()) {
pair.second->saveCurrentValues();
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::restorePreviousState() {
AKANTU_DEBUG_IN();
for (auto pair : internal_vectors_real) {
if (pair.second->hasHistory()) {
pair.second->restorePreviousValues();
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Compute the internal forces by assembling @f$\int_{e} \sigma_e \frac{\partial
* \varphi}{\partial X} dX @f$
*
* @param[in] ghost_type compute the internal forces for _ghost or _not_ghost
* element
*/
void Material::assembleInternalForces(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
- if (!finite_deformation) {
+ tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) {
+ constexpr auto dim = aka::decay_v<decltype(_)>;
- auto & internal_force = const_cast<Array<Real> &>(model.getInternalForce());
-
- // Mesh & mesh = fem.getMesh();
- for (auto && type :
- element_filter.elementTypes(spatial_dimension, ghost_type)) {
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
- UInt nb_element = elem_filter.size();
-
- if (nb_element == 0) {
- continue;
- }
-
- const Array<Real> & shapes_derivatives =
- fem.getShapesDerivatives(type, ghost_type);
-
- UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
- UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
-
- /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by
- /// @f$\mathbf{B}^t \mathbf{\sigma}_q@f$
- auto * sigma_dphi_dx =
- new Array<Real>(nb_element * nb_quadrature_points,
- size_of_shapes_derivatives, "sigma_x_dphi_/_dX");
-
- fem.computeBtD(stress(type, ghost_type), *sigma_dphi_dx, type, ghost_type,
- elem_filter);
-
- /**
- * compute @f$\int \sigma * \frac{\partial \varphi}{\partial X}dX@f$ by
- * @f$ \sum_q \mathbf{B}^t
- * \mathbf{\sigma}_q \overline w_q J_q@f$
- */
- auto * int_sigma_dphi_dx =
- new Array<Real>(nb_element, nb_nodes_per_element * spatial_dimension,
- "int_sigma_x_dphi_/_dX");
-
- fem.integrate(*sigma_dphi_dx, *int_sigma_dphi_dx,
- size_of_shapes_derivatives, type, ghost_type, elem_filter);
- delete sigma_dphi_dx;
-
- /// assemble
- model.getDOFManager().assembleElementalArrayLocalArray(
- *int_sigma_dphi_dx, internal_force, type, ghost_type, -1,
- elem_filter);
- delete int_sigma_dphi_dx;
- }
- } else {
- switch (spatial_dimension) {
- case 1:
- this->assembleInternalForces<1>(ghost_type);
- break;
- case 2:
- this->assembleInternalForces<2>(ghost_type);
- break;
- case 3:
- this->assembleInternalForces<3>(ghost_type);
- break;
- }
- }
+ for (auto && type :
+ element_filter.elementTypes(spatial_dimension, ghost_type)) {
+ if (not finite_deformation) {
+ this->assembleInternalForces<dim>(type, ghost_type);
+ } else {
+ this->assembleInternalForcesFiniteDeformation<dim>(type,
+ ghost_type);
+ }
+ }
+ },
+ spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Compute the stress from the gradu
*
* @param[in] ghost_type compute the residual for _ghost or _not_ghost element
*/
void Material::computeAllStresses(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ auto spatial_dimension = model.getSpatialDimension();
for (const auto & type :
element_filter.elementTypes(spatial_dimension, ghost_type)) {
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
+ auto & elem_filter = element_filter(type, ghost_type);
if (elem_filter.empty()) {
continue;
}
- Array<Real> & gradu_vect = gradu(type, ghost_type);
+ auto & gradu_vect = gradu(type, ghost_type);
/// compute @f$\nabla u@f$
fem.gradientOnIntegrationPoints(model.getDisplacement(), gradu_vect,
spatial_dimension, type, ghost_type,
elem_filter);
gradu_vect -= eigengradu(type, ghost_type);
/// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$
computeStress(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::computeAllCauchyStresses(GhostType ghost_type) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(finite_deformation, "The Cauchy stress can only be "
"computed if you are working in "
"finite deformation.");
for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
- switch (spatial_dimension) {
- case 1:
- this->StoCauchy<1>(type, ghost_type);
- break;
- case 2:
- this->StoCauchy<2>(type, ghost_type);
- break;
- case 3:
- this->StoCauchy<3>(type, ghost_type);
- break;
- }
+ tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) {
+ constexpr auto dim = aka::decay_v<decltype(_)>;
+ this->StoCauchy<dim>(type, ghost_type);
+ },
+ spatial_dimension);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void Material::StoCauchy(ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- auto gradu_it = this->gradu(el_type, ghost_type).begin(dim, dim);
- auto gradu_end = this->gradu(el_type, ghost_type).end(dim, dim);
+ for (auto && data :
+ zip(make_view<dim, dim>(this->gradu(el_type, ghost_type)),
+ make_view<dim, dim>(this->piola_kirchhoff_2(el_type, ghost_type)),
+ make_view<dim, dim>(this->stress(el_type, ghost_type)))) {
+ auto && grad_u = std::get<0>(data);
+ auto && piola = std::get<1>(data);
+ auto && sigma = std::get<2>(data);
- auto piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(dim, dim);
- auto stress_it = this->stress(el_type, ghost_type).begin(dim, dim);
-
- for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it) {
- Matrix<Real> & grad_u = *gradu_it;
- Matrix<Real> & piola = *piola_it;
- Matrix<Real> & sigma = *stress_it;
-
- auto F_tensor = gradUToF<dim>(grad_u);
- this->StoCauchy<dim>(F_tensor, piola, sigma);
+ Matrix<Real, dim, dim> F = gradUToF<dim>(grad_u);
+ this->StoCauchy<dim>(F, piola, sigma);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::setToSteadyState(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- const Array<Real> & displacement = model.getDisplacement();
+ const auto & displacement = model.getDisplacement();
// resizeInternalArray(gradu);
- UInt spatial_dimension = model.getSpatialDimension();
+ auto spatial_dimension = model.getSpatialDimension();
for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
- Array<Real> & gradu_vect = gradu(type, ghost_type);
+ auto & elem_filter = element_filter(type, ghost_type);
+ auto & gradu_vect = gradu(type, ghost_type);
/// compute @f$\nabla u@f$
fem.gradientOnIntegrationPoints(displacement, gradu_vect, spatial_dimension,
type, ghost_type, elem_filter);
setToSteadyState(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Compute the stiffness matrix by assembling @f$\int_{\omega} B^t \times D
* \times B d\omega @f$
*
* @param[in] ghost_type compute the residual for _ghost or _not_ghost element
*/
void Material::assembleStiffnessMatrix(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ auto spatial_dimension = model.getSpatialDimension();
- for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
- if (finite_deformation) {
- switch (spatial_dimension) {
- case 1: {
- assembleStiffnessMatrixNL<1>(type, ghost_type);
- assembleStiffnessMatrixL2<1>(type, ghost_type);
- break;
- }
- case 2: {
- assembleStiffnessMatrixNL<2>(type, ghost_type);
- assembleStiffnessMatrixL2<2>(type, ghost_type);
- break;
- }
- case 3: {
- assembleStiffnessMatrixNL<3>(type, ghost_type);
- assembleStiffnessMatrixL2<3>(type, ghost_type);
- break;
- }
- }
- } else {
- switch (spatial_dimension) {
- case 1: {
- assembleStiffnessMatrix<1>(type, ghost_type);
- break;
- }
- case 2: {
- assembleStiffnessMatrix<2>(type, ghost_type);
- break;
- }
- case 3: {
- assembleStiffnessMatrix<3>(type, ghost_type);
- break;
- }
- }
- }
- }
+ tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) {
+ constexpr auto dim = aka::decay_v<decltype(_)>;
+
+ for (auto type :
+ element_filter.elementTypes(spatial_dimension, ghost_type)) {
+ if (finite_deformation) {
+ this->assembleStiffnessMatrixFiniteDeformation<dim>(type,
+ ghost_type);
+ } else {
+ this->assembleStiffnessMatrix<dim>(type, ghost_type);
+ }
+ }
+ },
+ spatial_dimension);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void Material::assembleStiffnessMatrix(ElementType type, GhostType ghost_type) {
+ tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
+ this->assembleStiffnessMatrix<dim, type>(ghost_type);
+ },
+ type);
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, ElementType type>
+void Material::assembleStiffnessMatrix(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
+ const auto & elem_filter = element_filter(type, ghost_type);
if (elem_filter.empty()) {
AKANTU_DEBUG_OUT();
return;
}
- // const Array<Real> & shapes_derivatives =
- // fem.getShapesDerivatives(type, ghost_type);
+ auto & gradu_vect = gradu(type, ghost_type);
- Array<Real> & gradu_vect = gradu(type, ghost_type);
-
- UInt nb_element = elem_filter.size();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ auto nb_element = elem_filter.size();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ constexpr auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ constexpr auto tangent_size = getTangentStiffnessVoigtSize(dim);
gradu_vect.resize(nb_quadrature_points * nb_element);
fem.gradientOnIntegrationPoints(model.getDisplacement(), gradu_vect, dim,
type, ghost_type, elem_filter);
- UInt tangent_size = getTangentStiffnessVoigtSize(dim);
-
- auto * tangent_stiffness_matrix =
- new Array<Real>(nb_element * nb_quadrature_points,
- tangent_size * tangent_size, "tangent_stiffness_matrix");
+ auto tangent_stiffness_matrix = std::make_unique<Array<Real>>(
+ nb_element * nb_quadrature_points, tangent_size * tangent_size,
+ "tangent_stiffness_matrix");
tangent_stiffness_matrix->zero();
computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type);
/// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
- UInt bt_d_b_size = dim * nb_nodes_per_element;
+ auto bt_d_b_size = dim * nb_nodes_per_element;
- auto * bt_d_b = new Array<Real>(nb_element * nb_quadrature_points,
- bt_d_b_size * bt_d_b_size, "B^t*D*B");
+ auto bt_d_b = std::make_unique<Array<Real>>(
+ nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B");
fem.computeBtDB(*tangent_stiffness_matrix, *bt_d_b, 4, type, ghost_type,
elem_filter);
- delete tangent_stiffness_matrix;
-
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
- auto * K_e = new Array<Real>(nb_element, bt_d_b_size * bt_d_b_size, "K_e");
+ auto K_e = std::make_unique<Array<Real>>(nb_element,
+ bt_d_b_size * bt_d_b_size, "K_e");
fem.integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type,
elem_filter);
- delete bt_d_b;
-
model.getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter);
- delete K_e;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-void Material::assembleStiffnessMatrixNL(ElementType type,
- GhostType ghost_type) {
- AKANTU_DEBUG_IN();
+template <Int dim>
+void Material::assembleStiffnessMatrixFiniteDeformation(ElementType type,
+ GhostType ghost_type) {
+ tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
+ this->assembleStiffnessMatrixNL<dim, type>(ghost_type);
+ this->assembleStiffnessMatrixL2<dim, type>(ghost_type);
+ },
+ type);
+}
- const Array<Real> & shapes_derivatives =
- fem.getShapesDerivatives(type, ghost_type);
+/* -------------------------------------------------------------------------- */
+template <Int dim, ElementType type>
+void Material::assembleStiffnessMatrixNL(GhostType ghost_type) {
+ AKANTU_DEBUG_IN();
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
- // Array<Real> & gradu_vect = delta_gradu(type, ghost_type);
+ const auto & shapes_derivatives = fem.getShapesDerivatives(type, ghost_type);
+ const auto & elem_filter = element_filter(type, ghost_type);
- UInt nb_element = elem_filter.size();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ const auto nb_element = elem_filter.size();
+ constexpr auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ const auto nb_quadrature_points =
+ fem.getNbIntegrationPoints(type, ghost_type);
- auto * shapes_derivatives_filtered = new Array<Real>(
+ auto shapes_derivatives_filtered = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points, dim * nb_nodes_per_element,
"shapes derivatives filtered");
FEEngine::filterElementalData(fem.getMesh(), shapes_derivatives,
*shapes_derivatives_filtered, type, ghost_type,
elem_filter);
/// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
- UInt bt_s_b_size = dim * nb_nodes_per_element;
-
- auto * bt_s_b = new Array<Real>(nb_element * nb_quadrature_points,
- bt_s_b_size * bt_s_b_size, "B^t*D*B");
-
- UInt piola_matrix_size = getCauchyStressMatrixSize(dim);
+ constexpr auto bt_s_b_size = dim * nb_nodes_per_element;
+ constexpr auto piola_matrix_size = getCauchyStressMatrixSize(dim);
- Matrix<Real> B(piola_matrix_size, bt_s_b_size);
- Matrix<Real> Bt_S(bt_s_b_size, piola_matrix_size);
- Matrix<Real> S(piola_matrix_size, piola_matrix_size);
+ auto bt_s_b = std::make_unique<Array<Real>>(
+ nb_element * nb_quadrature_points, bt_s_b_size * bt_s_b_size, "B^t*D*B");
- auto shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(
- spatial_dimension, nb_nodes_per_element);
+ Matrix<Real, piola_matrix_size, bt_s_b_size> B;
+ Matrix<Real, piola_matrix_size, piola_matrix_size> S;
- auto Bt_S_B_it = bt_s_b->begin(bt_s_b_size, bt_s_b_size);
- auto Bt_S_B_end = bt_s_b->end(bt_s_b_size, bt_s_b_size);
- auto piola_it = piola_kirchhoff_2(type, ghost_type).begin(dim, dim);
-
- for (; Bt_S_B_it != Bt_S_B_end;
- ++Bt_S_B_it, ++shapes_derivatives_filtered_it, ++piola_it) {
- auto & Bt_S_B = *Bt_S_B_it;
- const auto & Piola_kirchhoff_matrix = *piola_it;
+ for (auto && data :
+ zip(make_view<bt_s_b_size, bt_s_b_size>(*bt_s_b),
+ make_view<dim, dim>(piola_kirchhoff_2(type, ghost_type)),
+ make_view<dim, nb_nodes_per_element>(
+ *shapes_derivatives_filtered))) {
+ auto && Bt_S_B = std::get<0>(data);
+ auto && Piola_kirchhoff_matrix = std::get<1>(data);
+ auto && shapes_derivatives = std::get<2>(data);
setCauchyStressMatrix<dim>(Piola_kirchhoff_matrix, S);
- VoigtHelper<dim>::transferBMatrixToBNL(*shapes_derivatives_filtered_it, B,
+ VoigtHelper<dim>::transferBMatrixToBNL(shapes_derivatives, B,
nb_nodes_per_element);
- Bt_S.template mul<true, false>(B, S);
- Bt_S_B.template mul<false, false>(Bt_S, B);
+ Bt_S_B = B.transpose() * S * B;
}
- delete shapes_derivatives_filtered;
-
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
- auto * K_e = new Array<Real>(nb_element, bt_s_b_size * bt_s_b_size, "K_e");
+ auto K_e = std::make_unique<Array<Real>>(nb_element,
+ bt_s_b_size * bt_s_b_size, "K_e");
fem.integrate(*bt_s_b, *K_e, bt_s_b_size * bt_s_b_size, type, ghost_type,
elem_filter);
- delete bt_s_b;
-
model.getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter);
- delete K_e;
-
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-void Material::assembleStiffnessMatrixL2(ElementType type,
- GhostType ghost_type) {
+template <Int dim, ElementType type>
+void Material::assembleStiffnessMatrixL2(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- const Array<Real> & shapes_derivatives =
- fem.getShapesDerivatives(type, ghost_type);
+ const auto & shapes_derivatives = fem.getShapesDerivatives(type, ghost_type);
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
- Array<Real> & gradu_vect = gradu(type, ghost_type);
+ auto & elem_filter = element_filter(type, ghost_type);
+ auto & gradu_vect = gradu(type, ghost_type);
- UInt nb_element = elem_filter.size();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ auto nb_element = elem_filter.size();
+ constexpr auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
gradu_vect.resize(nb_quadrature_points * nb_element);
fem.gradientOnIntegrationPoints(model.getDisplacement(), gradu_vect, dim,
type, ghost_type, elem_filter);
- UInt tangent_size = getTangentStiffnessVoigtSize(dim);
+ constexpr auto tangent_size = getTangentStiffnessVoigtSize(dim);
- auto * tangent_stiffness_matrix =
- new Array<Real>(nb_element * nb_quadrature_points,
- tangent_size * tangent_size, "tangent_stiffness_matrix");
+ auto tangent_stiffness_matrix = std::make_unique<Array<Real>>(
+ nb_element * nb_quadrature_points, tangent_size * tangent_size,
+ "tangent_stiffness_matrix");
tangent_stiffness_matrix->zero();
computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type);
- auto * shapes_derivatives_filtered = new Array<Real>(
+ auto shapes_derivatives_filtered = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points, dim * nb_nodes_per_element,
"shapes derivatives filtered");
FEEngine::filterElementalData(fem.getMesh(), shapes_derivatives,
*shapes_derivatives_filtered, type, ghost_type,
elem_filter);
/// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
- UInt bt_d_b_size = dim * nb_nodes_per_element;
-
- auto * bt_d_b = new Array<Real>(nb_element * nb_quadrature_points,
- bt_d_b_size * bt_d_b_size, "B^t*D*B");
-
- Matrix<Real> B(tangent_size, dim * nb_nodes_per_element);
- Matrix<Real> B2(tangent_size, dim * nb_nodes_per_element);
- Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size);
-
- auto shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(
- spatial_dimension, nb_nodes_per_element);
-
- auto Bt_D_B_it = bt_d_b->begin(bt_d_b_size, bt_d_b_size);
- auto grad_u_it = gradu_vect.begin(dim, dim);
- auto D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size);
- auto D_end = tangent_stiffness_matrix->end(tangent_size, tangent_size);
-
- for (; D_it != D_end;
- ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it, ++grad_u_it) {
- const auto & grad_u = *grad_u_it;
- const auto & D = *D_it;
- auto & Bt_D_B = *Bt_D_B_it;
+ constexpr auto bt_d_b_size = dim * nb_nodes_per_element;
+ auto bt_d_b = std::make_unique<Array<Real>>(
+ nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B");
+
+ Matrix<Real, tangent_size, bt_d_b_size> B;
+ Matrix<Real, tangent_size, bt_d_b_size> B2;
+
+ for (auto && data :
+ zip(make_view<bt_d_b_size, bt_d_b_size>(*bt_d_b),
+ make_view<dim, dim>(gradu_vect),
+ make_view<tangent_size, tangent_size>(*tangent_stiffness_matrix),
+ make_view<dim, nb_nodes_per_element>(
+ *shapes_derivatives_filtered))) {
+ auto && Bt_D_B = std::get<0>(data);
+ auto && grad_u = std::get<1>(data);
+ auto && D = std::get<2>(data);
+ auto && shapes_derivative = std::get<3>(data);
// transferBMatrixToBL1<dim > (*shapes_derivatives_filtered_it, B,
// nb_nodes_per_element);
- VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(
- *shapes_derivatives_filtered_it, B, nb_nodes_per_element);
- VoigtHelper<dim>::transferBMatrixToBL2(*shapes_derivatives_filtered_it,
- grad_u, B2, nb_nodes_per_element);
+ VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(shapes_derivative, B,
+ nb_nodes_per_element);
+ VoigtHelper<dim>::transferBMatrixToBL2(shapes_derivative, grad_u, B2,
+ nb_nodes_per_element);
B += B2;
- Bt_D.template mul<true, false>(B, D);
- Bt_D_B.template mul<false, false>(Bt_D, B);
+ Bt_D_B = B.transpose() * D * B;
}
- delete tangent_stiffness_matrix;
- delete shapes_derivatives_filtered;
-
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
- auto * K_e = new Array<Real>(nb_element, bt_d_b_size * bt_d_b_size, "K_e");
+ auto K_e = std::make_unique<Array<Real>>(nb_element,
+ bt_d_b_size * bt_d_b_size, "K_e");
fem.integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type,
elem_filter);
- delete bt_d_b;
-
model.getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter);
- delete K_e;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-void Material::assembleInternalForces(GhostType ghost_type) {
-
- AKANTU_DEBUG_IN();
+template <Int dim>
+void Material::assembleInternalForces(ElementType type, GhostType ghost_type) {
+ tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
+ this->assembleInternalForces<dim, type>(ghost_type);
+ },
+ type);
+}
- Array<Real> & internal_force = model.getInternalForce();
+/* -------------------------------------------------------------------------- */
+template <Int dim, ElementType type>
+void Material::assembleInternalForces(GhostType ghost_type) {
+ auto & internal_force = model.getInternalForce();
- Mesh & mesh = fem.getMesh();
- for (auto type : element_filter.elementTypes(_ghost_type = ghost_type)) {
- const Array<Real> & shapes_derivatives =
- fem.getShapesDerivatives(type, ghost_type);
+ // Mesh & mesh = fem.getMesh();
+ auto && elem_filter = element_filter(type, ghost_type);
+ auto nb_element = elem_filter.size();
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
- if (elem_filter.empty()) {
- continue;
- }
- UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
- UInt nb_element = elem_filter.size();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ if (nb_element == 0) {
+ return;
+ }
- auto * shapesd_filtered = new Array<Real>(
- nb_element, size_of_shapes_derivatives, "filtered shapesd");
+ const Array<Real> & shapes_derivatives =
+ fem.getShapesDerivatives(type, ghost_type);
- FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered,
- type, ghost_type, elem_filter);
+ UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
+ UInt nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- Array<Real>::matrix_iterator shapes_derivatives_filtered_it =
- shapesd_filtered->begin(dim, nb_nodes_per_element);
+ /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by
+ /// @f$\mathbf{B}^t \mathbf{\sigma}_q@f$
+ auto * sigma_dphi_dx =
+ new Array<Real>(nb_element * nb_quadrature_points,
+ size_of_shapes_derivatives, "sigma_x_dphi_/_dX");
+
+ fem.computeBtD(stress(type, ghost_type), *sigma_dphi_dx, type, ghost_type,
+ elem_filter);
+
+ /**
+ * compute @f$\int \sigma * \frac{\partial \varphi}{\partial X}dX@f$ by
+ * @f$ \sum_q \mathbf{B}^t
+ * \mathbf{\sigma}_q \overline w_q J_q@f$
+ */
+ auto * int_sigma_dphi_dx =
+ new Array<Real>(nb_element, nb_nodes_per_element * spatial_dimension,
+ "int_sigma_x_dphi_/_dX");
+
+ fem.integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, size_of_shapes_derivatives,
+ type, ghost_type, elem_filter);
+ delete sigma_dphi_dx;
+
+ /// assemble
+ model.getDOFManager().assembleElementalArrayLocalArray(
+ *int_sigma_dphi_dx, internal_force, type, ghost_type, -1, elem_filter);
+ delete int_sigma_dphi_dx;
+}
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+void Material::assembleInternalForcesFiniteDeformation(ElementType type,
+ GhostType ghost_type) {
+ tuple_dispatch<AllElementTypes>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
+ this->assembleInternalForcesFiniteDeformation<dim, type>(ghost_type);
+ },
+ type);
+}
- // Set stress vectors
- UInt stress_size = getTangentStiffnessVoigtSize(dim);
+/* -------------------------------------------------------------------------- */
+template <Int dim, ElementType type>
+void Material::assembleInternalForcesFiniteDeformation(GhostType ghost_type) {
+ AKANTU_DEBUG_IN();
- // Set matrices B and BNL*
- UInt bt_s_size = dim * nb_nodes_per_element;
+ auto & internal_force = model.getInternalForce();
+ auto & mesh = fem.getMesh();
+ const auto & shapes_derivatives = fem.getShapesDerivatives(type, ghost_type);
- auto * bt_s =
- new Array<Real>(nb_element * nb_quadrature_points, bt_s_size, "B^t*S");
+ auto & elem_filter = element_filter(type, ghost_type);
+ if (elem_filter.size() == 0)
+ return;
- auto grad_u_it = this->gradu(type, ghost_type).begin(dim, dim);
- auto grad_u_end = this->gradu(type, ghost_type).end(dim, dim);
- auto stress_it = this->piola_kirchhoff_2(type, ghost_type).begin(dim, dim);
- shapes_derivatives_filtered_it =
- shapesd_filtered->begin(dim, nb_nodes_per_element);
+ auto size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
+ auto nb_element = elem_filter.size();
- Array<Real>::matrix_iterator bt_s_it = bt_s->begin(bt_s_size, 1);
+ constexpr auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ constexpr auto stress_size = getTangentStiffnessVoigtSize(dim);
+ constexpr auto bt_s_size = dim * nb_nodes_per_element;
- Matrix<Real> B_tensor(stress_size, bt_s_size);
- Matrix<Real> B2_tensor(stress_size, bt_s_size);
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
- for (; grad_u_it != grad_u_end; ++grad_u_it, ++stress_it,
- ++shapes_derivatives_filtered_it,
- ++bt_s_it) {
- auto & grad_u = *grad_u_it;
- auto & r = *bt_s_it;
- auto & S = *stress_it;
+ auto shapesd_filtered = std::make_unique<Array<Real>>(
+ nb_element, size_of_shapes_derivatives, "filtered shapesd");
- VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(
- *shapes_derivatives_filtered_it, B_tensor, nb_nodes_per_element);
+ FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered,
+ type, ghost_type, elem_filter);
- VoigtHelper<dim>::transferBMatrixToBL2(*shapes_derivatives_filtered_it,
- grad_u, B2_tensor,
- nb_nodes_per_element);
+ // Set stress vectors
+ auto bt_s = std::make_unique<Array<Real>>(nb_element * nb_quadrature_points,
+ bt_s_size, "B^t*S");
- B_tensor += B2_tensor;
+ Matrix<Real, stress_size, bt_s_size> B_tensor;
+ Matrix<Real, stress_size, bt_s_size> B2_tensor;
- auto S_vect = Material::stressToVoigt<dim>(S);
- Matrix<Real> S_voigt(S_vect.storage(), stress_size, 1);
+ for (auto && data :
+ zip(make_view<dim, dim>(this->gradu(type, ghost_type)),
+ make_view<dim, dim>(this->piola_kirchhoff_2(type, ghost_type)),
+ make_view<bt_s_size>(*bt_s),
+ make_view<dim, nb_nodes_per_element>(*shapesd_filtered))) {
+ auto && grad_u = std::get<0>(data);
+ auto && S = std::get<1>(data);
+ auto && r = std::get<2>(data);
+ auto && shapes_derivative = std::get<3>(data);
- r.template mul<true, false>(B_tensor, S_voigt);
- }
+ VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(
+ shapes_derivative, B_tensor, nb_nodes_per_element);
- delete shapesd_filtered;
+ VoigtHelper<dim>::transferBMatrixToBL2(shapes_derivative, grad_u, B2_tensor,
+ nb_nodes_per_element);
- /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
- auto * r_e = new Array<Real>(nb_element, bt_s_size, "r_e");
+ B_tensor += B2_tensor;
+ auto && S_voight = Material::stressToVoigt<dim>(S);
+ r = B_tensor.transpose() * S_voight;
+ }
- fem.integrate(*bt_s, *r_e, bt_s_size, type, ghost_type, elem_filter);
+ /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
+ auto r_e = std::make_unique<Array<Real>>(nb_element, bt_s_size, "r_e");
+ fem.integrate(*bt_s, *r_e, bt_s_size, type, ghost_type, elem_filter);
- delete bt_s;
+ model.getDOFManager().assembleElementalArrayLocalArray(
+ *r_e, internal_force, type, ghost_type, -1., elem_filter);
- model.getDOFManager().assembleElementalArrayLocalArray(
- *r_e, internal_force, type, ghost_type, -1., elem_filter);
- delete r_e;
- }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::computePotentialEnergyByElements() {
AKANTU_DEBUG_IN();
for (auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) {
computePotentialEnergy(type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void Material::computePotentialEnergy(ElementType /*unused*/) {
- AKANTU_DEBUG_IN();
- AKANTU_TO_IMPLEMENT();
- AKANTU_DEBUG_OUT();
-}
+void Material::computePotentialEnergy(ElementType) { AKANTU_TO_IMPLEMENT(); }
/* -------------------------------------------------------------------------- */
Real Material::getPotentialEnergy() {
AKANTU_DEBUG_IN();
Real epot = 0.;
computePotentialEnergyByElements();
/// integrate the potential energy for each type of elements
for (auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) {
epot += fem.integrate(potential_energy(type, _not_ghost), type, _not_ghost,
element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return epot;
}
/* -------------------------------------------------------------------------- */
-Real Material::getPotentialEnergy(ElementType & type, UInt index) {
- AKANTU_DEBUG_IN();
- Real epot = 0.;
+Real Material::getPotentialEnergy(ElementType type, Int index) {
+ return getPotentialEnergy({type, index, _not_ghost});
+}
- Vector<Real> epot_on_quad_points(fem.getNbIntegrationPoints(type));
+/* -------------------------------------------------------------------------- */
+Real Material::getPotentialEnergy(const Element & element) {
+ AKANTU_DEBUG_IN();
- computePotentialEnergyByElement(type, index, epot_on_quad_points);
+ Vector<Real> epot_on_quad_points(fem.getNbIntegrationPoints(element.type));
+ computePotentialEnergyByElement(element, epot_on_quad_points);
- epot = fem.integrate(epot_on_quad_points, type, element_filter(type)(index));
+ auto epot = fem.integrate(epot_on_quad_points,
+ {element.type,
+ element_filter(element.type)(element.element),
+ _not_ghost});
AKANTU_DEBUG_OUT();
return epot;
}
/* -------------------------------------------------------------------------- */
Real Material::getEnergy(const std::string & type) {
AKANTU_DEBUG_IN();
if (type == "potential") {
return getPotentialEnergy();
}
AKANTU_DEBUG_OUT();
return 0.;
}
/* -------------------------------------------------------------------------- */
-Real Material::getEnergy(const std::string & energy_id, ElementType type,
- UInt index) {
+Real Material::getEnergy(const std::string & energy_id,
+ const Element & element) {
AKANTU_DEBUG_IN();
if (energy_id == "potential") {
- return getPotentialEnergy(type, index);
+ return getPotentialEnergy(element);
}
AKANTU_DEBUG_OUT();
return 0.;
}
/* -------------------------------------------------------------------------- */
void Material::initElementalFieldInterpolation(
const ElementTypeMapArray<Real> & interpolation_points_coordinates) {
AKANTU_DEBUG_IN();
this->fem.initElementalFieldInterpolationFromIntegrationPoints(
interpolation_points_coordinates, this->interpolation_points_matrices,
this->interpolation_inverse_coordinates, &(this->element_filter));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::interpolateStress(ElementTypeMapArray<Real> & result,
const GhostType ghost_type) {
-
this->fem.interpolateElementalFieldFromIntegrationPoints(
this->stress, this->interpolation_points_matrices,
this->interpolation_inverse_coordinates, result, ghost_type,
&(this->element_filter));
}
/* -------------------------------------------------------------------------- */
void Material::interpolateStressOnFacets(
ElementTypeMapArray<Real> & result,
ElementTypeMapArray<Real> & by_elem_result, const GhostType ghost_type) {
-
interpolateStress(by_elem_result, ghost_type);
- UInt stress_size = this->stress.getNbComponent();
+ auto stress_size = this->stress.getNbComponent();
- const Mesh & mesh = this->model.getMesh();
- const Mesh & mesh_facets = mesh.getMeshFacets();
+ const auto & mesh = this->model.getMesh();
+ const auto & mesh_facets = mesh.getMeshFacets();
for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
- Array<UInt> & elem_fil = element_filter(type, ghost_type);
- Array<Real> & by_elem_res = by_elem_result(type, ghost_type);
- UInt nb_element = elem_fil.size();
- UInt nb_element_full = this->model.getMesh().getNbElement(type, ghost_type);
- UInt nb_interpolation_points_per_elem =
- by_elem_res.size() / nb_element_full;
-
- const Array<Element> & facet_to_element =
+ auto nb_element_full = mesh.getNbElement(type, ghost_type);
+
+ auto nb_interpolation_points_per_elem =
+ by_elem_result(type, ghost_type).size() / nb_element_full;
+
+ const auto & facet_to_element =
mesh_facets.getSubelementToElement(type, ghost_type);
- ElementType type_facet = Mesh::getFacetType(type);
- UInt nb_facet_per_elem = facet_to_element.getNbComponent();
- UInt nb_quad_per_facet =
+
+ auto nb_facet_per_elem = facet_to_element.getNbComponent();
+ auto nb_quad_per_facet =
nb_interpolation_points_per_elem / nb_facet_per_elem;
- Element element_for_comparison{type, 0, ghost_type};
- const Array<std::vector<Element>> * element_to_facet = nullptr;
- GhostType current_ghost_type = _casper;
- Array<Real> * result_vec = nullptr;
-
- Array<Real>::const_matrix_iterator result_it =
- by_elem_res.begin_reinterpret(
- stress_size, nb_interpolation_points_per_elem, nb_element_full);
-
- for (UInt el = 0; el < nb_element; ++el) {
- UInt global_el = elem_fil(el);
- element_for_comparison.element = global_el;
- for (UInt f = 0; f < nb_facet_per_elem; ++f) {
-
- Element facet_elem = facet_to_element(global_el, f);
- UInt global_facet = facet_elem.element;
- if (facet_elem.ghost_type != current_ghost_type) {
- current_ghost_type = facet_elem.ghost_type;
- element_to_facet = &mesh_facets.getElementToSubelement(
- type_facet, current_ghost_type);
- result_vec = &result(type_facet, current_ghost_type);
- }
+ Element element{type, 0, ghost_type};
- bool is_second_element =
- (*element_to_facet)(global_facet)[0] != element_for_comparison;
+ auto && by_elem_res =
+ make_view(by_elem_result(type, ghost_type), stress_size,
+ nb_quad_per_facet, nb_facet_per_elem)
+ .begin();
- for (UInt q = 0; q < nb_quad_per_facet; ++q) {
- Vector<Real> result_local(result_vec->storage() +
- (global_facet * nb_quad_per_facet + q) *
- result_vec->getNbComponent() +
- static_cast<UInt>(is_second_element) *
- stress_size,
- stress_size);
+ for (auto global_el : element_filter(type, ghost_type)) {
+ element.element = global_el;
- const Matrix<Real> & result_tmp(result_it[global_el]);
- result_local = result_tmp(f * nb_quad_per_facet + q);
+ auto && result_per_elem = by_elem_res[global_el];
+
+ for (Int f = 0; f < nb_facet_per_elem; ++f) {
+ auto facet_elem = facet_to_element(global_el, f);
+ Int is_second_element =
+ mesh_facets.getElementToSubelement(facet_elem)[0] != element;
+
+ auto && result_local =
+ result.get(facet_elem, stress_size, 2, nb_quad_per_facet);
+
+ for (auto && data : zip(result_local, result_per_elem(f))) {
+ std::get<0>(data)(is_second_element) = std::get<1>(data);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void Material::addElements(const Array<Element> & elements_to_add) {
if (elements_to_add.empty()) {
return; // noops if no changes
}
AKANTU_DEBUG_IN();
UInt mat_id = model.getMaterialIndex(name);
for (const auto & element : elements_to_add) {
auto index = this->addElement(element);
model.material_index(element) = mat_id;
model.material_local_numbering(element) = index;
}
this->resizeInternals();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::removeElements(const Array<Element> & elements_to_remove) {
if (elements_to_remove.empty()) {
return; // noops if no changes
}
AKANTU_DEBUG_IN();
auto & mesh = this->model.getMesh();
auto el_begin = elements_to_remove.begin();
auto el_end = elements_to_remove.end();
- ElementTypeMapArray<UInt> material_local_new_numbering(
+ ElementTypeMapArray<Idx> material_local_new_numbering(
"remove mat filter elem", id);
material_local_new_numbering.initialize(
mesh, _element_filter = &element_filter, _element_kind = _ek_not_defined,
_with_nb_element = true);
- ElementTypeMapArray<UInt> element_filter_tmp("element_filter_tmp", id);
+ ElementTypeMapArray<Idx> element_filter_tmp("element_filter_tmp", id);
element_filter_tmp.initialize(mesh, _element_filter = &element_filter,
_element_kind = _ek_not_defined);
- ElementTypeMap<UInt> new_ids, element_ids;
+ ElementTypeMap<Idx> new_ids, element_ids;
for_each_element(
mesh,
[&](auto && el) {
if (not new_ids(el.type, el.ghost_type)) {
element_ids(el.type, el.ghost_type) = 0;
}
auto & element_id = element_ids(el.type, el.ghost_type);
auto l_el = Element{el.type, element_id, el.ghost_type};
if (std::find(el_begin, el_end, el) != el_end) {
material_local_new_numbering(l_el) = UInt(-1);
return;
}
element_filter_tmp(el.type, el.ghost_type).push_back(el.element);
if (not new_ids(el.type, el.ghost_type)) {
new_ids(el.type, el.ghost_type) = 0;
}
auto & new_id = new_ids(el.type, el.ghost_type);
material_local_new_numbering(l_el) = new_id;
model.material_local_numbering(el) = new_id;
++new_id;
++element_id;
},
_element_filter = &element_filter, _element_kind = _ek_not_defined);
for (auto ghost_type : ghost_types) {
for (const auto & type : element_filter.elementTypes(
_ghost_type = ghost_type, _element_kind = _ek_not_defined)) {
element_filter(type, ghost_type)
.copy(element_filter_tmp(type, ghost_type));
}
}
for (auto it = internal_vectors_real.begin();
it != internal_vectors_real.end(); ++it) {
it->second->removeIntegrationPoints(material_local_new_numbering);
}
- for (auto it = internal_vectors_uint.begin();
- it != internal_vectors_uint.end(); ++it) {
+ for (auto it = internal_vectors_int.begin(); it != internal_vectors_int.end();
+ ++it) {
it->second->removeIntegrationPoints(material_local_new_numbering);
}
for (auto it = internal_vectors_bool.begin();
it != internal_vectors_bool.end(); ++it) {
it->second->removeIntegrationPoints(material_local_new_numbering);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::resizeInternals() {
AKANTU_DEBUG_IN();
for (auto it = internal_vectors_real.begin();
it != internal_vectors_real.end(); ++it) {
it->second->resize();
}
- for (auto it = internal_vectors_uint.begin();
- it != internal_vectors_uint.end(); ++it) {
+ for (auto it = internal_vectors_int.begin(); it != internal_vectors_int.end();
+ ++it) {
it->second->resize();
}
for (auto it = internal_vectors_bool.begin();
it != internal_vectors_bool.end(); ++it) {
it->second->resize();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::onElementsAdded(const Array<Element> & /*unused*/,
const NewElementsEvent & /*unused*/) {
this->resizeInternals();
}
/* -------------------------------------------------------------------------- */
void Material::onElementsRemoved(
const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
[[gnu::unused]] const RemovedElementsEvent & event) {
- UInt my_num = model.getInternalIndexFromID(getID());
+ auto my_num = model.getInternalIndexFromID(getID());
- ElementTypeMapArray<UInt> material_local_new_numbering(
+ ElementTypeMapArray<Idx> material_local_new_numbering(
"remove mat filter elem", getID());
auto el_begin = element_list.begin();
auto el_end = element_list.end();
for (auto && gt : ghost_types) {
for (auto && type :
new_numbering.elementTypes(_all_dimensions, gt, _ek_not_defined)) {
if (not element_filter.exists(type, gt) ||
element_filter(type, gt).empty()) {
continue;
}
auto & elem_filter = element_filter(type, gt);
auto & mat_indexes = this->model.material_index(type, gt);
auto & mat_loc_num = this->model.material_local_numbering(type, gt);
auto nb_element = this->model.getMesh().getNbElement(type, gt);
// all materials will resize of the same size...
mat_indexes.resize(nb_element);
mat_loc_num.resize(nb_element);
if (!material_local_new_numbering.exists(type, gt)) {
material_local_new_numbering.alloc(elem_filter.size(), 1, type, gt);
}
auto & mat_renumbering = material_local_new_numbering(type, gt);
const auto & renumbering = new_numbering(type, gt);
- Array<UInt> elem_filter_tmp;
+ Array<Idx> elem_filter_tmp;
UInt ni = 0;
Element el{type, 0, gt};
- for (UInt i = 0; i < elem_filter.size(); ++i) {
- el.element = elem_filter(i);
+ for (auto && data : enumerate(elem_filter)) {
+ el.element = std::get<1>(data);
if (std::find(el_begin, el_end, el) == el_end) {
- UInt new_el = renumbering(el.element);
- AKANTU_DEBUG_ASSERT(new_el != UInt(-1),
+ auto new_el = renumbering(el.element);
+ AKANTU_DEBUG_ASSERT(new_el != -1,
"A not removed element as been badly renumbered");
elem_filter_tmp.push_back(new_el);
- mat_renumbering(i) = ni;
+ mat_renumbering(std::get<0>(data)) = ni;
mat_indexes(new_el) = my_num;
mat_loc_num(new_el) = ni;
++ni;
} else {
- mat_renumbering(i) = UInt(-1);
+ mat_renumbering(std::get<0>(data)) = -1;
}
}
elem_filter.resize(elem_filter_tmp.size());
elem_filter.copy(elem_filter_tmp);
}
}
for (auto it = internal_vectors_real.begin();
it != internal_vectors_real.end(); ++it) {
it->second->removeIntegrationPoints(material_local_new_numbering);
}
- for (auto it = internal_vectors_uint.begin();
- it != internal_vectors_uint.end(); ++it) {
+ for (auto it = internal_vectors_int.begin(); it != internal_vectors_int.end();
+ ++it) {
it->second->removeIntegrationPoints(material_local_new_numbering);
}
for (auto it = internal_vectors_bool.begin();
it != internal_vectors_bool.end(); ++it) {
it->second->removeIntegrationPoints(material_local_new_numbering);
}
}
/* -------------------------------------------------------------------------- */
void Material::beforeSolveStep() { this->savePreviousState(); }
/* -------------------------------------------------------------------------- */
void Material::afterSolveStep(bool converged) {
if (not converged) {
this->restorePreviousState();
return;
}
for (const auto & type : element_filter.elementTypes(
_all_dimensions, _not_ghost, _ek_not_defined)) {
this->updateEnergies(type);
}
}
/* -------------------------------------------------------------------------- */
void Material::onDamageIteration() { this->savePreviousState(); }
/* -------------------------------------------------------------------------- */
void Material::onDamageUpdate() {
for (const auto & type : element_filter.elementTypes(
_all_dimensions, _not_ghost, _ek_not_defined)) {
this->updateEnergiesAfterDamage(type);
}
}
/* -------------------------------------------------------------------------- */
void Material::onDump() {
if (this->isFiniteDeformation()) {
this->computeAllCauchyStresses(_not_ghost);
}
}
/* -------------------------------------------------------------------------- */
void Material::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
std::string type = getID().substr(getID().find_last_of(':') + 1);
stream << space << "Material " << type << " [" << std::endl;
Parsable::printself(stream, indent);
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
/// extrapolate internal values
void Material::extrapolateInternal(const ID & id, const Element & element,
- [[gnu::unused]] const Matrix<Real> & point,
+ const Matrix<Real> & /*point*/,
Matrix<Real> & extrapolated) {
if (this->isInternal<Real>(id, element.kind())) {
- UInt nb_element =
- this->element_filter(element.type, element.ghost_type).size();
- const ID name = this->getID() + ":" + id;
- UInt nb_quads =
+ auto name = this->getID() + ":" + id;
+ auto nb_quads =
this->internal_vectors_real[name]->getFEEngine().getNbIntegrationPoints(
element.type, element.ghost_type);
- const Array<Real> & internal =
+ const auto & internal =
this->getArray<Real>(id, element.type, element.ghost_type);
- UInt nb_component = internal.getNbComponent();
- Array<Real>::const_matrix_iterator internal_it =
- internal.begin_reinterpret(nb_component, nb_quads, nb_element);
- Element local_element = this->convertToLocalElement(element);
+ auto nb_component = internal.getNbComponent();
+ auto internal_it = make_view(internal, nb_component, nb_quads).begin();
+ auto local_element = this->convertToLocalElement(element);
/// instead of really extrapolating, here the value of the first GP
/// is copied into the result vector. This works only for linear
/// elements
/// @todo extrapolate!!!!
AKANTU_DEBUG_WARNING("This is a fix, values are not truly extrapolated");
- const Matrix<Real> & values = internal_it[local_element.element];
- UInt index = 0;
+ auto && values = internal_it[local_element.element];
+ Int index = 0;
Vector<Real> tmp(nb_component);
- for (UInt j = 0; j < values.cols(); ++j) {
+ for (Int j = 0; j < values.cols(); ++j) {
tmp = values(j);
if (tmp.norm() > 0) {
index = j;
break;
}
}
- for (UInt i = 0; i < extrapolated.size(); ++i) {
+ for (Int i = 0; i < extrapolated.size(); ++i) {
extrapolated(i) = values(index);
}
} else {
- Matrix<Real> default_values(extrapolated.rows(), extrapolated.cols(), 0.);
- extrapolated = default_values;
+ extrapolated.fill(0.);
}
}
/* -------------------------------------------------------------------------- */
void Material::applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
const GhostType ghost_type) {
-
for (auto && type : element_filter.elementTypes(_all_dimensions, _not_ghost,
_ek_not_defined)) {
if (element_filter(type, ghost_type).empty()) {
continue;
}
for (auto & eigengradu : make_view(this->eigengradu(type, ghost_type),
spatial_dimension, spatial_dimension)) {
eigengradu = prescribed_eigen_grad_u;
}
}
}
/* -------------------------------------------------------------------------- */
MaterialFactory & Material::getFactory() {
return MaterialFactory::getInstance();
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh
index 7f8155aa4..4465b3163 100644
--- a/src/model/solid_mechanics/material.hh
+++ b/src/model/solid_mechanics/material.hh
@@ -1,720 +1,820 @@
/**
* @file material.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Enrico Milanese <enrico.milanese@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Mother class for all materials
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_factory.hh"
#include "aka_voigthelper.hh"
#include "data_accessor.hh"
#include "integration_point.hh"
#include "parsable.hh"
#include "parser.hh"
/* -------------------------------------------------------------------------- */
#include "internal_field.hh"
#include "random_internal_field.hh"
/* -------------------------------------------------------------------------- */
#include "mesh_events.hh"
#include "solid_mechanics_model_event_handler.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_HH_
#define AKANTU_MATERIAL_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class Model;
class SolidMechanicsModel;
class Material;
} // namespace akantu
namespace akantu {
using MaterialFactory =
- Factory<Material, ID, UInt, const ID &, SolidMechanicsModel &, const ID &>;
+ Factory<Material, ID, Int, const ID &, SolidMechanicsModel &, const ID &>;
/**
* Interface of all materials
* Prerequisites for a new material
* - inherit from this class
* - implement the following methods:
* \code
* virtual Real getStableTimeStep(Real h, const Element & element =
* ElementNull);
*
* virtual void computeStress(ElementType el_type,
* GhostType ghost_type = _not_ghost);
*
* virtual void computeTangentStiffness(ElementType el_type,
* Array<Real> & tangent_matrix,
* GhostType ghost_type = _not_ghost);
* \endcode
*
*/
class Material : public DataAccessor<Element>,
public Parsable,
public MeshEventHandler,
protected SolidMechanicsModelEventHandler {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
Material(const Material & mat) = delete;
Material & operator=(const Material & mat) = delete;
/// Initialize material with defaults
Material(SolidMechanicsModel & model, const ID & id = "");
/// Initialize material with custom mesh & fe_engine
- Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
+ Material(SolidMechanicsModel & model, Int dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id = "");
/// Destructor
~Material() override;
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Function that materials can/should reimplement */
/* ------------------------------------------------------------------------ */
protected:
/// constitutive law
virtual void computeStress(ElementType /* el_type */,
GhostType /* ghost_type */ = _not_ghost) {
AKANTU_TO_IMPLEMENT();
}
/// compute the tangent stiffness matrix
virtual void computeTangentModuli(ElementType /*el_type*/,
Array<Real> & /*tangent_matrix*/,
GhostType /*ghost_type*/ = _not_ghost) {
AKANTU_TO_IMPLEMENT();
}
/// compute the potential energy
virtual void computePotentialEnergy(ElementType el_type);
/// compute the potential energy for an element
+ [[gnu::deprecated("Use the interface with an Element")]] virtual void
+ computePotentialEnergyByElement(ElementType /*type*/, Int /*index*/,
+ Vector<Real> & /*epot_on_quad_points*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
+
virtual void
- computePotentialEnergyByElement(ElementType /*type*/, UInt /*index*/,
+ computePotentialEnergyByElement(const Element & /*element*/,
Vector<Real> & /*epot_on_quad_points*/) {
AKANTU_TO_IMPLEMENT();
}
virtual void updateEnergies(ElementType /*el_type*/) {}
virtual void updateEnergiesAfterDamage(ElementType /*el_type*/) {}
/// set the material to steady state (to be implemented for materials that
/// need it)
virtual void setToSteadyState(ElementType /*el_type*/,
GhostType /*ghost_type*/ = _not_ghost) {}
/// function called to update the internal parameters when the modifiable
/// parameters are modified
virtual void updateInternalParameters() {}
public:
/// extrapolate internal values
virtual void extrapolateInternal(const ID & id, const Element & element,
const Matrix<Real> & points,
Matrix<Real> & extrapolated);
/// compute the p-wave speed in the material
virtual Real getPushWaveSpeed(const Element & /*element*/) const {
AKANTU_TO_IMPLEMENT();
}
/// compute the s-wave speed in the material
virtual Real getShearWaveSpeed(const Element & /*element*/) const {
AKANTU_TO_IMPLEMENT();
}
/// get a material celerity to compute the stable time step (default: is the
/// push wave speed)
virtual Real getCelerity(const Element & element) const {
return getPushWaveSpeed(element);
}
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
template <typename T> void registerInternal(InternalField<T> & /*vect*/) {
AKANTU_TO_IMPLEMENT();
}
template <typename T> void unregisterInternal(InternalField<T> & /*vect*/) {
AKANTU_TO_IMPLEMENT();
}
/// initialize the material computed parameter
virtual void initMaterial();
/// compute the residual for this material
// virtual void updateResidual(GhostType ghost_type = _not_ghost);
/// assemble the residual for this material
virtual void assembleInternalForces(GhostType ghost_type);
- /// save the stress in the previous_stress if needed
+ /// save the internals in the previous_stress if needed
virtual void savePreviousState();
- /// restore the stress from previous_stress if needed
+ /// restore the internals from previous_stress if needed
virtual void restorePreviousState();
/// compute the stresses for this material
virtual void computeAllStresses(GhostType ghost_type = _not_ghost);
// virtual void
// computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost);
virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost);
/// set material to steady state
void setToSteadyState(GhostType ghost_type = _not_ghost);
/// compute the stiffness matrix
virtual void assembleStiffnessMatrix(GhostType ghost_type);
/// add an element to the local mesh filter
- inline UInt addElement(ElementType type, UInt element, GhostType ghost_type);
- inline UInt addElement(const Element & element);
+ inline auto addElement(ElementType type, Int element, GhostType ghost_type);
+ inline auto addElement(const Element & element);
/// add many elements at once
void addElements(const Array<Element> & elements_to_add);
/// remove many element at once
void removeElements(const Array<Element> & elements_to_remove);
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override;
/**
* interpolate stress on given positions for each element by means
* of a geometrical interpolation on quadrature points
*/
void interpolateStress(ElementTypeMapArray<Real> & result,
GhostType ghost_type = _not_ghost);
/**
* interpolate stress on given positions for each element by means
* of a geometrical interpolation on quadrature points and store the
* results per facet
*/
void interpolateStressOnFacets(ElementTypeMapArray<Real> & result,
ElementTypeMapArray<Real> & by_elem_result,
GhostType ghost_type = _not_ghost);
/**
* function to initialize the elemental field interpolation
* function by inverting the quadrature points' coordinates
*/
void initElementalFieldInterpolation(
const ElementTypeMapArray<Real> & interpolation_points_coordinates);
/* ------------------------------------------------------------------------ */
/* Common part */
/* ------------------------------------------------------------------------ */
protected:
/* ------------------------------------------------------------------------ */
- static inline UInt getTangentStiffnessVoigtSize(UInt dim);
+ constexpr static inline Int getTangentStiffnessVoigtSize(Int dim) {
+ return (dim * (dim - 1) / 2 + dim);
+ }
+
+ template <Int dim>
+ constexpr static inline Int getTangentStiffnessVoigtSize() {
+ return getTangentStiffnessVoigtSize(dim);
+ }
/// compute the potential energy by element
void computePotentialEnergyByElements();
/// resize the intenals arrays
virtual void resizeInternals();
+ template <Int dim>
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ using namespace tuple;
+ auto && args =
+ zip("grad_u"_n = make_view<dim, dim>(this->gradu(el_type, ghost_type)),
+ "previous_sigma"_n =
+ make_view<dim, dim>(this->stress.previous(el_type, ghost_type)),
+ "previous_grad_u"_n =
+ make_view<dim, dim>(this->gradu.previous(el_type, ghost_type)));
+
+ if (not finite_deformation) {
+ return zip_append(
+ std::forward<decltype(args)>(args),
+ "sigma"_n = make_view<dim, dim>(this->stress(el_type, ghost_type)));
+ }
+
+ return zip_append(std::forward<decltype(args)>(args),
+ "sigma"_n = make_view<dim, dim>(
+ this->piola_kirchhoff_2(el_type, ghost_type)));
+ }
+
+ template <Int dim>
+ decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrix,
+ ElementType el_type,
+ GhostType ghost_type) {
+ using namespace tuple;
+ constexpr auto tangent_size = Material::getTangentStiffnessVoigtSize(dim);
+ return zip("tangent_moduli"_n =
+ make_view<tangent_size, tangent_size>(tangent_matrix),
+ "grad_u"_n =
+ make_view<dim, dim>(this->gradu(el_type, ghost_type)));
+ }
+
/* ------------------------------------------------------------------------ */
/* Finite deformation functions */
/* This functions area implementing what is described in the paper of Bathe */
/* et al, in IJNME, Finite Element Formulations For Large Deformation */
/* Dynamic Analysis, Vol 9, 353-386, 1975 */
/* ------------------------------------------------------------------------ */
protected:
- /// assemble the residual
- template <UInt dim> void assembleInternalForces(GhostType ghost_type);
+ /// assemble the internal forces
+ template <Int dim>
+ void assembleInternalForces(ElementType type, GhostType ghost_type);
+
+ /// assemble the internal forces
+ template <Int dim, ElementType type>
+ void assembleInternalForces(GhostType ghost_type);
- template <UInt dim>
+ /// assemble the internal forces in the case of finite deformation
+ template <Int dim>
+ void assembleInternalForcesFiniteDeformation(ElementType type,
+ GhostType ghost_type);
+
+ /// assemble the internal forces in the case of finite deformation
+ template <Int dim, ElementType type>
+ void assembleInternalForcesFiniteDeformation(GhostType ghost_type);
+
+ template <Int dim>
void computeAllStressesFromTangentModuli(ElementType type,
GhostType ghost_type);
- template <UInt dim>
+ template <Int dim>
void assembleStiffnessMatrix(ElementType type, GhostType ghost_type);
/// assembling in finite deformation
- template <UInt dim>
- void assembleStiffnessMatrixNL(ElementType type, GhostType ghost_type);
+ template <Int dim>
+ void assembleStiffnessMatrixFiniteDeformation(ElementType type,
+ GhostType ghost_type);
+
+ template <Int dim, ElementType type>
+ void assembleStiffnessMatrix(GhostType ghost_type);
+
+ /// assembling in finite deformation
+ template <Int dim, ElementType type>
+ void assembleStiffnessMatrixNL(GhostType ghost_type);
- template <UInt dim>
- void assembleStiffnessMatrixL2(ElementType type, GhostType ghost_type);
+ template <Int dim, ElementType type>
+ void assembleStiffnessMatrixL2(GhostType ghost_type);
/* ------------------------------------------------------------------------ */
/* Conversion functions */
/* ------------------------------------------------------------------------ */
public:
/// Size of the Stress matrix for the case of finite deformation see: Bathe et
/// al, IJNME, Vol 9, 353-386, 1975
- static inline UInt getCauchyStressMatrixSize(UInt dim);
+ static constexpr inline Int getCauchyStressMatrixSize(Int dim) {
+ return (dim * dim);
+ }
/// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386,
/// 1975
- template <UInt dim>
- static inline void setCauchyStressMatrix(const Matrix<Real> & S_t,
- Matrix<Real> & sigma);
+ template <Int dim, typename D1, typename D2>
+ static constexpr inline void
+ setCauchyStressMatrix(const Eigen::MatrixBase<D1> & S_t,
+ Eigen::MatrixBase<D2> & sigma);
/// write the stress tensor in the Voigt notation.
- template <UInt dim>
- static inline decltype(auto) stressToVoigt(const Matrix<Real> & stress) {
+ template <Int dim, typename D1>
+ static constexpr inline decltype(auto)
+ stressToVoigt(const Eigen::MatrixBase<D1> & stress) {
return VoigtHelper<dim>::matrixToVoigt(stress);
}
/// write the strain tensor in the Voigt notation.
- template <UInt dim>
- static inline decltype(auto) strainToVoigt(const Matrix<Real> & strain) {
+ template <Int dim, typename D1>
+ static constexpr inline decltype(auto)
+ strainToVoigt(const Eigen::MatrixBase<D1> & strain) {
return VoigtHelper<dim>::matrixToVoigtWithFactors(strain);
}
/// write a voigt vector to stress
- template <UInt dim>
- static inline void voigtToStress(const Vector<Real> & voigt,
- Matrix<Real> & stress) {
+ template <Int dim, typename D1, typename D2>
+ static constexpr inline void
+ voigtToStress(const Eigen::MatrixBase<D1> & voigt,
+ Eigen::MatrixBase<D2> & stress) {
VoigtHelper<dim>::voigtToMatrix(voigt, stress);
}
/// Computation of Cauchy stress tensor in the case of finite deformation from
/// the 2nd Piola-Kirchhoff for a given element type
- template <UInt dim>
+ template <Int dim>
void StoCauchy(ElementType el_type, GhostType ghost_type = _not_ghost);
/// Computation the Cauchy stress the 2nd Piola-Kirchhoff and the deformation
/// gradient
- template <UInt dim>
- inline void StoCauchy(const Matrix<Real> & F, const Matrix<Real> & S,
- Matrix<Real> & sigma, const Real & C33 = 1.0) const;
-
- template <UInt dim>
- static inline void gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F);
-
- template <UInt dim>
- static inline decltype(auto) gradUToF(const Matrix<Real> & grad_u);
-
- static inline void rightCauchy(const Matrix<Real> & F, Matrix<Real> & C);
- static inline void leftCauchy(const Matrix<Real> & F, Matrix<Real> & B);
-
- template <UInt dim>
- static inline void gradUToEpsilon(const Matrix<Real> & grad_u,
- Matrix<Real> & epsilon);
- template <UInt dim>
- static inline decltype(auto) gradUToEpsilon(const Matrix<Real> & grad_u);
-
- template <UInt dim>
- static inline void gradUToE(const Matrix<Real> & grad_u,
- Matrix<Real> & epsilon);
+ template <Int dim, typename D1, typename D2, typename D3>
+ static constexpr inline void
+ StoCauchy(const Eigen::MatrixBase<D1> & F, const Eigen::MatrixBase<D2> & S,
+ Eigen::MatrixBase<D3> & sigma, const Real & C33 = 1.0);
+
+ template <Int dim, typename D1, typename D2>
+ static constexpr inline decltype(auto)
+ StoCauchy(const Eigen::MatrixBase<D1> & F, const Eigen::MatrixBase<D2> & S,
+ const Real & C33 = 1.0);
+
+ template <Int dim, typename D1, typename D2>
+ static constexpr inline void gradUToF(const Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & F);
+
+ template <Int dim, typename D>
+ static constexpr inline decltype(auto)
+ gradUToF(const Eigen::MatrixBase<D> & grad_u);
+
+ template <typename D1, typename D2>
+ static constexpr inline void rightCauchy(const Eigen::MatrixBase<D1> & F,
+ Eigen::MatrixBase<D2> & C);
+ template <Int dim, typename D>
+ static constexpr inline decltype(auto)
+ rightCauchy(const Eigen::MatrixBase<D> & F);
+
+ template <typename D1, typename D2>
+ static constexpr inline void leftCauchy(const Eigen::MatrixBase<D1> & F,
+ Eigen::MatrixBase<D2> & B);
+ template <Int dim, typename D>
+ static constexpr inline decltype(auto)
+ leftCauchy(const Eigen::MatrixBase<D> & F);
+
+ template <Int dim, typename D1, typename D2>
+ static constexpr inline void
+ gradUToEpsilon(const Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & epsilon);
+ template <Int dim, typename D1>
+ static constexpr inline decltype(auto)
+ gradUToEpsilon(const Eigen::MatrixBase<D1> & grad_u);
+
+ template <Int dim, typename D1, typename D2>
+ static constexpr inline void gradUToE(const Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & E);
+
+ template <Int dim, typename D1>
+ static constexpr inline decltype(auto)
+ gradUToE(const Eigen::MatrixBase<D1> & grad_u);
+
+ template <Int dim, typename D1, typename D2>
+ static constexpr inline void
+ computeDeviatoric(const Eigen::MatrixBase<D1> & sigma,
+ Eigen::MatrixBase<D2> & sigma_dev) {
+ sigma_dev =
+ sigma - Matrix<Real, dim, dim>::Identity() * sigma.trace() / dim;
+ }
- template <UInt dim>
- static inline decltype(auto) gradUToE(const Matrix<Real> & grad_u);
+ template <Int dim, typename D>
+ static constexpr inline decltype(auto)
+ computeDeviatoric(const Eigen::MatrixBase<D> & sigma) {
+ Matrix<Real, dim, dim> sigma_dev;
+ Material::computeDeviatoric<dim>(sigma, sigma_dev);
+ return sigma_dev;
+ }
- static inline Real stressToVonMises(const Matrix<Real> & stress);
+ template <typename D1>
+ static inline Real stressToVonMises(const Eigen::MatrixBase<D1> & stress);
protected:
/// converts global element to local element
inline Element convertToLocalElement(const Element & global_element) const;
/// converts local element to global element
inline Element convertToGlobalElement(const Element & local_element) const;
/// converts global quadrature point to local quadrature point
inline IntegrationPoint
convertToLocalPoint(const IntegrationPoint & global_point) const;
/// converts local quadrature point to global quadrature point
inline IntegrationPoint
convertToGlobalPoint(const IntegrationPoint & local_point) const;
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
template <typename T>
inline void packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack,
CommunicationBuffer & buffer,
const Array<Element> & elements,
const ID & fem_id = ID()) const;
template <typename T>
inline void unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack,
CommunicationBuffer & buffer,
const Array<Element> & elements,
const ID & fem_id = ID());
/* ------------------------------------------------------------------------ */
/* MeshEventHandler inherited members */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
- void onNodesAdded(const Array<UInt> & /*unused*/,
- const NewNodesEvent & /*unused*/) override{};
- void onNodesRemoved(const Array<UInt> & /*unused*/,
- const Array<UInt> & /*unused*/,
- const RemovedNodesEvent & /*unused*/) override{};
+ void onNodesAdded(const Array<Idx> &, const NewNodesEvent &) override{};
+ void onNodesRemoved(const Array<Idx> &, const Array<Idx> &,
+ const RemovedNodesEvent &) override{};
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
void onElementsRemoved(const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) override;
- void onElementsChanged(const Array<Element> & /*unused*/,
- const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const ChangedElementsEvent & /*unused*/) override{};
+ void onElementsChanged(const Array<Element> &, const Array<Element> &,
+ const ElementTypeMapArray<Idx> &,
+ const ChangedElementsEvent &) override{};
/* ------------------------------------------------------------------------ */
/* SolidMechanicsModelEventHandler inherited members */
/* ------------------------------------------------------------------------ */
public:
virtual void beforeSolveStep();
virtual void afterSolveStep(bool converged = true);
void onDamageIteration() override;
void onDamageUpdate() override;
void onDump() override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(Name, name, const std::string &);
AKANTU_SET_MACRO(Name, name, const std::string &);
AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &)
AKANTU_GET_MACRO(ID, id, const ID &);
AKANTU_GET_MACRO(Rho, rho, Real);
AKANTU_SET_MACRO(Rho, rho, Real);
- AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
+ AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, Int);
/// return the potential energy for the subset of elements contained by the
/// material
Real getPotentialEnergy();
+
/// return the potential energy for the provided element
- Real getPotentialEnergy(ElementType & type, UInt index);
+ Real getPotentialEnergy(const Element & element);
+
+ [[gnu::deprecated("Use the interface with an Element")]] Real
+ getPotentialEnergy(ElementType type, Int index);
/// return the energy (identified by id) for the subset of elements contained
/// by the material
virtual Real getEnergy(const std::string & type);
/// return the energy (identified by id) for the provided element
- virtual Real getEnergy(const std::string & energy_id, ElementType type,
- UInt index);
+ virtual Real getEnergy(const std::string & energy_id,
+ const Element & element);
+
+ [[gnu::deprecated("Use the interface with an Element")]] virtual Real
+ getEnergy(const std::string & energy_id, ElementType type, Idx index) final {
+ return getEnergy(energy_id, {type, index, _not_ghost});
+ }
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, Idx);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy,
Real);
AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray<Real> &);
AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray<Real> &);
AKANTU_GET_MACRO(ElementFilter, element_filter,
- const ElementTypeMapArray<UInt> &);
+ const ElementTypeMapArray<Int> &);
AKANTU_GET_MACRO(FEEngine, fem, FEEngine &);
bool isNonLocal() const { return is_non_local; }
template <typename T>
const Array<T> & getArray(const ID & id, ElementType type,
GhostType ghost_type = _not_ghost) const;
template <typename T>
Array<T> & getArray(const ID & id, ElementType type,
GhostType ghost_type = _not_ghost);
template <typename T>
const InternalField<T> & getInternal(const ID & id) const;
template <typename T> InternalField<T> & getInternal(const ID & id);
template <typename T>
inline bool isInternal(const ID & id, ElementKind element_kind) const;
template <typename T>
- ElementTypeMap<UInt> getInternalDataPerElem(const ID & id,
- ElementKind element_kind) const;
+ ElementTypeMap<Int> getInternalDataPerElem(const ID & id,
+ ElementKind element_kind) const;
bool isFiniteDeformation() const { return finite_deformation; }
bool isInelasticDeformation() const { return inelastic_deformation; }
template <typename T> inline void setParam(const ID & param, T value);
inline const Parameter & getParam(const ID & param) const;
template <typename T>
void flattenInternal(const std::string & field_id,
ElementTypeMapArray<T> & internal_flat,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined) const;
template <typename T>
void inflateInternal(const std::string & field_id,
const ElementTypeMapArray<T> & field,
GhostType ghost_type = _not_ghost,
ElementKind element_kind = _ek_not_defined);
/// apply a constant eigengrad_u everywhere in the material
virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
GhostType /*ghost_type*/ = _not_ghost);
bool hasMatrixChanged(const ID & id) {
if (id == "K") {
return hasStiffnessMatrixChanged() or finite_deformation;
}
return true;
}
MatrixType getMatrixType(const ID & id) {
if (id == "K") {
return getTangentType();
}
if (id == "M") {
return _symmetric;
}
return _mt_not_defined;
}
/// specify if the matrix need to be recomputed for this material
virtual bool hasStiffnessMatrixChanged() { return true; }
/// specify the type of matrix, if not overloaded the material is not valid
/// for static or implicit computations
virtual MatrixType getTangentType() { return _mt_not_defined; }
/// static method to reteive the material factory
static MaterialFactory & getFactory();
protected:
bool isInit() const { return is_init; }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// boolean to know if the material has been initialized
bool is_init{false};
std::map<ID, InternalField<Real> *> internal_vectors_real;
- std::map<ID, InternalField<UInt> *> internal_vectors_uint;
+ std::map<ID, InternalField<Int> *> internal_vectors_int;
std::map<ID, InternalField<bool> *> internal_vectors_bool;
protected:
ID id;
/// Link to the fem object in the model
FEEngine & fem;
/// Finite deformation
bool finite_deformation{false};
/// Finite deformation
bool inelastic_deformation{false};
/// material name
std::string name;
/// The model to witch the material belong
SolidMechanicsModel & model;
/// density : rho
Real rho{0.};
/// spatial dimension
- UInt spatial_dimension;
+ Int spatial_dimension;
/// list of element handled by the material
- ElementTypeMapArray<UInt> element_filter;
+ ElementTypeMapArray<Idx> element_filter;
/// stresses arrays ordered by element types
InternalField<Real> stress;
/// eigengrad_u arrays ordered by element types
InternalField<Real> eigengradu;
/// grad_u arrays ordered by element types
InternalField<Real> gradu;
/// Green Lagrange strain (Finite deformation)
InternalField<Real> green_strain;
/// Second Piola-Kirchhoff stress tensor arrays ordered by element types
/// (Finite deformation)
InternalField<Real> piola_kirchhoff_2;
/// potential energy by element
InternalField<Real> potential_energy;
/// tell if using in non local mode or not
bool is_non_local{false};
/// tell if the material need the previous stress state
bool use_previous_stress{false};
/// tell if the material need the previous strain state
bool use_previous_gradu{false};
/// elemental field interpolation coordinates
InternalField<Real> interpolation_inverse_coordinates;
/// elemental field interpolation points
InternalField<Real> interpolation_points_matrices;
/// vector that contains the names of all the internals that need to
/// be transferred when material interfaces move
std::vector<ID> internals_to_transfer;
private:
/// eigen_grad_u for the parser
Matrix<Real> eigen_grad_u;
};
/// standard output stream operator
inline std::ostream & operator<<(std::ostream & stream,
const Material & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "material_inline_impl.hh"
#include "internal_field_tmpl.hh"
#include "random_internal_field_tmpl.hh"
/* -------------------------------------------------------------------------- */
/* Auto loop */
/* -------------------------------------------------------------------------- */
/// This can be used to automatically write the loop on quadrature points in
/// functions such as computeStress. This macro in addition to write the loop
/// provides two tensors (matrices) sigma and grad_u
#define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \
auto && grad_u_view = \
make_view(this->gradu(el_type, ghost_type), this->spatial_dimension, \
this->spatial_dimension); \
\
auto stress_view = \
make_view(this->stress(el_type, ghost_type), this->spatial_dimension, \
this->spatial_dimension); \
\
if (this->isFiniteDeformation()) { \
stress_view = make_view(this->piola_kirchhoff_2(el_type, ghost_type), \
this->spatial_dimension, this->spatial_dimension); \
} \
\
for (auto && data : zip(grad_u_view, stress_view)) { \
- [[gnu::unused]] Matrix<Real> & grad_u = std::get<0>(data); \
- [[gnu::unused]] Matrix<Real> & sigma = std::get<1>(data)
+ [[gnu::unused]] auto && grad_u = std::get<0>(data); \
+ [[gnu::unused]] auto && sigma = std::get<1>(data)
#define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END }
/// This can be used to automatically write the loop on quadrature points in
/// functions such as computeTangentModuli. This macro in addition to write the
/// loop provides two tensors (matrices) sigma_tensor, grad_u, and a matrix
/// where the elemental tangent moduli should be stored in Voigt Notation
#define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \
auto && grad_u_view = \
make_view(this->gradu(el_type, ghost_type), this->spatial_dimension, \
this->spatial_dimension); \
\
auto && stress_view = \
make_view(this->stress(el_type, ghost_type), this->spatial_dimension, \
this->spatial_dimension); \
\
auto tangent_size = \
- this->getTangentStiffnessVoigtSize(this->spatial_dimension); \
+ Material::getTangentStiffnessVoigtSize(this->spatial_dimension); \
\
auto && tangent_view = make_view(tangent_mat, tangent_size, tangent_size); \
\
for (auto && data : zip(grad_u_view, stress_view, tangent_view)) { \
- [[gnu::unused]] Matrix<Real> & grad_u = std::get<0>(data); \
- [[gnu::unused]] Matrix<Real> & sigma = std::get<1>(data); \
- Matrix<Real> & tangent = std::get<2>(data);
+ [[gnu::unused]] auto && grad_u = std::get<0>(data); \
+ [[gnu::unused]] auto && sigma = std::get<1>(data); \
+ auto && tangent = std::get<2>(data);
#define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END }
/* -------------------------------------------------------------------------- */
-
-#define INSTANTIATE_MATERIAL_ONLY(mat_name) \
- template class mat_name<1>; /* NOLINT */ \
- template class mat_name<2>; /* NOLINT */ \
- template class mat_name<3> /* NOLINT */
-
-#define MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name) \
- [](UInt dim, const ID &, SolidMechanicsModel & model, \
- const ID & id) /* NOLINT */ \
- -> std::unique_ptr< \
- Material> { /* NOLINT */ \
- switch (dim) { \
- case 1: \
- return std::make_unique<mat_name<1>>(/* NOLINT */ \
- model, id); \
- case 2: \
- return std::make_unique<mat_name<2>>(/* NOLINT */ \
- model, id); \
- case 3: \
- return std::make_unique<mat_name<3>>(/* NOLINT */ \
- model, id); \
- default: \
- AKANTU_EXCEPTION( \
- "The dimension " \
- << dim \
- << "is not a valid dimension for the material " \
- << #id); \
- } \
+namespace akantu {
+namespace {
+ template <template <Int> class Mat> bool instantiateMaterial(const ID & id) {
+ return MaterialFactory::getInstance().registerAllocator(
+ id,
+ [](Int dim, const ID &, SolidMechanicsModel & model, const ID & id) {
+ return tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) -> std::unique_ptr<Material> {
+ constexpr auto && dim_ = aka::decay_v<decltype(_)>;
+ return std::make_unique<Mat<dim_>>(model, id);
+ },
+ dim);
+ });
}
-
-#define INSTANTIATE_MATERIAL(id, mat_name) \
- INSTANTIATE_MATERIAL_ONLY(mat_name); \
- static bool material_is_alocated_##id = \
- MaterialFactory::getInstance().registerAllocator( \
- #id, MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name))
+} // namespace
+} // namespace akantu
#endif /* AKANTU_MATERIAL_HH_ */
diff --git a/src/model/solid_mechanics/material_inline_impl.hh b/src/model/solid_mechanics/material_inline_impl.hh
index ed64e6253..844b4ff48 100644
--- a/src/model/solid_mechanics/material_inline_impl.hh
+++ b/src/model/solid_mechanics/material_inline_impl.hh
@@ -1,590 +1,594 @@
/**
* @file material_inline_impl.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Enrico Milanese <enrico.milanese@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Jul 27 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of the inline functions of the class material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "integration_point.hh"
+#include "material.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_MATERIAL_INLINE_IMPL_HH_
-#define AKANTU_MATERIAL_INLINE_IMPL_HH_
+// #ifndef __AKANTU_MATERIAL_INLINE_IMPL_CC__
+// #define __AKANTU_MATERIAL_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt Material::addElement(ElementType type, UInt element,
+inline auto Material::addElement(ElementType type, Int element,
GhostType ghost_type) {
- Array<UInt> & el_filter = this->element_filter(type, ghost_type);
+ auto & el_filter = this->element_filter(type, ghost_type);
el_filter.push_back(element);
return el_filter.size() - 1;
}
/* -------------------------------------------------------------------------- */
-inline UInt Material::addElement(const Element & element) {
+inline auto Material::addElement(const Element & element) {
return this->addElement(element.type, element.element, element.ghost_type);
}
/* -------------------------------------------------------------------------- */
-inline UInt Material::getTangentStiffnessVoigtSize(UInt dim) {
- return (dim * (dim - 1) / 2 + dim);
+template <Int dim, typename D1, typename D2>
+constexpr inline void Material::gradUToF(const Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & F) {
+ assert(F.size() >= grad_u.size() && grad_u.size() == dim * dim &&
+ "The dimension of the tensor F should be greater or "
+ "equal to the dimension of the tensor grad_u.");
+
+ F.setIdentity();
+ F.template block<dim, dim>(0, 0) += grad_u;
}
/* -------------------------------------------------------------------------- */
-inline UInt Material::getCauchyStressMatrixSize(UInt dim) {
- return (dim * dim);
+template <Int dim, typename D1>
+constexpr inline decltype(auto)
+Material::gradUToF(const Eigen::MatrixBase<D1> & grad_u) {
+ Matrix<Real, dim, dim> F;
+ gradUToF<dim>(grad_u, F);
+ return F;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void Material::gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F) {
- AKANTU_DEBUG_ASSERT(F.size() >= grad_u.size() && grad_u.size() == dim * dim,
- "The dimension of the tensor F should be greater or "
- "equal to the dimension of the tensor grad_u.");
- F.eye();
+template <Int dim, typename D1, typename D2, typename D3>
+constexpr inline void Material::StoCauchy(const Eigen::MatrixBase<D1> & F,
+ const Eigen::MatrixBase<D2> & S,
+ Eigen::MatrixBase<D3> & sigma,
+ const Real & C33) {
+ Real J = F.determinant() * std::sqrt(C33);
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- F(i, j) += grad_u(i, j);
- }
- }
+ Matrix<Real, dim, dim> F_S;
+ F_S = F * S;
+ Real constant = J ? 1. / J : 0;
+ sigma = constant * F_S * F.transpose();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline decltype(auto) Material::gradUToF(const Matrix<Real> & grad_u) {
- Matrix<Real> F(dim, dim);
- gradUToF<dim>(grad_u, F);
- return F;
+template <Int dim, typename D1, typename D2>
+constexpr inline decltype(auto)
+Material::StoCauchy(const Eigen::MatrixBase<D1> & F,
+ const Eigen::MatrixBase<D2> & S, const Real & C33) {
+ Matrix<Real, dim, dim> sigma;
+ Material::StoCauchy<dim>(F, S, sigma, C33);
+ return sigma;
}
-
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void Material::StoCauchy(const Matrix<Real> & F, const Matrix<Real> & S,
- Matrix<Real> & sigma, const Real & C33) const {
- Real J = F.det() * sqrt(C33);
+template <typename D1, typename D2>
+constexpr inline void Material::rightCauchy(const Eigen::MatrixBase<D1> & F,
+ Eigen::MatrixBase<D2> & C) {
+ C = F.transpose() * F;
+}
- Matrix<Real> F_S(dim, dim);
- F_S = F * S;
- Real constant = J ? 1. / J : 0;
- sigma.mul<false, true>(F_S, F, constant);
+/* -------------------------------------------------------------------------- */
+template <Int dim, typename D>
+constexpr inline decltype(auto)
+Material::rightCauchy(const Eigen::MatrixBase<D> & F) {
+ Matrix<Real, dim, dim> C;
+ rightCauchy(F, C);
+ return C;
}
/* -------------------------------------------------------------------------- */
-inline void Material::rightCauchy(const Matrix<Real> & F, Matrix<Real> & C) {
- C.mul<true, false>(F, F);
+template <typename D1, typename D2>
+constexpr inline void Material::leftCauchy(const Eigen::MatrixBase<D1> & F,
+ Eigen::MatrixBase<D2> & B) {
+ B = F * F.transpose();
}
/* -------------------------------------------------------------------------- */
-inline void Material::leftCauchy(const Matrix<Real> & F, Matrix<Real> & B) {
- B.mul<false, true>(F, F);
+template <Int dim, typename D>
+constexpr inline decltype(auto)
+Material::leftCauchy(const Eigen::MatrixBase<D> & F) {
+ Matrix<Real, dim, dim> B;
+ rightCauchy(F, B);
+ return B;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void Material::gradUToEpsilon(const Matrix<Real> & grad_u,
- Matrix<Real> & epsilon) {
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- epsilon(i, j) = 0.5 * (grad_u(i, j) + grad_u(j, i));
- }
- }
+template <Int dim, typename D1, typename D2>
+constexpr inline void
+Material::gradUToEpsilon(const Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & epsilon) {
+ epsilon = .5 * (grad_u.transpose() + grad_u);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline decltype(auto) Material::gradUToEpsilon(const Matrix<Real> & grad_u) {
- Matrix<Real> epsilon(dim, dim);
- Material::template gradUToEpsilon<dim>(grad_u, epsilon);
+template <Int dim, typename D1>
+inline decltype(auto) constexpr Material::gradUToEpsilon(
+ const Eigen::MatrixBase<D1> & grad_u) {
+ Matrix<Real, dim, dim> epsilon;
+ Material::gradUToEpsilon<dim>(grad_u, epsilon);
return epsilon;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void Material::gradUToE(const Matrix<Real> & grad_u, Matrix<Real> & E) {
- E.mul<true, false>(grad_u, grad_u, .5);
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- E(i, j) += 0.5 * (grad_u(i, j) + grad_u(j, i));
- }
- }
+template <Int dim, typename D1, typename D2>
+constexpr inline void Material::gradUToE(const Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & E) {
+ E = (grad_u.transpose() * grad_u + grad_u.transpose() + grad_u) / 2.;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline decltype(auto) Material::gradUToE(const Matrix<Real> & grad_u) {
- Matrix<Real> E(dim, dim);
+template <Int dim, typename D1>
+constexpr inline decltype(auto)
+Material::gradUToE(const Eigen::MatrixBase<D1> & grad_u) {
+ Matrix<Real, dim, dim> E;
gradUToE<dim>(grad_u, E);
return E;
}
/* -------------------------------------------------------------------------- */
-inline Real Material::stressToVonMises(const Matrix<Real> & stress) {
+template <typename D1>
+inline Real Material::stressToVonMises(const Eigen::MatrixBase<D1> & stress) {
// compute deviatoric stress
- UInt dim = stress.cols();
- Matrix<Real> deviatoric_stress =
- Matrix<Real>::eye(dim, -1. * stress.trace() / 3.);
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- deviatoric_stress(i, j) += stress(i, j);
- }
- }
+ auto dim = stress.cols();
+ auto && deviatoric_stress =
+ stress - Matrix<Real>::Identity(dim, dim) * stress.trace() / 3.;
// return Von Mises stress
return std::sqrt(3. * deviatoric_stress.doubleDot(deviatoric_stress) / 2.);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void Material::setCauchyStressMatrix(const Matrix<Real> & S_t,
- Matrix<Real> & sigma) {
- AKANTU_DEBUG_IN();
-
+template <Int dim, typename D1, typename D2>
+constexpr inline void
+Material::setCauchyStressMatrix(const Eigen::MatrixBase<D1> & S_t,
+ Eigen::MatrixBase<D2> & sigma) {
sigma.zero();
/// see Finite ekement formulations for large deformation dynamic analysis,
/// Bathe et al. IJNME vol 9, 1975, page 364 ^t \f$\tau\f$
- for (UInt i = 0; i < dim; ++i) {
- for (UInt m = 0; m < dim; ++m) {
- for (UInt n = 0; n < dim; ++n) {
+ for (Int i = 0; i < dim; ++i) {
+ for (Int m = 0; m < dim; ++m) {
+ for (Int n = 0; n < dim; ++n) {
sigma(i * dim + m, i * dim + n) = S_t(m, n);
}
}
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
inline Element
Material::convertToLocalElement(const Element & global_element) const {
- UInt ge = global_element.element;
+ auto ge = global_element.element;
#ifndef AKANTU_NDEBUG
- UInt model_mat_index = this->model.getMaterialByElement(
+ auto model_mat_index = this->model.getMaterialByElement(
global_element.type, global_element.ghost_type)(ge);
- UInt mat_index = this->model.getMaterialIndex(this->name);
+ auto mat_index = this->model.getMaterialIndex(this->name);
AKANTU_DEBUG_ASSERT(model_mat_index == mat_index,
"Conversion of a global element in a local element for "
"the wrong material "
<< this->name << std::endl);
#endif
- UInt le = this->model.getMaterialLocalNumbering(
+ auto le = this->model.getMaterialLocalNumbering(
global_element.type, global_element.ghost_type)(ge);
Element tmp_quad{global_element.type, le, global_element.ghost_type};
return tmp_quad;
}
/* -------------------------------------------------------------------------- */
inline Element
Material::convertToGlobalElement(const Element & local_element) const {
- UInt le = local_element.element;
- UInt ge =
+ auto le = local_element.element;
+ auto ge =
this->element_filter(local_element.type, local_element.ghost_type)(le);
Element tmp_quad{local_element.type, ge, local_element.ghost_type};
return tmp_quad;
}
/* -------------------------------------------------------------------------- */
inline IntegrationPoint
Material::convertToLocalPoint(const IntegrationPoint & global_point) const {
const FEEngine & fem = this->model.getFEEngine();
- UInt nb_quad = fem.getNbIntegrationPoints(global_point.type);
- Element el =
+ auto && nb_quad = fem.getNbIntegrationPoints(global_point.type);
+ auto && el =
this->convertToLocalElement(static_cast<const Element &>(global_point));
- IntegrationPoint tmp_quad(el, global_point.num_point, nb_quad);
- return tmp_quad;
+ return IntegrationPoint(el, global_point.num_point, nb_quad);
}
/* -------------------------------------------------------------------------- */
inline IntegrationPoint
Material::convertToGlobalPoint(const IntegrationPoint & local_point) const {
const FEEngine & fem = this->model.getFEEngine();
- UInt nb_quad = fem.getNbIntegrationPoints(local_point.type);
+ auto nb_quad = fem.getNbIntegrationPoints(local_point.type);
Element el =
this->convertToGlobalElement(static_cast<const Element &>(local_point));
IntegrationPoint tmp_quad(el, local_point.num_point, nb_quad);
return tmp_quad;
}
/* -------------------------------------------------------------------------- */
-inline UInt Material::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+inline Int Material::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
if (tag == SynchronizationTag::_smm_stress) {
return (this->isFiniteDeformation() ? 3 : 1) * spatial_dimension *
spatial_dimension * sizeof(Real) *
this->getModel().getNbIntegrationPoints(elements);
}
return 0;
}
/* -------------------------------------------------------------------------- */
inline void Material::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
if (tag == SynchronizationTag::_smm_stress) {
if (this->isFiniteDeformation()) {
packElementDataHelper(piola_kirchhoff_2, buffer, elements);
packElementDataHelper(gradu, buffer, elements);
}
packElementDataHelper(stress, buffer, elements);
}
}
/* -------------------------------------------------------------------------- */
inline void Material::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
if (tag == SynchronizationTag::_smm_stress) {
if (this->isFiniteDeformation()) {
unpackElementDataHelper(piola_kirchhoff_2, buffer, elements);
unpackElementDataHelper(gradu, buffer, elements);
}
unpackElementDataHelper(stress, buffer, elements);
}
}
/* -------------------------------------------------------------------------- */
inline const Parameter & Material::getParam(const ID & param) const {
try {
return get(param);
} catch (...) {
AKANTU_EXCEPTION("No parameter " << param << " in the material "
<< getID());
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void Material::setParam(const ID & param, T value) {
try {
set<T>(param, value);
} catch (...) {
AKANTU_EXCEPTION("No parameter " << param << " in the material "
<< getID());
}
updateInternalParameters();
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void Material::packElementDataHelper(
const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
const Array<Element> & elements, const ID & fem_id) const {
DataAccessor::packElementalDataHelper<T>(data_to_pack, buffer, elements, true,
model.getFEEngine(fem_id));
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline void Material::unpackElementDataHelper(
ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer,
const Array<Element> & elements, const ID & fem_id) {
DataAccessor::unpackElementalDataHelper<T>(data_to_unpack, buffer, elements,
true, model.getFEEngine(fem_id));
}
/* -------------------------------------------------------------------------- */
template <>
inline void Material::registerInternal<Real>(InternalField<Real> & vect) {
internal_vectors_real[vect.getID()] = &vect;
}
template <>
-inline void Material::registerInternal<UInt>(InternalField<UInt> & vect) {
- internal_vectors_uint[vect.getID()] = &vect;
+inline void Material::registerInternal<Int>(InternalField<Int> & vect) {
+ internal_vectors_int[vect.getID()] = &vect;
}
template <>
inline void Material::registerInternal<bool>(InternalField<bool> & vect) {
internal_vectors_bool[vect.getID()] = &vect;
}
/* -------------------------------------------------------------------------- */
template <>
inline void Material::unregisterInternal<Real>(InternalField<Real> & vect) {
internal_vectors_real.erase(vect.getID());
}
template <>
-inline void Material::unregisterInternal<UInt>(InternalField<UInt> & vect) {
- internal_vectors_uint.erase(vect.getID());
+inline void Material::unregisterInternal<Int>(InternalField<Int> & vect) {
+ internal_vectors_int.erase(vect.getID());
}
template <>
inline void Material::unregisterInternal<bool>(InternalField<bool> & vect) {
internal_vectors_bool.erase(vect.getID());
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline bool Material::isInternal(const ID & /*id*/,
ElementKind /*element_kind*/) const {
AKANTU_TO_IMPLEMENT();
}
template <>
inline bool Material::isInternal<Real>(const ID & id,
ElementKind element_kind) const {
auto internal_array = internal_vectors_real.find(this->getID() + ":" + id);
return not(internal_array == internal_vectors_real.end() ||
internal_array->second->getElementKind() != element_kind);
}
/* -------------------------------------------------------------------------- */
template <typename T>
-inline ElementTypeMap<UInt>
+inline ElementTypeMap<Int>
Material::getInternalDataPerElem(const ID & field_id,
ElementKind element_kind) const {
if (!this->template isInternal<T>(field_id, element_kind)) {
AKANTU_EXCEPTION("Cannot find internal field " << id << " in material "
<< this->name);
}
const InternalField<T> & internal_field =
this->template getInternal<T>(field_id);
- const FEEngine & fe_engine = internal_field.getFEEngine();
- UInt nb_data_per_quad = internal_field.getNbComponent();
+ const auto & fe_engine = internal_field.getFEEngine();
+ auto nb_data_per_quad = internal_field.getNbComponent();
- ElementTypeMap<UInt> res;
+ ElementTypeMap<Int> res;
for (auto ghost_type : ghost_types) {
- for (auto & type : internal_field.elementTypes(ghost_type)) {
- UInt nb_quadrature_points =
+ for (auto && type : internal_field.elementTypes(ghost_type)) {
+ auto nb_quadrature_points =
fe_engine.getNbIntegrationPoints(type, ghost_type);
res(type, ghost_type) = nb_data_per_quad * nb_quadrature_points;
}
}
return res;
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Material::flattenInternal(const std::string & field_id,
ElementTypeMapArray<T> & internal_flat,
const GhostType ghost_type,
ElementKind element_kind) const {
if (!this->template isInternal<T>(field_id, element_kind)) {
AKANTU_EXCEPTION("Cannot find internal field " << id << " in material "
<< this->name);
}
- const InternalField<T> & internal_field =
- this->template getInternal<T>(field_id);
+ const auto & internal_field = this->template getInternal<T>(field_id);
- const FEEngine & fe_engine = internal_field.getFEEngine();
- const Mesh & mesh = fe_engine.getMesh();
+ const auto & fe_engine = internal_field.getFEEngine();
+ const auto & mesh = fe_engine.getMesh();
for (auto && type : internal_field.filterTypes(ghost_type)) {
const auto & src_vect = internal_field(type, ghost_type);
const auto & filter = internal_field.getFilter(type, ghost_type);
// total number of elements in the corresponding mesh
- UInt nb_element_dst = mesh.getNbElement(type, ghost_type);
+ auto nb_element_dst = mesh.getNbElement(type, ghost_type);
// number of element in the internal field
- UInt nb_element_src = filter.size();
+ // auto nb_element_src = filter.size();
// number of quadrature points per elem
- UInt nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type);
+ auto nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type);
// number of data per quadrature point
- UInt nb_data_per_quad = internal_field.getNbComponent();
+ auto nb_data_per_quad = internal_field.getNbComponent();
- if (!internal_flat.exists(type, ghost_type)) {
+ if (not internal_flat.exists(type, ghost_type)) {
internal_flat.alloc(nb_element_dst * nb_quad_per_elem, nb_data_per_quad,
type, ghost_type);
}
// number of data per element
- UInt nb_data = nb_quad_per_elem * nb_data_per_quad;
+ auto nb_data = nb_quad_per_elem * nb_data_per_quad;
- Array<Real> & dst_vect = internal_flat(type, ghost_type);
+ auto & dst_vect = internal_flat(type, ghost_type);
dst_vect.resize(nb_element_dst * nb_quad_per_elem);
auto it_dst = make_view(dst_vect, nb_data).begin();
for (auto && data : zip(filter, make_view(src_vect, nb_data))) {
it_dst[std::get<0>(data)] = std::get<1>(data);
}
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Material::inflateInternal(const std::string & field_id,
const ElementTypeMapArray<T> & field,
GhostType ghost_type, ElementKind element_kind) {
if (!this->template isInternal<T>(field_id, element_kind)) {
AKANTU_EXCEPTION("Cannot find internal field " << id << " in material "
<< this->name);
}
InternalField<T> & internal_field = this->template getInternal<T>(field_id);
const FEEngine & fe_engine = internal_field.getFEEngine();
for (auto && type : field.elementTypes(ghost_type)) {
if (not internal_field.exists(type, ghost_type)) {
continue;
}
const auto & filter = internal_field.getFilter(type, ghost_type);
const auto & src_array = field(type, ghost_type);
auto & dest_array = internal_field(type, ghost_type);
auto nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type);
auto nb_component = src_array.getNbComponent();
AKANTU_DEBUG_ASSERT(
field.size() == fe_engine.getMesh().getNbElement(type, ghost_type) *
nb_quad_per_elem,
"The ElementTypeMapArray to inflate is not of the proper size");
AKANTU_DEBUG_ASSERT(
dest_array.getNbComponent() == nb_component,
"The ElementTypeMapArray has not the proper number of components");
auto src =
make_view(field(type, ghost_type), nb_component, nb_quad_per_elem)
.begin();
for (auto && data :
zip(filter, make_view(dest_array, nb_component, nb_quad_per_elem))) {
std::get<1>(data) = src[std::get<0>(data)];
}
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline const InternalField<T> &
-Material::getInternal([[gnu::unused]] const ID & int_id) const {
+Material::getInternal(const ID & /*int_id*/) const {
AKANTU_TO_IMPLEMENT();
- return NULL;
}
/* -------------------------------------------------------------------------- */
template <typename T>
-inline InternalField<T> &
-Material::getInternal([[gnu::unused]] const ID & int_id) {
+inline InternalField<T> & Material::getInternal(const ID & /*int_id*/) {
AKANTU_TO_IMPLEMENT();
- return NULL;
}
/* -------------------------------------------------------------------------- */
template <>
inline const InternalField<Real> &
Material::getInternal(const ID & int_id) const {
auto it = internal_vectors_real.find(getID() + ":" + int_id);
if (it == internal_vectors_real.end()) {
AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
<< ") does not contain an internal "
<< int_id << " ("
<< (getID() + ":" + int_id) << ")");
}
return *it->second;
}
/* -------------------------------------------------------------------------- */
template <>
inline InternalField<Real> & Material::getInternal(const ID & int_id) {
auto it = internal_vectors_real.find(getID() + ":" + int_id);
if (it == internal_vectors_real.end()) {
AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
<< ") does not contain an internal "
<< int_id << " ("
<< (getID() + ":" + int_id) << ")");
}
return *it->second;
}
/* -------------------------------------------------------------------------- */
template <>
-inline const InternalField<UInt> &
+inline const InternalField<Int> &
Material::getInternal(const ID & int_id) const {
- auto it = internal_vectors_uint.find(getID() + ":" + int_id);
- if (it == internal_vectors_uint.end()) {
+ auto it = internal_vectors_int.find(getID() + ":" + int_id);
+ if (it == internal_vectors_int.end()) {
AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
<< ") does not contain an internal "
<< int_id << " ("
<< (getID() + ":" + int_id) << ")");
}
return *it->second;
}
/* -------------------------------------------------------------------------- */
template <>
-inline InternalField<UInt> & Material::getInternal(const ID & int_id) {
- auto it = internal_vectors_uint.find(getID() + ":" + int_id);
- if (it == internal_vectors_uint.end()) {
+inline InternalField<Int> & Material::getInternal(const ID & int_id) {
+ auto it = internal_vectors_int.find(getID() + ":" + int_id);
+ if (it == internal_vectors_int.end()) {
AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
<< ") does not contain an internal "
<< int_id << " ("
<< (getID() + ":" + int_id) << ")");
}
return *it->second;
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline const Array<T> & Material::getArray(const ID & vect_id, ElementType type,
GhostType ghost_type) const {
try {
return this->template getInternal<T>(vect_id)(type, ghost_type);
} catch (debug::Exception & e) {
AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
<< ") does not contain a vector "
<< vect_id << " [" << e << "]");
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
inline Array<T> & Material::getArray(const ID & vect_id, ElementType type,
GhostType ghost_type) {
try {
return this->template getInternal<T>(vect_id)(type, ghost_type);
} catch (debug::Exception & e) {
AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
<< ") does not contain a vector "
<< vect_id << " [" << e << "]");
}
}
} // namespace akantu
-#endif /* AKANTU_MATERIAL_INLINE_IMPL_HH_ */
+//#endif /* __AKANTU_MATERIAL_INLINE_IMPL_CC__ */
diff --git a/src/model/solid_mechanics/material_selector.hh b/src/model/solid_mechanics/material_selector.hh
index 6550a4057..919e9187a 100644
--- a/src/model/solid_mechanics/material_selector.hh
+++ b/src/model/solid_mechanics/material_selector.hh
@@ -1,159 +1,159 @@
/**
* @file material_selector.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri Apr 09 2021
*
* @brief class describing how to choose a material for a given element
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <memory>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_SELECTOR_HH_
#define AKANTU_MATERIAL_SELECTOR_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class SolidMechanicsModel;
/**
* main class to assign same or different materials for different
* elements
*/
class MaterialSelector {
public:
MaterialSelector() = default;
virtual ~MaterialSelector() = default;
- virtual inline UInt operator()(const Element & element) {
+ virtual inline Int operator()(const Element & element) {
if (fallback_selector) {
return (*fallback_selector)(element);
}
return fallback_value;
}
- inline void setFallback(UInt f) { fallback_value = f; }
+ inline void setFallback(Int f) { fallback_value = f; }
inline void
setFallback(const std::shared_ptr<MaterialSelector> & fallback_selector) {
this->fallback_selector = fallback_selector;
}
inline std::shared_ptr<MaterialSelector> & getFallbackSelector() {
return this->fallback_selector;
}
- inline UInt getFallbackValue() const { return this->fallback_value; }
+ inline Int getFallbackValue() const { return this->fallback_value; }
protected:
- UInt fallback_value{0};
+ Int fallback_value{0};
std::shared_ptr<MaterialSelector> fallback_selector;
};
/* -------------------------------------------------------------------------- */
/**
* class that assigns the first material to regular elements by default
*/
class DefaultMaterialSelector : public MaterialSelector {
public:
explicit DefaultMaterialSelector(
- const ElementTypeMapArray<UInt> & material_index)
+ const ElementTypeMapArray<Idx> & material_index)
: material_index(material_index) {}
- UInt operator()(const Element & element) override {
+ Int operator()(const Element & element) override {
if (not material_index.exists(element.type, element.ghost_type)) {
return MaterialSelector::operator()(element);
}
const auto & mat_indexes = material_index(element.type, element.ghost_type);
if (element.element < mat_indexes.size()) {
auto && tmp_mat = mat_indexes(element.element);
- if (tmp_mat != UInt(-1)) {
+ if (tmp_mat != Int(-1)) {
return tmp_mat;
}
}
return MaterialSelector::operator()(element);
}
private:
- const ElementTypeMapArray<UInt> & material_index;
+ const ElementTypeMapArray<Idx> & material_index;
};
/* -------------------------------------------------------------------------- */
/**
* Use elemental data to assign materials
*/
template <typename T>
class ElementDataMaterialSelector : public MaterialSelector {
public:
ElementDataMaterialSelector(const ElementTypeMapArray<T> & element_data,
const SolidMechanicsModel & model,
- UInt first_index = 1)
+ Int first_index = 1)
: element_data(element_data), model(model), first_index(first_index) {}
inline T elementData(const Element & element) {
DebugLevel dbl = debug::getDebugLevel();
debug::setDebugLevel(dblError);
T data = element_data(element);
debug::setDebugLevel(dbl);
return data;
}
- inline UInt operator()(const Element & element) override;
+ inline Int operator()(const Element & element) override;
protected:
/// list of element with the specified data (i.e. tag value)
const ElementTypeMapArray<T> & element_data;
/// the model that the materials belong
const SolidMechanicsModel & model;
/// first material index: equal to 1 if none specified
- UInt first_index;
+ Int first_index;
};
/* -------------------------------------------------------------------------- */
/**
* class to use mesh data information to assign different materials
* where name is the tag value: tag_0, tag_1
*/
template <typename T>
class MeshDataMaterialSelector : public ElementDataMaterialSelector<T> {
public:
MeshDataMaterialSelector(const std::string & name,
const SolidMechanicsModel & model,
- UInt first_index = 1);
+ Int first_index = 1);
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_SELECTOR_HH_ */
diff --git a/src/model/solid_mechanics/material_selector_tmpl.hh b/src/model/solid_mechanics/material_selector_tmpl.hh
index a770f8c5a..f3a694caa 100644
--- a/src/model/solid_mechanics/material_selector_tmpl.hh
+++ b/src/model/solid_mechanics/material_selector_tmpl.hh
@@ -1,82 +1,81 @@
/**
* @file material_selector_tmpl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of the template MaterialSelector
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_selector.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_SELECTOR_TMPL_HH_
#define AKANTU_MATERIAL_SELECTOR_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <>
-inline UInt
+inline Int
ElementDataMaterialSelector<std::string>::operator()(const Element & element) {
try {
std::string material_name = this->elementData(element);
return model.getMaterialIndex(material_name);
} catch (std::exception & e) {
return MaterialSelector::operator()(element);
}
}
/* -------------------------------------------------------------------------- */
template <>
-inline UInt
-ElementDataMaterialSelector<UInt>::operator()(const Element & element) {
+inline Int
+ElementDataMaterialSelector<Int>::operator()(const Element & element) {
try {
return this->elementData(element) - first_index;
} catch (...) {
return MaterialSelector::operator()(element);
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
-inline UInt
-ElementDataMaterialSelector<T>::operator()(const Element & element) {
+inline Int ElementDataMaterialSelector<T>::operator()(const Element & element) {
return MaterialSelector::operator()(element);
}
/* -------------------------------------------------------------------------- */
template <typename T>
MeshDataMaterialSelector<T>::MeshDataMaterialSelector(
const std::string & name, const SolidMechanicsModel & model,
- UInt first_index)
+ Int first_index)
: ElementDataMaterialSelector<T>(model.getMesh().getData<T>(name), model,
first_index) {}
} // namespace akantu
#endif /* AKANTU_MATERIAL_SELECTOR_TMPL_HH_ */
diff --git a/src/model/solid_mechanics/materials/internal_field.hh b/src/model/solid_mechanics/materials/internal_field.hh
index 09c4fe533..410461ab6 100644
--- a/src/model/solid_mechanics/materials/internal_field.hh
+++ b/src/model/solid_mechanics/materials/internal_field.hh
@@ -1,249 +1,250 @@
/**
* @file internal_field.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Mar 26 2021
*
* @brief Material internal properties
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "element_type_map.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_INTERNAL_FIELD_HH_
#define AKANTU_INTERNAL_FIELD_HH_
namespace akantu {
class Material;
class FEEngine;
/**
* class for the internal fields of materials
* to store values for each quadrature
*/
template <class Material_, typename T>
class InternalFieldTmpl : public ElementTypeMapArray<T> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using Material = Material_;
InternalFieldTmpl(const ID & id, Material & material);
~InternalFieldTmpl() override;
/// This constructor is only here to let cohesive elements compile
InternalFieldTmpl(const ID & id, Material & material, FEEngine & fem,
- const ElementTypeMapArray<UInt> & element_filter);
+ const ElementTypeMapArray<Idx> & element_filter);
/// More general constructor
- InternalFieldTmpl(const ID & id, Material & material, UInt dim,
- FEEngine & fem,
- const ElementTypeMapArray<UInt> & element_filter);
+ InternalFieldTmpl(const ID & id, Material & material, Int dim, FEEngine & fem,
+ const ElementTypeMapArray<Idx> & element_filter);
InternalFieldTmpl(const ID & id,
const InternalFieldTmpl<Material, T> & other);
- InternalFieldTmpl operator=(const InternalFieldTmpl &) = delete;
+ auto operator=(const InternalFieldTmpl &) -> InternalFieldTmpl = delete;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// function to reset the FEEngine for the internal field
virtual void setFEEngine(FEEngine & fe_engine);
/// function to reset the element kind for the internal
virtual void setElementKind(ElementKind element_kind);
/// initialize the field to a given number of component
virtual void initialize(UInt nb_component);
/// activate the history of this field
virtual void initializeHistory();
/// resize the arrays and set the new element to 0
virtual void resize();
/// set the field to a given value v
virtual void setDefaultValue(const T & v);
/// reset all the fields to the default value
virtual void reset();
/// save the current values in the history
virtual void saveCurrentValues();
/// restore the previous values from the history
virtual void restorePreviousValues();
/// remove the quadrature points corresponding to suppressed elements
virtual void
- removeIntegrationPoints(const ElementTypeMapArray<UInt> & new_numbering);
+ removeIntegrationPoints(const ElementTypeMapArray<Int> & new_numbering);
/// print the content
void printself(std::ostream & stream, int /*indent*/ = 0) const override;
/// get the default value
inline operator T() const;
- virtual FEEngine & getFEEngine() { return *fem; }
+ virtual auto getFEEngine() -> FEEngine & { return *fem; }
- virtual const FEEngine & getFEEngine() const { return *fem; }
+ virtual auto getFEEngine() const -> const FEEngine & { return *fem; }
protected:
/// initialize the arrays in the ElementTypeMapArray<T>
- void internalInitialize(UInt nb_component);
+ void internalInitialize(Int nb_component);
/// set the values for new internals
virtual void setArrayValues(T * begin, T * end);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get filter types for range loop
decltype(auto) elementTypes(GhostType ghost_type = _not_ghost) const {
return ElementTypeMapArray<T>::elementTypes(
_spatial_dimension = this->spatial_dimension,
_element_kind = this->element_kind, _ghost_type = ghost_type);
}
/// get filter types for range loop
decltype(auto) filterTypes(GhostType ghost_type = _not_ghost) const {
return this->element_filter.elementTypes(
_spatial_dimension = this->spatial_dimension,
_element_kind = this->element_kind, _ghost_type = ghost_type);
}
/// get the array for a given type of the element_filter
- const Array<UInt> & getFilter(ElementType type,
- GhostType ghost_type = _not_ghost) const {
- return this->element_filter(type, ghost_type);
+ decltype(auto) getFilter(ElementType type,
+ GhostType ghost_type = _not_ghost) const {
+ return (this->element_filter(type, ghost_type));
}
/// get the Array corresponding to the type en ghost_type specified
- virtual Array<T> & operator()(ElementType type,
- GhostType ghost_type = _not_ghost) {
+ virtual auto operator()(ElementType type, GhostType ghost_type = _not_ghost)
+ -> Array<T> & {
return ElementTypeMapArray<T>::operator()(type, ghost_type);
}
- virtual const Array<T> & operator()(ElementType type,
- GhostType ghost_type = _not_ghost) const {
+ virtual auto operator()(ElementType type,
+ GhostType ghost_type = _not_ghost) const
+ -> const Array<T> & {
return ElementTypeMapArray<T>::operator()(type, ghost_type);
}
- virtual Array<T> & previous(ElementType type,
- GhostType ghost_type = _not_ghost) {
+ virtual auto previous(ElementType type, GhostType ghost_type = _not_ghost)
+ -> Array<T> & {
AKANTU_DEBUG_ASSERT(previous_values != nullptr,
"The history of the internal "
<< this->getID() << " has not been activated");
return this->previous_values->operator()(type, ghost_type);
}
- virtual const Array<T> & previous(ElementType type,
- GhostType ghost_type = _not_ghost) const {
+ virtual auto previous(ElementType type,
+ GhostType ghost_type = _not_ghost) const
+ -> const Array<T> & {
AKANTU_DEBUG_ASSERT(previous_values != nullptr,
"The history of the internal "
<< this->getID() << " has not been activated");
return this->previous_values->operator()(type, ghost_type);
}
- virtual InternalFieldTmpl<Material, T> & previous() {
+ virtual auto previous() -> InternalFieldTmpl & {
AKANTU_DEBUG_ASSERT(previous_values != nullptr,
"The history of the internal "
<< this->getID() << " has not been activated");
return *(this->previous_values);
}
- virtual const InternalFieldTmpl<Material, T> & previous() const {
+ virtual auto previous() const -> const InternalFieldTmpl & {
AKANTU_DEBUG_ASSERT(previous_values != nullptr,
"The history of the internal "
<< this->getID() << " has not been activated");
return *(this->previous_values);
}
/// check if the history is used or not
- bool hasHistory() const { return (previous_values != nullptr); }
+ auto hasHistory() const -> bool { return (previous_values != nullptr); }
- /// get the kind treated by the internal
- ElementKind getElementKind() const { return element_kind; }
+ /// get the kind treated by the internal
+ AKANTU_GET_MACRO_AUTO(ElementKind, element_kind);
/// return the number of components
- UInt getNbComponent() const { return nb_component; }
+ AKANTU_GET_MACRO_AUTO(NbComponent, nb_component);
/// return the spatial dimension corresponding to the internal element type
/// loop filter
- UInt getSpatialDimension() const { return this->spatial_dimension; }
+ AKANTU_GET_MACRO_AUTO(SpatialDimension, spatial_dimension);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// the material for which this is an internal parameter
Material & material;
/// the fem containing the mesh and the element informations
FEEngine * fem{nullptr};
/// Element filter if needed
- const ElementTypeMapArray<UInt> & element_filter;
+ const ElementTypeMapArray<Int> & element_filter;
/// default value
T default_value{};
/// spatial dimension of the element to consider
- UInt spatial_dimension{0};
+ Int spatial_dimension{0};
/// ElementKind of the element to consider
ElementKind element_kind{_ek_regular};
/// Number of component of the internal field
- UInt nb_component{0};
+ Int nb_component{0};
/// Is the field initialized
bool is_init{false};
/// previous values
std::unique_ptr<InternalFieldTmpl<Material, T>> previous_values;
};
/// standard output stream operator
template <class Material, typename T>
-inline std::ostream & operator<<(std::ostream & stream,
- const InternalFieldTmpl<Material, T> & _this) {
+inline auto operator<<(std::ostream & stream, const InternalFieldTmpl<Material, T> & _this)
+ -> std::ostream & {
_this.printself(stream);
return stream;
}
template <typename T> using InternalField = InternalFieldTmpl<Material, T>;
} // namespace akantu
#endif /* AKANTU_INTERNAL_FIELD_HH_ */
diff --git a/src/model/solid_mechanics/materials/internal_field_tmpl.hh b/src/model/solid_mechanics/materials/internal_field_tmpl.hh
index 38eb03344..569662f2c 100644
--- a/src/model/solid_mechanics/materials/internal_field_tmpl.hh
+++ b/src/model/solid_mechanics/materials/internal_field_tmpl.hh
@@ -1,335 +1,336 @@
/**
* @file internal_field_tmpl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 13 2013
* @date last modification: Fri Apr 02 2021
*
* @brief Material internal properties
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_INTERNAL_FIELD_TMPL_HH_
#define AKANTU_INTERNAL_FIELD_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
InternalFieldTmpl<Material, T>::InternalFieldTmpl(const ID & id,
Material & material)
: ElementTypeMapArray<T>(id, material.getID()), material(material),
fem(&(material.getModel().getFEEngine())),
element_filter(material.getElementFilter()),
spatial_dimension(material.getModel().getSpatialDimension()) {}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
InternalFieldTmpl<Material, T>::InternalFieldTmpl(
const ID & id, Material & material, FEEngine & fem,
- const ElementTypeMapArray<UInt> & element_filter)
+ const ElementTypeMapArray<Idx> & element_filter)
: ElementTypeMapArray<T>(id, material.getID()), material(material),
fem(&fem), element_filter(element_filter),
spatial_dimension(material.getSpatialDimension()) {}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
InternalFieldTmpl<Material, T>::InternalFieldTmpl(
- const ID & id, Material & material, UInt dim, FEEngine & fem,
- const ElementTypeMapArray<UInt> & element_filter)
+ const ID & id, Material & material, Int dim, FEEngine & fem,
+ const ElementTypeMapArray<Idx> & element_filter)
: ElementTypeMapArray<T>(id, material.getID()), material(material),
fem(&fem), element_filter(element_filter), spatial_dimension(dim) {}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
InternalFieldTmpl<Material, T>::InternalFieldTmpl(
const ID & id, const InternalFieldTmpl<Material, T> & other)
: ElementTypeMapArray<T>(id, other.material.getID()),
material(other.material), fem(other.fem),
element_filter(other.element_filter), default_value(other.default_value),
spatial_dimension(other.spatial_dimension),
element_kind(other.element_kind), nb_component(other.nb_component) {
AKANTU_DEBUG_ASSERT(other.is_init,
"Cannot create a copy of a non initialized field");
this->internalInitialize(this->nb_component);
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
InternalFieldTmpl<Material, T>::~InternalFieldTmpl() {
if (this->is_init) {
this->material.unregisterInternal(*this);
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::setFEEngine(FEEngine & fe_engine) {
this->fem = &fe_engine;
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::setElementKind(ElementKind element_kind) {
this->element_kind = element_kind;
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::initialize(UInt nb_component) {
internalInitialize(nb_component);
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::initializeHistory() {
if (!previous_values) {
previous_values = std::make_unique<InternalFieldTmpl<Material, T>>(
"previous_" + this->getID(), *this);
+ previous_values->reset();
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::resize() {
if (!this->is_init) {
return;
}
for (auto ghost : ghost_types) {
for (const auto & type : this->filterTypes(ghost)) {
UInt nb_element = this->element_filter(type, ghost).size();
UInt nb_quadrature_points =
this->fem->getNbIntegrationPoints(type, ghost);
UInt new_size = nb_element * nb_quadrature_points;
UInt old_size = 0;
Array<T> * vect = nullptr;
if (this->exists(type, ghost)) {
vect = &(this->operator()(type, ghost));
old_size = vect->size();
vect->resize(new_size);
} else {
vect = &(this->alloc(nb_element * nb_quadrature_points, nb_component,
type, ghost));
}
- this->setArrayValues(vect->storage() + old_size * vect->getNbComponent(),
- vect->storage() + new_size * vect->getNbComponent());
+ this->setArrayValues(vect->data() + old_size * vect->getNbComponent(),
+ vect->data() + new_size * vect->getNbComponent());
}
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::setDefaultValue(const T & value) {
this->default_value = value;
this->reset();
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::reset() {
for (auto ghost_type : ghost_types) {
for (const auto & type : this->elementTypes(ghost_type)) {
Array<T> & vect = (*this)(type, ghost_type);
// vect.zero();
- this->setArrayValues(
- vect.storage(), vect.storage() + vect.size() * vect.getNbComponent());
+ this->setArrayValues(vect.data(),
+ vect.data() + vect.size() * vect.getNbComponent());
}
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
-void InternalFieldTmpl<Material, T>::internalInitialize(UInt nb_component) {
+void InternalFieldTmpl<Material, T>::internalInitialize(Int nb_component) {
if (!this->is_init) {
this->nb_component = nb_component;
for (auto ghost : ghost_types) {
for (const auto & type : this->filterTypes(ghost)) {
- UInt nb_element = this->element_filter(type, ghost).size();
- UInt nb_quadrature_points =
+ auto nb_element = this->element_filter(type, ghost).size();
+ auto nb_quadrature_points =
this->fem->getNbIntegrationPoints(type, ghost);
if (this->exists(type, ghost)) {
this->operator()(type, ghost)
.resize(nb_element * nb_quadrature_points);
} else {
this->alloc(nb_element * nb_quadrature_points, nb_component, type,
ghost);
}
}
}
this->material.registerInternal(*this);
this->is_init = true;
}
this->reset();
if (this->previous_values) {
this->previous_values->internalInitialize(nb_component);
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::setArrayValues(T * begin, T * end) {
for (; begin < end; ++begin) {
*begin = this->default_value;
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::saveCurrentValues() {
AKANTU_DEBUG_ASSERT(this->previous_values != nullptr,
"The history of the internal "
<< this->getID() << " has not been activated");
if (not this->is_init) {
return;
}
for (auto ghost_type : ghost_types) {
for (const auto & type : this->elementTypes(ghost_type)) {
(*this->previous_values)(type, ghost_type)
.copy((*this)(type, ghost_type));
}
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::restorePreviousValues() {
AKANTU_DEBUG_ASSERT(this->previous_values != nullptr,
"The history of the internal "
<< this->getID() << " has not been activated");
if (not this->is_init) {
return;
}
for (auto ghost_type : ghost_types) {
for (const auto & type : this->elementTypes(ghost_type)) {
(*this)(type, ghost_type)
.copy((*this->previous_values)(type, ghost_type));
}
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::removeIntegrationPoints(
- const ElementTypeMapArray<UInt> & new_numbering) {
+ const ElementTypeMapArray<Idx> & new_numbering) {
for (auto ghost_type : ghost_types) {
for (auto type : new_numbering.elementTypes(_all_dimensions, ghost_type,
_ek_not_defined)) {
if (not this->exists(type, ghost_type)) {
continue;
}
Array<T> & vect = (*this)(type, ghost_type);
if (vect.empty()) {
continue;
}
- const Array<UInt> & renumbering = new_numbering(type, ghost_type);
+ const auto & renumbering = new_numbering(type, ghost_type);
- UInt nb_quad_per_elem = fem->getNbIntegrationPoints(type, ghost_type);
- UInt nb_component = vect.getNbComponent();
+ auto nb_quad_per_elem = fem->getNbIntegrationPoints(type, ghost_type);
+ auto nb_component = vect.getNbComponent();
Array<T> tmp(renumbering.size() * nb_quad_per_elem, nb_component);
AKANTU_DEBUG_ASSERT(
tmp.size() == vect.size(),
"Something strange append some mater was created from nowhere!!");
AKANTU_DEBUG_ASSERT(
tmp.size() == vect.size(),
"Something strange append some mater was created or disappeared in "
<< vect.getID() << "(" << vect.size() << "!=" << tmp.size()
<< ") "
"!!");
UInt new_size = 0;
- for (UInt i = 0; i < renumbering.size(); ++i) {
- UInt new_i = renumbering(i);
- if (new_i != UInt(-1)) {
- memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem,
- vect.storage() + i * nb_component * nb_quad_per_elem,
+ for (Int i = 0; i < renumbering.size(); ++i) {
+ auto new_i = renumbering(i);
+ if (new_i != Int(-1)) {
+ memcpy(tmp.data() + new_i * nb_component * nb_quad_per_elem,
+ vect.data() + i * nb_component * nb_quad_per_elem,
nb_component * nb_quad_per_elem * sizeof(T));
++new_size;
}
}
tmp.resize(new_size * nb_quad_per_elem);
vect.copy(tmp);
}
}
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
void InternalFieldTmpl<Material, T>::printself(std::ostream & stream, int indent
[[gnu::unused]]) const {
stream << "InternalField [ " << this->getID();
#if !defined(AKANTU_NDEBUG)
if (AKANTU_DEBUG_TEST(dblDump)) {
stream << std::endl;
ElementTypeMapArray<T>::printself(stream, indent + 3);
} else {
#endif
stream << " {" << this->getData(_not_ghost).size() << " types - "
<< this->getData(_ghost).size() << " ghost types"
<< "}";
#if !defined(AKANTU_NDEBUG)
}
#endif
stream << " ]";
}
/* -------------------------------------------------------------------------- */
template <>
inline void
ParameterTyped<InternalField<Real>>::setAuto(const ParserParameter & in_param) {
Parameter::setAuto(in_param);
Real r = in_param;
param.setDefaultValue(r);
}
/* -------------------------------------------------------------------------- */
template <class Material, typename T>
inline InternalFieldTmpl<Material, T>::operator T() const {
return default_value;
}
} // namespace akantu
#endif /* AKANTU_INTERNAL_FIELD_TMPL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.cc b/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.cc
index 85fb1fc45..274112ea8 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.cc
@@ -1,84 +1,65 @@
/**
* @file material_anisotropic_damage.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Jul 03 2019
* @date last modification: Fri Jul 24 2020
*
* @brief Base class for anisotropic damage materials
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_anisotropic_damage.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-namespace {
- template <UInt dim>
- std::unique_ptr<Material>
- materialAnisotropicDamage(std::integral_constant<UInt, dim> /*unused*/,
- const ID & option, SolidMechanicsModel & model,
- const ID & id) {
- if (option.empty() or option == "mazars") {
- return std::make_unique<MaterialAnisotropicDamage<
- dim, EquivalentStrainMazars, DamageThresholdTan>>(model, id);
- }
- if (option == "mazars-drucker-prager") {
- return std::make_unique<MaterialAnisotropicDamage<
- dim, EquivalentStrainMazarsDruckerPrager, DamageThresholdTan>>(model,
- id);
- }
- AKANTU_EXCEPTION("The option " << option
- << " is not valid for the material " << id);
- }
-
- template <class... Args>
- decltype(auto) dimensionDispatch(UInt dim, Args &&... args) {
- switch (dim) {
- case 1:
- return materialAnisotropicDamage(std::integral_constant<UInt, 1>{},
- std::forward<Args>(args)...);
- case 2:
- return materialAnisotropicDamage(std::integral_constant<UInt, 2>{},
- std::forward<Args>(args)...);
- case 3:
- return materialAnisotropicDamage(std::integral_constant<UInt, 3>{},
- std::forward<Args>(args)...);
- default: {
- AKANTU_EXCEPTION("In what dimension are you leaving ?");
- }
- }
- }
-} // namespace
static bool material_is_alocated_anisotropic_damage [[gnu::unused]] =
MaterialFactory::getInstance().registerAllocator(
"anisotropic_damage",
- [](UInt dim, const ID & option, SolidMechanicsModel & model,
+ [](Int dim, const ID & option, SolidMechanicsModel & model,
const ID & id) -> std::unique_ptr<Material> {
- return dimensionDispatch(dim, option, model, id);
+ return tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) -> std::unique_ptr<Material> {
+ constexpr auto dim_ = aka::decay_v<decltype(_)>;
+
+ if (option.empty() or option == "mazars") {
+ return std::make_unique<MaterialAnisotropicDamage<
+ dim_, EquivalentStrainMazars, DamageThresholdTan>>(model,
+ id);
+ }
+ if (option == "mazars-drucker-prager") {
+ return std::make_unique<MaterialAnisotropicDamage<
+ dim_, EquivalentStrainMazarsDruckerPrager,
+ DamageThresholdTan>>(model, id);
+ }
+ AKANTU_EXCEPTION("The option "
+ << option << " is not valid for the material "
+ << id);
+ },
+ dim);
});
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.hh b/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.hh
index 18753a634..4503d3bfb 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage.hh
@@ -1,91 +1,109 @@
/**
* @file material_anisotropic_damage.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Feb 03 2018
* @date last modification: Fri Jul 24 2020
*
* @brief Base class for anisotropic damage materials
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ANISOTROPIC_DAMAGE_HH_
#define AKANTU_MATERIAL_ANISOTROPIC_DAMAGE_HH_
namespace akantu {
-template <UInt dim, template <UInt> class EquivalentStrain,
- template <UInt> class DamageThreshold,
- template <UInt> class Parent = MaterialElastic>
+template <Int dim, template <Int> class EquivalentStrain,
+ template <Int> class DamageThreshold,
+ template <Int> class Parent = MaterialElastic>
class MaterialAnisotropicDamage : public Parent<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialAnisotropicDamage(SolidMechanicsModel & model, const ID & id = "");
~MaterialAnisotropicDamage() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void computeStress(ElementType el_type, GhostType ghost_type) override;
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ Parent<dim>::getArguments(el_type, ghost_type),
+ "damage"_n = make_view<dim, dim>(this->damage(el_type, ghost_type)),
+ "sigma_el"_n =
+ make_view<dim, dim>(this->elastic_stress(el_type, ghost_type)),
+ "epsilon_hat"_n = this->equivalent_strain(el_type, ghost_type),
+ "TrD"_n = this->trace_damage(el_type, ghost_type),
+ "TrD_n_1"_n = this->trace_damage.previous(el_type, ghost_type),
+ "equivalent_strain_data"_n = equivalent_strain_function,
+ "damage_threshold_data"_n = damage_threshold_function);
+ }
+
+ template <class Args> void computeStressOnQuad(Args && args);
+
private:
- void damageStress(Matrix<double> & sigma, const Matrix<double> & sigma_el,
- const Matrix<double> & D, Real TrD);
+ template <class D1, class D2, class D3>
+ void damageStress(Eigen::MatrixBase<D1> & sigma,
+ const Eigen::MatrixBase<D2> & sigma_el,
+ const Eigen::MatrixBase<D3> & D, Real TrD);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
Real Dc{0.99};
/// damage internal variable
InternalField<Real> damage;
/// elastic stress
InternalField<Real> elastic_stress;
/// equivalent strain
InternalField<Real> equivalent_strain;
/// trace of the damageThreshold
InternalField<Real> trace_damage;
/// damage criteria
EquivalentStrain<dim> equivalent_strain_function;
/// damage evolution
DamageThreshold<dim> damage_threshold_function;
};
} // namespace akantu
#include "material_anisotropic_damage_tmpl.hh"
#endif /* AKANTU_MATERIAL_ANISOTROPIC_DAMAGE_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh b/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh
index bd8d91853..404561459 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh
@@ -1,380 +1,379 @@
/**
* @file material_anisotropic_damage_tmpl.hh
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Jul 03 2019
* @date last modification: Fri Jul 24 2020
*
* @brief Base class for anisotropic damage materials
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "material_anisotropic_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ANISOTROPIC_DAMAGE_TMPL_HH_
#define AKANTU_MATERIAL_ANISOTROPIC_DAMAGE_TMPL_HH_
namespace akantu {
struct EmptyIteratorContainer {
+ using size_type = std::size_t;
+
struct iterator {
auto & operator++() { return *this; }
Real operator*() { return 0; }
bool operator!=(const iterator & /*unused*/) const { return true; }
bool operator==(const iterator & /*unused*/) const { return false; }
};
auto begin() const // NOLINT(readability-convert-member-functions-to-static)
{
return iterator();
}
auto end() const // NOLINT(readability-convert-member-functions-to-static)
{
return iterator();
}
};
} // namespace akantu
namespace std {
template <> struct iterator_traits<::akantu::EmptyIteratorContainer::iterator> {
using iterator_category = forward_iterator_tag;
using value_type = akantu::Real;
using difference_type = std::ptrdiff_t;
using pointer = akantu::Real *;
using reference = akantu::Real &;
};
} // namespace std
namespace akantu {
namespace {
- template <UInt dim, class Op>
- void tensorPlus_(const Matrix<Real> & A, Op && oper) {
- Vector<Real> A_eigs(dim);
+ template <Int dim, class D, class Op>
+ void tensorPlus_(const Eigen::MatrixBase<D> & A, Op && oper) {
+ Vector<Real, dim> A_eigs;
A.eig(A_eigs);
for (auto & ap : A_eigs) {
oper(ap);
}
}
- template <UInt dim> auto tensorPlus2(const Matrix<Real> & A) {
+ template <Int dim, class D> auto tensorPlus2(const Eigen::MatrixBase<D> & A) {
Real square = 0;
tensorPlus_<dim>(A, [&](Real eig) {
eig = std::max(eig, 0.);
square += eig * eig;
});
return square;
}
- template <UInt dim> auto tensorPlusTrace(const Matrix<Real> & A) {
- Real trace_plus = 0;
- Real trace_minus = 0;
+ template <Int dim, class D>
+ auto tensorPlusTrace(const Eigen::MatrixBase<D> & A) {
+ Real trace_plus = 0.;
+ Real trace_minus = 0.;
tensorPlus_<dim>(A, [&](Real eig) {
trace_plus += std::max(eig, 0.);
trace_minus += std::min(eig, 0.);
});
return std::make_pair(trace_plus, trace_minus);
}
- template <UInt dim, class Op>
- auto tensorPlusOp(const Matrix<Real> & A, Matrix<Real> & A_directions,
- Op && oper, bool sorted = false) {
- Vector<Real> A_eigs(dim);
- Matrix<Real> A_diag(dim, dim);
- A.eig(A_eigs, A_directions, sorted);
+ template <Int dim, class Op, class D1, class D2>
+ auto tensorPlusOp(const Eigen::MatrixBase<D1> & A,
+ Eigen::MatrixBase<D2> & A_directions, Op && oper) {
+ Vector<Real, dim> A_eigs;
+ Matrix<Real, dim, dim> A_diag;
+ A.eig(A_eigs, A_directions);
- for (auto && data : enumerate(A_eigs)) {
- auto i = std::get<0>(data);
- A_diag(i, i) = oper(std::max(std::get<1>(data), 0.), i);
+ for (auto && [i, eig] : enumerate(A_eigs)) {
+ A_diag(i, i) = oper(std::max(eig, 0.), i);
}
- return A_directions * A_diag * A_directions.transpose();
+ Matrix<Real, dim, dim> res =
+ A_directions * A_diag * A_directions.transpose();
+ return res;
}
- template <UInt dim, class Op>
- auto tensorPlus(const Matrix<Real> & A, Matrix<Real> & A_directions,
- bool sorted = false) {
- return tensorPlusOp<dim>(
- A, A_directions, [](Real x, Real /*unused*/) { return x; }, sorted);
+ template <Int dim, class D1, class D2, class Op>
+ auto tensorPlus(const Eigen::MatrixBase<D1> & A,
+ Eigen::MatrixBase<D2> & A_directions) {
+ return tensorPlusOp<dim>(A, A_directions, [](Real x, Real) { return x; });
}
- template <UInt dim, class Op>
- auto tensorPlusOp(const Matrix<Real> & A, Op && oper) {
- Matrix<Real> A_directions(dim, dim);
+ template <Int dim, class D, class Op>
+ auto tensorPlusOp(const Eigen::MatrixBase<D> & A, Op && oper) {
+ Matrix<Real, dim, dim> A_directions;
+ A_directions.zero();
return tensorPlusOp<dim>(A, A_directions, std::forward<Op>(oper));
}
- template <UInt dim> auto tensorPlus(const Matrix<Real> & A) {
- return tensorPlusOp<dim>(A, [](Real x, Real /*unused*/) { return x; });
+ template <Int dim, class D> auto tensorPlus(const Eigen::MatrixBase<D> & A) {
+ return tensorPlusOp<dim>(A, [](Real x, Real) { return x; });
}
- template <UInt dim> auto tensorSqrt(const Matrix<Real> & A) {
- return tensorPlusOp<dim>(
- A, [](Real x, UInt /*unused*/) { return std::sqrt(x); });
+ template <Int dim, class D> auto tensorSqrt(const Eigen::MatrixBase<D> & A) {
+ return tensorPlusOp<dim>(A, [](Real x, Int) { return std::sqrt(x); });
}
} // namespace
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <UInt dim, template <UInt> class EquivalentStrain,
- template <UInt> class DamageThreshold, template <UInt> class Parent>
+template <Int dim, template <Int> class EquivalentStrain,
+ template <Int> class DamageThreshold, template <Int> class Parent>
MaterialAnisotropicDamage<dim, EquivalentStrain, DamageThreshold, Parent>::
MaterialAnisotropicDamage(SolidMechanicsModel & model, const ID & id)
: Parent<dim>(model, id), damage("damage_tensor", *this),
elastic_stress("elastic_stress", *this),
equivalent_strain("equivalent_strain", *this),
trace_damage("trace_damage", *this), equivalent_strain_function(*this),
damage_threshold_function(*this) {
this->registerParam("Dc", Dc, _pat_parsable, "Critical damage");
this->damage.initialize(dim * dim);
this->elastic_stress.initialize(dim * dim);
this->equivalent_strain.initialize(1);
this->trace_damage.initialize(1);
this->trace_damage.initializeHistory();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim, template <UInt> class EquivalentStrain,
- template <UInt> class DamageThreshold, template <UInt> class Parent>
+template <Int dim, template <Int> class EquivalentStrain,
+ template <Int> class DamageThreshold, template <Int> class Parent>
+template <class D1, class D2, class D3>
void MaterialAnisotropicDamage<dim, EquivalentStrain, DamageThreshold, Parent>::
- damageStress(Matrix<Real> & sigma, const Matrix<Real> & sigma_el,
- const Matrix<Real> & D, Real TrD) {
+ damageStress(Eigen::MatrixBase<D1> & sigma,
+ const Eigen::MatrixBase<D2> & sigma_el,
+ const Eigen::MatrixBase<D3> & D, Real TrD) {
// σ_(n + 1) = (1 − D_(n + 1))^(1/2) σ~_(n + 1) (1 − D_(n + 1))^(1 / 2)
// - ((1 − D_(n + 1)) : σ~_(n + 1))/ (3 - Tr(D_(n+1))) (1 − D_(n + 1))
// + 1/3 (1 - Tr(D_(n+1)) <Tr(σ~_(n + 1))>_+ + <Tr(σ~_(n + 1))>_-) I
- auto one_D = Matrix<Real>::eye(dim) - D;
+ Matrix<Real, dim, dim> one_D = Matrix<Real, dim, dim>::Identity() - D;
auto sqrt_one_D = tensorSqrt<dim>(one_D);
Real Tr_sigma_plus;
Real Tr_sigma_minus;
std::tie(Tr_sigma_plus, Tr_sigma_minus) = tensorPlusTrace<dim>(sigma_el);
- auto I = Matrix<Real>::eye(dim);
+ auto I = Matrix<Real, dim, dim>::Identity();
sigma = sqrt_one_D * sigma_el * sqrt_one_D -
(one_D.doubleDot(sigma_el) / (dim - TrD) * one_D) +
1. / dim * ((1 - TrD) * Tr_sigma_plus - Tr_sigma_minus) * I;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim, template <UInt> class EquivalentStrain,
- template <UInt> class DamageThreshold, template <UInt> class Parent>
+template <Int dim, template <Int> class EquivalentStrain,
+ template <Int> class DamageThreshold, template <Int> class Parent>
+template <class Args>
void MaterialAnisotropicDamage<dim, EquivalentStrain, DamageThreshold,
- Parent>::computeStress(ElementType type,
- GhostType ghost_type) {
+ Parent>::computeStressOnQuad(Args && args) {
+ auto & sigma = args["sigma"_n];
+ auto & grad_u = args["grad_u"_n];
+ auto & sigma_el = args["sigma_el"_n];
+ auto & epsilon_hat = args["epsilon_hat"_n];
+ auto & D = args["damage"_n];
+ auto & TrD_n_1 = args["TrD_n_1"_n];
+ auto & TrD = args["TrD"_n];
+ auto & equivalent_strain_data = args["equivalent_strain_data"_n];
+ auto & damage_threshold_data = args["damage_threshold_data"_n];
- for (auto && data :
- zip(make_view(this->stress(type, ghost_type), dim, dim),
- make_view(this->gradu(type, ghost_type), dim, dim),
- make_view(this->sigma_th(type, ghost_type)),
- make_view(this->elastic_stress(type, ghost_type), dim, dim),
- make_view(this->equivalent_strain(type, ghost_type)),
- make_view(this->damage(type, ghost_type), dim, dim),
- make_view(this->trace_damage(type, ghost_type)),
- make_view(this->trace_damage.previous(type, ghost_type)),
- equivalent_strain_function, damage_threshold_function)) {
- auto & sigma = std::get<0>(data);
- auto & grad_u = std::get<1>(data);
- auto & sigma_th = std::get<2>(data);
- auto & sigma_el = std::get<3>(data);
- auto & epsilon_hat = std::get<4>(data);
- auto & D = std::get<5>(data);
- auto & TrD_n_1 = std::get<6>(data);
- auto & TrD = std::get<7>(data);
- auto & equivalent_strain_data = std::get<8>(data);
- auto & damage_threshold_data = std::get<9>(data);
-
- Matrix<Real> Dtmp(dim, dim);
- Real TrD_n_1_tmp;
- Matrix<Real> epsilon(dim, dim);
-
- // yes you read properly this is a label for a goto
- auto computeDamage = [&]() {
- MaterialElastic<dim>::computeStressOnQuad(grad_u, sigma_el, sigma_th);
-
- this->template gradUToEpsilon<dim>(grad_u, epsilon);
-
- // evaluate the damage criteria
- epsilon_hat = equivalent_strain_function(epsilon, equivalent_strain_data);
-
- // evolve the damage if needed
- auto K_TrD = damage_threshold_function.K(TrD, damage_threshold_data);
-
- auto f = epsilon_hat - K_TrD;
-
- // if test function > 0 evolve the damage
- if (f > 0) {
- TrD_n_1_tmp =
- damage_threshold_function.K_inv(epsilon_hat, damage_threshold_data);
-
- auto epsilon_plus = tensorPlus<dim>(epsilon);
- auto delta_lambda = (TrD_n_1_tmp - TrD) / (epsilon_hat * epsilon_hat);
-
- Dtmp = D + delta_lambda * epsilon_plus;
- return true;
- }
- return false;
- };
-
- // compute a temporary version of the new damage
- auto is_damage_updated = computeDamage();
-
- if (is_damage_updated) {
- /// Check and correct for broken case
- if (Dtmp.trace() > Dc) {
- if (epsilon.trace() > 0) { // tensile loading
- auto kpa = this->kpa;
- auto lambda = this->lambda;
-
- // change kappa to Kappa_broken = (1-Dc) Kappa
- kpa = (1 - Dc) * kpa;
- this->E = 9 * kpa * (kpa - lambda) / (3 * kpa - lambda);
- this->nu = lambda / (3 * kpa - lambda);
- this->updateInternalParameters();
-
- computeDamage();
- } else if (std::abs(epsilon.trace()) < 1e-10) { // deviatoric case
- Matrix<Real> n(dim, dim);
- std::vector<UInt> ns;
- tensorPlusOp<dim>(
- Dtmp, n,
- [&](Real x, UInt i) {
- if (x > this->Dc) {
- ns.push_back(i);
- return this->Dc;
- }
-
- return x;
- },
- true);
- }
- }
+ Matrix<Real, dim, dim> Dtmp;
+ Real TrD_n_1_tmp;
+ Matrix<Real, dim, dim> epsilon;
+
+ // yes you read properly this is a label for a goto
+ auto computeDamage = [&]() {
+ MaterialElastic<dim>::computeStressOnQuad(args);
+
+ epsilon = this->template gradUToEpsilon<dim>(grad_u);
+
+ // evaluate the damage criteria
+ epsilon_hat = equivalent_strain_function(epsilon, equivalent_strain_data);
+
+ // evolve the damage if needed
+ auto K_TrD = damage_threshold_function.K(TrD, damage_threshold_data);
+
+ auto f = epsilon_hat - K_TrD;
+
+ // if test function > 0 evolve the damage
+ if (f > 0) {
+ TrD_n_1_tmp =
+ damage_threshold_function.K_inv(epsilon_hat, damage_threshold_data);
+
+ auto epsilon_plus = tensorPlus<dim>(epsilon);
+ auto delta_lambda = (TrD_n_1_tmp - TrD) / (epsilon_hat * epsilon_hat);
- TrD_n_1 = TrD_n_1_tmp;
- D = Dtmp;
- } else {
- TrD_n_1 = TrD;
+ Dtmp = D + delta_lambda * epsilon_plus;
+ return true;
}
+ return false;
+ };
+
+ // compute a temporary version of the new damage
+ auto is_damage_updated = computeDamage();
+
+ if (is_damage_updated) {
+ /// Check and correct for broken case
+ if (Dtmp.trace() > Dc) {
+ if (epsilon.trace() > 0) { // tensile loading
+ auto kpa = this->kpa;
+ auto lambda = this->lambda;
+
+ // change kappa to Kappa_broken = (1-Dc) Kappa
+ kpa = (1 - Dc) * kpa;
+ this->E = 9 * kpa * (kpa - lambda) / (3 * kpa - lambda);
+ this->nu = lambda / (3 * kpa - lambda);
+ this->updateInternalParameters();
+
+ computeDamage();
+ } else if (std::abs(epsilon.trace()) < 1e-10) { // deviatoric case
+ Matrix<Real, dim, dim> n;
+ std::vector<Int> ns;
+ tensorPlusOp<dim>(Dtmp, n, [&](Real x, Int i) {
+ if (x > this->Dc) {
+ ns.push_back(i);
+ return this->Dc;
+ }
+
+ return x;
+ });
+ }
+ }
+
+ TrD_n_1 = TrD_n_1_tmp;
+ D = Dtmp;
+ } else {
+ TrD_n_1 = TrD;
+ }
- // apply the damage to the stress
- damageStress(sigma, sigma_el, D, TrD_n_1);
+ // apply the damage to the stress
+ damageStress(sigma, sigma_el, D, TrD_n_1);
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, template <Int> class EquivalentStrain,
+ template <Int> class DamageThreshold, template <Int> class Parent>
+void MaterialAnisotropicDamage<dim, EquivalentStrain, DamageThreshold,
+ Parent>::computeStress(ElementType type,
+ GhostType ghost_type) {
+ for (auto && args : getArguments(type, ghost_type)) {
+ computeStressOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
/* EquivalentStrain functions */
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
class EquivalentStrainMazars : public EmptyIteratorContainer {
public:
EquivalentStrainMazars(Material & /*mat*/) {}
- template <class... Other>
- Real operator()(const Matrix<Real> & epsilon, Other &&... /*other*/) {
+ template <class D, class... Other>
+ Real operator()(const Eigen::MatrixBase<D> & epsilon, Other &&... /*other*/) {
Real epsilon_hat = 0.;
std::tie(epsilon_hat, std::ignore) = tensorPlusTrace<dim>(epsilon);
return std::sqrt(epsilon_hat);
}
};
-template <UInt dim>
+template <Int dim>
class EquivalentStrainMazarsDruckerPrager : public EquivalentStrainMazars<dim> {
public:
EquivalentStrainMazarsDruckerPrager(Material & mat)
: EquivalentStrainMazars<dim>(mat) {
mat.registerParam("k", k, _pat_parsable, "k");
}
- template <class... Other>
- Real operator()(const Matrix<Real> & epsilon, Real /*unused*/) {
+ template <class D, class... Other>
+ Real operator()(const Eigen::MatrixBase<D> & epsilon, Real) {
Real epsilon_hat = EquivalentStrainMazars<dim>::operator()(epsilon);
epsilon_hat += k * epsilon.trace();
return epsilon_hat;
}
protected:
Real k;
};
/* -------------------------------------------------------------------------- */
/* DamageThreshold functions */
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-class DamageThresholdLinear : public EmptyIteratorContainer {
+template <Int dim> class DamageThresholdLinear : public EmptyIteratorContainer {
public:
DamageThresholdLinear(Material & mat) : mat(mat) {
mat.registerParam("A", A, _pat_parsable, "A");
mat.registerParam("K0", K0, _pat_parsable, "K0");
}
template <class... Other> Real K(Real x, Other &&... /*other*/) {
return 1. / A * x + K0;
}
template <class... Other> Real K_inv(Real x, Other &&... /*other*/) {
return A * (x - K0);
}
private:
Material & mat;
Real A;
Real K0;
};
-template <UInt dim> class DamageThresholdTan : public EmptyIteratorContainer {
+template <Int dim> class DamageThresholdTan : public EmptyIteratorContainer {
public:
DamageThresholdTan(Material & mat) : mat(mat) {
mat.registerParam("a", a, _pat_parsable, "a");
mat.registerParam("A", A, _pat_parsable, "A");
mat.registerParam("K0", K0, _pat_parsable, "K0");
}
template <class... Other> Real K(Real x, Other &&... /*other*/) {
return a * std::tan(std::atan2(x, a) - std::atan2(K0, a));
}
template <class... Other> Real K_inv(Real x, Other &&... /*other*/) {
return a * A * (std::atan2(x, a) - std::atan2(K0, a));
}
private:
Material & mat;
Real a{2.93e-4};
Real A{5e3};
Real K0{5e-5};
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_ANISOTROPIC_DAMAGE_TMPL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage.hh b/src/model/solid_mechanics/materials/material_damage/material_damage.hh
index 809d68bca..d8d08e74b 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_damage.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_damage.hh
@@ -1,109 +1,123 @@
/**
* @file material_damage.hh
*
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Material isotropic elastic
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_DAMAGE_HH_
#define AKANTU_MATERIAL_DAMAGE_HH_
namespace akantu {
-template <UInt spatial_dimension,
- template <UInt> class Parent = MaterialElastic>
-class MaterialDamage : public Parent<spatial_dimension> {
+template <Int dim, template <Int> class Parent = MaterialElastic>
+class MaterialDamage : public Parent<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialDamage(SolidMechanicsModel & model, const ID & id = "");
~MaterialDamage() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
- bool hasStiffnessMatrixChanged() override { return true; }
+ auto hasStiffnessMatrixChanged() -> bool override { return true; }
protected:
/// update the dissipated energy, must be called after the stress have been
/// computed
void updateEnergies(ElementType el_type) override;
/// compute the tangent stiffness matrix for a given quadrature point
- inline void computeTangentModuliOnQuad(Matrix<Real> & tangent, Real & dam);
+ template <class Args>
+ inline void computeTangentModuliOnQuad(Args && arguments);
+
+ auto getDissipatedEnergy() const -> Real;
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- /// give the dissipated energy for the time step
- Real getDissipatedEnergy() const;
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(Parent<dim>::getArguments(el_type, ghost_type),
+ "damage"_n =
+ make_view(this->damage(el_type, ghost_type)));
+ }
+
+ decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrix,
+ ElementType el_type,
+ GhostType ghost_type) {
+ return zip_append(
+ Parent<dim>::getArgumentsTangent(tangent_matrix, el_type, ghost_type),
+ "damage"_n = make_view(this->damage(el_type, ghost_type)));
+ }
Real getEnergy(const std::string & type) override;
- AKANTU_GET_MACRO_NOT_CONST(Damage, damage, ElementTypeMapArray<Real> &);
- AKANTU_GET_MACRO(Damage, damage, const ElementTypeMapArray<Real> &);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Damage, damage);
+ AKANTU_GET_MACRO_AUTO(Damage, damage);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real)
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// damage internal variable
InternalField<Real> damage;
/// dissipated energy
InternalField<Real> dissipated_energy;
/// contain the current value of @f$ \int_0^{\epsilon}\sigma(\omega)d\omega
/// @f$ the dissipated energy
InternalField<Real> int_sigma;
};
} // namespace akantu
#include "material_damage_tmpl.hh"
#endif /* AKANTU_MATERIAL_DAMAGE_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
index d7d60f366..8f50bc499 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
@@ -1,75 +1,80 @@
/**
* @file material_damage_non_local.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Aug 23 2012
* @date last modification: Fri Apr 09 2021
*
* @brief interface for non local damage material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_non_local.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH_
#define AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH_
namespace akantu {
-template <UInt dim, class MaterialDamageLocal>
+template <Int dim, class MaterialDamageLocal>
class MaterialDamageNonLocal
: public MaterialNonLocal<dim, MaterialDamageLocal> {
public:
using MaterialParent = MaterialNonLocal<dim, MaterialDamageLocal>;
MaterialDamageNonLocal(SolidMechanicsModel & model, const ID & id)
: MaterialParent(model, id){};
+public:
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ return MaterialDamageLocal::getArguments(el_type, ghost_type);
+ }
+
protected:
/* ------------------------------------------------------------------------ */
virtual void computeNonLocalStress(ElementType type,
GhostType ghost_type = _not_ghost) = 0;
/* ------------------------------------------------------------------------ */
void computeNonLocalStresses(GhostType ghost_type) override {
AKANTU_DEBUG_IN();
for (auto type : this->element_filter.elementTypes(dim, ghost_type)) {
auto & elem_filter = this->element_filter(type, ghost_type);
if (elem_filter.empty()) {
continue;
}
computeNonLocalStress(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh b/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh
index 5bc63e618..2a111ce5a 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh
@@ -1,174 +1,168 @@
/**
* @file material_damage_tmpl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Marion Estelle Chambart <mchambart@stucky.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Specialization of the material class for the damage material
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-MaterialDamage<spatial_dimension, Parent>::MaterialDamage(
- SolidMechanicsModel & model, const ID & id)
- : Parent<spatial_dimension>(model, id), damage("damage", *this),
+template <Int dim, template <Int> class Parent>
+MaterialDamage<dim, Parent>::MaterialDamage(SolidMechanicsModel & model,
+ const ID & id)
+ : Parent<dim>(model, id), damage("damage", *this),
dissipated_energy("damage dissipated energy", *this),
int_sigma("integral of sigma", *this) {
AKANTU_DEBUG_IN();
this->is_non_local = false;
this->use_previous_stress = true;
this->use_previous_gradu = true;
this->damage.initialize(1);
this->dissipated_energy.initialize(1);
this->int_sigma.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-void MaterialDamage<spatial_dimension, Parent>::initMaterial() {
+template <Int dim, template <Int> class Parent>
+void MaterialDamage<dim, Parent>::initMaterial() {
AKANTU_DEBUG_IN();
- Parent<spatial_dimension>::initMaterial();
+ Parent<dim>::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Compute the dissipated energy in each element by a trapezoidal approximation
* of
* @f$ Ed = \int_0^{\epsilon}\sigma(\omega)d\omega -
* \frac{1}{2}\sigma:\epsilon@f$
*/
-template <UInt spatial_dimension, template <UInt> class Parent>
-void MaterialDamage<spatial_dimension, Parent>::updateEnergies(
- ElementType el_type) {
- Parent<spatial_dimension>::updateEnergies(el_type);
+template <Int dim, template <Int> class Parent>
+void MaterialDamage<dim, Parent>::updateEnergies(ElementType el_type) {
+ Parent<dim>::updateEnergies(el_type);
this->computePotentialEnergy(el_type);
- auto epsilon_p =
- this->gradu.previous(el_type).begin(spatial_dimension, spatial_dimension);
- auto sigma_p = this->stress.previous(el_type).begin(spatial_dimension,
- spatial_dimension);
+ auto epsilon_p = this->gradu.previous(el_type).begin(dim, dim);
+ auto sigma_p = this->stress.previous(el_type).begin(dim, dim);
auto epot = this->potential_energy(el_type).begin();
auto ints = this->int_sigma(el_type).begin();
auto ed = this->dissipated_energy(el_type).begin();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
Matrix<Real> delta_gradu(grad_u);
delta_gradu -= *epsilon_p;
Matrix<Real> sigma_h(sigma);
sigma_h += *sigma_p;
Real dint = .5 * sigma_h.doubleDot(delta_gradu);
*ints += dint;
*ed = *ints - *epot;
++epsilon_p;
++sigma_p;
++epot;
++ints;
++ed;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-void MaterialDamage<spatial_dimension, Parent>::computeTangentModuli(
+template <Int dim, template <Int> class Parent>
+void MaterialDamage<dim, Parent>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
-
- Parent<spatial_dimension>::computeTangentModuli(el_type, tangent_matrix,
- ghost_type);
-
- Real * dam = this->damage(el_type, ghost_type).storage();
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
- computeTangentModuliOnQuad(tangent, *dam);
-
- ++dam;
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
+ constexpr auto tangent_size = Material::getTangentStiffnessVoigtSize(dim);
+
+ for (auto && data :
+ zip_append(getArguments(el_type, ghost_type),
+ "tangent_moduli"_n =
+ make_view<tangent_size, tangent_size>(tangent_matrix))) {
+ Parent<dim>::computeTangentModuliOnQuad(data);
+ computeTangentModuliOnQuad(data);
+ }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-void MaterialDamage<spatial_dimension, Parent>::computeTangentModuliOnQuad(
- Matrix<Real> & tangent, Real & dam) {
- tangent *= (1 - dam);
+template <Int dim, template <Int> class Parent>
+template <class Args>
+void MaterialDamage<dim, Parent>::computeTangentModuliOnQuad(
+ Args && arguments) {
+ arguments["tangent_moduli"_n].array() *= (1 - arguments["damage"_n]);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-Real MaterialDamage<spatial_dimension, Parent>::getDissipatedEnergy() const {
+template <Int dim, template <Int> class Parent>
+auto MaterialDamage<dim, Parent>::getDissipatedEnergy() const -> Real {
AKANTU_DEBUG_IN();
Real de = 0.;
/// integrate the dissipated energy for each type of elements
- for (auto & type :
- this->element_filter.elementTypes(spatial_dimension, _not_ghost)) {
+ for (auto && type : this->element_filter.elementTypes(dim, _not_ghost)) {
de +=
this->fem.integrate(dissipated_energy(type, _not_ghost), type,
_not_ghost, this->element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return de;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-Real MaterialDamage<spatial_dimension, Parent>::getEnergy(
- const std::string & type) {
+template <Int dim, template <Int> class Parent>
+Real MaterialDamage<dim, Parent>::getEnergy(const std::string & type) {
if (type == "dissipated") {
return getDissipatedEnergy();
}
- return Parent<spatial_dimension>::getEnergy(type);
+
+ return Parent<dim>::getEnergy(type);
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
index 256c52a88..f8bf6a0c1 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
@@ -1,104 +1,103 @@
/**
* @file material_marigo.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Specialization of the material class for the marigo material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_marigo.hh"
#include "solid_mechanics_model.hh"
+/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialMarigo<spatial_dimension>::MaterialMarigo(SolidMechanicsModel & model,
- const ID & id)
- : MaterialDamage<spatial_dimension>(model, id), Yd("Yd", *this),
- damage_in_y(false), yc_limit(false) {
+template <Int dim>
+MaterialMarigo<dim>::MaterialMarigo(SolidMechanicsModel & model, const ID & id)
+ : MaterialDamage<dim>(model, id), Yd("Yd", *this), damage_in_y(false),
+ yc_limit(false) {
AKANTU_DEBUG_IN();
this->registerParam("Sd", Sd, Real(5000.), _pat_parsable | _pat_modifiable);
this->registerParam("epsilon_c", epsilon_c, Real(0.), _pat_parsable,
"Critical strain");
this->registerParam("Yc limit", yc_limit, false, _pat_internal,
"As the material a critical Y");
this->registerParam("damage_in_y", damage_in_y, false, _pat_parsable,
"Use threshold (1-D)Y");
this->registerParam("Yd", Yd, _pat_parsable, "Damaging energy threshold");
this->Yd.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMarigo<spatial_dimension>::initMaterial() {
+template <Int dim> void MaterialMarigo<dim>::initMaterial() {
AKANTU_DEBUG_IN();
- MaterialDamage<spatial_dimension>::initMaterial();
+ MaterialDamage<dim>::initMaterial();
updateInternalParameters();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMarigo<spatial_dimension>::updateInternalParameters() {
- MaterialDamage<spatial_dimension>::updateInternalParameters();
+template <Int dim> void MaterialMarigo<dim>::updateInternalParameters() {
+ MaterialDamage<dim>::updateInternalParameters();
Yc = .5 * epsilon_c * this->E * epsilon_c;
yc_limit = (std::abs(epsilon_c) > std::numeric_limits<Real>::epsilon());
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMarigo<spatial_dimension>::computeStress(ElementType el_type,
- GhostType ghost_type) {
+template <Int dim>
+void MaterialMarigo<dim>::computeStress(ElementType el_type,
+ GhostType ghost_type) {
AKANTU_DEBUG_IN();
- auto dam = this->damage(el_type, ghost_type).begin();
- auto Yd_q = this->Yd(el_type, ghost_type).begin();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- Real Y = 0.;
- computeStressOnQuad(grad_u, sigma, *dam, Y, *Yd_q);
+ Y = 0.;
- ++dam;
- ++Yd_q;
+ auto && arguments = getArguments(el_type, ghost_type);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ for (auto && data : arguments) {
+ computeStressOnQuad(data);
+ }
AKANTU_DEBUG_OUT();
}
-INSTANTIATE_MATERIAL(marigo, MaterialMarigo);
+/* -------------------------------------------------------------------------- */
+template class MaterialMarigo<1>;
+template class MaterialMarigo<2>;
+template class MaterialMarigo<3>;
+
+static bool material_is_alocated_marigo =
+ instantiateMaterial<MaterialMarigo>("marigo");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
index 01da317dd..cf46cb855 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
@@ -1,124 +1,131 @@
/**
* @file material_marigo.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Marigo damage law
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_MARIGO_HH_
#define AKANTU_MATERIAL_MARIGO_HH_
namespace akantu {
/**
* Material marigo
*
* parameters in the material files :
* - Yd : (default: 50)
* - Sd : (default: 5000)
* - Ydrandomness : (default:0)
*/
-template <UInt spatial_dimension>
-class MaterialMarigo : public MaterialDamage<spatial_dimension> {
+template <Int dim> class MaterialMarigo : public MaterialDamage<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
+ using parent = MaterialDamage<dim>;
+
public:
MaterialMarigo(SolidMechanicsModel & model, const ID & id = "");
~MaterialMarigo() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
void updateInternalParameters() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
protected:
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(Matrix<Real> & grad_u, Matrix<Real> & sigma,
- Real & dam, Real & Y, Real & Ydq);
+ template <typename Args> inline void computeStressOnQuad(Args && arguments);
- inline void computeDamageAndStressOnQuad(Matrix<Real> & sigma, Real & dam,
- Real & Y, Real & Ydq);
+ template <typename Args>
+ inline void computeDamageAndStressOnQuad(Args && arguments);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ return zip_append(
+ parent::getArguments(el_type, ghost_type),
+ "Yd"_n = make_view(this->Yd(el_type, ghost_type)),
+ "Y"_n = broadcast(this->Y, this->damage(el_type, ghost_type).size()));
+ }
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// resistance to damage
RandomInternalField<Real> Yd;
/// damage threshold
- Real Sd;
+ Real Sd{5000};
/// critical epsilon when the material is considered as broken
- Real epsilon_c;
-
- Real Yc;
+ Real epsilon_c{0.};
- bool damage_in_y;
- bool yc_limit;
+ Real Yc{0.};
+ bool damage_in_y{false};
+ bool yc_limit{false};
+ Real Y{0};
};
} // namespace akantu
#include "material_marigo_inline_impl.hh"
#endif /* AKANTU_MATERIAL_MARIGO_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh
index c23c7c20b..2d2f9d8d2 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh
@@ -1,135 +1,142 @@
/**
* @file material_marigo_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of the inline functions of the material marigo
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_marigo.hh"
+/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_MATERIAL_MARIGO_INLINE_IMPL_HH_
-#define AKANTU_MATERIAL_MARIGO_INLINE_IMPL_HH_
+// #ifndef __AKANTU_MATERIAL_MARIGO_INLINE_IMPL_CC__
+// #define __AKANTU_MATERIAL_MARIGO_INLINE_IMPL_CC__
namespace akantu {
-template <UInt spatial_dimension>
-inline void MaterialMarigo<spatial_dimension>::computeStressOnQuad(
- Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam, Real & Y,
- Real & Ydq) {
- MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_u, sigma);
-
- Y = 0;
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- Y += sigma(i, j) * (grad_u(i, j) + grad_u(j, i)) / 2.;
- }
- }
- Y *= 0.5;
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+template <typename Args>
+inline void MaterialMarigo<dim>::computeStressOnQuad(Args && arguments) {
+ auto && sigma = arguments["sigma"_n];
+ auto && grad_u = arguments["grad_u"_n];
+ auto && dam = arguments["damage"_n];
+ auto && Y = arguments["Y"_n];
+
+ MaterialElastic<dim>::computeStressOnQuad(arguments);
+
+ Y = sigma.doubleDot(Material::gradUToEpsilon<dim>(grad_u)) / 2.;
- if (damage_in_y) {
+ if (this->damage_in_y) {
Y *= (1 - dam);
}
- if (yc_limit) {
- Y = std::min(Y, Yc);
+ if (this->yc_limit) {
+ Y = std::min(Y, this->Yc);
}
- if (!this->is_non_local) {
- computeDamageAndStressOnQuad(sigma, dam, Y, Ydq);
+ if (not this->is_non_local) {
+ computeDamageAndStressOnQuad(arguments);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void MaterialMarigo<spatial_dimension>::computeDamageAndStressOnQuad(
- Matrix<Real> & sigma, Real & dam, Real & Y, Real & Ydq) {
- Real Fd = Y - Ydq - Sd * dam;
+template <Int dim>
+template <typename Args>
+inline void
+MaterialMarigo<dim>::computeDamageAndStressOnQuad(Args && arguments) {
+ auto && sigma = arguments["sigma"_n];
+ auto && dam = arguments["damage"_n];
+ auto && Y = arguments["Y"_n];
+ auto && Yd = arguments["Yd"_n];
+
+ Real Fd = Y - Yd - Sd * dam;
if (Fd > 0) {
- dam = (Y - Ydq) / Sd;
+ dam = (Y - Yd) / Sd;
}
dam = std::min(dam, Real(1.));
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline UInt MaterialMarigo<spatial_dimension>::getNbData(
- const Array<Element> & elements, const SynchronizationTag & tag) const {
+template <Int dim>
+inline auto MaterialMarigo<dim>::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const
+ -> Int {
AKANTU_DEBUG_IN();
- UInt size = 0;
+ Int size = 0;
if (tag == SynchronizationTag::_smm_init_mat) {
size += sizeof(Real) * this->getModel().getNbIntegrationPoints(elements);
}
- size += MaterialDamage<spatial_dimension>::getNbData(elements, tag);
+ size += MaterialDamage<dim>::getNbData(elements, tag);
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void MaterialMarigo<spatial_dimension>::packData(
- CommunicationBuffer & buffer, const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+template <Int dim>
+inline void
+MaterialMarigo<dim>::packData(CommunicationBuffer & buffer,
+ const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
if (tag == SynchronizationTag::_smm_init_mat) {
this->packElementDataHelper(Yd, buffer, elements);
}
- MaterialDamage<spatial_dimension>::packData(buffer, elements, tag);
+ MaterialDamage<dim>::packData(buffer, elements, tag);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void
-MaterialMarigo<spatial_dimension>::unpackData(CommunicationBuffer & buffer,
- const Array<Element> & elements,
- const SynchronizationTag & tag) {
+template <Int dim>
+inline void MaterialMarigo<dim>::unpackData(CommunicationBuffer & buffer,
+ const Array<Element> & elements,
+ const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
if (tag == SynchronizationTag::_smm_init_mat) {
this->unpackElementDataHelper(Yd, buffer, elements);
}
- MaterialDamage<spatial_dimension>::unpackData(buffer, elements, tag);
+ MaterialDamage<dim>::unpackData(buffer, elements, tag);
AKANTU_DEBUG_OUT();
}
} // namespace akantu
-#endif /* AKANTU_MATERIAL_MARIGO_INLINE_IMPL_HH_ */
+//#endif /* __AKANTU_MATERIAL_MARIGO_INLINE_IMPL_CC__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
index 55bd77f06..a9509d1ad 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
@@ -1,107 +1,100 @@
/**
* @file material_marigo_non_local.cc
*
* @author Marion Estelle Chambart <mchambart@stucky.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Marigo non-local inline function implementation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_marigo_non_local.hh"
#include "non_local_neighborhood_base.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialMarigoNonLocal<spatial_dimension>::MaterialMarigoNonLocal(
- SolidMechanicsModel & model, const ID & id)
- : MaterialMarigoNonLocalParent(model, id), Y("Y", *this),
- Ynl("Y non local", *this) {
+template <Int dim>
+MaterialMarigoNonLocal<dim>::MaterialMarigoNonLocal(SolidMechanicsModel & model,
+ const ID & id)
+ : parent(model, id), Y("Y", *this), Ynl("Y non local", *this) {
AKANTU_DEBUG_IN();
this->is_non_local = true;
this->Y.initialize(1);
this->Ynl.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMarigoNonLocal<spatial_dimension>::registerNonLocalVariables() {
+template <Int dim>
+void MaterialMarigoNonLocal<dim>::registerNonLocalVariables() {
this->model.getNonLocalManager().registerNonLocalVariable(this->Y.getName(),
Ynl.getName(), 1);
this->model.getNonLocalManager()
.getNeighborhood(this->name)
.registerNonLocalVariable(Ynl.getName());
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMarigoNonLocal<spatial_dimension>::computeStress(
- ElementType el_type, GhostType ghost_type) {
+template <Int dim>
+void MaterialMarigoNonLocal<dim>::computeStress(ElementType el_type,
+ GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = this->damage(el_type, ghost_type).storage();
- Real * Yt = this->Y(el_type, ghost_type).storage();
- Real * Ydq = this->Yd(el_type, ghost_type).storage();
+ auto && arguments = getArguments(el_type, ghost_type);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- MaterialMarigo<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *dam,
- *Yt, *Ydq);
- ++dam;
- ++Yt;
- ++Ydq;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ for (auto && data : arguments) {
+ MaterialMarigo<dim>::computeStressOnQuad(data);
+ }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMarigoNonLocal<spatial_dimension>::computeNonLocalStress(
- ElementType type, GhostType ghost_type) {
+template <Int dim>
+void MaterialMarigoNonLocal<dim>::computeNonLocalStress(ElementType el_type,
+ GhostType ghost_type) {
AKANTU_DEBUG_IN();
- Real * dam = this->damage(type, ghost_type).storage();
- Real * Ydq = this->Yd(type, ghost_type).storage();
- Real * Ynlt = this->Ynl(type, ghost_type).storage();
+ auto && arguments = getArgumentsNonLocal(el_type, ghost_type);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(type, ghost_type);
- this->computeDamageAndStressOnQuad(sigma, *dam, *Ynlt, *Ydq);
-
- ++dam;
- ++Ynlt;
- ++Ydq;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ for (auto && data : arguments) {
+ this->computeDamageAndStressOnQuad(data);
+ }
AKANTU_DEBUG_OUT();
}
-INSTANTIATE_MATERIAL(marigo_non_local, MaterialMarigoNonLocal);
+/* -------------------------------------------------------------------------- */
+template class MaterialMarigoNonLocal<1>;
+template class MaterialMarigoNonLocal<2>;
+template class MaterialMarigoNonLocal<3>;
+
+static bool material_is_alocated_marigo_non_local =
+ instantiateMaterial<MaterialMarigo>("marigo_non_local");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
index 6eb57196e..95c3d52b1 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
@@ -1,94 +1,104 @@
/**
* @file material_marigo_non_local.hh
*
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Marigo non-local description
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_damage_non_local.hh"
#include "material_marigo.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH_
#define AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/**
* Material Marigo
*
* parameters in the material files :
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialMarigoNonLocal
: public MaterialDamageNonLocal<spatial_dimension,
MaterialMarigo<spatial_dimension>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- using MaterialMarigoNonLocalParent =
- MaterialDamageNonLocal<spatial_dimension,
- MaterialMarigo<spatial_dimension>>;
+ using parent = MaterialDamageNonLocal<spatial_dimension,
+ MaterialMarigo<spatial_dimension>>;
MaterialMarigoNonLocal(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
void registerNonLocalVariables() override;
/// constitutive law
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
void computeNonLocalStress(ElementType type,
GhostType ghost_type = _not_ghost) override;
-private:
+public:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ return zip_replace(parent::getArguments(el_type, ghost_type),
+ "Y"_n = make_view(this->Y(el_type, ghost_type)));
+ }
+
+ decltype(auto) getArgumentsNonLocal(ElementType el_type,
+ GhostType ghost_type) {
+ return zip_replace(parent::getArguments(el_type, ghost_type),
+ "Y"_n = make_view(this->Ynl(el_type, ghost_type)));
+ }
+
public:
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Y, Y, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
InternalField<Real> Y;
InternalField<Real> Ynl;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
index 7671616fa..6321ebd1f 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
@@ -1,82 +1,48 @@
/**
* @file material_mazars.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Specialization of the material class for the damage material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_mazars.hh"
-#include "solid_mechanics_model.hh"
namespace akantu {
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialMazars<spatial_dimension>::MaterialMazars(SolidMechanicsModel & model,
- const ID & id)
- : MaterialDamage<spatial_dimension>(model, id), K0("K0", *this),
- damage_in_compute_stress(true) {
- AKANTU_DEBUG_IN();
-
- this->registerParam("K0", K0, _pat_parsable, "K0");
- this->registerParam("At", At, Real(0.8), _pat_parsable, "At");
- this->registerParam("Ac", Ac, Real(1.4), _pat_parsable, "Ac");
- this->registerParam("Bc", Bc, Real(1900.), _pat_parsable, "Bc");
- this->registerParam("Bt", Bt, Real(12000.), _pat_parsable, "Bt");
- this->registerParam("beta", beta, Real(1.06), _pat_parsable, "beta");
-
- this->K0.initialize(1);
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMazars<spatial_dimension>::computeStress(ElementType el_type,
- GhostType ghost_type) {
- AKANTU_DEBUG_IN();
+template class MaterialMazars<1>;
+template class MaterialMazars<2>;
+template class MaterialMazars<3>;
- Real * dam = this->damage(el_type, ghost_type).storage();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- Real Ehat = 0;
- computeStressOnQuad(grad_u, sigma, *dam, Ehat);
- ++dam;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
-}
-/* -------------------------------------------------------------------------- */
+template <Int dim> using MaterialMazars_ = MaterialMazars<dim>;
-INSTANTIATE_MATERIAL(mazars, MaterialMazars);
+static bool material_is_alocated_mazars =
+ instantiateMaterial<MaterialMazars_>("mazars");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars.hh b/src/model/solid_mechanics/materials/material_damage/material_mazars.hh
index 4ba41edaa..c5ffabdf3 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.hh
@@ -1,126 +1,130 @@
/**
* @file material_mazars.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Marion Estelle Chambart <mchambart@stucky.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Material Following the Mazars law for damage evolution
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
#include "material.hh"
#include "material_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_MAZARS_HH_
#define AKANTU_MATERIAL_MAZARS_HH_
namespace akantu {
/**
* Material Mazars
*
* parameters in the material files :
* - rho : density (default: 0)
* - E : Young's modulus (default: 0)
* - nu : Poisson's ratio (default: 1/2)
* - K0 : Damage threshold
* - At : Parameter damage traction 1
* - Bt : Parameter damage traction 2
* - Ac : Parameter damage compression 1
* - Bc : Parameter damage compression 2
* - beta : Parameter for shear
*/
-template <UInt spatial_dimension>
-class MaterialMazars : public MaterialDamage<spatial_dimension> {
+template <Int dim, template <Int> class Parent = MaterialElastic>
+class MaterialMazars : public MaterialDamage<dim, Parent> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
+ using parent_damage = MaterialDamage<dim, Parent>;
+
public:
MaterialMazars(SolidMechanicsModel & model, const ID & id = "");
~MaterialMazars() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
protected:
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(const Matrix<Real> & grad_u,
- Matrix<Real> & sigma, Real & damage,
- Real & Ehat);
+ template <typename Args> inline void computeStressOnQuad(Args && args);
- inline void computeDamageAndStressOnQuad(const Matrix<Real> & grad_u,
- Matrix<Real> & sigma, Real & damage,
- Real & Ehat);
+ template <typename Args>
+ inline void computeDamageAndStressOnQuad(Args && args);
- inline void computeDamageOnQuad(const Real & epsilon_equ,
- const Matrix<Real> & sigma,
- const Vector<Real> & epsilon_princ,
- Real & dam);
+ template <typename Args, typename Derived>
+ inline void
+ computeDamageOnQuad(Args && args,
+ const Eigen::MatrixBase<Derived> & epsilon_princ);
- /* ------------------------------------------------------------------------ */
- /* Accessors */
- /* ------------------------------------------------------------------------ */
public:
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ return zip_append(
+ parent_damage::getArguments(el_type, ghost_type),
+ "K0"_n = make_view(this->K0(el_type, ghost_type)),
+ "Ehat"_n =
+ broadcast(this->Ehat, this->damage(el_type, ghost_type).size()));
+ }
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// damage threshold
RandomInternalField<Real> K0;
/// parameter damage traction 1
Real At;
/// parameter damage traction 2
Real Bt;
/// parameter damage compression 1
Real Ac;
/// parameter damage compression 2
Real Bc;
/// parameter for shear
Real beta;
/// specify the variable to average false = ehat, true = damage (only valid
/// for non local version)
bool damage_in_compute_stress;
+
+ Real Ehat{0};
};
+} // namespace akantu
+
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
-
-} // namespace akantu
-
#include "material_mazars_inline_impl.hh"
-#endif /* AKANTU_MATERIAL_MAZARS_HH_ */
+#endif /* __AKANTU_MATERIAL_MAZARS_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh b/src/model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh
index c2e25aa85..52bbe2995 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh
@@ -1,165 +1,184 @@
/**
* @file material_mazars_inline_impl.hh
*
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Marion Estelle Chambart <mchambart@stucky.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Apr 06 2011
* @date last modification: Thu Feb 20 2020
*
* @brief Implementation of the inline functions of the material damage
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "material_linear_isotropic_hardening.hh"
#include "material_mazars.hh"
-/* -------------------------------------------------------------------------- */
namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, template <Int> class Parent>
+MaterialMazars<dim, Parent>::MaterialMazars(SolidMechanicsModel & model,
+ const ID & id)
+ : parent_damage(model, id), K0("K0", *this),
+ damage_in_compute_stress(true) {
+ this->registerParam("K0", this->K0, _pat_parsable, "K0");
+ this->registerParam("At", this->At, Real(0.8), _pat_parsable, "At");
+ this->registerParam("Ac", this->Ac, Real(1.4), _pat_parsable, "Ac");
+ this->registerParam("Bc", this->Bc, Real(1900.), _pat_parsable, "Bc");
+ this->registerParam("Bt", this->Bt, Real(12000.), _pat_parsable, "Bt");
+ this->registerParam("beta", this->beta, Real(1.06), _pat_parsable, "beta");
+
+ this->K0.initialize(1);
+}
+
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void MaterialMazars<spatial_dimension>::computeStressOnQuad(
- const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam,
- Real & Ehat) {
- Matrix<Real> epsilon(3, 3);
- epsilon.zero();
-
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- epsilon(i, j) = .5 * (grad_u(i, j) + grad_u(j, i));
- }
+template <Int dim, template <Int> class Parent>
+void MaterialMazars<dim, Parent>::computeStress(ElementType el_type,
+ GhostType ghost_type) {
+ auto && arguments = getArguments(el_type, ghost_type);
+ for (auto && args : arguments) {
+ computeStressOnQuad(args);
}
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, template <Int> class Parent>
+template <typename Args>
+inline void MaterialMazars<dim, Parent>::computeStressOnQuad(Args && args) {
+ Parent<dim>::computeStressOnQuad(args);
- Vector<Real> Fdiag(3);
- Math::matrixEig(3, epsilon.storage(), Fdiag.storage());
+ auto & grad_u = args["grad_u"_n];
+
+ if constexpr (named_tuple_t<Args>::has("inelastic_strain"_n)) {
+ grad_u -= args["inelastic_strain"_n];
+ }
+
+ Matrix<Real, 3, 3> epsilon = Matrix<Real, 3, 3>::Zero();
+
+ epsilon.block<dim, dim>(0, 0) = Material::gradUToEpsilon<dim>(grad_u);
+
+ Vector<Real, 3> Fdiag;
+ epsilon.eig(Fdiag);
+
+ auto & Ehat = args["Ehat"_n];
Ehat = 0.;
- for (UInt i = 0; i < 3; ++i) {
+ for (Int i = 0; i < 3; ++i) {
Real epsilon_p = std::max(Real(0.), Fdiag(i));
Ehat += epsilon_p * epsilon_p;
}
- Ehat = sqrt(Ehat);
-
- MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_u, sigma);
+ Ehat = std::sqrt(Ehat);
if (damage_in_compute_stress) {
- computeDamageOnQuad(Ehat, sigma, Fdiag, dam);
+ computeDamageOnQuad(args, Fdiag);
}
if (not this->is_non_local) {
- computeDamageAndStressOnQuad(grad_u, sigma, dam, Ehat);
+ computeDamageAndStressOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void MaterialMazars<spatial_dimension>::computeDamageAndStressOnQuad(
- const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam,
- Real & Ehat) {
- if (!damage_in_compute_stress) {
- Vector<Real> Fdiag(3);
- Fdiag.zero();
-
- Matrix<Real> epsilon(3, 3);
- epsilon.zero();
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- epsilon(i, j) = .5 * (grad_u(i, j) + grad_u(j, i));
- }
- }
-
- Math::matrixEig(3, epsilon.storage(), Fdiag.storage());
-
- computeDamageOnQuad(Ehat, sigma, Fdiag, dam);
+template <Int dim, template <Int> class Parent>
+template <typename Args>
+inline void
+MaterialMazars<dim, Parent>::computeDamageAndStressOnQuad(Args && args) {
+ auto && grad_u = args["grad_u"_n];
+ if (not damage_in_compute_stress) {
+ Vector<Real, 3> Fdiag;
+ Matrix<Real, 3, 3> epsilon = Matrix<Real, 3, 3>::Zero();
+
+ epsilon.block<dim, dim>(0, 0) = Material::gradUToEpsilon<dim>(grad_u);
+
+ epsilon.eig(Fdiag);
+ computeDamageOnQuad(args, Fdiag);
}
+ auto && sigma = args["sigma"_n];
+ auto && dam = args["damage"_n];
sigma *= 1 - dam;
+
+ if constexpr (named_tuple_t<Args>::has("inelastic_strain"_n)) {
+ grad_u += args["inelastic_strain"_n];
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void MaterialMazars<spatial_dimension>::computeDamageOnQuad(
- const Real & epsilon_equ,
- __attribute__((unused)) const Matrix<Real> & sigma,
- const Vector<Real> & epsilon_princ, Real & dam) {
- Real Fs = epsilon_equ - K0;
- if (Fs > 0.) {
- Real dam_t;
- Real dam_c;
- dam_t =
- 1 - K0 * (1 - At) / epsilon_equ - At * (exp(-Bt * (epsilon_equ - K0)));
- dam_c =
- 1 - K0 * (1 - Ac) / epsilon_equ - Ac * (exp(-Bc * (epsilon_equ - K0)));
-
- Real Cdiag;
- Cdiag = this->E * (1 - this->nu) / ((1 + this->nu) * (1 - 2 * this->nu));
-
- Vector<Real> sigma_princ(3);
- sigma_princ(0) = Cdiag * epsilon_princ(0) +
- this->lambda * (epsilon_princ(1) + epsilon_princ(2));
- sigma_princ(1) = Cdiag * epsilon_princ(1) +
- this->lambda * (epsilon_princ(0) + epsilon_princ(2));
- sigma_princ(2) = Cdiag * epsilon_princ(2) +
- this->lambda * (epsilon_princ(1) + epsilon_princ(0));
-
- Vector<Real> sigma_p(3);
- for (UInt i = 0; i < 3; i++) {
- sigma_p(i) = std::max(Real(0.), sigma_princ(i));
- }
- // sigma_p *= 1. - dam;
-
- Real trace_p = this->nu / this->E * (sigma_p(0) + sigma_p(1) + sigma_p(2));
-
- Real alpha_t = 0;
- for (UInt i = 0; i < 3; ++i) {
- Real epsilon_t = (1 + this->nu) / this->E * sigma_p(i) - trace_p;
- Real epsilon_p = std::max(Real(0.), epsilon_princ(i));
- alpha_t += epsilon_t * epsilon_p;
- }
-
- alpha_t /= epsilon_equ * epsilon_equ;
- alpha_t = std::min(alpha_t, Real(1.));
-
- Real alpha_c = 1. - alpha_t;
-
- alpha_t = std::pow(alpha_t, beta);
- alpha_c = std::pow(alpha_c, beta);
-
- Real damtemp;
- damtemp = alpha_t * dam_t + alpha_c * dam_c;
-
- dam = std::max(damtemp, dam);
- dam = std::min(dam, Real(1.));
+template <Int dim, template <Int> class Parent>
+template <typename Args, typename Derived>
+inline void MaterialMazars<dim, Parent>::computeDamageOnQuad(
+ Args && args, const Eigen::MatrixBase<Derived> & epsilon_princ) {
+ auto && dam = args["damage"_n];
+ auto && Ehat = args["Ehat"_n];
+
+ auto Fs = Ehat - K0;
+
+ if (Fs <= 0.) {
+ return;
+ }
+
+ auto dam_t = 1 - K0 * (1 - At) / Ehat - At * (exp(-Bt * (Ehat - K0)));
+ auto dam_c = 1 - K0 * (1 - Ac) / Ehat - Ac * (exp(-Bc * (Ehat - K0)));
+
+ auto Cdiag = this->E * (1 - this->nu) / ((1 + this->nu) * (1 - 2 * this->nu));
+
+ Vector<Real, 3> sigma_princ;
+ sigma_princ(0) = Cdiag * epsilon_princ(0) +
+ this->lambda * (epsilon_princ(1) + epsilon_princ(2));
+ sigma_princ(1) = Cdiag * epsilon_princ(1) +
+ this->lambda * (epsilon_princ(0) + epsilon_princ(2));
+ sigma_princ(2) = Cdiag * epsilon_princ(2) +
+ this->lambda * (epsilon_princ(1) + epsilon_princ(0));
+
+ Vector<Real, 3> sigma_p;
+ for (Int i = 0; i < 3; i++) {
+ sigma_p(i) = std::max(Real(0.), sigma_princ(i));
+ }
+ // sigma_p *= 1. - dam;
+
+ auto trace_p = this->nu / this->E * (sigma_p(0) + sigma_p(1) + sigma_p(2));
+
+ Real alpha_t = 0;
+ for (Int i = 0; i < 3; ++i) {
+ auto epsilon_t = (1 + this->nu) / this->E * sigma_p(i) - trace_p;
+ auto epsilon_p = std::max(Real(0.), epsilon_princ(i));
+ alpha_t += epsilon_t * epsilon_p;
}
+
+ alpha_t /= Ehat * Ehat;
+ alpha_t = std::min(alpha_t, Real(1.));
+
+ auto alpha_c = 1. - alpha_t;
+
+ alpha_t = std::pow(alpha_t, beta);
+ alpha_c = std::pow(alpha_c, beta);
+
+ auto damtemp = alpha_t * dam_t + alpha_c * dam_c;
+
+ dam = std::max(damtemp, dam);
+ dam = std::min(dam, Real(1.));
}
-/* -------------------------------------------------------------------------- */
-// template<UInt spatial_dimension>
-// inline void
-// MaterialMazars<spatial_dimension>::computeTangentModuliOnQuad(Matrix<Real> &
-// tangent) {
-// MaterialElastic<spatial_dimension>::computeTangentModuliOnQuad(tangent);
-
-// tangent *= (1-dam);
-// }
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
index bf378c08e..edd0fd6c8 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
@@ -1,126 +1,49 @@
/**
* @file material_mazars_non_local.cc
*
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Specialization of the material class for the non-local mazars
* material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_mazars_non_local.hh"
-#include "solid_mechanics_model.hh"
namespace akantu {
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialMazarsNonLocal<spatial_dimension>::MaterialMazarsNonLocal(
- SolidMechanicsModel & model, const ID & id)
- : MaterialNonLocalParent(model, id), Ehat("epsilon_equ", *this),
- non_local_variable("mazars_non_local", *this) {
- AKANTU_DEBUG_IN();
-
- this->is_non_local = true;
- this->Ehat.initialize(1);
- this->non_local_variable.initialize(1);
-
- this->registerParam("average_on_damage", this->damage_in_compute_stress,
- false, _pat_parsable | _pat_modifiable,
- "Is D the non local variable");
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMazarsNonLocal<spatial_dimension>::registerNonLocalVariables() {
- ID local;
- if (this->damage_in_compute_stress) {
- local = this->damage.getName();
- } else {
- local = this->Ehat.getName();
- }
-
- this->model.getNonLocalManager().registerNonLocalVariable(
- local, non_local_variable.getName(), 1);
- this->model.getNonLocalManager()
- .getNeighborhood(this->name)
- .registerNonLocalVariable(non_local_variable.getName());
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMazarsNonLocal<spatial_dimension>::computeStress(
- ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- Real * damage = this->damage(el_type, ghost_type).storage();
- Real * epsilon_equ = this->Ehat(el_type, ghost_type).storage();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- MaterialMazars<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *damage,
- *epsilon_equ);
- ++damage;
- ++epsilon_equ;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStress(
- ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
- auto & non_loc_var = non_local_variable(el_type, ghost_type);
- Real * damage;
- Real * epsilon_equ;
- if (this->damage_in_compute_stress) {
- damage = non_loc_var.storage();
- epsilon_equ = this->Ehat(el_type, ghost_type).storage();
- } else {
- damage = this->damage(el_type, ghost_type).storage();
- epsilon_equ = non_loc_var.storage();
- }
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- this->computeDamageAndStressOnQuad(grad_u, sigma, *damage, *epsilon_equ);
-
- ++damage;
- ++epsilon_equ;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+template class MaterialMazarsNonLocal<1>;
+template class MaterialMazarsNonLocal<2>;
+template class MaterialMazarsNonLocal<3>;
- AKANTU_DEBUG_OUT();
-}
+template <Int dim> using MaterialMazarsNonLocal_ = MaterialMazarsNonLocal<dim>;
-INSTANTIATE_MATERIAL(mazars_non_local, MaterialMazarsNonLocal);
+static bool material_is_alocated_mazars_non_local =
+ instantiateMaterial<MaterialMazarsNonLocal_>("mazars_non_local");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh
index 631ef2280..01e431f4f 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh
@@ -1,92 +1,96 @@
/**
* @file material_mazars_non_local.hh
*
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Mazars non-local description
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_damage_non_local.hh"
#include "material_mazars.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_MAZARS_NON_LOCAL_HH_
#define AKANTU_MATERIAL_MAZARS_NON_LOCAL_HH_
namespace akantu {
/**
* Material Mazars Non local
*
* parameters in the material files :
*/
-template <UInt spatial_dimension>
+template <Int dim, template <Int> class Parent = MaterialElastic>
class MaterialMazarsNonLocal
- : public MaterialDamageNonLocal<spatial_dimension,
- MaterialMazars<spatial_dimension>> {
+ : public MaterialDamageNonLocal<dim, MaterialMazars<dim, Parent>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- using MaterialNonLocalParent =
- MaterialDamageNonLocal<spatial_dimension,
- MaterialMazars<spatial_dimension>>;
+ using parent = MaterialDamageNonLocal<dim, MaterialMazars<dim, Parent>>;
MaterialMazarsNonLocal(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
void computeNonLocalStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
void registerNonLocalVariables() override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ return zip_replace(parent::getArguments(el_type, ghost_type),
+ "Ehat"_n = make_view(this->Ehat(el_type, ghost_type)));
+ }
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// the ehat per quadrature points to perform the averaging
InternalField<Real> Ehat;
InternalField<Real> non_local_variable;
};
} // namespace akantu
+#include "material_mazars_non_local_tmpl.hh"
+
#endif /* AKANTU_MATERIAL_MAZARS_NON_LOCAL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh
new file mode 100644
index 000000000..f062a72d4
--- /dev/null
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh
@@ -0,0 +1,106 @@
+/**
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "solid_mechanics_model.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_MATERIAL_MAZARS_NON_LOCAL_TMPL_HH_
+#define AKANTU_MATERIAL_MAZARS_NON_LOCAL_TMPL_HH_
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, template <Int> class Parent>
+MaterialMazarsNonLocal<dim, Parent>::MaterialMazarsNonLocal(
+ SolidMechanicsModel & model, const ID & id)
+ : parent(model, id), Ehat("epsilon_equ", *this),
+ non_local_variable("mazars_non_local", *this) {
+ AKANTU_DEBUG_IN();
+
+ this->is_non_local = true;
+ this->Ehat.initialize(1);
+ this->non_local_variable.initialize(1);
+
+ this->registerParam("average_on_damage", this->damage_in_compute_stress,
+ false, _pat_parsable | _pat_modifiable,
+ "Is D the non local variable");
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, template <Int> class Parent>
+void MaterialMazarsNonLocal<dim, Parent>::registerNonLocalVariables() {
+ ID local;
+ if (this->damage_in_compute_stress) {
+ local = this->damage.getName();
+ } else {
+ local = this->Ehat.getName();
+ }
+
+ this->model.getNonLocalManager().registerNonLocalVariable(
+ local, non_local_variable.getName(), 1);
+ this->model.getNonLocalManager()
+ .getNeighborhood(this->name)
+ .registerNonLocalVariable(non_local_variable.getName());
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, template <Int> class Parent>
+void MaterialMazarsNonLocal<dim, Parent>::computeStress(ElementType el_type,
+ GhostType ghost_type) {
+ AKANTU_DEBUG_IN();
+
+ auto && arguments = getArguments(el_type, ghost_type);
+
+ for (auto && data : arguments) {
+ parent::MaterialParent::computeStressOnQuad(data);
+ }
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim, template <Int> class Parent>
+void MaterialMazarsNonLocal<dim, Parent>::computeNonLocalStress(
+ ElementType el_type, GhostType ghost_type) {
+ AKANTU_DEBUG_IN();
+ auto & non_loc_var = non_local_variable(el_type, ghost_type);
+
+ if (this->damage_in_compute_stress) {
+ auto && arguments = zip_replace(getArguments(el_type, ghost_type),
+ "damage"_n = make_view(non_loc_var));
+
+ for (auto && data : arguments) {
+ parent::MaterialParent::computeDamageAndStressOnQuad(data);
+ }
+ } else {
+ auto && arguments = zip_replace(getArguments(el_type, ghost_type),
+ "Ehat"_n = make_view(non_loc_var));
+
+ for (auto && data : arguments) {
+ parent::MaterialParent::computeDamageAndStressOnQuad(data);
+ }
+ }
+ AKANTU_DEBUG_OUT();
+}
+
+} // namespace akantu
+
+#endif // AKANTU_MATERIAL_MAZARS_NON_LOCAL_TMPL_HH_
diff --git a/src/model/solid_mechanics/materials/material_damage/material_phasefield.cc b/src/model/solid_mechanics/materials/material_damage/material_phasefield.cc
index 82cad2cd9..69efd7bd9 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_phasefield.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_phasefield.cc
@@ -1,117 +1,89 @@
/**
* @file material_phasefield.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Fri Apr 02 2021
*
* @brief Specialization of the material class for the phasefield material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_phasefield.hh"
#include "aka_common.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialPhaseField<spatial_dimension>::MaterialPhaseField(
- SolidMechanicsModel & model, const ID & id)
+template <Int dim>
+MaterialPhaseField<dim>::MaterialPhaseField(SolidMechanicsModel & model,
+ const ID & id)
: Parent(model, id), effective_damage("effective_damage", *this) {
-
- AKANTU_DEBUG_IN();
-
this->registerParam("eta", eta, Real(0.), _pat_parsable, "eta");
this->damage.initialize(0);
this->effective_damage.initialize(1);
-
- AKANTU_DEBUG_OUT();
}
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialPhaseField<spatial_dimension>::computeStress(
- ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
+template <Int dim>
+void MaterialPhaseField<dim>::computeStress(ElementType el_type,
+ GhostType ghost_type) {
computeEffectiveDamage(el_type, ghost_type);
- auto dam = this->effective_damage(el_type, ghost_type).begin();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_u, sigma);
- sigma *= (1. - *dam) * (1. - *dam) + eta;
-
- ++dam;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ for (auto && args : getArguments(el_type, ghost_type)) {
+ computeStressOnQuad(args);
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialPhaseField<spatial_dimension>::computeTangentModuli(
- ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- Parent::computeTangentModuli(el_type, tangent_matrix, ghost_type);
-
+template <Int dim>
+void MaterialPhaseField<dim>::computeTangentModuli(ElementType el_type,
+ Array<Real> & tangent_matrix,
+ GhostType ghost_type) {
computeEffectiveDamage(el_type, ghost_type);
- auto dam = this->effective_damage(el_type, ghost_type).begin();
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
-
- tangent *= (1. - *dam) * (1. - *dam) + eta;
- ++dam;
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ for (auto && args :
+ getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
+ computeTangentModuliOnQuad(args);
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialPhaseField<spatial_dimension>::computeEffectiveDamage(
- ElementType el_type, GhostType ghost_type) {
-
- auto && grad_u_view =
- make_view(this->gradu(el_type, ghost_type), this->spatial_dimension,
- this->spatial_dimension);
-
- for (auto && data : zip(grad_u_view, this->damage(el_type, ghost_type),
- this->effective_damage(el_type, ghost_type))) {
- auto & grad_u = std::get<0>(data);
- auto & dam = std::get<1>(data);
- auto & eff_dam = std::get<2>(data);
-
- computeEffectiveDamageOnQuad(grad_u, dam, eff_dam);
+template <Int dim>
+void MaterialPhaseField<dim>::computeEffectiveDamage(ElementType el_type,
+ GhostType ghost_type) {
+ for (auto && args : getArguments(el_type, ghost_type)) {
+ computeEffectiveDamageOnQuad(args);
}
}
-INSTANTIATE_MATERIAL(phasefield, MaterialPhaseField);
+/* -------------------------------------------------------------------------- */
+template class MaterialPhaseField<1>;
+template class MaterialPhaseField<2>;
+template class MaterialPhaseField<3>;
+
+static bool material_is_allocated_phasefield =
+ instantiateMaterial<MaterialPhaseField>("phasefield");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_phasefield.hh b/src/model/solid_mechanics/materials/material_damage/material_phasefield.hh
index 12a6437b4..fa08b2679 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_phasefield.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_phasefield.hh
@@ -1,99 +1,112 @@
/**
* @file material_phasefield.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 02 2021
*
* @brief Phasefield damage law
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_damage.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_MATERIAL_PHASEFIELD_HH__
#define __AKANTU_MATERIAL_PHASEFIELD_HH__
namespace akantu {
-template <UInt spatial_dimension>
-class MaterialPhaseField : public MaterialDamage<spatial_dimension> {
- using Parent = MaterialDamage<spatial_dimension>;
+template <Int dim> class MaterialPhaseField : public MaterialDamage<dim> {
+ using Parent = MaterialDamage<dim>;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialPhaseField(SolidMechanicsModel & model, const ID & id = "");
~MaterialPhaseField() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
+ /* ------------------------------------------------------------------------ */
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(Parent::getArguments(el_type, ghost_type),
+ "effective_damage"_n = make_view(
+ this->effective_damage(el_type, ghost_type)));
+ }
+
+ decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrix,
+ ElementType el_type,
+ GhostType ghost_type) {
+ return zip_append(
+ Parent::getArgumentsTangent(tangent_matrix, el_type, ghost_type),
+ "effective_damage"_n =
+ make_view(this->effective_damage(el_type, ghost_type)));
+ }
+
protected:
/// constitutive law for a given quadrature point
+ template <class Args> inline void computeStressOnQuad(Args && args);
/// compute the tangent stiffness matrix for a given quadrature point
+ template <class Args> inline void computeTangentModuliOnQuad(Args && args);
+ /// Compute the effective damage
void computeEffectiveDamage(ElementType el_type,
GhostType ghost_type = _not_ghost);
- inline void computeEffectiveDamageOnQuad(Matrix<Real> & grad_u, Real & dam,
- Real & eff_dam);
+ template <class Args> inline void computeEffectiveDamageOnQuad(Args && args);
- /* ------------------------------------------------------------------------ */
- /* Accessors */
- /* ------------------------------------------------------------------------ */
-public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
Real eta;
// effective damage to conserve stiffness in compression
InternalField<Real> effective_damage;
};
-
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_phasefield_inline_impl.hh"
#endif /* __AKANTU_MATERIAL_PHASEFIELD_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_phasefield_inline_impl.hh b/src/model/solid_mechanics/materials/material_damage/material_phasefield_inline_impl.hh
index b98ead0b3..3f9bca8ba 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_phasefield_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_phasefield_inline_impl.hh
@@ -1,93 +1,100 @@
/**
* @file material_phasefield_inline_impl.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Fri Apr 02 2021
*
* @brief Implementation of the inline functions of the material phasefield
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "material_phasefield.hh"
#ifndef AKANTU_MATERIAL_PHASEFIELD_INLINE_IMPL_HH_
#define AKANTU_MATERIAL_PHASEFIELD_INLINE_IMPL_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
+template <Int dim>
+template <class Args>
+inline void MaterialPhaseField<dim>::computeStressOnQuad(Args && args) {
+ MaterialElastic<dim>::computeStressOnQuad(args);
-template <UInt spatial_dimension>
-inline void MaterialPhaseField<spatial_dimension>::computeEffectiveDamageOnQuad(
- Matrix<Real> & grad_u, Real & dam, Real & eff_dam) {
+ auto && dam = args["effective_damage"_n];
+ args["sigma"_n] *= (1 - dam) * (1 - dam) + eta;
+}
- Matrix<Real> strain(spatial_dimension, spatial_dimension);
- Matrix<Real> strain_plus(spatial_dimension, spatial_dimension);
- Matrix<Real> strain_minus(spatial_dimension, spatial_dimension);
- Matrix<Real> strain_dir(spatial_dimension, spatial_dimension);
- Matrix<Real> strain_diag_plus(spatial_dimension, spatial_dimension);
- Matrix<Real> strain_diag_minus(spatial_dimension, spatial_dimension);
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+template <class Args>
+void MaterialPhaseField<dim>::computeTangentModuliOnQuad(Args && args) {
+ MaterialElastic<dim>::computeTangentModuliOnQuad(args);
- Vector<Real> strain_values(spatial_dimension);
+ auto dam = args["effective_damage"_n];
+ args["tangent_moduli"_n] *= (1 - dam) * (1 - dam) + eta;
+}
- Real trace_plus, trace_minus;
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+template <class Args>
+inline void
+MaterialPhaseField<dim>::computeEffectiveDamageOnQuad(Args && args) {
+ using Mat = Matrix<Real, dim, dim>;
- this->template gradUToEpsilon<spatial_dimension>(grad_u, strain);
+ auto strain = Material::gradUToEpsilon<dim>(args["grad_u"_n]);
+ Mat strain_dir;
+ Vector<Real, dim> strain_values;
strain.eig(strain_values, strain_dir);
- for (UInt i = 0; i < spatial_dimension; i++) {
+ Mat strain_diag_plus;
+ Mat strain_diag_minus;
+
+ strain_diag_plus.zero();
+ strain_diag_minus.zero();
+
+ for (UInt i = 0; i < dim; i++) {
strain_diag_plus(i, i) = std::max(Real(0.), strain_values(i));
strain_diag_minus(i, i) = std::min(Real(0.), strain_values(i));
}
- Matrix<Real> mat_tmp(spatial_dimension, spatial_dimension);
- Matrix<Real> sigma_plus(spatial_dimension, spatial_dimension);
- Matrix<Real> sigma_minus(spatial_dimension, spatial_dimension);
-
- mat_tmp.mul<false, true>(strain_diag_plus, strain_dir);
- strain_plus.mul<false, false>(strain_dir, mat_tmp);
- mat_tmp.mul<false, true>(strain_diag_minus, strain_dir);
- strain_minus.mul<false, true>(strain_dir, mat_tmp);
+ Mat strain_plus = strain_dir * strain_diag_plus * strain_dir.transpose();
+ Mat strain_minus = strain_dir * strain_diag_minus * strain_dir.transpose();
- trace_plus = std::max(Real(0.), strain.trace());
- trace_minus = std::min(Real(0.), strain.trace());
+ auto trace_plus = std::max(Real(0.), strain.trace());
+ auto trace_minus = std::min(Real(0.), strain.trace());
- Real lambda = MaterialElastic<spatial_dimension>::getLambda();
- Real mu = MaterialElastic<spatial_dimension>::getMu();
+ Mat sigma_plus =
+ Mat::Identity() * trace_plus * this->lambda + 2. * this->mu * strain_plus;
+ Mat sigma_minus = Mat::Identity() * trace_minus * this->lambda +
+ 2. * this->mu * strain_minus;
- for (UInt i = 0; i < spatial_dimension; i++) {
- for (UInt j = 0; j < spatial_dimension; j++) {
- sigma_plus(i, j) = static_cast<double>(i == j) * lambda * trace_plus +
- 2 * mu * strain_plus(i, j);
- sigma_minus(i, j) = static_cast<double>(i == j) * lambda * trace_minus +
- 2 * mu * strain_minus(i, j);
- }
- }
- auto strain_energy_plus = 0.5 * sigma_plus.doubleDot(strain_plus);
- auto strain_energy_minus = 0.5 * sigma_minus.doubleDot(strain_minus);
+ auto strain_energy_plus = sigma_plus.doubleDot(strain_plus) / 2.;
+ auto strain_energy_minus = sigma_minus.doubleDot(strain_minus) / 2.;
- eff_dam = dam * static_cast<Real>(strain_energy_minus < strain_energy_plus);
+ args["effective_damage"_n] =
+ args["damage"_n] * (strain_energy_minus < strain_energy_plus);
}
-} // namespace akantu
+} // namespace akantu
#endif
diff --git a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.cc b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.cc
index 2dc753912..10d58f82f 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.cc
@@ -1,180 +1,44 @@
/**
* @file material_von_mises_mazars.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Apr 07 2014
* @date last modification: Fri Dec 04 2020
*
* @brief Mazars damage with Von Misses criteria
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_von_mises_mazars.hh"
-#include "solid_mechanics_model.hh"
namespace akantu {
-/* -------------------------------------------------------------------------- */
-template <UInt dim, template <UInt> class Parent>
-MaterialVonMisesMazars<dim, Parent>::MaterialVonMisesMazars(
- SolidMechanicsModel & model, const ID & id)
- : MaterialDamage<dim, Parent>(model, id), K0("K0", *this),
- damage_in_compute_stress(true) {
- AKANTU_DEBUG_IN();
-
- this->registerParam("K0", K0, _pat_parsable, "K0");
- this->registerParam("At", At, Real(0.8), _pat_parsable, "At");
- this->registerParam("Ac", Ac, Real(1.4), _pat_parsable, "Ac");
- this->registerParam("Bc", Bc, Real(1900.), _pat_parsable, "Bc");
- this->registerParam("Bt", Bt, Real(12000.), _pat_parsable, "Bt");
- this->registerParam("beta", beta, Real(1.06), _pat_parsable, "beta");
-
- this->K0.initialize(1);
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-void MaterialVonMisesMazars<spatial_dimension, Parent>::computeStress(
- ElementType el_type, GhostType ghost_type) {
-
- AKANTU_DEBUG_IN();
-
- MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type);
- // infinitesimal and finite deformation
- auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
-
- auto previous_sigma_th_it =
- this->sigma_th.previous(el_type, ghost_type).begin();
-
- auto previous_gradu_it = this->gradu.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_stress_it = this->stress.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto inelastic_strain_it = this->inelastic_strain(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_inelastic_strain_it =
- this->inelastic_strain.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto iso_hardening_it = this->iso_hardening(el_type, ghost_type).begin();
-
- auto previous_iso_hardening_it =
- this->iso_hardening.previous(el_type, ghost_type).begin();
-
- Real * dam = this->damage(el_type, ghost_type).storage();
-
- //
- // Finite Deformations
- //
- if (this->finite_deformation) {
- auto previous_piola_kirchhoff_2_it =
- this->piola_kirchhoff_2.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto green_strain_it = this->green_strain(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- auto & inelastic_strain_tensor = *inelastic_strain_it;
- auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
- auto & previous_grad_u = *previous_gradu_it;
- auto & previous_sigma = *previous_piola_kirchhoff_2_it;
-
- auto & green_strain = *green_strain_it;
- this->template gradUToE<spatial_dimension>(grad_u, green_strain);
- Matrix<Real> previous_green_strain(spatial_dimension, spatial_dimension);
- this->template gradUToE<spatial_dimension>(previous_grad_u,
- previous_green_strain);
- Matrix<Real> F_tensor(spatial_dimension, spatial_dimension);
- this->template gradUToF<spatial_dimension>(grad_u, F_tensor);
-
- MaterialLinearIsotropicHardening<spatial_dimension>::computeStressOnQuad(
- green_strain, previous_green_strain, sigma, previous_sigma,
- inelastic_strain_tensor, previous_inelastic_strain_tensor,
- *iso_hardening_it, *previous_iso_hardening_it, *sigma_th_it,
- *previous_sigma_th_it, F_tensor);
-
- ++sigma_th_it;
- ++inelastic_strain_it;
- ++iso_hardening_it;
- ++previous_sigma_th_it;
- //++previous_stress_it;
- ++previous_gradu_it;
- ++green_strain_it;
- ++previous_inelastic_strain_it;
- ++previous_iso_hardening_it;
- ++previous_piola_kirchhoff_2_it;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- }
- // Infinitesimal deformations
- else {
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- Real Ehat = 0;
-
- auto & inelastic_strain_tensor = *inelastic_strain_it;
- auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
- auto & previous_grad_u = *previous_gradu_it;
- auto & previous_sigma = *previous_stress_it;
-
- MaterialLinearIsotropicHardening<spatial_dimension>::computeStressOnQuad(
- grad_u, previous_grad_u, sigma, previous_sigma, inelastic_strain_tensor,
- previous_inelastic_strain_tensor, *iso_hardening_it,
- *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it);
-
- Matrix<Real> grad_u_elastic(grad_u);
- grad_u_elastic -= inelastic_strain_tensor;
-
- computeStressOnQuad(grad_u_elastic, sigma, *dam, Ehat);
-
- ++dam;
-
- ++sigma_th_it;
- ++inelastic_strain_it;
- ++iso_hardening_it;
- ++previous_sigma_th_it;
- ++previous_stress_it;
- ++previous_gradu_it;
- ++previous_inelastic_strain_it;
- ++previous_iso_hardening_it;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
- }
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
+template class MaterialMazars<1, MaterialLinearIsotropicHardening>;
+template class MaterialMazars<2, MaterialLinearIsotropicHardening>;
+template class MaterialMazars<3, MaterialLinearIsotropicHardening>;
-INSTANTIATE_MATERIAL(plastic_mazars, MaterialVonMisesMazars);
+static bool material_is_allocated_plastic_mazars =
+ instantiateMaterial<MaterialVonMisesMazars>("plastic_mazars");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.hh b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.hh
index 35b19b878..4f04fd540 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars.hh
@@ -1,110 +1,49 @@
/**
* @file material_von_mises_mazars.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Dec 04 2020
*
* @brief Mazars damage with Von Misses criteria
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
-#include "aka_voigthelper.hh"
-#include "material_damage.hh"
#include "material_linear_isotropic_hardening.hh"
+#include "material_mazars.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_MATERIAL_VONMISES_MAZARS_HH__
#define __AKANTU_MATERIAL_VONMISES_MAZARS_HH__
namespace akantu {
-template <UInt spatial_dimension,
- template <UInt> class Parent = MaterialLinearIsotropicHardening>
-class MaterialVonMisesMazars
- : public MaterialDamage<spatial_dimension, Parent> {
-
- /* ------------------------------------------------------------------------ */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------ */
-public:
- MaterialVonMisesMazars(SolidMechanicsModel & model, const ID & id = "");
- MaterialVonMisesMazars(SolidMechanicsModel & model, UInt dim,
- const Mesh & mesh, FEEngine & fe_engine,
- const ID & id = "");
- /* ------------------------------------------------------------------------ */
- /* Methods */
- /* ------------------------------------------------------------------------ */
-public:
- /// constitutive law for all element of a type
- void computeStress(ElementType el_type,
- GhostType ghost_type = _not_ghost) override;
-
-protected:
- /// constitutive law for a given quadrature point
- inline void computeStressOnQuad(const Matrix<Real> & grad_u,
- Matrix<Real> & sigma, Real & damage,
- Real & Ehat);
-
- inline void computeDamageAndStressOnQuad(const Matrix<Real> & grad_u,
- Matrix<Real> & sigma, Real & damage,
- Real & Ehat);
-
- inline void computeDamageOnQuad(const Real & epsilon_equ,
- const Matrix<Real> & sigma,
- const Vector<Real> & epsilon_princ,
- Real & dam);
-
- /* ------------------------------------------------------------------------ */
- /* Accessors */
- /* ------------------------------------------------------------------------ */
-public:
- /* ------------------------------------------------------------------------ */
- /* Class Members */
- /* ------------------------------------------------------------------------ */
-protected:
- /// damage threshold
- RandomInternalField<Real> K0;
- /// parameter damage traction 1
- Real At;
- /// parameter damage traction 2
- Real Bt;
- /// parameter damage compression 1
- Real Ac;
- /// parameter damage compression 2
- Real Bc;
- /// parameter for shear
- Real beta;
-
- /// specify the variable to average false = ehat, true = damage (only valid
- /// for non local version)
- bool damage_in_compute_stress;
-};
+template <Int dim>
+using MaterialVonMisesMazars =
+ MaterialMazars<dim, MaterialLinearIsotropicHardening>;
} // namespace akantu
-#include "material_von_mises_mazars_inline_impl.hh"
-
#endif /* __AKANTU_MATERIAL_VONMISES_MAZARS_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh
index 9821fb1f1..147354b36 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh
@@ -1,156 +1,143 @@
/**
* @file material_von_mises_mazars_inline_impl.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed Apr 06 2011
* @date last modification: Wed Dec 23 2020
*
* @brief Mazars damage with Von Misses criteria
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_von_mises_mazars.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-inline void
-MaterialVonMisesMazars<spatial_dimension, Parent>::computeStressOnQuad(
+template <Int dim, template <UInt> class Parent>
+inline void MaterialVonMisesMazars<dim, Parent>::computeStressOnQuad(
const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam,
Real & Ehat) {
Matrix<Real> epsilon(3, 3);
epsilon.zero();
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- epsilon(i, j) = .5 * (grad_u(i, j) + grad_u(j, i));
- }
- }
+ epsilon.block<dim, dim>(0, 0) = Material::gradUToEpsilon(grad_u);
- Vector<Real> Fdiag(3);
- Math::matrixEig(3, epsilon.storage(), Fdiag.storage());
+ Vector<Real, 3> Fdiag(3);
+ epsilon.eig(Fdiag);
Ehat = 0.;
for (UInt i = 0; i < 3; ++i) {
Real epsilon_p = std::max(Real(0.), Fdiag(i));
Ehat += epsilon_p * epsilon_p;
}
- Ehat = sqrt(Ehat);
+ Ehat = std::sqrt(Ehat);
- // MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_u, sigma);
+ // MaterialElastic<dim>::computeStressOnQuad(grad_u, sigma);
if (damage_in_compute_stress) {
computeDamageOnQuad(Ehat, sigma, Fdiag, dam);
}
if (not this->is_non_local) {
computeDamageAndStressOnQuad(grad_u, sigma, dam, Ehat);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-inline void
-MaterialVonMisesMazars<spatial_dimension, Parent>::computeDamageAndStressOnQuad(
+template <Int dim, template <UInt> class Parent>
+inline void MaterialVonMisesMazars<dim, Parent>::computeDamageAndStressOnQuad(
const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & dam,
Real & Ehat) {
if (!damage_in_compute_stress) {
- Vector<Real> Fdiag(3);
- Fdiag.zero();
-
- Matrix<Real> epsilon(3, 3);
- epsilon.zero();
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- epsilon(i, j) = .5 * (grad_u(i, j) + grad_u(j, i));
- }
- }
- Math::matrixEig(3, epsilon.storage(), Fdiag.storage());
+ auto && Fdiag = Vector<Real, 3>::Zero();
+
+ auto && epsilon = Matrix<Real, 3, 3>::Zero();
+ epsilon.block(0, 0, dim, dim) = Material::gradUToEpsilon<dim>(grad_u);
+ epsilon.eig(Fdiag);
computeDamageOnQuad(Ehat, sigma, Fdiag, dam);
}
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension, template <UInt> class Parent>
-inline void
-MaterialVonMisesMazars<spatial_dimension, Parent>::computeDamageOnQuad(
+template <Int dim, template <UInt> class Parent>
+inline void MaterialVonMisesMazars<dim, Parent>::computeDamageOnQuad(
const Real & epsilon_equ,
__attribute__((unused)) const Matrix<Real> & sigma,
const Vector<Real> & epsilon_princ, Real & dam) {
Real Fs = epsilon_equ - K0;
if (Fs > 0.) {
Real dam_t;
Real dam_c;
dam_t =
1 - K0 * (1 - At) / epsilon_equ - At * (exp(-Bt * (epsilon_equ - K0)));
dam_c =
1 - K0 * (1 - Ac) / epsilon_equ - Ac * (exp(-Bc * (epsilon_equ - K0)));
Real Cdiag;
Cdiag = this->E * (1 - this->nu) / ((1 + this->nu) * (1 - 2 * this->nu));
Vector<Real> sigma_princ(3);
sigma_princ(0) = Cdiag * epsilon_princ(0) +
this->lambda * (epsilon_princ(1) + epsilon_princ(2));
sigma_princ(1) = Cdiag * epsilon_princ(1) +
this->lambda * (epsilon_princ(0) + epsilon_princ(2));
sigma_princ(2) = Cdiag * epsilon_princ(2) +
this->lambda * (epsilon_princ(1) + epsilon_princ(0));
Vector<Real> sigma_p(3);
- for (UInt i = 0; i < 3; i++) {
+ for (Int i = 0; i < 3; i++) {
sigma_p(i) = std::max(Real(0.), sigma_princ(i));
}
// sigma_p *= 1. - dam;
Real trace_p = this->nu / this->E * (sigma_p(0) + sigma_p(1) + sigma_p(2));
Real alpha_t = 0;
- for (UInt i = 0; i < 3; ++i) {
+ for (Int i = 0; i < 3; ++i) {
Real epsilon_t = (1 + this->nu) / this->E * sigma_p(i) - trace_p;
Real epsilon_p = std::max(Real(0.), epsilon_princ(i));
alpha_t += epsilon_t * epsilon_p;
}
alpha_t /= epsilon_equ * epsilon_equ;
alpha_t = std::min(alpha_t, Real(1.));
Real alpha_c = 1. - alpha_t;
alpha_t = std::pow(alpha_t, beta);
alpha_c = std::pow(alpha_c, beta);
Real damtemp;
damtemp = alpha_t * dam_t + alpha_c * dam_c;
dam = std::max(damtemp, dam);
dam = std::min(dam, Real(1.));
}
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.cc b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.cc
index 813f889b2..36b25ca8d 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.cc
@@ -1,125 +1,45 @@
/**
* @file material_von_mises_mazars_non_local.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Dec 17 2020
*
* @brief Mazars damage with Von Misses criteria
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_von_mises_mazars_non_local.hh"
-#include "solid_mechanics_model.hh"
namespace akantu {
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialVonMisesMazarsNonLocal<spatial_dimension>::
- MaterialVonMisesMazarsNonLocal(SolidMechanicsModel & model, const ID & id)
- : MaterialNonLocalParent(model, id), Ehat("epsilon_equ", *this),
- non_local_variable("mazars_non_local", *this) {
- AKANTU_DEBUG_IN();
-
- this->is_non_local = true;
- this->Ehat.initialize(1);
- this->non_local_variable.initialize(1);
-
- this->registerParam("average_on_damage", this->damage_in_compute_stress,
- false, _pat_parsable | _pat_modifiable,
- "Is D the non local variable");
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialVonMisesMazarsNonLocal<
- spatial_dimension>::registerNonLocalVariables() {
- ID local;
- if (this->damage_in_compute_stress) {
- local = this->damage.getName();
- } else {
- local = this->Ehat.getName();
- }
-
- this->model.getNonLocalManager().registerNonLocalVariable(
- local, non_local_variable.getName(), 1);
- this->model.getNonLocalManager()
- .getNeighborhood(this->name)
- .registerNonLocalVariable(non_local_variable.getName());
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialVonMisesMazarsNonLocal<spatial_dimension>::computeStress(
- ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- Real * damage = this->damage(el_type, ghost_type).storage();
- Real * epsilon_equ = this->Ehat(el_type, ghost_type).storage();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- MaterialVonMisesMazars<spatial_dimension>::computeStressOnQuad(
- grad_u, sigma, *damage, *epsilon_equ);
- ++damage;
- ++epsilon_equ;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialVonMisesMazarsNonLocal<spatial_dimension>::computeNonLocalStress(
- ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
- auto & non_loc_var = non_local_variable(el_type, ghost_type);
- Real * damage;
- Real * epsilon_equ;
- if (this->damage_in_compute_stress) {
- damage = non_loc_var.storage();
- epsilon_equ = this->Ehat(el_type, ghost_type).storage();
- } else {
- damage = this->damage(el_type, ghost_type).storage();
- epsilon_equ = non_loc_var.storage();
- }
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- this->computeDamageAndStressOnQuad(grad_u, sigma, *damage, *epsilon_equ);
-
- ++damage;
- ++epsilon_equ;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
-}
+template class MaterialMazarsNonLocal<1, MaterialLinearIsotropicHardening>;
+template class MaterialMazarsNonLocal<2, MaterialLinearIsotropicHardening>;
+template class MaterialMazarsNonLocal<3, MaterialLinearIsotropicHardening>;
-INSTANTIATE_MATERIAL(von_mises_mazars_non_local,
- MaterialVonMisesMazarsNonLocal);
+static bool material_is_allocated_plastic_mazars_non_local =
+ instantiateMaterial<MaterialVonMisesMazarsNonLocal>(
+ "plastic_mazars_non_local");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.hh
index 958bca1eb..9d049c07f 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_von_mises_mazars_non_local.hh
@@ -1,92 +1,51 @@
/**
* @file material_von_mises_mazars_non_local.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Dec 17 2020
*
* @brief Mazars damage with Von Misses criteria
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "material_damage_non_local.hh"
-#include "material_von_mises_mazars.hh"
+#include "material_linear_isotropic_hardening.hh"
+#include "material_mazars_non_local.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_VON_MISES_MAZARS_NON_LOCAL_HH_
#define AKANTU_MATERIAL_VON_MISES_MAZARS_NON_LOCAL_HH_
namespace akantu {
/**
* Material Mazars Non local + Von Mises plasticity
- *
- * parameters in the material files :
*/
-template <UInt spatial_dimension>
-class MaterialVonMisesMazarsNonLocal
- : public MaterialDamageNonLocal<spatial_dimension,
- MaterialVonMisesMazars<spatial_dimension>> {
- /* ------------------------------------------------------------------------ */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------ */
-public:
- using MaterialNonLocalParent =
- MaterialDamageNonLocal<spatial_dimension,
- MaterialVonMisesMazars<spatial_dimension>>;
-
- MaterialVonMisesMazarsNonLocal(SolidMechanicsModel & model,
- const ID & id = "");
-
- /* ------------------------------------------------------------------------ */
- /* Methods */
- /* ------------------------------------------------------------------------ */
-protected:
- /// constitutive law for all element of a type
- void computeStress(ElementType el_type,
- GhostType ghost_type = _not_ghost) override;
-
- void computeNonLocalStress(ElementType el_type,
- GhostType ghost_type = _not_ghost) override;
-
- void registerNonLocalVariables() override;
-
- /* ------------------------------------------------------------------------ */
- /* Accessors */
- /* ------------------------------------------------------------------------ */
-public:
- /* ------------------------------------------------------------------------ */
- /* Class Members */
- /* ------------------------------------------------------------------------ */
-private:
- /// the ehat per quadrature points to perform the averaging
- InternalField<Real> Ehat;
-
- InternalField<Real> non_local_variable;
-};
+template <Int dim>
+using MaterialVonMisesMazarsNonLocal =
+ MaterialMazarsNonLocal<dim, MaterialLinearIsotropicHardening>;
} // namespace akantu
#endif /* AKANTU_MATERIAL_VON_MISES_MAZARS_NON_LOCAL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc
index 0d5d6c12b..98a3cb811 100644
--- a/src/model/solid_mechanics/materials/material_elastic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic.cc
@@ -1,259 +1,256 @@
/**
* @file material_elastic.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Specialization of the material class for the elastic material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model,
const ID & id)
: Parent(model, id), was_stiffness_assembled(false) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model,
- UInt /*a_dim*/, const Mesh & mesh,
+ Int /*a_dim*/, const Mesh & mesh,
FEEngine & fe_engine, const ID & id)
: Parent(model, dim, mesh, fe_engine, id), was_stiffness_assembled(false) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialElastic<dim>::initialize() {
+template <Int dim> void MaterialElastic<dim>::initialize() {
this->registerParam("lambda", lambda, _pat_readable,
"First Lamé coefficient");
this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialElastic<dim>::initMaterial() {
+template <Int dim> void MaterialElastic<dim>::initMaterial() {
AKANTU_DEBUG_IN();
Parent::initMaterial();
if (dim == 1) {
this->nu = 0.;
}
this->updateInternalParameters();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialElastic<dim>::updateInternalParameters() {
+template <Int dim> void MaterialElastic<dim>::updateInternalParameters() {
MaterialThermal<dim>::updateInternalParameters();
this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
this->mu = this->E / (2 * (1 + this->nu));
this->kpa = this->lambda + 2. / 3. * this->mu;
this->was_stiffness_assembled = false;
}
/* -------------------------------------------------------------------------- */
template <> void MaterialElastic<2>::updateInternalParameters() {
MaterialThermal<2>::updateInternalParameters();
this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
this->mu = this->E / (2 * (1 + this->nu));
if (this->plane_stress) {
this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - this->nu));
}
this->kpa = this->lambda + 2. / 3. * this->mu;
this->was_stiffness_assembled = false;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElastic<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
Parent::computeStress(el_type, ghost_type);
- Array<Real>::const_scalar_iterator sigma_th_it =
- this->sigma_th(el_type, ghost_type).begin();
+ auto && arguments = Parent::getArguments(el_type, ghost_type);
- if (!this->finite_deformation) {
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- const Real & sigma_th = *sigma_th_it;
- this->computeStressOnQuad(grad_u, sigma, sigma_th);
- ++sigma_th_it;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ if (not this->finite_deformation) {
+ for (auto && args : arguments) {
+ this->computeStressOnQuad(args);
+ }
} else {
- /// finite gradus
- Matrix<Real> E(dim, dim);
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- /// compute E
- this->template gradUToE<dim>(grad_u, E);
-
- const Real & sigma_th = *sigma_th_it;
-
- /// compute second Piola-Kirchhoff stress tensor
- this->computeStressOnQuad(E, sigma, sigma_th);
-
- ++sigma_th_it;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ for (auto && args : arguments) {
+ auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
+ this->computeStressOnQuad(tuple::replace(args, "grad_u"_n = E));
+ }
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElastic<dim>::computeTangentModuli(ElementType el_type,
Array<Real> & tangent_matrix,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
- this->computeTangentModuliOnQuad(tangent);
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
+ auto && arguments =
+ Parent::getArgumentsTangent(tangent_matrix, el_type, ghost_type);
+
+ for (auto && args : arguments) {
+ this->computeTangentModuliOnQuad(args);
+ }
this->was_stiffness_assembled = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-Real MaterialElastic<dim>::getPushWaveSpeed(const Element & /*unused*/) const {
+template <Int dim>
+Real MaterialElastic<dim>::getPushWaveSpeed(const Element &) const {
return sqrt((lambda + 2 * mu) / this->rho);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-Real MaterialElastic<dim>::getShearWaveSpeed(const Element & /*unused*/) const {
+template <Int dim>
+Real MaterialElastic<dim>::getShearWaveSpeed(const Element &) const {
return sqrt(mu / this->rho);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElastic<dim>::computePotentialEnergy(ElementType el_type) {
AKANTU_DEBUG_IN();
- // MaterialThermal<dim>::computePotentialEnergy(ElementType)
// needs to be implemented
// MaterialThermal<dim>::computePotentialEnergy(el_type);
auto epot = this->potential_energy(el_type, _not_ghost).begin();
- if (!this->finite_deformation) {
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
-
- this->computePotentialEnergyOnQuad(grad_u, sigma, *epot);
- ++epot;
+ auto && arguments = Parent::getArguments(el_type, _not_ghost);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ if (not this->finite_deformation) {
+ for (auto && [args, epot] :
+ zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+ this->computePotentialEnergyOnQuad(args, epot);
+ }
} else {
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
- auto E = this->template gradUToE<dim>(grad_u);
-
- this->computePotentialEnergyOnQuad(E, sigma, *epot);
- ++epot;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ for (auto && [args, epot] :
+ zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+ auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
+ this->computePotentialEnergyOnQuad(tuple::replace(args, "grad_u"_n = E),
+ epot);
+ }
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElastic<dim>::computePotentialEnergyByElement(
- ElementType type, UInt index, Vector<Real> & epot_on_quad_points) {
- auto gradu_it = this->gradu(type).begin(dim, dim);
- auto gradu_end = this->gradu(type).begin(dim, dim);
- auto stress_it = this->stress(type).begin(dim, dim);
+ const Element & element, Vector<Real> & epot_on_quad_points) {
+ auto type = element.type;
+ auto gradu_view = make_view<dim, dim>(this->gradu(type));
+ auto stress_view = make_view<dim, dim>(this->stress(type));
if (this->finite_deformation) {
- stress_it = this->piola_kirchhoff_2(type).begin(dim, dim);
+ stress_view = make_view<dim, dim>(this->piola_kirchhoff_2(type));
}
- UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
+ auto nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
- gradu_it += index * nb_quadrature_points;
- gradu_end += (index + 1) * nb_quadrature_points;
- stress_it += index * nb_quadrature_points;
+ auto gradu_it = gradu_view.begin() + element.element * nb_quadrature_points;
+ auto gradu_end = gradu_it + nb_quadrature_points;
+ auto stress_it = stress_view.begin() + element.element * nb_quadrature_points;
+ auto stress_end = stress_it + nb_quadrature_points;
- Real * epot_quad = epot_on_quad_points.storage();
+ auto epot_quad = epot_on_quad_points.begin();
Matrix<Real> grad_u(dim, dim);
if (this->finite_deformation) {
- for (; gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) {
- auto E = this->template gradUToE<dim>(*gradu_it);
- this->computePotentialEnergyOnQuad(E, *stress_it, *epot_quad);
+ for (auto && data : zip("grad_u"_n = range(gradu_it, gradu_end),
+ "sigma"_n = range(stress_it, stress_end),
+ "Epot"_n = epot_on_quad_points)) {
+ auto E = this->template gradUToE<dim>(data["grad_u"_n]);
+ this->computePotentialEnergyOnQuad(tuple::replace(data, "grad_u"_n = E),
+ data["Epot"_n]);
}
} else {
- for (; gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) {
- this->computePotentialEnergyOnQuad(*gradu_it, *stress_it, *epot_quad);
+ for (auto && data : zip("grad_u"_n = range(gradu_it, gradu_end),
+ "sigma"_n = range(stress_it, stress_end),
+ "Epot"_n = epot_on_quad_points)) {
+ this->computePotentialEnergyOnQuad(data, data["Epot"_n]);
}
}
}
/* -------------------------------------------------------------------------- */
template <>
Real MaterialElastic<1>::getPushWaveSpeed(const Element & /*element*/) const {
return std::sqrt(this->E / this->rho);
}
template <>
Real MaterialElastic<1>::getShearWaveSpeed(const Element & /*element*/) const {
AKANTU_EXCEPTION("There is no shear wave speed in 1D");
}
+
/* -------------------------------------------------------------------------- */
+template class MaterialElastic<1>;
+template class MaterialElastic<2>;
+template class MaterialElastic<3>;
-INSTANTIATE_MATERIAL(elastic, MaterialElastic);
+static bool material_is_allocated_elastic =
+ instantiateMaterial<MaterialElastic>("elastic");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_elastic.hh b/src/model/solid_mechanics/materials/material_elastic.hh
index c5453132f..861c4f4e6 100644
--- a/src/model/solid_mechanics/materials/material_elastic.hh
+++ b/src/model/solid_mechanics/materials/material_elastic.hh
@@ -1,157 +1,159 @@
/**
* @file material_elastic.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Material isotropic elastic
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_thermal.hh"
#include "plane_stress_toolbox.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ELASTIC_HH_
#define AKANTU_MATERIAL_ELASTIC_HH_
namespace akantu {
/**
* Material elastic isotropic
*
* parameters in the material files :
* - E : Young's modulus (default: 0)
* - nu : Poisson's ratio (default: 1/2)
* - Plane_Stress : if 0: plane strain, else: plane stress (default: 0)
*/
-template <UInt spatial_dimension>
-class MaterialElastic
- : public PlaneStressToolbox<spatial_dimension,
- MaterialThermal<spatial_dimension>> {
+template <Int dim>
+class MaterialElastic : public PlaneStressToolbox<dim, MaterialThermal<dim>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
private:
- using Parent =
- PlaneStressToolbox<spatial_dimension, MaterialThermal<spatial_dimension>>;
+ using Parent = PlaneStressToolbox<dim, MaterialThermal<dim>>;
public:
MaterialElastic(SolidMechanicsModel & model, const ID & id = "");
- MaterialElastic(SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
- FEEngine & fe_engine, const ID & id = "");
+ MaterialElastic(SolidMechanicsModel & model, Int spatial_dimension,
+ const Mesh & mesh, FEEngine & fe_engine, const ID & id = "");
~MaterialElastic() override = default;
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
/// compute the elastic potential energy
void computePotentialEnergy(ElementType el_type) override;
+ [[gnu::deprecated("Use the interface with an Element")]] void
+ computePotentialEnergyByElement(ElementType type, Int index,
+ Vector<Real> & epot_on_quad_points) override {
+ computePotentialEnergyByElement({type, index, _not_ghost},
+ epot_on_quad_points);
+ }
+
void
- computePotentialEnergyByElement(ElementType type, UInt index,
+ computePotentialEnergyByElement(const Element & element,
Vector<Real> & epot_on_quad_points) override;
/// compute the p-wave speed in the material
- Real getPushWaveSpeed(const Element & element) const override;
+ auto getPushWaveSpeed(const Element & element) const -> Real override;
/// compute the s-wave speed in the material
- Real getShearWaveSpeed(const Element & element) const override;
+ auto getShearWaveSpeed(const Element & element) const -> Real override;
protected:
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(const Matrix<Real> & grad_u,
- Matrix<Real> & sigma,
- Real sigma_th = 0) const;
+ template <typename Args> inline void computeStressOnQuad(Args && args) const;
/// compute the tangent stiffness matrix for an element
- inline void computeTangentModuliOnQuad(Matrix<Real> & tangent) const;
+ template <typename Args>
+ inline void computeTangentModuliOnQuad(Args && args) const;
/// recompute the lame coefficient if E or nu changes
void updateInternalParameters() override;
- static inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & sigma,
- Real & epot);
+ template <class Args>
+ static inline void computePotentialEnergyOnQuad(Args && args, Real & epot);
- bool hasStiffnessMatrixChanged() override {
+ auto hasStiffnessMatrixChanged() -> bool override {
return (not was_stiffness_assembled);
}
- MatrixType getTangentType() override { return _symmetric; }
+ auto getTangentType() -> MatrixType override { return _symmetric; }
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get first Lame constant
AKANTU_GET_MACRO(Lambda, lambda, Real);
/// get second Lame constant
AKANTU_GET_MACRO(Mu, mu, Real);
/// get bulk modulus
AKANTU_GET_MACRO(Kappa, kpa, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// First Lamé coefficient
Real lambda;
/// Second Lamé coefficient (shear modulus)
Real mu;
/// Bulk modulus
Real kpa;
/// defines if the stiffness was computed
bool was_stiffness_assembled;
};
} // namespace akantu
#include "material_elastic_inline_impl.hh"
#endif /* AKANTU_MATERIAL_ELASTIC_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_elastic_inline_impl.hh b/src/model/solid_mechanics/materials/material_elastic_inline_impl.hh
index 215d63240..ac423d23b 100644
--- a/src/model/solid_mechanics/materials/material_elastic_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_elastic_inline_impl.hh
@@ -1,122 +1,132 @@
/**
* @file material_elastic_inline_impl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Thu Feb 20 2020
*
* @brief Implementation of the inline functions of the material elastic
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_MATERIAL_ELASTIC_INLINE_IMPL_HH_
-#define AKANTU_MATERIAL_ELASTIC_INLINE_IMPL_HH_
+// #ifndef __AKANTU_MATERIAL_ELASTIC_INLINE_IMPL_CC__
+// #define __AKANTU_MATERIAL_ELASTIC_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void MaterialElastic<spatial_dimension>::computeStressOnQuad(
- const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real sigma_th) const {
+template <Int dim>
+template <typename Args>
+inline void MaterialElastic<dim>::computeStressOnQuad(Args && args) const {
+ auto && sigma = args["sigma"_n];
+ auto && grad_u = args["grad_u"_n];
+ Real sigma_th = 0.;
+
+ if constexpr (named_tuple_t<Args>::has("sigma_th"_n)) {
+ sigma_th = args["sigma_th"_n];
+ }
+
Real trace = grad_u.trace(); // trace = (\nabla u)_{kk}
// \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla
// u_{ij} + \nabla u_{ji})
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- sigma(i, j) = Math::kronecker(i, j) * lambda * trace +
- mu * (grad_u(i, j) + grad_u(j, i)) +
- Math::kronecker(i, j) * sigma_th;
- }
- }
+ sigma = 2. * mu * Material::gradUToEpsilon<dim>(grad_u) +
+ (lambda * trace + sigma_th) * Matrix<Real, dim, dim>::Identity();
}
/* -------------------------------------------------------------------------- */
template <>
-inline void MaterialElastic<1>::computeStressOnQuad(const Matrix<Real> & grad_u,
- Matrix<Real> & sigma,
- Real sigma_th) const {
+template <typename Args>
+inline void MaterialElastic<1>::computeStressOnQuad(Args && args) const {
+ auto && sigma = args["sigma"_n];
+ auto && grad_u = args["grad_u"_n];
+ Real sigma_th = 0.;
+
+ if constexpr (std::decay_t<Args>::has("sigma_th"_n)) {
+ sigma_th = args["sigma_th"_n];
+ }
+
sigma(0, 0) = this->E * grad_u(0, 0) + sigma_th;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-inline void MaterialElastic<spatial_dimension>::computeTangentModuliOnQuad(
- Matrix<Real> & tangent) const {
- UInt n = tangent.cols();
+template <Int dim>
+template <typename Args>
+inline void
+MaterialElastic<dim>::computeTangentModuliOnQuad(Args && args) const {
+ auto && tangent = args["tangent_moduli"_n];
+ tangent.zero();
+
+ constexpr auto n = Material::getTangentStiffnessVoigtSize(dim);
// Real Ep = E/((1+nu)*(1-2*nu));
- Real Miiii = lambda + 2 * mu;
- Real Miijj = lambda;
- Real Mijij = mu;
- if (spatial_dimension == 1) {
+ if constexpr (dim == 1) {
tangent(0, 0) = this->E;
- } else {
- tangent(0, 0) = Miiii;
+ return;
}
+ auto Miiii = lambda + 2 * mu;
+ [[maybe_unused]] auto Miijj = lambda;
+ [[maybe_unused]] auto Mijij = mu;
+
+ tangent(0, 0) = Miiii;
+
// test of dimension should by optimized out by the compiler due to the
// template
- if (spatial_dimension >= 2) {
+ if constexpr (dim >= 2) {
tangent(1, 1) = Miiii;
tangent(0, 1) = Miijj;
tangent(1, 0) = Miijj;
tangent(n - 1, n - 1) = Mijij;
}
- if (spatial_dimension == 3) {
+ if constexpr (dim == 3) {
tangent(2, 2) = Miiii;
tangent(0, 2) = Miijj;
tangent(1, 2) = Miijj;
tangent(2, 0) = Miijj;
tangent(2, 1) = Miijj;
tangent(3, 3) = Mijij;
tangent(4, 4) = Mijij;
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void MaterialElastic<dim>::computePotentialEnergyOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot) {
- epot = .5 * sigma.doubleDot(grad_u);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline void
-MaterialElastic<1>::computeTangentModuliOnQuad(Matrix<Real> & tangent) const {
- tangent(0, 0) = E;
+template <Int dim>
+template <class Args>
+inline void MaterialElastic<dim>::computePotentialEnergyOnQuad(Args && args,
+ Real & epot) {
+ epot = .5 * args["sigma"_n].doubleDot(args["grad_u"_n]);
}
} // namespace akantu
-#endif /* AKANTU_MATERIAL_ELASTIC_INLINE_IMPL_HH_ */
+// #endif /* __AKANTU_MATERIAL_ELASTIC_INLINE_IMPL_CC__ */
diff --git a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
index 3fa8b9909..5a5cad362 100644
--- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
@@ -1,262 +1,262 @@
/**
* @file material_elastic_linear_anisotropic.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Till Junge <till.junge@epfl.ch>
* @author Enrico Milanese <enrico.milanese@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Sep 25 2013
* @date last modification: Fri Jul 24 2020
*
* @brief Anisotropic elastic material
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "material_elastic_linear_anisotropic.hh"
#include "solid_mechanics_model.hh"
#include <algorithm>
#include <sstream>
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialElasticLinearAnisotropic<dim>::MaterialElasticLinearAnisotropic(
SolidMechanicsModel & model, const ID & id, bool symmetric)
: Material(model, id), rot_mat(dim, dim), Cprime(dim * dim, dim * dim),
C(voigt_h::size, voigt_h::size), eigC(voigt_h::size),
symmetric(symmetric), was_stiffness_assembled(false) {
AKANTU_DEBUG_IN();
- this->dir_vecs.push_back(std::make_unique<Vector<Real>>(dim));
- (*this->dir_vecs.back())[0] = 1.;
- this->registerParam("n1", *(this->dir_vecs.back()), _pat_parsmod,
- "Direction of main material axis");
-
- if (dim > 1) {
- this->dir_vecs.push_back(std::make_unique<Vector<Real>>(dim));
- (*this->dir_vecs.back())[1] = 1.;
- this->registerParam("n2", *(this->dir_vecs.back()), _pat_parsmod,
- "Direction of secondary material axis");
- }
-
- if (dim > 2) {
- this->dir_vecs.push_back(std::make_unique<Vector<Real>>(dim));
- (*this->dir_vecs.back())[2] = 1.;
- this->registerParam("n3", *(this->dir_vecs.back()), _pat_parsmod,
- "Direction of tertiary material axis");
+ for (int i : arange(dim)) {
+ this->dir_vecs.emplace_back(std::make_unique<Vector<Real, dim>>());
+ auto && n = *this->dir_vecs.back();
+ n.zero();
+ n[i] = 1.;
+ this->registerParam("n" + std::to_string(i + 1), *(this->dir_vecs.back()),
+ _pat_parsmod, "Direction of main material axis");
}
- for (UInt i = 0; i < voigt_h::size; ++i) {
- UInt start = 0;
+ for (auto i : arange(voigt_h::size)) {
+ decltype(i) start = 0;
if (this->symmetric) {
start = i;
}
- for (UInt j = start; j < voigt_h::size; ++j) {
- std::stringstream param("C");
- param << "C" << i + 1 << j + 1;
- this->registerParam(param.str(), this->Cprime(i, j), Real(0.),
- _pat_parsmod, "Coefficient " + param.str());
+ for (auto j : arange(start, voigt_h::size)) {
+ auto param = "C" + std::to_string(i + 1) + std::to_string(j + 1);
+ this->registerParam(param, this->Cprime(i, j), Real(0.), _pat_parsmod,
+ "Coefficient " + param);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::initMaterial() {
+template <Int dim> void MaterialElasticLinearAnisotropic<dim>::initMaterial() {
AKANTU_DEBUG_IN();
Material::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::updateInternalParameters() {
Material::updateInternalParameters();
if (this->symmetric) {
- for (UInt i = 0; i < voigt_h::size; ++i) {
- for (UInt j = i + 1; j < voigt_h::size; ++j) {
+ for (auto i : arange(voigt_h::size)) {
+ for (auto j : arange(i + 1, voigt_h::size)) {
this->Cprime(j, i) = this->Cprime(i, j);
}
}
}
this->rotateCprime();
this->C.eig(this->eigC);
this->was_stiffness_assembled = false;
}
/* -------------------------------------------------------------------------- */
-template <UInt Dim> void MaterialElasticLinearAnisotropic<Dim>::rotateCprime() {
+template <Int Dim> void MaterialElasticLinearAnisotropic<Dim>::rotateCprime() {
// start by filling the empty parts fo Cprime
- UInt diff = Dim * Dim - voigt_h::size;
- for (UInt i = voigt_h::size; i < Dim * Dim; ++i) {
- for (UInt j = 0; j < Dim * Dim; ++j) {
+ auto diff = Dim * Dim - voigt_h::size;
+ for (auto i : arange(voigt_h::size, Dim * Dim)) {
+ for (auto j : arange(Dim * Dim)) {
this->Cprime(i, j) = this->Cprime(i - diff, j);
}
}
- for (UInt i = 0; i < Dim * Dim; ++i) {
- for (UInt j = voigt_h::size; j < Dim * Dim; ++j) {
+ for (auto i : arange(Dim * Dim)) {
+ for (auto j : arange(voigt_h::size, Dim * Dim)) {
this->Cprime(i, j) = this->Cprime(i, j - diff);
}
}
// construction of rotator tensor
// normalise rotation matrix
- for (UInt j = 0; j < Dim; ++j) {
- Vector<Real> rot_vec = this->rot_mat(j);
+ for (auto j : arange(Dim)) {
+ auto && rot_vec = this->rot_mat(j);
rot_vec = *this->dir_vecs[j];
rot_vec.normalize();
}
// make sure the vectors form a right-handed base
- Vector<Real> test_axis(3);
- Vector<Real> v1(3);
- Vector<Real> v2(3);
- Vector<Real> v3(3, 0.);
-
+ Real test_axis = 0.;
if (Dim == 2) {
- for (UInt i = 0; i < Dim; ++i) {
- v1[i] = this->rot_mat(0, i);
- v2[i] = this->rot_mat(1, i);
- }
+ Vector<Real, 3> v1 = Vector<Real, 3>::Zero();
+ Vector<Real, 3> v2 = Vector<Real, 3>::Zero();
+ v1.block<Dim, 1>(0, 0) = this->rot_mat(0);
+ v2.block<Dim, 1>(0, 0) = this->rot_mat(1);
- v3.crossProduct(v1, v2);
+ Vector<Real, 3> v3 = v1.cross(v2);
if (v3.norm() < 8 * std::numeric_limits<Real>::epsilon()) {
AKANTU_ERROR("The axis vectors parallel.");
}
v3.normalize();
+ test_axis = (v1.cross(v2) - v3).norm();
} else if (Dim == 3) {
- v1 = this->rot_mat(0);
- v2 = this->rot_mat(1);
- v3 = this->rot_mat(2);
+ Vector<Real, 3> v1 = this->rot_mat(0);
+ Vector<Real, 3> v2 = this->rot_mat(1);
+ Vector<Real, 3> v3 = this->rot_mat(2);
+ test_axis = (v1.cross(v2) - v3).norm();
}
- test_axis.crossProduct(v1, v2);
- test_axis -= v3;
- if (test_axis.norm() > 8 * std::numeric_limits<Real>::epsilon()) {
+ if (test_axis > 8 * std::numeric_limits<Real>::epsilon()) {
AKANTU_ERROR("The axis vectors do not form a right-handed coordinate "
<< "system. I. e., ||n1 x n2 - n3|| should be zero, but "
- << "it is " << test_axis.norm() << ".");
+ << "it is " << test_axis << ".");
}
// create the rotator and the reverse rotator
- Matrix<Real> rotator(Dim * Dim, Dim * Dim);
- Matrix<Real> revrotor(Dim * Dim, Dim * Dim);
- for (UInt i = 0; i < Dim; ++i) {
- for (UInt j = 0; j < Dim; ++j) {
- for (UInt k = 0; k < Dim; ++k) {
- for (UInt l = 0; l < Dim; ++l) {
- UInt I = voigt_h::mat[i][j];
- UInt J = voigt_h::mat[k][l];
+ Matrix<Real, Dim * Dim, Dim * Dim> rotator;
+ Matrix<Real, Dim * Dim, Dim * Dim> revrotor;
+ for (auto i : arange(Dim)) {
+ for (auto j : arange(Dim)) {
+ for (auto k : arange(Dim)) {
+ for (auto l : arange(Dim)) {
+ auto I = voigt_h::mat[i][j];
+ auto J = voigt_h::mat[k][l];
rotator(I, J) = this->rot_mat(k, i) * this->rot_mat(l, j);
revrotor(I, J) = this->rot_mat(i, k) * this->rot_mat(j, l);
}
}
}
}
// create the full rotated matrix
- Matrix<Real> Cfull(Dim * Dim, Dim * Dim);
+ Matrix<Real, Dim * Dim, Dim * Dim> Cfull(Dim * Dim, Dim * Dim);
Cfull = rotator * Cprime * revrotor;
- for (UInt i = 0; i < voigt_h::size; ++i) {
- for (UInt j = 0; j < voigt_h::size; ++j) {
+ for (auto i : arange(voigt_h::size)) {
+ for (auto j : arange(voigt_h::size)) {
this->C(i, j) = Cfull(i, j);
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::computeStress(
ElementType el_type, GhostType ghost_type) {
- // Wikipedia convention:
- // 2*eps_ij (i!=j) = voigt_eps_I
- // http://en.wikipedia.org/wiki/Voigt_notation
- AKANTU_DEBUG_IN();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- this->computeStressOnQuad(grad_u, sigma);
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ auto && arguments = getArguments(el_type, ghost_type);
+ for (auto && data : arguments) {
+ this->computeStressOnQuad(data);
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
+ auto && arguments =
+ Material::getArgumentsTangent<dim>(tangent_matrix, el_type, ghost_type);
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
-
- this->computeTangentModuliOnQuad(tangent);
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
+ for (auto && args : arguments) {
+ this->computeTangentModuliOnQuad(args);
+ }
this->was_stiffness_assembled = true;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::computePotentialEnergy(
ElementType el_type) {
- AKANTU_DEBUG_IN();
-
AKANTU_DEBUG_ASSERT(!this->finite_deformation,
"finite deformation not possible in material anisotropic "
"(TO BE IMPLEMENTED)");
- Array<Real>::scalar_iterator epot =
- this->potential_energy(el_type, _not_ghost).begin();
+ auto && arguments = Material::getArguments<dim>(el_type, _not_ghost);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
+ for (auto && args :
+ zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+ this->computePotentialEnergyOnQuad(std::get<0>(args), std::get<1>(args));
+ }
+}
- computePotentialEnergyOnQuad(grad_u, sigma, *epot);
- ++epot;
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+void MaterialElasticLinearAnisotropic<dim>::computePotentialEnergyByElement(
+ ElementType type, Int index, Vector<Real> & epot_on_quad_points) {
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ auto gradu_view = make_view<dim, dim>(this->gradu(type));
+ auto stress_view = make_view<dim, dim>(this->stress(type));
- AKANTU_DEBUG_OUT();
+ auto nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
+
+ auto gradu_it = gradu_view.begin() + index * nb_quadrature_points;
+ auto gradu_end = gradu_it + nb_quadrature_points;
+ auto stress_it = stress_view.begin() + index * nb_quadrature_points;
+ auto stress_end = stress_it + nb_quadrature_points;
+
+ auto epot_quad = epot_on_quad_points.begin();
+
+ Matrix<Real> grad_u(dim, dim);
+
+ for (auto data : zip("grad_u"_n = range(gradu_it, gradu_end),
+ "sigma"_n = range(stress_it, stress_end),
+ "Epot"_n = epot_on_quad_points)) {
+ this->computePotentialEnergyOnQuad(data, data["Epot"_n]);
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
Real MaterialElasticLinearAnisotropic<dim>::getCelerity(
- __attribute__((unused)) const Element & element) const {
+ const Element & /*element*/) const {
return std::sqrt(this->eigC(0) / rho);
}
/* -------------------------------------------------------------------------- */
+template class MaterialElasticLinearAnisotropic<1>;
+template class MaterialElasticLinearAnisotropic<2>;
+template class MaterialElasticLinearAnisotropic<3>;
-INSTANTIATE_MATERIAL(elastic_anisotropic, MaterialElasticLinearAnisotropic);
+static bool material_is_alocated_elastic =
+ instantiateMaterial<MaterialElasticLinearAnisotropic>(
+ "elastic_anisotropic");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh
index 309ec4b7d..6b2234551 100644
--- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh
+++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh
@@ -1,138 +1,145 @@
/**
* @file material_elastic_linear_anisotropic.hh
*
* @author Till Junge <till.junge@epfl.ch>
* @author Enrico Milanese <enrico.milanese@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Orthotropic elastic material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH_
#define AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH_
namespace akantu {
/**
* General linear anisotropic elastic material
* The only constraint on the elastic tensor is that it can be represented
* as a symmetric 6x6 matrix (3D) or 3x3 (2D).
*
* parameters in the material files :
* - rho : density (default: 0)
* - C_ij : entry on the stiffness
*/
-template <UInt Dim> class MaterialElasticLinearAnisotropic : public Material {
+template <Int dim> class MaterialElasticLinearAnisotropic : public Material {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialElasticLinearAnisotropic(SolidMechanicsModel & model,
const ID & id = "", bool symmetric = true);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
/// compute the elastic potential energy
void computePotentialEnergy(ElementType el_type) override;
void updateInternalParameters() override;
bool hasStiffnessMatrixChanged() override {
return (not was_stiffness_assembled);
}
MatrixType getTangentType() override { return _symmetric; }
protected:
// compute C from Cprime
void rotateCprime();
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(const Matrix<Real> & grad_u,
- Matrix<Real> & sigma) const;
+ template <typename Args> inline void computeStressOnQuad(Args && args) const;
/// tangent matrix for a given quadrature point
- inline void computeTangentModuliOnQuad(Matrix<Real> & tangent) const;
+ template <typename Args>
+ inline void computeTangentModuliOnQuad(Args && args) const;
- inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & sigma,
- Real & epot);
+ template <typename Args>
+ inline void computePotentialEnergyOnQuad(Args && args, Real & epot);
+
+ void
+ computePotentialEnergyByElement(ElementType type, Int index,
+ Vector<Real> & epot_on_quad_points) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ return Material::template getArguments<dim>(el_type, ghost_type);
+ }
+
/// compute max wave celerity
Real getCelerity(const Element & element) const override;
AKANTU_GET_MACRO(VoigtStiffness, C, Matrix<Real>);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
- using voigt_h = VoigtHelper<Dim>;
+ using voigt_h = VoigtHelper<dim>;
/// direction matrix and vectors
- std::vector<std::unique_ptr<Vector<Real>>> dir_vecs;
+ std::vector<std::unique_ptr<Vector<Real, dim>>> dir_vecs;
Matrix<Real> rot_mat;
/// Elastic stiffness tensor in material frame and full vectorised notation
Matrix<Real> Cprime;
/// Elastic stiffness tensor in voigt notation
Matrix<Real> C;
/// eigenvalues of stiffness tensor
Vector<Real> eigC;
bool symmetric;
/// defines if the stiffness was computed
bool was_stiffness_assembled;
};
} // namespace akantu
#include "material_elastic_linear_anisotropic_inline_impl.hh"
#endif /* AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh
index 8ff964519..5702feddb 100644
--- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh
@@ -1,74 +1,79 @@
/**
* @file material_elastic_linear_anisotropic_inline_impl.hh
*
* @author Enrico Milanese <enrico.milanese@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Feb 16 2018
* @date last modification: Thu Feb 20 2020
*
* @brief Implementation of the inline functions of the material elastic linear
* anisotropic
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic_linear_anisotropic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_INLINE_IMPL_HH_
#define AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void MaterialElasticLinearAnisotropic<dim>::computeStressOnQuad(
- const Matrix<Real> & grad_u, Matrix<Real> & sigma) const {
+template <Int dim>
+template <typename Args>
+inline void
+MaterialElasticLinearAnisotropic<dim>::computeStressOnQuad(Args && args) const {
+ auto && sigma = args["sigma"_n];
+ auto && grad_u = args["grad_u"_n];
+
auto voigt_strain = strainToVoigt<dim>(gradUToEpsilon<dim>(grad_u));
auto voigt_stress = this->C * voigt_strain;
voigtToStress<dim>(voigt_stress, sigma);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
+template <class Args>
inline void MaterialElasticLinearAnisotropic<dim>::computeTangentModuliOnQuad(
- Matrix<Real> & tangent) const {
-
- tangent.copy(this->C);
+ Args && args) const {
+ args["tangent_moduli"_n] = this->C;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
+template <class Args>
inline void MaterialElasticLinearAnisotropic<dim>::computePotentialEnergyOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot) {
+ Args && args, Real & epot) {
AKANTU_DEBUG_ASSERT(this->symmetric,
"The elastic constants matrix is not symmetric,"
"energy is not path independent.");
- epot = .5 * sigma.doubleDot(grad_u);
+ epot = args["sigma"_n].doubleDot(args["grad_u"_n]) / 2.;
}
} // namespace akantu
#endif /* AKANTU_MATERIAL_ELASTIC_LINEAR_ANISOTROPIC_INLINE_IMPL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
index ced8a92d4..c0991dca7 100644
--- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
@@ -1,177 +1,152 @@
/**
* @file material_elastic_orthotropic.cc
*
* @author Till Junge <till.junge@epfl.ch>
* @author Enrico Milanese <enrico.milanese@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Orthotropic elastic material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "material_elastic_orthotropic.hh"
#include "solid_mechanics_model.hh"
#include <algorithm>
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt Dim>
+template <Int Dim>
MaterialElasticOrthotropic<Dim>::MaterialElasticOrthotropic(
SolidMechanicsModel & model, const ID & id)
: MaterialElasticLinearAnisotropic<Dim>(model, id) {
AKANTU_DEBUG_IN();
this->registerParam("E1", E1, Real(0.), _pat_parsmod, "Young's modulus (n1)");
this->registerParam("E2", E2, Real(0.), _pat_parsmod, "Young's modulus (n2)");
this->registerParam("nu12", nu12, Real(0.), _pat_parsmod,
"Poisson's ratio (12)");
this->registerParam("G12", G12, Real(0.), _pat_parsmod, "Shear modulus (12)");
if (Dim > 2) {
this->registerParam("E3", E3, Real(0.), _pat_parsmod,
"Young's modulus (n3)");
this->registerParam("nu13", nu13, Real(0.), _pat_parsmod,
"Poisson's ratio (13)");
this->registerParam("nu23", nu23, Real(0.), _pat_parsmod,
"Poisson's ratio (23)");
this->registerParam("G13", G13, Real(0.), _pat_parsmod,
"Shear modulus (13)");
this->registerParam("G23", G23, Real(0.), _pat_parsmod,
"Shear modulus (23)");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt Dim> void MaterialElasticOrthotropic<Dim>::initMaterial() {
+template <Int Dim> void MaterialElasticOrthotropic<Dim>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialElasticLinearAnisotropic<Dim>::initMaterial();
AKANTU_DEBUG_ASSERT(not this->finite_deformation,
"finite deformation not possible in material orthotropic "
"(TO BE IMPLEMENTED)");
updateInternalParameters();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt Dim>
+template <Int Dim>
void MaterialElasticOrthotropic<Dim>::updateInternalParameters() {
this->C.zero();
this->Cprime.zero();
/* 1) construction of temporary material frame stiffness tensor------------ */
// http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
- Real nu21 = nu12 * E2 / E1;
- Real nu31 = nu13 * E3 / E1;
- Real nu32 = nu23 * E3 / E2;
+ auto nu21 = nu12 * E2 / E1;
+ auto nu31 = nu13 * E3 / E1;
+ auto nu32 = nu23 * E3 / E2;
// Full (i.e. dim^2 by dim^2) stiffness tensor in material frame
if (Dim == 1) {
AKANTU_ERROR("Dimensions 1 not implemented: makes no sense to have "
"orthotropy for 1D");
}
Real Gamma;
if (Dim == 3) {
Gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
2 * nu21 * nu32 * nu13);
}
if (Dim == 2) {
Gamma = 1 / (1 - nu12 * nu21);
}
// Lamé's first parameters
this->Cprime(0, 0) = E1 * (1 - nu23 * nu32) * Gamma;
this->Cprime(1, 1) = E2 * (1 - nu13 * nu31) * Gamma;
if (Dim == 3) {
this->Cprime(2, 2) = E3 * (1 - nu12 * nu21) * Gamma;
}
// normalised poisson's ratio's
this->Cprime(1, 0) = this->Cprime(0, 1) = E1 * (nu21 + nu31 * nu23) * Gamma;
if (Dim == 3) {
this->Cprime(2, 0) = this->Cprime(0, 2) = E1 * (nu31 + nu21 * nu32) * Gamma;
this->Cprime(2, 1) = this->Cprime(1, 2) = E2 * (nu32 + nu12 * nu31) * Gamma;
}
// Lamé's second parameters (shear moduli)
if (Dim == 3) {
this->Cprime(3, 3) = G23;
this->Cprime(4, 4) = G13;
this->Cprime(5, 5) = G12;
} else {
this->Cprime(2, 2) = G12;
}
/* 1) rotation of C into the global frame */
this->rotateCprime();
this->C.eig(this->eigC);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialElasticOrthotropic<spatial_dimension>::
- computePotentialEnergyByElement(ElementType type, UInt index,
- Vector<Real> & epot_on_quad_points) {
+template class MaterialElasticOrthotropic<1>;
+template class MaterialElasticOrthotropic<2>;
+template class MaterialElasticOrthotropic<3>;
- Array<Real>::matrix_iterator gradu_it =
- this->gradu(type).begin(spatial_dimension, spatial_dimension);
- Array<Real>::matrix_iterator gradu_end =
- this->gradu(type).begin(spatial_dimension, spatial_dimension);
- Array<Real>::matrix_iterator stress_it =
- this->stress(type).begin(spatial_dimension, spatial_dimension);
-
- UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
-
- gradu_it += index * nb_quadrature_points;
- gradu_end += (index + 1) * nb_quadrature_points;
- stress_it += index * nb_quadrature_points;
-
- Real * epot_quad = epot_on_quad_points.storage();
-
- Matrix<Real> grad_u(spatial_dimension, spatial_dimension);
-
- for (; gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) {
- grad_u.copy(*gradu_it);
-
- this->computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad);
- }
-}
-
-/* -------------------------------------------------------------------------- */
-INSTANTIATE_MATERIAL(elastic_orthotropic, MaterialElasticOrthotropic);
+static bool material_is_allocated_elastic_orthotropic =
+ instantiateMaterial<MaterialElasticOrthotropic>("elastic_orthotropic");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh b/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh
index 00ddd8be3..89857183c 100644
--- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh
+++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh
@@ -1,137 +1,133 @@
/**
* @file material_elastic_orthotropic.hh
*
* @author Till Junge <till.junge@epfl.ch>
* @author Enrico Milanese <enrico.milanese@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Orthotropic elastic material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_elastic_linear_anisotropic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH_
#define AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH_
namespace akantu {
/**
* Orthotropic elastic material
*
* parameters in the material files :
* - n1 : direction of x-axis in material base, normalisation not necessary
* (default: {1, 0, 0})
* - n2 : direction of y-axis in material base, normalisation not necessary
* (default: {0, 1, 0})
* - n3 : direction of z-axis in material base, normalisation not necessary
* (default: {0, 0, 1})
* - rho : density (default: 0)
* - E1 : Young's modulus along n1 (default: 0)
* - E2 : Young's modulus along n2 (default: 0)
* - E3 : Young's modulus along n3 (default: 0)
* - nu12 : Poisson's ratio along 12 (default: 0)
* - nu13 : Poisson's ratio along 13 (default: 0)
* - nu23 : Poisson's ratio along 23 (default: 0)
* - G12 : Shear modulus along 12 (default: 0)
* - G13 : Shear modulus along 13 (default: 0)
* - G23 : Shear modulus along 23 (default: 0)
*/
-template <UInt Dim>
+template <Int Dim>
class MaterialElasticOrthotropic
: public MaterialElasticLinearAnisotropic<Dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialElasticOrthotropic(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
void updateInternalParameters() override;
- void
- computePotentialEnergyByElement(ElementType type, UInt index,
- Vector<Real> & epot_on_quad_points) override;
-
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(E1, E1, Real);
AKANTU_GET_MACRO(E2, E2, Real);
AKANTU_GET_MACRO(E3, E3, Real);
AKANTU_GET_MACRO(Nu12, nu12, Real);
AKANTU_GET_MACRO(Nu13, nu13, Real);
AKANTU_GET_MACRO(Nu23, nu23, Real);
AKANTU_GET_MACRO(G12, G12, Real);
AKANTU_GET_MACRO(G13, G13, Real);
AKANTU_GET_MACRO(G23, G23, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// the n1 young modulus
Real E1{0.};
/// the n2 young modulus
Real E2{0.};
/// the n3 young modulus
Real E3{0.};
/// 12 Poisson coefficient
Real nu12{0.};
/// 13 Poisson coefficient
Real nu13{0.};
/// 23 Poisson coefficient
Real nu23{0.};
/// 12 shear modulus
Real G12{0.};
/// 13 shear modulus
Real G13{0.};
/// 23 shear modulus
Real G23{0.};
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
index aa2c13c57..aecf85d85 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
+++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
@@ -1,208 +1,204 @@
/**
* @file material_reinforcement.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri Mar 13 2015
* @date last modification: Fri Feb 09 2018
*
* @brief Reinforcement material
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_REINFORCEMENT_HH_
#define AKANTU_MATERIAL_REINFORCEMENT_HH_
#include "aka_common.hh"
#include "embedded_interface_model.hh"
#include "material.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* @brief Material used to represent embedded reinforcements
*
* This class is used for computing the reinforcement stiffness matrix
* along with the reinforcement residual. Room is made for constitutive law,
* but actual use of contitutive laws is made in MaterialReinforcementTemplate.
*
* Be careful with the dimensions in this class :
* - this->spatial_dimension is always 1
* - the template parameter dim is the dimension of the problem
*/
-template <class Mat, UInt dim> class MaterialReinforcement : public Mat {
+template <class Mat, Int dim> class MaterialReinforcement : public Mat {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
/// Constructor
MaterialReinforcement(EmbeddedInterfaceModel & model, const ID & id = "");
/// Destructor
~MaterialReinforcement() override;
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// Init the material
void initMaterial() override;
/// Init the filters for background elements
void initFilters();
/// Init the background shape derivatives
void initBackgroundShapeDerivatives();
/// Init the cosine matrices
void initDirectingCosines();
/// Assemble stiffness matrix
void assembleStiffnessMatrix(GhostType ghost_type) override;
/// Compute all the stresses !
void computeAllStresses(GhostType ghost_type) override;
/// Compute energy
Real getEnergy(const std::string & id) override;
/// Assemble the residual of one type of element (typically _segment_2)
void assembleInternalForces(GhostType ghost_type) override;
/* ------------------------------------------------------------------------ */
/* Protected methods */
/* ------------------------------------------------------------------------ */
protected:
/// Allocate the background shape derivatives
void allocBackgroundShapeDerivatives();
/// Compute the directing cosines matrix for one element type
void computeDirectingCosines(ElementType type, GhostType ghost_type);
/// Compute the directing cosines matrix on quadrature points.
- inline void computeDirectingCosinesOnQuad(const Matrix<Real> & nodes,
- Matrix<Real> & cosines);
+ template <class Derived1, class Derived2>
+ inline void
+ computeDirectingCosinesOnQuad(const Eigen::MatrixBase<Derived1> & nodes,
+ Eigen::MatrixBase<Derived2> & cosines);
/// Add the prestress to the computed stress
void addPrestress(ElementType type, GhostType ghost_type);
/// Compute displacement gradient in reinforcement
void computeGradU(ElementType interface_type, GhostType ghost_type);
/// Assemble the stiffness matrix for an element type (typically _segment_2)
void assembleStiffnessMatrix(ElementType type, GhostType ghost_type);
/// Assemble the stiffness matrix for background & interface types
void assembleStiffnessMatrixInterface(ElementType interface_type,
ElementType background_type,
GhostType ghost_type);
/// Compute the background shape derivatives for a type
void computeBackgroundShapeDerivatives(ElementType type,
GhostType ghost_type);
/// Compute the background shape derivatives for a type pair
void computeBackgroundShapeDerivatives(ElementType interface_type,
ElementType bg_type,
GhostType ghost_type,
- const Array<UInt> & filter);
+ const Array<Idx> & filter);
/// Filter elements crossed by interface of a type
- void filterInterfaceBackgroundElements(Array<UInt> & foreground,
- Array<UInt> & background,
+ void filterInterfaceBackgroundElements(Array<Idx> & foreground,
+ Array<Idx> & background,
ElementType type,
ElementType interface_type,
GhostType ghost_type);
/// Assemble the residual of one type of element (typically _segment_2)
void assembleInternalForces(ElementType type, GhostType ghost_type);
/// Assemble the residual for a pair of elements
void assembleInternalForcesInterface(ElementType interface_type,
ElementType background_type,
GhostType ghost_type);
- // TODO figure out why voigt size is 4 in 2D
- inline void stressTensorToVoigtVector(const Matrix<Real> & tensor,
- Vector<Real> & vector);
- inline void strainTensorToVoigtVector(const Matrix<Real> & tensor,
- Vector<Real> & vector);
-
/// Get background filter
- Array<UInt> & getBackgroundFilter(ElementType fg_type, ElementType bg_type,
- GhostType ghost_type) {
+ Array<Idx> & getBackgroundFilter(ElementType fg_type, ElementType bg_type,
+ GhostType ghost_type) {
return (*background_filter(fg_type, ghost_type))(bg_type, ghost_type);
}
/// Get foreground filter
- Array<UInt> & getForegroundFilter(ElementType fg_type, ElementType bg_type,
- GhostType ghost_type) {
+ Array<Idx> & getForegroundFilter(ElementType fg_type, ElementType bg_type,
+ GhostType ghost_type) {
return (*foreground_filter(fg_type, ghost_type))(bg_type, ghost_type);
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// Embedded model
EmbeddedInterfaceModel & emodel;
/// Gradu of concrete on reinforcement
InternalField<Real> gradu_embedded;
/// C matrix on quad
InternalField<Real> directing_cosines;
/// Prestress on quad
InternalField<Real> pre_stress;
/// Cross-sectional area
Real area;
template <typename T>
using CrossMap = ElementTypeMap<std::unique_ptr<ElementTypeMapArray<T>>>;
/// Background mesh shape derivatives
CrossMap<Real> shape_derivatives;
/// Foreground mesh filter (contains segment ids)
- CrossMap<UInt> foreground_filter;
+ CrossMap<Idx> foreground_filter;
/// Background element filter (contains bg ids)
- CrossMap<UInt> background_filter;
+ CrossMap<Idx> background_filter;
};
} // namespace akantu
#include "material_reinforcement_tmpl.hh"
#endif // AKANTU_MATERIAL_REINFORCEMENT_HH_
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh
index cdf84ef1c..c363d69a9 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh
+++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh
@@ -1,777 +1,690 @@
/**
* @file material_reinforcement_tmpl.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Wed Mar 25 2015
* @date last modification: Fri Apr 09 2021
*
* @brief Reinforcement material
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_voigthelper.hh"
#include "material_reinforcement.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
MaterialReinforcement<Mat, dim>::MaterialReinforcement(
EmbeddedInterfaceModel & model, const ID & id)
: Mat(model, 1, model.getInterfaceMesh(),
model.getFEEngine("EmbeddedInterfaceFEEngine"), id),
emodel(model),
gradu_embedded("gradu_embedded", *this, 1,
model.getFEEngine("EmbeddedInterfaceFEEngine"),
this->element_filter),
directing_cosines("directing_cosines", *this, 1,
model.getFEEngine("EmbeddedInterfaceFEEngine"),
this->element_filter),
pre_stress("pre_stress", *this, 1,
model.getFEEngine("EmbeddedInterfaceFEEngine"),
this->element_filter),
area(1.0) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::initialize() {
AKANTU_DEBUG_IN();
this->registerParam("area", area, _pat_parsable | _pat_modifiable,
"Reinforcement cross-sectional area");
this->registerParam("pre_stress", pre_stress, _pat_parsable | _pat_modifiable,
"Uniform pre-stress");
// Reallocate the element filter
this->element_filter.initialize(this->emodel.getInterfaceMesh(),
_spatial_dimension = 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
MaterialReinforcement<Mat, dim>::~MaterialReinforcement() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::initMaterial() {
Mat::initMaterial();
gradu_embedded.initialize(dim * dim);
pre_stress.initialize(1);
/// We initialise the stuff that is not going to change during the simulation
this->initFilters();
this->allocBackgroundShapeDerivatives();
this->initBackgroundShapeDerivatives();
this->initDirectingCosines();
}
/* -------------------------------------------------------------------------- */
/// Initialize the filter for background elements
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::initFilters() {
for (auto gt : ghost_types) {
for (auto && type : emodel.getInterfaceMesh().elementTypes(1, gt)) {
std::string shaped_id = "filter";
if (gt == _ghost) {
shaped_id += ":ghost";
}
auto & background =
- background_filter(std::make_unique<ElementTypeMapArray<UInt>>(
+ background_filter(std::make_unique<ElementTypeMapArray<Idx>>(
"bg_" + shaped_id, this->name),
type, gt);
auto & foreground = foreground_filter(
- std::make_unique<ElementTypeMapArray<UInt>>(shaped_id, this->name),
+ std::make_unique<ElementTypeMapArray<Idx>>(shaped_id, this->name),
type, gt);
foreground->initialize(emodel.getMesh(), _nb_component = 1,
_ghost_type = gt);
background->initialize(emodel.getMesh(), _nb_component = 1,
_ghost_type = gt);
// Computing filters
for (auto && bg_type : background->elementTypes(dim, gt)) {
filterInterfaceBackgroundElements(
(*foreground)(bg_type), (*background)(bg_type), bg_type, type, gt);
}
}
}
}
/* -------------------------------------------------------------------------- */
/// Construct a filter for a (interface_type, background_type) pair
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::filterInterfaceBackgroundElements(
- Array<UInt> & foreground, Array<UInt> & background, ElementType type,
+ Array<Idx> & foreground, Array<Idx> & background, ElementType type,
ElementType interface_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
foreground.resize(0);
background.resize(0);
Array<Element> & elements =
emodel.getInterfaceAssociatedElements(interface_type, ghost_type);
- Array<UInt> & elem_filter = this->element_filter(interface_type, ghost_type);
+ auto & elem_filter = this->element_filter(interface_type, ghost_type);
for (auto & elem_id : elem_filter) {
Element & elem = elements(elem_id);
if (elem.type == type) {
background.push_back(elem.element);
foreground.push_back(elem_id);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
namespace detail {
class BackgroundShapeDInitializer : public ElementTypeMapArrayInitializer {
public:
- BackgroundShapeDInitializer(UInt spatial_dimension, FEEngine & engine,
+ BackgroundShapeDInitializer(Int spatial_dimension, FEEngine & engine,
ElementType foreground_type,
- const ElementTypeMapArray<UInt> & filter,
+ const ElementTypeMapArray<Idx> & filter,
GhostType ghost_type)
: ElementTypeMapArrayInitializer(
[](ElementType bgtype, GhostType /*unused*/) {
return ShapeFunctions::getShapeDerivativesSize(bgtype);
},
spatial_dimension, ghost_type, _ek_regular) {
auto nb_quad = engine.getNbIntegrationPoints(foreground_type);
// Counting how many background elements are affected by elements of
// interface_type
for (auto type : filter.elementTypes(this->spatial_dimension)) {
// Inserting size
array_size_per_bg_type(filter(type).size() * nb_quad, type,
this->ghost_type);
}
}
auto elementTypes() const -> decltype(auto) {
return array_size_per_bg_type.elementTypes();
}
UInt size(ElementType bgtype) const {
return array_size_per_bg_type(bgtype, this->ghost_type);
}
protected:
ElementTypeMap<UInt> array_size_per_bg_type;
};
} // namespace detail
/**
* Background shape derivatives need to be stored per background element
* types but also per embedded element type, which is why they are stored
* in an ElementTypeMap<ElementTypeMapArray<Real> *>. The outer ElementTypeMap
* refers to the embedded types, and the inner refers to the background types.
*/
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::allocBackgroundShapeDerivatives() {
AKANTU_DEBUG_IN();
for (auto gt : ghost_types) {
for (auto && type : emodel.getInterfaceMesh().elementTypes(1, gt)) {
std::string shaped_id = "embedded_shape_derivatives";
if (gt == _ghost) {
shaped_id += ":ghost";
}
auto & shaped_etma = shape_derivatives(
std::make_unique<ElementTypeMapArray<Real>>(shaped_id, this->name),
type, gt);
shaped_etma->initialize(
detail::BackgroundShapeDInitializer(
emodel.getSpatialDimension(),
emodel.getFEEngine("EmbeddedInterfaceFEEngine"), type,
*background_filter(type, gt), gt),
0, true);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::initBackgroundShapeDerivatives() {
AKANTU_DEBUG_IN();
for (auto interface_type :
this->element_filter.elementTypes(this->spatial_dimension)) {
for (auto type : background_filter(interface_type)->elementTypes(dim)) {
computeBackgroundShapeDerivatives(interface_type, type, _not_ghost,
this->element_filter(interface_type));
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::computeBackgroundShapeDerivatives(
ElementType interface_type, ElementType bg_type, GhostType ghost_type,
- const Array<UInt> & filter) {
+ const Array<Idx> & filter) {
auto & interface_engine = emodel.getFEEngine("EmbeddedInterfaceFEEngine");
auto & engine = emodel.getFEEngine();
auto & interface_mesh = emodel.getInterfaceMesh();
const auto nb_nodes_elem_bg = Mesh::getNbNodesPerElement(bg_type);
// const auto nb_strss = VoigtHelper<dim>::size;
const auto nb_quads_per_elem =
interface_engine.getNbIntegrationPoints(interface_type);
Array<Real> quad_pos(0, dim, "interface_quad_pos");
interface_engine.interpolateOnIntegrationPoints(interface_mesh.getNodes(),
quad_pos, dim, interface_type,
ghost_type, filter);
auto & background_shapesd =
(*shape_derivatives(interface_type, ghost_type))(bg_type, ghost_type);
auto & background_elements =
(*background_filter(interface_type, ghost_type))(bg_type, ghost_type);
auto & foreground_elements =
(*foreground_filter(interface_type, ghost_type))(bg_type, ghost_type);
auto shapesd_begin =
background_shapesd.begin(dim, nb_nodes_elem_bg, nb_quads_per_elem);
auto quad_begin = quad_pos.begin(dim, nb_quads_per_elem);
for (auto && tuple : zip(background_elements, foreground_elements)) {
auto bg = std::get<0>(tuple);
auto fg = std::get<1>(tuple);
- for (UInt i = 0; i < nb_quads_per_elem; ++i) {
- Matrix<Real> shapesd = Tensor3<Real>(shapesd_begin[fg])(i);
- Vector<Real> quads = Matrix<Real>(quad_begin[fg])(i);
-
- engine.computeShapeDerivatives(quads, bg, bg_type, shapesd, ghost_type);
+ for (Int i = 0; i < nb_quads_per_elem; ++i) {
+ engine.computeShapeDerivatives(quad_begin[fg](i), bg, bg_type,
+ shapesd_begin[fg](i), ghost_type);
}
}
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::initDirectingCosines() {
AKANTU_DEBUG_IN();
Mesh & mesh = emodel.getInterfaceMesh();
const UInt voigt_size = VoigtHelper<dim>::size;
directing_cosines.initialize(voigt_size);
for (auto && type : mesh.elementTypes(1, _not_ghost)) {
computeDirectingCosines(type, _not_ghost);
// computeDirectingCosines(*type_it, _ghost);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::assembleStiffnessMatrix(
GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh & interface_mesh = emodel.getInterfaceMesh();
for (auto && type : interface_mesh.elementTypes(1, _not_ghost)) {
assembleStiffnessMatrix(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::assembleInternalForces(
GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh & interface_mesh = emodel.getInterfaceMesh();
for (auto && type : interface_mesh.elementTypes(1, _not_ghost)) {
this->assembleInternalForces(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::computeAllStresses(GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh & interface_mesh = emodel.getInterfaceMesh();
for (auto && type : interface_mesh.elementTypes(_ghost_type = ghost_type)) {
computeGradU(type, ghost_type);
this->computeStress(type, ghost_type);
addPrestress(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::addPrestress(ElementType type,
GhostType ghost_type) {
auto & stress = this->stress(type, ghost_type);
auto & sigma_p = this->pre_stress(type, ghost_type);
for (auto && tuple : zip(stress, sigma_p)) {
std::get<0>(tuple) += std::get<1>(tuple);
}
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::assembleInternalForces(
ElementType type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh & mesh = emodel.getMesh();
for (auto && mesh_type : mesh.elementTypes(dim, ghost_type)) {
assembleInternalForcesInterface(type, mesh_type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Computes and assemble the residual. Residual in reinforcement is computed as:
*
* \f[
* \vec{r} = A_s \int_S{\mathbf{B}^T\mathbf{C}^T \vec{\sigma_s}\,\mathrm{d}s}
* \f]
*/
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::assembleInternalForcesInterface(
ElementType interface_type, ElementType background_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt voigt_size = VoigtHelper<dim>::size;
+ constexpr auto voigt_size = VoigtHelper<dim>::size;
FEEngine & interface_engine = emodel.getFEEngine("EmbeddedInterfaceFEEngine");
- Array<UInt> & elem_filter = this->element_filter(interface_type, ghost_type);
+ const auto & elem_filter = this->element_filter(interface_type, ghost_type);
- UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type);
- UInt nb_quadrature_points =
+ auto nodes_per_background_e = Mesh::getNbNodesPerElement(background_type);
+ auto nb_quadrature_points =
interface_engine.getNbIntegrationPoints(interface_type, ghost_type);
- UInt nb_element = elem_filter.size();
+ auto nb_element = elem_filter.size();
- UInt back_dof = dim * nodes_per_background_e;
+ auto back_dof = dim * nodes_per_background_e;
- Array<Real> & shapesd = (*shape_derivatives(interface_type, ghost_type))(
+ const auto & shapesd = (*shape_derivatives(interface_type, ghost_type))(
background_type, ghost_type);
Array<Real> integrant(nb_quadrature_points * nb_element, back_dof,
"integrant");
- auto integrant_it = integrant.begin(back_dof);
- auto integrant_end = integrant.end(back_dof);
-
- Array<Real>::matrix_iterator B_it =
- shapesd.begin(dim, nodes_per_background_e);
- auto C_it = directing_cosines(interface_type, ghost_type).begin(voigt_size);
-
- auto sigma_it = this->stress(interface_type, ghost_type).begin();
-
Matrix<Real> Bvoigt(voigt_size, back_dof);
- for (; integrant_it != integrant_end;
- ++integrant_it, ++B_it, ++C_it, ++sigma_it) {
- VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*B_it, Bvoigt,
+ for (auto && [BtCt_sigma, C, sigma, B] :
+ zip(make_view(integrant, back_dof),
+ make_view(directing_cosines(interface_type, ghost_type), voigt_size),
+ this->stress(interface_type, ghost_type),
+ make_view(shapesd, dim, nodes_per_background_e))) {
+ VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(B, Bvoigt,
nodes_per_background_e);
- Vector<Real> & C = *C_it;
- Vector<Real> & BtCt_sigma = *integrant_it;
-
- BtCt_sigma.mul<true>(Bvoigt, C);
- BtCt_sigma *= *sigma_it * area;
+ BtCt_sigma = Bvoigt.transpose() * C * sigma * area;
}
Array<Real> residual_interface(nb_element, back_dof, "residual_interface");
interface_engine.integrate(integrant, residual_interface, back_dof,
interface_type, ghost_type, elem_filter);
integrant.resize(0);
- Array<UInt> background_filter(nb_element, 1, "background_filter");
+ Array<Idx> background_filter(nb_element, 1, "background_filter");
auto & filter =
getBackgroundFilter(interface_type, background_type, ghost_type);
emodel.getDOFManager().assembleElementalArrayLocalArray(
residual_interface, emodel.getInternalForce(), background_type,
ghost_type, -1., filter);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::computeDirectingCosines(
ElementType type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh & interface_mesh = emodel.getInterfaceMesh();
- const UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- const UInt steel_dof = dim * nb_nodes_per_element;
- const UInt voigt_size = VoigtHelper<dim>::size;
- const UInt nb_quad_points = emodel.getFEEngine("EmbeddedInterfaceFEEngine")
+ const auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ const auto steel_dof = dim * nb_nodes_per_element;
+ constexpr auto voigt_size = VoigtHelper<dim>::size;
+ const auto nb_quad_points = emodel.getFEEngine("EmbeddedInterfaceFEEngine")
.getNbIntegrationPoints(type, ghost_type);
Array<Real> node_coordinates(this->element_filter(type, ghost_type).size(),
steel_dof);
this->emodel.getFEEngine().template extractNodalToElementField<Real>(
interface_mesh, interface_mesh.getNodes(), node_coordinates, type,
ghost_type, this->element_filter(type, ghost_type));
- Array<Real>::matrix_iterator directing_cosines_it =
- directing_cosines(type, ghost_type).begin(1, voigt_size);
-
- Array<Real>::matrix_iterator node_coordinates_it =
- node_coordinates.begin(dim, nb_nodes_per_element);
- Array<Real>::matrix_iterator node_coordinates_end =
- node_coordinates.end(dim, nb_nodes_per_element);
-
- for (; node_coordinates_it != node_coordinates_end; ++node_coordinates_it) {
- for (UInt i = 0; i < nb_quad_points; i++, ++directing_cosines_it) {
- Matrix<Real> & nodes = *node_coordinates_it;
- Matrix<Real> & cosines = *directing_cosines_it;
-
- computeDirectingCosinesOnQuad(nodes, cosines);
- }
+ for (auto && data :
+ zip(repeat_n(make_view(node_coordinates, dim, nb_nodes_per_element),
+ nb_quad_points),
+ make_view<1, voigt_size>(directing_cosines(type, ghost_type)))) {
+ computeDirectingCosinesOnQuad(std::get<0>(data), std::get<1>(data));
}
// Mauro: the directing_cosines internal is defined on the quadrature points
// of each element
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::assembleStiffnessMatrix(
ElementType type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh & mesh = emodel.getMesh();
for (auto && mesh_type : mesh.elementTypes(dim, ghost_type)) {
assembleStiffnessMatrixInterface(type, mesh_type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Computes the reinforcement stiffness matrix (Gomes & Awruch, 2001)
* \f[
* \mathbf{K}_e = \sum_{i=1}^R{A_i\int_{S_i}{\mathbf{B}^T
* \mathbf{C}_i^T \mathbf{D}_{s, i} \mathbf{C}_i \mathbf{B}\,\mathrm{d}s}}
* \f]
*/
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::assembleStiffnessMatrixInterface(
ElementType interface_type, ElementType background_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
- UInt voigt_size = VoigtHelper<dim>::size;
+ constexpr Int voigt_size = VoigtHelper<dim>::size;
FEEngine & interface_engine = emodel.getFEEngine("EmbeddedInterfaceFEEngine");
- Array<UInt> & elem_filter = this->element_filter(interface_type, ghost_type);
+ Array<Idx> & elem_filter = this->element_filter(interface_type, ghost_type);
Array<Real> & grad_u = gradu_embedded(interface_type, ghost_type);
- UInt nb_element = elem_filter.size();
- UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type);
- UInt nb_quadrature_points =
+ Int nb_element = elem_filter.size();
+ Int nodes_per_background_e = Mesh::getNbNodesPerElement(background_type);
+ Int nb_quadrature_points =
interface_engine.getNbIntegrationPoints(interface_type, ghost_type);
- UInt back_dof = dim * nodes_per_background_e;
+ Int back_dof = dim * nodes_per_background_e;
- UInt integrant_size = back_dof;
+ Int integrant_size = back_dof;
grad_u.resize(nb_quadrature_points * nb_element);
Array<Real> tangent_moduli(nb_element * nb_quadrature_points, 1,
"interface_tangent_moduli");
this->computeTangentModuli(interface_type, tangent_moduli, ghost_type);
Array<Real> & shapesd = (*shape_derivatives(interface_type, ghost_type))(
background_type, ghost_type);
Array<Real> integrant(nb_element * nb_quadrature_points,
integrant_size * integrant_size, "B^t*C^t*D*C*B");
/// Temporary matrices for integrant product
Matrix<Real> Bvoigt(voigt_size, back_dof);
- Matrix<Real> DCB(1, back_dof);
- Matrix<Real> CtDCB(voigt_size, back_dof);
-
- Array<Real>::scalar_iterator D_it = tangent_moduli.begin();
- Array<Real>::scalar_iterator D_end = tangent_moduli.end();
-
- Array<Real>::matrix_iterator C_it =
- directing_cosines(interface_type, ghost_type).begin(1, voigt_size);
- Array<Real>::matrix_iterator B_it =
- shapesd.begin(dim, nodes_per_background_e);
- Array<Real>::matrix_iterator integrant_it =
- integrant.begin(integrant_size, integrant_size);
-
- for (; D_it != D_end; ++D_it, ++C_it, ++B_it, ++integrant_it) {
- Real & D = *D_it;
- Matrix<Real> & C = *C_it;
- Matrix<Real> & B = *B_it;
- Matrix<Real> & BtCtDCB = *integrant_it;
+ for (auto && [D, C, B, BtCtDCB] :
+ zip(tangent_moduli,
+ make_view(directing_cosines(interface_type, ghost_type), 1,
+ voigt_size),
+ make_view(shapesd, dim, nodes_per_background_e),
+ make_view(integrant, integrant_size, integrant_size))) {
VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(B, Bvoigt,
nodes_per_background_e);
- DCB.mul<false, false>(C, Bvoigt);
- DCB *= D * area;
- CtDCB.mul<true, false>(C, DCB);
- BtCtDCB.mul<true, false>(Bvoigt, CtDCB);
+ BtCtDCB = Bvoigt.transpose() * C.transpose() * D * C * Bvoigt * area;
}
tangent_moduli.resize(0);
Array<Real> K_interface(nb_element, integrant_size * integrant_size,
"K_interface");
interface_engine.integrate(integrant, K_interface,
integrant_size * integrant_size, interface_type,
ghost_type, elem_filter);
integrant.resize(0);
// Mauro: Here K_interface contains the local stiffness matrices,
// directing_cosines contains the information about the orientation
// of the reinforcements, any rotation of the local stiffness matrix
// can be done here
auto & filter =
getBackgroundFilter(interface_type, background_type, ghost_type);
emodel.getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", K_interface, background_type, ghost_type, _symmetric,
filter);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
Real MaterialReinforcement<Mat, dim>::getEnergy(const std::string & id) {
AKANTU_DEBUG_IN();
if (id == "potential") {
Real epot = 0.;
this->computePotentialEnergyByElements();
for (auto && type :
this->element_filter.elementTypes(this->spatial_dimension)) {
FEEngine & interface_engine =
emodel.getFEEngine("EmbeddedInterfaceFEEngine");
epot += interface_engine.integrate(
this->potential_energy(type, _not_ghost), type, _not_ghost,
this->element_filter(type, _not_ghost));
epot *= area;
}
return epot;
}
AKANTU_DEBUG_OUT();
return 0;
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::computeGradU(ElementType interface_type,
GhostType ghost_type) {
// Looping over background types
for (auto && bg_type :
background_filter(interface_type, ghost_type)->elementTypes(dim)) {
- const UInt nodes_per_background_e = Mesh::getNbNodesPerElement(bg_type);
- const UInt voigt_size = VoigtHelper<dim>::size;
+ const Int nodes_per_background_e = Mesh::getNbNodesPerElement(bg_type);
+ constexpr Int voigt_size = VoigtHelper<dim>::size;
auto & bg_shapesd =
(*shape_derivatives(interface_type, ghost_type))(bg_type, ghost_type);
auto & filter = getBackgroundFilter(interface_type, bg_type, ghost_type);
Array<Real> disp_per_element(0, dim * nodes_per_background_e, "disp_elem");
FEEngine::extractNodalToElementField(
emodel.getMesh(), emodel.getDisplacement(), disp_per_element, bg_type,
ghost_type, filter);
- Matrix<Real> concrete_du(dim, dim);
- Matrix<Real> epsilon(dim, dim);
- Vector<Real> evoigt(voigt_size);
+ Matrix<Real, dim, dim> concrete_du(dim, dim);
+ Matrix<Real, dim, dim> epsilon(dim, dim);
+ Vector<Real, voigt_size> evoigt(voigt_size);
- for (auto && tuple :
+ for (auto && [u, B, du, C] :
zip(make_view(disp_per_element, dim, nodes_per_background_e),
make_view(bg_shapesd, dim, nodes_per_background_e),
this->gradu(interface_type, ghost_type),
make_view(this->directing_cosines(interface_type, ghost_type),
voigt_size))) {
- auto & u = std::get<0>(tuple);
- auto & B = std::get<1>(tuple);
- auto & du = std::get<2>(tuple);
- auto & C = std::get<3>(tuple);
- concrete_du.mul<false, true>(u, B);
+ concrete_du = u * B.transpose();
auto epsilon = 0.5 * (concrete_du + concrete_du.transpose());
- strainTensorToVoigtVector(epsilon, evoigt);
+ VoigtHelper<dim>::matrixToVoigtWithFactors(epsilon, evoigt);
du = C.dot(evoigt);
}
}
}
/* -------------------------------------------------------------------------- */
/**
* The structure of the directing cosines matrix is :
* \f{eqnarray*}{
* C_{1,\cdot} & = & (l^2, m^2, n^2, mn, ln, lm) \\
* C_{i,j} & = & 0
* \f}
*
* with :
* \f[
* (l, m, n) = \frac{1}{\|\frac{\mathrm{d}\vec{r}(s)}{\mathrm{d}s}\|} \cdot
* \frac{\mathrm{d}\vec{r}(s)}{\mathrm{d}s}
* \f]
*/
-template <class Mat, UInt dim>
+template <class Mat, Int dim>
+template <class Derived1, class Derived2>
inline void MaterialReinforcement<Mat, dim>::computeDirectingCosinesOnQuad(
- const Matrix<Real> & nodes, Matrix<Real> & cosines) {
+ const Eigen::MatrixBase<Derived1> & nodes,
+ Eigen::MatrixBase<Derived2> & cosines) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT(nodes.cols() == 2,
"Higher order reinforcement elements not implemented");
+ Vector<Real> delta = nodes(1) - nodes(0);
- const Vector<Real> a = nodes(0);
- const Vector<Real> b = nodes(1);
- Vector<Real> delta = b - a;
-
- Real sq_length = 0.;
- for (UInt i = 0; i < dim; i++) {
- sq_length += delta(i) * delta(i);
- }
+ Real sq_length = delta.dot(delta);
if (dim == 2) {
cosines(0, 0) = delta(0) * delta(0); // l^2
cosines(0, 1) = delta(1) * delta(1); // m^2
cosines(0, 2) = delta(0) * delta(1); // lm
} else if (dim == 3) {
cosines(0, 0) = delta(0) * delta(0); // l^2
cosines(0, 1) = delta(1) * delta(1); // m^2
cosines(0, 2) = delta(2) * delta(2); // n^2
cosines(0, 3) = delta(1) * delta(2); // mn
cosines(0, 4) = delta(0) * delta(2); // ln
cosines(0, 5) = delta(0) * delta(1); // lm
}
cosines /= sq_length;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <class Mat, UInt dim>
-inline void MaterialReinforcement<Mat, dim>::stressTensorToVoigtVector(
- const Matrix<Real> & tensor, Vector<Real> & vector) {
- AKANTU_DEBUG_IN();
-
- for (UInt i = 0; i < dim; i++) {
- vector(i) = tensor(i, i);
- }
-
- if (dim == 2) {
- vector(2) = tensor(0, 1);
- } else if (dim == 3) {
- vector(3) = tensor(1, 2);
- vector(4) = tensor(0, 2);
- vector(5) = tensor(0, 1);
- }
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-
-template <class Mat, UInt dim>
-inline void MaterialReinforcement<Mat, dim>::strainTensorToVoigtVector(
- const Matrix<Real> & tensor, Vector<Real> & vector) {
- AKANTU_DEBUG_IN();
-
- for (UInt i = 0; i < dim; i++) {
- vector(i) = tensor(i, i);
- }
-
- if (dim == 2) {
- vector(2) = 2 * tensor(0, 1);
- } else if (dim == 3) {
- vector(3) = 2 * tensor(1, 2);
- vector(4) = 2 * tensor(0, 2);
- vector(5) = 2 * tensor(0, 1);
- }
-
- AKANTU_DEBUG_OUT();
-}
-
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
index 1cba8b5f0..c07cb410b 100644
--- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
+++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
@@ -1,274 +1,247 @@
/**
* @file material_neohookean.cc
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Apr 08 2013
* @date last modification: Thu Feb 20 2020
*
* @brief Specialization of the material class for finite deformation
* neo-hookean material
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_neohookean.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialNeohookean<spatial_dimension>::MaterialNeohookean(
SolidMechanicsModel & model, const ID & id)
- : PlaneStressToolbox<spatial_dimension>(model, id) {
+ : Parent(model, id) {
AKANTU_DEBUG_IN();
this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable,
"Young's modulus");
this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable,
"Poisson's ratio");
this->registerParam("lambda", lambda, _pat_readable,
"First Lamé coefficient");
this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
this->finite_deformation = true;
this->initialize_third_axis_deformation = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialNeohookean<spatial_dimension>::initMaterial() {
- AKANTU_DEBUG_IN();
PlaneStressToolbox<spatial_dimension>::initMaterial();
if (spatial_dimension == 1) {
nu = 0.;
}
this->updateInternalParameters();
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <> void MaterialNeohookean<2>::initMaterial() {
- AKANTU_DEBUG_IN();
PlaneStressToolbox<2>::initMaterial();
this->updateInternalParameters();
if (this->plane_stress) {
this->third_axis_deformation.setDefaultValue(1.);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialNeohookean<spatial_dimension>::updateInternalParameters() {
lambda = nu * E / ((1 + nu) * (1 - 2 * nu));
mu = E / (2 * (1 + nu));
kpa = lambda + 2. / 3. * mu;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialNeohookean<dim>::computeCauchyStressPlaneStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
PlaneStressToolbox<dim>::computeCauchyStressPlaneStress(el_type, ghost_type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <>
void MaterialNeohookean<2>::computeCauchyStressPlaneStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto gradu_it = this->gradu(el_type, ghost_type).begin(2, 2);
auto gradu_end = this->gradu(el_type, ghost_type).end(2, 2);
auto piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(2, 2);
auto stress_it = this->stress(el_type, ghost_type).begin(2, 2);
auto c33_it = this->third_axis_deformation(el_type, ghost_type).begin();
for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it, ++c33_it) {
- Matrix<Real> & grad_u = *gradu_it;
- Matrix<Real> & piola = *piola_it;
- Matrix<Real> & sigma = *stress_it;
+ auto && grad_u = *gradu_it;
+ auto && piola = *piola_it;
+ auto && sigma = *stress_it;
StoCauchy<2>(gradUToF<2>(grad_u), piola, sigma, *c33_it);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialNeohookean<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- computeStressOnQuad(grad_u, sigma);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ for (auto && args : this->getArguments(el_type, ghost_type)) {
+ computeStressOnQuad(args);
+ }
}
/* -------------------------------------------------------------------------- */
template <>
void MaterialNeohookean<2>::computeStress(ElementType el_type,
GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
+ auto && arguments = getArguments(el_type, ghost_type);
if (this->plane_stress) {
PlaneStressToolbox<2>::computeStress(el_type, ghost_type);
- auto c33_it = this->third_axis_deformation(el_type, ghost_type).begin();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- computeStressOnQuad(grad_u, sigma, *c33_it);
- ++c33_it;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ for (auto && args : zip_replace(
+ std::forward<decltype(arguments)>(arguments),
+ "C33"_n = this->third_axis_deformation(el_type, ghost_type))) {
+ computeStressOnQuad(args);
+ }
} else {
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- computeStressOnQuad(grad_u, sigma);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ for (auto && args : arguments) {
+ computeStressOnQuad(args);
+ }
}
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialNeohookean<dim>::computeThirdAxisDeformation(
ElementType /*el_type*/, GhostType /*ghost_type*/) {}
/* -------------------------------------------------------------------------- */
template <>
void MaterialNeohookean<2>::computeThirdAxisDeformation(ElementType el_type,
GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
AKANTU_DEBUG_ASSERT(this->plane_stress, "The third component of the strain "
"can only be computed for 2D "
"problems in Plane Stress!!");
- Array<Real>::scalar_iterator c33_it =
- this->third_axis_deformation(el_type, ghost_type).begin();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
- computeThirdAxisDeformationOnQuad(grad_u, *c33_it);
- ++c33_it;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ for (auto && args : zip_replace(
+ getArguments(el_type, ghost_type),
+ "C33"_n = this->third_axis_deformation(el_type, ghost_type))) {
+ computeThirdAxisDeformationOnQuad(args);
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialNeohookean<spatial_dimension>::computePotentialEnergy(
ElementType el_type) {
AKANTU_DEBUG_IN();
Material::computePotentialEnergy(el_type);
Array<Real>::scalar_iterator epot = this->potential_energy(el_type).begin();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
computePotentialEnergyOnQuad(grad_u, *epot);
++epot;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialNeohookean<spatial_dimension>::computeTangentModuli(
- __attribute__((unused)) ElementType el_type, Array<Real> & tangent_matrix,
- __attribute__((unused)) GhostType ghost_type) {
- AKANTU_DEBUG_IN();
+ ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
+ auto && arguments = getArgumentsTangent(tangent_matrix, el_type, ghost_type);
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
- computeTangentModuliOnQuad(tangent, grad_u);
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ for (auto && args : arguments) {
+ computeTangentModuliOnQuad(args);
+ }
}
/* -------------------------------------------------------------------------- */
template <>
-void MaterialNeohookean<2>::computeTangentModuli(__attribute__((unused))
- ElementType el_type,
+void MaterialNeohookean<2>::computeTangentModuli(ElementType el_type,
Array<Real> & tangent_matrix,
- __attribute__((unused))
GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
if (this->plane_stress) {
PlaneStressToolbox<2>::computeStress(el_type, ghost_type);
- Array<Real>::const_scalar_iterator c33_it =
- this->third_axis_deformation(el_type, ghost_type).begin();
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
- computeTangentModuliOnQuad(tangent, grad_u, *c33_it);
- ++c33_it;
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
-
+ for (auto && args : zip_replace(
+ getArgumentsTangent(tangent_matrix, el_type, ghost_type),
+ "C33"_n = this->third_axis_deformation(el_type, ghost_type))) {
+ computeTangentModuliOnQuad(args);
+ }
} else {
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
- computeTangentModuliOnQuad(tangent, grad_u);
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
+ for (auto && args :
+ getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
+ computeTangentModuliOnQuad(args);
+ }
}
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
Real MaterialNeohookean<spatial_dimension>::getPushWaveSpeed(
- __attribute__((unused)) const Element & element) const {
+ const Element & /*element*/) const {
return sqrt((this->lambda + 2 * this->mu) / this->rho);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
Real MaterialNeohookean<spatial_dimension>::getShearWaveSpeed(
- __attribute__((unused)) const Element & element) const {
+ const Element & /*element*/) const {
return sqrt(this->mu / this->rho);
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(neohookean, MaterialNeohookean);
+template class MaterialNeohookean<1>;
+template class MaterialNeohookean<2>;
+template class MaterialNeohookean<3>;
+static bool material_is_allocated_neohookean =
+ instantiateMaterial<MaterialNeohookean>("neohookean");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh
index de2b5bbf8..4267da1c1 100644
--- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh
+++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh
@@ -1,168 +1,185 @@
/**
* @file material_neohookean.hh
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Feb 20 2020
*
* @brief Material isotropic elastic
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "plane_stress_toolbox.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_NEOHOOKEAN_HH_
#define AKANTU_MATERIAL_NEOHOOKEAN_HH_
namespace akantu {
/**
* Material elastic isotropic
*
* parameters in the material files :
* - rho : density (default: 0)
* - E : Young's modulus (default: 0)
* - nu : Poisson's ratio (default: 1/2)
* - Plane_Stress : if 0: plane strain, else: plane stress (default: 0)
*/
-template <UInt spatial_dimension>
-class MaterialNeohookean : public PlaneStressToolbox<spatial_dimension> {
+template <Int dim> class MaterialNeohookean : public PlaneStressToolbox<dim> {
+ using Parent = PlaneStressToolbox<dim>;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialNeohookean(SolidMechanicsModel & model, const ID & id = "");
~MaterialNeohookean() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material computed parameter
void initMaterial() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// Computation of the cauchy stress for plane strain materials
void
computeCauchyStressPlaneStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// Non linear computation of the third direction strain in 2D plane stress
/// case
void computeThirdAxisDeformation(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the elastic potential energy
void computePotentialEnergy(ElementType el_type) override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
/// compute the p-wave speed in the material
Real getPushWaveSpeed(const Element & element) const override;
/// compute the s-wave speed in the material
Real getShearWaveSpeed(const Element & element) const override;
MatrixType getTangentType() override { return _symmetric; }
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ Material::getArguments<dim>(el_type, ghost_type),
+ "C33"_n =
+ broadcast(C33, this->element_filter(el_type, ghost_type).size()));
+ }
+
+ decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrix,
+ ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ Material::getArgumentsTangent<dim>(tangent_matrix, el_type, ghost_type),
+ "C33"_n =
+ broadcast(C33, this->element_filter(el_type, ghost_type).size()));
+ }
+
protected:
/// constitutive law for a given quadrature point
inline void computePiolaKirchhoffOnQuad(const Matrix<Real> & E,
Matrix<Real> & S);
/// constitutive law for a given quadrature point (first piola)
inline void computeFirstPiolaKirchhoffOnQuad(const Matrix<Real> & grad_u,
const Matrix<Real> & S,
Matrix<Real> & P);
/// constitutive law for a given quadrature point
inline void computeDeltaStressOnQuad(const Matrix<Real> & grad_u,
const Matrix<Real> & grad_delta_u,
Matrix<Real> & delta_S);
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(Matrix<Real> & grad_u, Matrix<Real> & S,
- const Real & C33 = 1.0);
+ template <class Args> inline void computeStressOnQuad(Args && args);
/// constitutive law for a given quadrature point
- inline void computeThirdAxisDeformationOnQuad(Matrix<Real> & grad_u,
- Real & c33_value);
+ template <class Args>
+ inline void computeThirdAxisDeformationOnQuad(Args && args);
/// constitutive law for a given quadrature point
// inline void updateStressOnQuad(const Matrix<Real> & sigma,
// Matrix<Real> & cauchy_sigma);
/// compute the potential energy for a quadrature point
inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u,
Real & epot);
/// compute the tangent stiffness matrix for an element
- void computeTangentModuliOnQuad(Matrix<Real> & tangent, Matrix<Real> & grad_u,
- const Real & C33 = 1.0);
+ template <class Args> void computeTangentModuliOnQuad(Args && args);
/// recompute the lame coefficient if E or nu changes
void updateInternalParameters() override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// the young modulus
Real E;
/// Poisson coefficient
Real nu;
/// First Lamé coefficient
Real lambda;
/// Second Lamé coefficient (shear modulus)
Real mu;
/// Bulk modulus
Real kpa;
+
+ Real C33{1.};
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_neohookean_inline_impl.hh"
#endif /* AKANTU_MATERIAL_NEOHOOKEAN_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh
index da9909112..39050fc59 100644
--- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh
@@ -1,201 +1,171 @@
/**
* @file material_neohookean_inline_impl.hh
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
* @date creation: Mon Apr 08 2013
* @date last modification: Thu Feb 20 2020
*
* @brief Implementation of the inline functions of the material elastic
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_neohookean.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <iostream>
#include <utility>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
inline void MaterialNeohookean<dim>::computeDeltaStressOnQuad(
__attribute__((unused)) const Matrix<Real> & grad_u,
__attribute__((unused)) const Matrix<Real> & grad_delta_u,
__attribute__((unused)) Matrix<Real> & delta_S) {}
//! computes the second piola kirchhoff stress, called S
-template <UInt dim>
-inline void MaterialNeohookean<dim>::computeStressOnQuad(Matrix<Real> & grad_u,
- Matrix<Real> & S,
- const Real & C33) {
+template <Int dim>
+template <class Args>
+inline void MaterialNeohookean<dim>::computeStressOnQuad(Args && args) {
// Neo hookean book
- Matrix<Real> F(dim, dim);
- Matrix<Real> C(dim, dim); // Right green
- Matrix<Real> Cminus(dim, dim); // Right green
-
- this->template gradUToF<dim>(grad_u, F);
- this->rightCauchy(F, C);
- Real J = F.det() * sqrt(C33); // the term sqrt(C33) corresponds to the off
- // plane strain (2D plane stress)
- // std::cout<<"det(F) -> "<<J<<std::endl;
- Cminus.inverse(C);
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- S(i, j) =
- Math::kronecker(i, j) * mu + (lambda * log(J) - mu) * Cminus(i, j);
- }
- }
+ auto && F = Material::gradUToF<dim>(args["grad_u"_n]);
+ auto && C = Material::rightCauchy<dim>(F);
+ // the term sqrt(C33) corresponds to the off plane strain (2D plane stress)
+ auto J = F.determinant() * std::sqrt(args["C33"_n]);
+
+ args["sigma"_n] = Matrix<Real, dim, dim>::Identity() * mu +
+ (lambda * log(J) - mu) * C.inverse();
}
/* -------------------------------------------------------------------------- */
-class C33_NR : public Math::NewtonRaphsonFunctor {
+class C33_NR : public Math::NewtonRaphsonFunctor<Real> {
public:
C33_NR(std::string name, const Real & lambda, const Real & mu,
const Matrix<Real> & C)
: NewtonRaphsonFunctor(std::move(name)), lambda(lambda), mu(mu), C(C) {}
- inline Real f(Real x) const override {
+ inline Real f(const Real & x) const override {
return (this->lambda / 2. *
(std::log(x) + std::log(this->C(0, 0) * this->C(1, 1) -
Math::pow<2>(this->C(0, 1)))) +
this->mu * (x - 1.));
}
- inline Real f_prime(Real x) const override {
+ inline Real f_prime(const Real & x) const override {
AKANTU_DEBUG_ASSERT(std::abs(x) > Math::getTolerance(),
"x is zero (x should be the off plane right Cauchy"
<< " measure in this function so you made a mistake"
<< " somewhere else that lead to a zero here!!!");
return (this->lambda / (2. * x) + this->mu);
}
private:
const Real & lambda;
const Real & mu;
const Matrix<Real> & C;
};
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void MaterialNeohookean<dim>::computeThirdAxisDeformationOnQuad(
- Matrix<Real> & grad_u, Real & c33_value) {
+template <Int dim>
+template <class Args>
+inline void
+MaterialNeohookean<dim>::computeThirdAxisDeformationOnQuad(Args && args) {
// Neo hookean book
- Matrix<Real> F(dim, dim);
- Matrix<Real> C(dim, dim); // Right green
+ auto F = Material::gradUToF<dim>(args["grad_u"_n]);
+ auto C = Material::rightCauchy<dim>(F);
- this->template gradUToF<dim>(grad_u, F);
- this->rightCauchy(F, C);
+ Math::NewtonRaphson<Real> nr(1e-5, 100);
+ auto & C33 = args["C33"_n];
- Math::NewtonRaphson nr(1e-5, 100);
- c33_value = nr.solve(
- C33_NR("Neohookean_plan_stress", this->lambda, this->mu, C), c33_value);
+ C33 = nr.solve(C33_NR("Neohookean_plan_stress", this->lambda, this->mu, C),
+ C33);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
inline void
MaterialNeohookean<dim>::computePiolaKirchhoffOnQuad(const Matrix<Real> & E,
Matrix<Real> & S) {
-
- Real trace = E.trace(); /// \f$ trace = (\nabla u)_{kk} \f$
-
/// \f$ \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla
/// u_{ij} + \nabla u_{ji}) \f$
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- S(i, j) = Math::kronecker(i, j) * lambda * trace + 2.0 * mu * E(i, j);
- }
- }
+ S = Matrix<Real, dim, dim>::Identity() * lambda * E.trace() + 2.0 * mu * E;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
inline void MaterialNeohookean<dim>::computeFirstPiolaKirchhoffOnQuad(
const Matrix<Real> & grad_u, const Matrix<Real> & S, Matrix<Real> & P) {
-
- Matrix<Real> F(dim, dim);
- Matrix<Real> C(dim, dim); // Right green
-
- this->template gradUToF<dim>(grad_u, F);
+ auto F = Material::gradUToF<dim>(grad_u);
// first Piola-Kirchhoff is computed as the product of the deformation
// gracient
// tensor and the second Piola-Kirchhoff stress tensor
-
P = F * S;
}
/**************************************************************************************/
/* Computation of the potential energy for a this neo hookean material */
-template <UInt dim>
+template <Int dim>
inline void MaterialNeohookean<dim>::computePotentialEnergyOnQuad(
const Matrix<Real> & grad_u, Real & epot) {
- Matrix<Real> F(dim, dim);
- Matrix<Real> C(dim, dim); // Right green
-
- this->template gradUToF<dim>(grad_u, F);
- this->rightCauchy(F, C);
- Real J = F.det();
- // std::cout<<"det(F) -> "<<J<<std::endl;
+ auto F = Material::gradUToF<dim>(grad_u);
+ auto C = Material::rightCauchy<dim>(F);
+ auto J = F.determinant();
epot =
0.5 * lambda * pow(log(J), 2.) + mu * (-log(J) + 0.5 * (C.trace() - dim));
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void MaterialNeohookean<dim>::computeTangentModuliOnQuad(
- Matrix<Real> & tangent, Matrix<Real> & grad_u, const Real & C33) {
-
+template <Int dim>
+template <class Args>
+inline void MaterialNeohookean<dim>::computeTangentModuliOnQuad(Args && args) {
+ auto & tangent = args["tangent_moduli"_n];
// Neo hookean book
- UInt cols = tangent.cols();
- UInt rows = tangent.rows();
- Matrix<Real> F(dim, dim);
- Matrix<Real> C(dim, dim);
- Matrix<Real> Cminus(dim, dim);
- this->template gradUToF<dim>(grad_u, F);
- this->rightCauchy(F, C);
- Real J = F.det() * sqrt(C33);
- // std::cout<<"det(F) -> "<<J<<std::endl;
- Cminus.inverse(C);
-
- for (UInt m = 0; m < rows; m++) {
+ auto cols = tangent.cols();
+ auto rows = tangent.rows();
+ auto F = Material::gradUToF<dim>(args["grad_u"_n]);
+ auto C = Material::rightCauchy<dim>(F);
+ auto J = F.determinant() * sqrt(C33);
+
+ auto && Cminus = C.inverse();
+
+ for (Int m = 0; m < rows; m++) {
UInt i = VoigtHelper<dim>::vec[m][0];
UInt j = VoigtHelper<dim>::vec[m][1];
- for (UInt n = 0; n < cols; n++) {
+ for (Int n = 0; n < cols; n++) {
UInt k = VoigtHelper<dim>::vec[n][0];
UInt l = VoigtHelper<dim>::vec[n][1];
// book belytchko
tangent(m, n) = lambda * Cminus(i, j) * Cminus(k, l) +
(mu - lambda * log(J)) * (Cminus(i, k) * Cminus(j, l) +
Cminus(i, l) * Cminus(k, j));
}
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_non_local.hh b/src/model/solid_mechanics/materials/material_non_local.hh
index a5239c9b4..277e26f5f 100644
--- a/src/model/solid_mechanics/materials/material_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_non_local.hh
@@ -1,119 +1,119 @@
/**
* @file material_non_local.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Material class that handle the non locality of a law for example
* damage.
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_NON_LOCAL_HH_
#define AKANTU_MATERIAL_NON_LOCAL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
class MaterialNonLocalInterface {
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material the non local parts of the material
void initMaterialNonLocal() {
this->registerNeighborhood();
this->registerNonLocalVariables();
};
/// insert the quadrature points in the neighborhoods of the non-local manager
virtual void insertIntegrationPointsInNeighborhoods(
GhostType ghost_type,
const ElementTypeMapReal & quadrature_points_coordinates) = 0;
/// update the values in the non-local internal fields
virtual void updateNonLocalInternals(ElementTypeMapReal & non_local_flattened,
const ID & field_id,
GhostType ghost_type,
ElementKind kind) = 0;
/// constitutive law
virtual void computeNonLocalStresses(GhostType ghost_type = _not_ghost) = 0;
protected:
/// get the name of the neighborhood for this material
virtual ID getNeighborhoodName() = 0;
/// register the neighborhoods for the material
virtual void registerNeighborhood() = 0;
/// register the non local internal variable
virtual void registerNonLocalVariables() = 0;
virtual inline void onElementsAdded(const Array<Element> & /*unused*/,
const NewElementsEvent & /*unused*/) {}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <UInt dim, class LocalParent>
+template <Int dim, class LocalParent>
class MaterialNonLocal : public MaterialNonLocalInterface, public LocalParent {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
explicit MaterialNonLocal(SolidMechanicsModel & model, const ID & id);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// insert the quadrature points in the neighborhoods of the non-local manager
void insertIntegrationPointsInNeighborhoods(
GhostType ghost_type,
const ElementTypeMapReal & quadrature_points_coordinates) override;
/// update the values in the non-local internal fields
void updateNonLocalInternals(ElementTypeMapReal & non_local_flattened,
const ID & field_id, GhostType ghost_type,
ElementKind kind) override;
/// register the neighborhoods for the material
void registerNeighborhood() override;
protected:
/// get the name of the neighborhood for this material
ID getNeighborhoodName() override { return this->name; }
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
#include "material_non_local_tmpl.hh"
#endif /* AKANTU_MATERIAL_NON_LOCAL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh b/src/model/solid_mechanics/materials/material_non_local_tmpl.hh
index 6c033166f..446f7686f 100644
--- a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh
+++ b/src/model/solid_mechanics/materials/material_non_local_tmpl.hh
@@ -1,129 +1,129 @@
/**
* @file material_non_local_tmpl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Jul 06 2017
* @date last modification: Fri Mar 26 2021
*
* @brief Implementation of material non-local
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material.hh"
#include "material_non_local.hh"
#include "non_local_neighborhood.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim, class LocalParent>
+template <Int dim, class LocalParent>
MaterialNonLocal<dim, LocalParent>::MaterialNonLocal(
SolidMechanicsModel & model, const ID & id)
: LocalParent(model, id) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim, class LocalParent>
+template <Int dim, class LocalParent>
void MaterialNonLocal<dim, LocalParent>::insertIntegrationPointsInNeighborhoods(
GhostType ghost_type,
const ElementTypeMapReal & quadrature_points_coordinates) {
IntegrationPoint q;
q.ghost_type = ghost_type;
auto & neighborhood = this->model.getNonLocalManager().getNeighborhood(
this->getNeighborhoodName());
- for (auto & type :
+ for (auto && type :
this->element_filter.elementTypes(dim, ghost_type, _ek_regular)) {
q.type = type;
const auto & elem_filter = this->element_filter(type, ghost_type);
- UInt nb_element = elem_filter.size();
-
- if (nb_element != 0U) {
- UInt nb_quad =
- this->getFEEngine().getNbIntegrationPoints(type, ghost_type);
-
- const auto & quads = quadrature_points_coordinates(type, ghost_type);
-
- auto nb_total_element =
- this->model.getMesh().getNbElement(type, ghost_type);
- auto quads_it = quads.begin_reinterpret(dim, nb_quad, nb_total_element);
- for (auto & elem : elem_filter) {
- Matrix<Real> quads = quads_it[elem];
- q.element = elem;
- for (UInt nq = 0; nq < nb_quad; ++nq) {
- q.num_point = nq;
- q.global_num = q.element * nb_quad + nq;
- neighborhood.insertIntegrationPoint(q, quads(nq));
- }
+ auto nb_element = elem_filter.size();
+
+ if (nb_element == 0) {
+ continue;
+ }
+
+ auto nb_quad = this->getFEEngine().getNbIntegrationPoints(type, ghost_type);
+
+ auto && quads_it =
+ make_view(quadrature_points_coordinates(type, ghost_type), dim, nb_quad)
+ .begin();
+ for (auto & elem : elem_filter) {
+ auto && quads = quads_it[elem];
+ q.element = elem;
+ for (auto && data : enumerate(quads)) {
+ auto nq = std::get<0>(data);
+ q.num_point = nq;
+ q.global_num = q.element * nb_quad + nq;
+ neighborhood.insertIntegrationPoint(q, std::get<1>(data));
}
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim, class LocalParent>
+template <Int dim, class LocalParent>
void MaterialNonLocal<dim, LocalParent>::updateNonLocalInternals(
ElementTypeMapReal & non_local_flattened, const ID & field_id,
GhostType ghost_type, ElementKind kind) {
/// loop over all types in the material
- for (auto & el_type :
+ for (auto && el_type :
this->element_filter.elementTypes(dim, ghost_type, kind)) {
- Array<Real> & internal =
+ auto & internal =
this->template getInternal<Real>(field_id)(el_type, ghost_type);
auto & internal_flat = non_local_flattened(el_type, ghost_type);
auto nb_component = internal_flat.getNbComponent();
auto internal_it = internal.begin(nb_component);
auto internal_flat_it = internal_flat.begin(nb_component);
/// loop all elements for the given type
const auto & filter = this->element_filter(el_type, ghost_type);
- UInt nb_quads =
+ Int nb_quads =
this->getFEEngine().getNbIntegrationPoints(el_type, ghost_type);
for (auto & elem : filter) {
- for (UInt q = 0; q < nb_quads; ++q, ++internal_it) {
- UInt global_quad = elem * nb_quads + q;
+ for (Int q = 0; q < nb_quads; ++q, ++internal_it) {
+ auto global_quad = elem * nb_quads + q;
*internal_it = internal_flat_it[global_quad];
}
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim, class LocalParent>
+template <Int dim, class LocalParent>
void MaterialNonLocal<dim, LocalParent>::registerNeighborhood() {
ID name = this->getNeighborhoodName();
this->model.getNonLocalManager().registerNeighborhood(name, name);
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.cc b/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.cc
index e110857cc..92bf656cf 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.cc
@@ -1,195 +1,99 @@
/**
* @file material_drucker_prager.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Mon Apr 07 2014
* @date last modification: Tue Apr 06 2021
*
* @brief Implementation of the akantu::MaterialDruckerPrager class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_drucker_prager.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
-template <UInt spatial_dimension>
-MaterialDruckerPrager<spatial_dimension>::MaterialDruckerPrager(
- SolidMechanicsModel & model, const ID & id)
- : MaterialPlastic<spatial_dimension>(model, id) {
-
- AKANTU_DEBUG_IN();
+template <Int dim>
+MaterialDruckerPrager<dim>::MaterialDruckerPrager(SolidMechanicsModel & model,
+ const ID & id)
+ : Parent(model, id) {
this->initialize();
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialDruckerPrager<spatial_dimension>::MaterialDruckerPrager(
- SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
- FEEngine & fe_engine, const ID & id)
- : MaterialPlastic<spatial_dimension>(model, dim, mesh, fe_engine, id) {
-
- AKANTU_DEBUG_IN();
+template <Int dim>
+MaterialDruckerPrager<dim>::MaterialDruckerPrager(SolidMechanicsModel & model,
+ Int spatial_dimension,
+ const Mesh & mesh,
+ FEEngine & fe_engine,
+ const ID & id)
+ : Parent(model, spatial_dimension, mesh, fe_engine, id) {
this->initialize();
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialDruckerPrager<spatial_dimension>::initialize() {
+template <Int dim> void MaterialDruckerPrager<dim>::initialize() {
this->registerParam("phi", phi, Real(0.), _pat_parsable | _pat_modifiable,
"Internal friction angle in degrees");
this->registerParam("fc", fc, Real(1.), _pat_parsable | _pat_modifiable,
"Compressive strength");
this->registerParam("radial_return", radial_return_mapping, bool(true),
_pat_parsable | _pat_modifiable, "Radial return mapping");
-
- this->updateInternalParameters();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialDruckerPrager<spatial_dimension>::updateInternalParameters() {
- MaterialElastic<spatial_dimension>::updateInternalParameters();
+template <Int dim> void MaterialDruckerPrager<dim>::updateInternalParameters() {
+ Parent::updateInternalParameters();
// compute alpha and k parameters for Drucker-Prager
Real phi_radian = this->phi * M_PI / 180.;
this->alpha = (6. * sin(phi_radian)) / (3. - sin(phi_radian));
Real cohesion = this->fc * (1. - sin(phi_radian)) / (2. * cos(phi_radian));
this->k = (6. * cohesion * cos(phi_radian)) / (3. - sin(phi_radian));
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialDruckerPrager<spatial_dimension>::computeStress(
- ElementType el_type, GhostType ghost_type) {
-
- AKANTU_DEBUG_IN();
-
- MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type);
- // infinitesimal and finite deformation
- auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
-
- auto previous_sigma_th_it =
- this->sigma_th.previous(el_type, ghost_type).begin();
-
- auto previous_gradu_it = this->gradu.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_stress_it = this->stress.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto inelastic_strain_it = this->inelastic_strain(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_inelastic_strain_it =
- this->inelastic_strain.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- //
- // Finite Deformations
- //
+template <Int dim>
+void MaterialDruckerPrager<dim>::computeStress(ElementType el_type,
+ GhostType ghost_type) {
if (this->finite_deformation) {
- auto previous_piola_kirchhoff_2_it =
- this->piola_kirchhoff_2.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto green_strain_it = this->green_strain(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- auto & inelastic_strain_tensor = *inelastic_strain_it;
- auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
- auto & previous_grad_u = *previous_gradu_it;
- auto & previous_sigma = *previous_piola_kirchhoff_2_it;
-
- auto & green_strain = *green_strain_it;
- this->template gradUToE<spatial_dimension>(grad_u, green_strain);
- Matrix<Real> previous_green_strain(spatial_dimension, spatial_dimension);
- this->template gradUToE<spatial_dimension>(previous_grad_u,
- previous_green_strain);
- Matrix<Real> F_tensor(spatial_dimension, spatial_dimension);
- this->template gradUToF<spatial_dimension>(grad_u, F_tensor);
-
- computeStressOnQuad(green_strain, previous_green_strain, sigma,
- previous_sigma, inelastic_strain_tensor,
- previous_inelastic_strain_tensor, *sigma_th_it,
- *previous_sigma_th_it, F_tensor);
-
- ++sigma_th_it;
- ++inelastic_strain_it;
- ++previous_sigma_th_it;
- //++previous_stress_it;
- ++previous_gradu_it;
- ++green_strain_it;
- ++previous_inelastic_strain_it;
- ++previous_piola_kirchhoff_2_it;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
+ AKANTU_TO_IMPLEMENT();
}
- // Infinitesimal deformations
- else {
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- auto & inelastic_strain_tensor = *inelastic_strain_it;
- auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
- auto & previous_grad_u = *previous_gradu_it;
- auto & previous_sigma = *previous_stress_it;
- computeStressOnQuad(
- grad_u, previous_grad_u, sigma, previous_sigma, inelastic_strain_tensor,
- previous_inelastic_strain_tensor, *sigma_th_it, *previous_sigma_th_it);
- ++sigma_th_it;
- ++inelastic_strain_it;
- ++previous_sigma_th_it;
- ++previous_stress_it;
- ++previous_gradu_it;
- ++previous_inelastic_strain_it;
+ MaterialThermal<dim>::computeStress(el_type, ghost_type);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ // infinitesimal and finite deformation
+ for (auto && args : Parent::getArguments(el_type, ghost_type)) {
+ computeStressOnQuad(args);
}
-
- AKANTU_DEBUG_OUT();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialDruckerPrager<spatial_dimension>::computeTangentModuli(
- ElementType /*el_type*/, Array<Real> & /*tangent_matrix*/,
- GhostType /*ghost_type*/) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(plastic_drucker_prager, MaterialDruckerPrager);
+template class MaterialDruckerPrager<1>;
+template class MaterialDruckerPrager<2>;
+template class MaterialDruckerPrager<3>;
+static bool material_is_allocated_plastic_drucker_prager =
+ instantiateMaterial<MaterialDruckerPrager>("plastic_drucker_prager");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.hh b/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.hh
index 228f4deae..1a98569e4 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager.hh
@@ -1,141 +1,121 @@
/**
* @file material_drucker_prager.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Apr 06 2021
*
* @brief Specialization of the material class for isotropic
* plasticity with Drucker-Pruger yield criterion
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_voigthelper.hh"
#include "material_plastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_MATERIAL_DRUCKER_PRAGER_HH__
#define __AKANTU_MATERIAL_DRUCKER_PRAGER_HH__
namespace akantu {
/**
* Material plastic with a Drucker-pruger yield criterion
*/
-template <UInt spatial_dimension>
-class MaterialDruckerPrager : public MaterialPlastic<spatial_dimension> {
+template <Int dim> class MaterialDruckerPrager : public MaterialPlastic<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
+ using Parent = MaterialPlastic<dim>;
+
public:
MaterialDruckerPrager(SolidMechanicsModel & model, const ID & id = "");
- MaterialDruckerPrager(SolidMechanicsModel & model, UInt dim,
+ MaterialDruckerPrager(SolidMechanicsModel & model, Int spatial_dimension,
const Mesh & mesh, FEEngine & fe_engine,
const ID & id = "");
protected:
- using voigt_h = VoigtHelper<spatial_dimension>;
+ using voigt_h = VoigtHelper<dim>;
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
- /// compute the tangent stiffness matrix for an element type
- void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
- GhostType ghost_type = _not_ghost) override;
-
protected:
- /// Infinitesimal deformations
- inline void
- computeStressOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain,
- const Real & sigma_th, const Real & previous_sigma_th);
-
- /// Finite deformations
- inline void computeStressOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain, const Real & sigma_th,
- const Real & previous_sigma_th, const Matrix<Real> & F_tensor);
-
+ template <class Args> inline void computeStressOnQuad(Args && args);
inline void computeTangentModuliOnQuad(
Matrix<Real> & tangent, const Matrix<Real> & grad_u,
const Matrix<Real> & previous_grad_u, const Matrix<Real> & sigma_tensor,
const Matrix<Real> & previous_sigma_tensor) const;
inline Real computeYieldFunction(const Matrix<Real> & sigma);
-
inline Real computeYieldStress(const Matrix<Real> & sigma);
- inline void computeDeviatoricStress(const Matrix<Real> & sigma,
- Matrix<Real> & sigma_dev);
-
/// rcompute the alpha and k parameters
void updateInternalParameters() override;
public:
// closet point projection method to compute stress state on the
// yield surface
+ template <typename D1, typename D2, typename D3,
+ aka::enable_if_t<aka::are_vectors_v<D2, D3>> * = nullptr>
inline void computeGradientAndPlasticMultplier(
- const Matrix<Real> & sigma_tr, Real & plastic_multiplier_guess,
- Vector<Real> & gradient_f, Vector<Real> & delta_inelastic_strain,
- UInt max_iterations = 100, Real tolerance = 1e-10);
+ const Eigen::MatrixBase<D1> & sigma_trial,
+ Real & plastic_multiplier_guess, Eigen::MatrixBase<D2> & gradient_f,
+ Eigen::MatrixBase<D3> & delta_inelastic_strain, Int max_iterations = 100,
+ Real tolerance = 1e-10);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
// Internal friction angle of the material
Real phi;
// Compressive strength of the material
Real fc;
// modified friction angle for Drucker-Prager
Real alpha;
// modified compressive strength for Drucker-Prager
Real k;
// radial return mapping
bool radial_return_mapping;
};
} // namespace akantu
#include "material_drucker_prager_inline_impl.hh"
#endif /*__AKANTU_MATERIAL_DRUCKER_PRAGER_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh b/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh
index 125c71dbc..20098e47a 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh
@@ -1,471 +1,347 @@
/**
* @file material_drucker_prager_inline_impl.hh
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sat Sep 12 2020
* @date last modification: Tue Apr 06 2021
*
* @brief Implementation of the inline functions of the material
* Drucker-Prager
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "material_drucker_prager.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
/// Deviatoric Stress
-template <UInt dim>
-inline void
-MaterialDruckerPrager<dim>::computeDeviatoricStress(const Matrix<Real> & sigma,
- Matrix<Real> & sigma_dev) {
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- sigma_dev(i, j) = sigma(i, j);
- }
- }
-
- sigma_dev -= Matrix<Real>::eye(dim, sigma.trace() / dim);
-}
/* -------------------------------------------------------------------------- */
/// Yield Stress
-template <UInt dim>
+template <Int dim>
inline Real
MaterialDruckerPrager<dim>::computeYieldStress(const Matrix<Real> & sigma) {
return this->alpha * sigma.trace() - this->k;
}
/* -------------------------------------------------------------------------- */
/// Yield function
-template <UInt dim>
+template <Int dim>
inline Real
MaterialDruckerPrager<dim>::computeYieldFunction(const Matrix<Real> & sigma) {
- Matrix<Real> sigma_dev(dim, dim, 0);
- this->computeDeviatoricStress(sigma, sigma_dev);
+ Matrix<Real, dim, dim> sigma_dev = Material::computeDeviatoric<dim>(sigma);
// compute deviatoric invariant J2
- Real j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
- Real sigma_dev_eff = std::sqrt(3. * j2);
+ auto j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
+ auto sigma_dev_eff = std::sqrt(3. * j2);
- Real modified_yield_stress = computeYieldStress(sigma);
+ auto modified_yield_stress = computeYieldStress(sigma);
return sigma_dev_eff + modified_yield_stress;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
+template <typename D1, typename D2, typename D3,
+ aka::enable_if_t<aka::are_vectors_v<D2, D3>> *>
inline void MaterialDruckerPrager<dim>::computeGradientAndPlasticMultplier(
- const Matrix<Real> & sigma_trial, Real & plastic_multiplier_guess,
- Vector<Real> & gradient_f, Vector<Real> & delta_inelastic_strain,
- UInt max_iterations, Real tolerance) {
+ const Eigen::MatrixBase<D1> & sigma_trial, Real & plastic_multiplier_guess,
+ Eigen::MatrixBase<D2> & gradient_f,
+ Eigen::MatrixBase<D3> & delta_inelastic_strain, Int max_iterations,
+ Real tolerance) {
- UInt size = voigt_h::size;
+ const Int size = voigt_h::size;
// guess stress state at each iteration, initial guess is the trial state
- Matrix<Real> sigma_guess(sigma_trial);
+ Matrix<Real, dim, dim> sigma_guess(sigma_trial);
// plastic multiplier guess at each iteration, initial guess is zero
plastic_multiplier_guess = 0.;
// gradient of yield surface in voigt notation
gradient_f.zero();
// plastic strain increment at each iteration
delta_inelastic_strain.zero();
// variation in sigma at each iteration
- Vector<Real> delta_sigma(size, 0.);
+ Vector<Real, size> delta_sigma;
// krocker delta vector in voigt notation
- Vector<Real> kronecker_delta(size, 0.);
- for (auto i : arange(dim)) {
- kronecker_delta[i] = 1.;
- }
+ Vector<Real, size> kronecker_delta;
+ kronecker_delta.template block<dim, 1>(0, 0).fill(1.);
// hessian matrix of yield surface
- Matrix<Real> hessian_f(size, size, 0.);
+ Matrix<Real, size, size> hessian_f;
// scaling matrix for computing gradient and hessian from voigt notation
- Matrix<Real> scaling_matrix(size, size, 0.);
- scaling_matrix.eye(1.);
- for (auto i : arange(dim, size)) {
- for (auto j : arange(dim, size)) {
- scaling_matrix(i, j) *= 2.;
- }
- }
+ Matrix<Real, size, size> scaling_matrix =
+ Matrix<Real, size, size>::Identity();
+ scaling_matrix.template block<dim, dim>(0, 0) =
+ scaling_matrix.template block<dim, dim>(0, 0) * 2;
// elastic stifnness tensor
- Matrix<Real> De(size, size, 0.);
- MaterialElastic<dim>::computeTangentModuliOnQuad(De);
+ Matrix<Real, size, size> De;
+ MaterialElastic<dim>::computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = De));
// elastic compliance tensor
- Matrix<Real> Ce(size, size, 0.);
- Ce.inverse(De);
+ Matrix<Real, size, size> Ce = De.inverse();
// objective function to be computed
- Vector<Real> f(size, 0.);
+ Vector<Real, size> f;
+ f.zero();
// yield function value at each iteration
Real yield_function;
// if sigma is above the threshold value
auto above_threshold = [&sigma_guess](Real & k, Real & alpha) {
- Real I1 = sigma_guess.trace();
-
+ auto I1 = sigma_guess.trace();
return I1 >= k / alpha;
};
// to project stress state at origin of yield function if first
// invariant is greater than the threshold
if (above_threshold(k, alpha) and this->alpha > 0) {
-
auto update_first_obj = [&sigma_guess]() {
- // const UInt dimension = sigma_guess.cols();
-
- Matrix<Real> sigma_dev(dim, dim, 0);
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- sigma_dev(i, j) = sigma_guess(i, j);
- }
- }
-
- sigma_dev -= Matrix<Real>::eye(dim, sigma_guess.trace() / dim);
-
+ auto sigma_dev = Material::computeDeviatoric<dim>(sigma_guess);
auto error = (1. / 2) * sigma_dev.doubleDot(sigma_dev);
return error;
};
auto update_sec_obj = [&sigma_guess](Real & k, Real & alpha) {
auto error = alpha * sigma_guess.trace() - k;
return error;
};
auto projection_error = update_first_obj();
while (tolerance < projection_error) {
+ auto sigma_dev = Material::computeDeviatoric<dim>(sigma_guess);
- Matrix<Real> delta_sigma(dim, dim);
-
- Matrix<Real> jacobian(dim, dim);
- Matrix<Real> jacobian_inv(dim, dim);
-
- Matrix<Real> sigma_dev(dim, dim, 0);
- this->computeDeviatoricStress(sigma_guess, sigma_dev);
-
- jacobian_inv.inverse(sigma_dev);
-
- delta_sigma = -projection_error * jacobian_inv;
- sigma_guess += delta_sigma;
+ sigma_guess += -projection_error * sigma_dev.inverse();
projection_error = update_first_obj();
}
projection_error = update_sec_obj(k, alpha);
while (tolerance < projection_error) {
-
- Matrix<Real> delta_sigma(dim, dim);
- Matrix<Real> jacobian(dim, dim);
- Matrix<Real> jacobian_inv(dim, dim);
-
- jacobian = this->alpha * Matrix<Real>::eye(dim, dim);
- jacobian_inv.inverse(jacobian);
-
- delta_sigma += -projection_error * jacobian_inv;
- sigma_guess += delta_sigma;
+ sigma_guess += -projection_error * 1. / this->alpha *
+ Matrix<Real, dim, dim>::Identity();
projection_error = update_sec_obj(k, alpha);
}
auto delta_sigma_final = sigma_trial - sigma_guess;
auto delta_sigma_voigt = voigt_h::matrixToVoigt(delta_sigma_final);
- delta_inelastic_strain.mul<false>(Ce, delta_sigma_voigt);
+ delta_inelastic_strain = Ce * delta_sigma_voigt;
return;
}
// lambda function to compute gradient of yield surface in voigt notation
auto compute_gradient_f = [&sigma_guess, &scaling_matrix, &kronecker_delta,
&gradient_f](Real & alpha) {
- // const UInt dimension = sigma_guess.cols();
-
- Matrix<Real> sigma_dev(dim, dim, 0);
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- sigma_dev(i, j) = sigma_guess(i, j);
- }
- }
-
- sigma_dev -= Matrix<Real>::eye(dim, sigma_guess.trace() / dim);
-
+ auto sigma_dev = Material::computeDeviatoric<dim>(sigma_guess);
Vector<Real> sigma_dev_voigt = voigt_h::matrixToVoigt(sigma_dev);
// compute deviatoric invariant
- Real j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
+ auto j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
- gradient_f.mul<false>(scaling_matrix, sigma_dev_voigt,
- 3. / (2. * std::sqrt(3. * j2)));
- gradient_f += alpha * kronecker_delta;
+ gradient_f =
+ scaling_matrix * sigma_dev_voigt * 3. / (2. * std::sqrt(3. * j2)) +
+ alpha * kronecker_delta;
};
// lambda function to compute hessian matrix of yield surface
auto compute_hessian_f = [&sigma_guess, &hessian_f, &scaling_matrix,
&kronecker_delta]() {
- Matrix<Real> sigma_dev(dim, dim, 0);
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- sigma_dev(i, j) = sigma_guess(i, j);
- }
- }
-
- sigma_dev -= Matrix<Real>::eye(dim, sigma_guess.trace() / dim);
-
+ const Int size = voigt_h::size;
+ auto sigma_dev = Material::computeDeviatoric<dim>(sigma_guess);
auto sigma_dev_voigt = voigt_h::matrixToVoigt(sigma_dev);
// compute deviatoric invariant J2
- Real j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
+ auto j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
- Vector<Real> temp(sigma_dev_voigt.size());
- temp.mul<false>(scaling_matrix, sigma_dev_voigt);
+ auto temp = scaling_matrix * sigma_dev_voigt;
- Matrix<Real> id(kronecker_delta.size(), kronecker_delta.size());
- id.outerProduct(kronecker_delta, kronecker_delta);
- id *= -1. / 3.;
- id += Matrix<Real>::eye(kronecker_delta.size(), 1.);
+ auto id = -kronecker_delta * kronecker_delta.transpose() / 3. +
+ Matrix<Real, size, size>::Identity();
- Matrix<Real> tmp3(kronecker_delta.size(), kronecker_delta.size());
- tmp3.mul<false, false>(scaling_matrix, id);
- hessian_f.outerProduct(temp, temp);
- hessian_f *= -9. / (4. * pow(3. * j2, 3. / 2.));
- hessian_f += (3. / (2. * pow(3. * j2, 1. / 2.))) * tmp3;
+ hessian_f =
+ temp * temp.transpose() * -9. / (4. * std::pow(3. * j2, 3. / 2.)) +
+ +(3. / (2. * std::pow(3. * j2, 1. / 2.))) * scaling_matrix * id;
};
/* --------------------------- */
/* init before iteration loop */
/* --------------------------- */
auto update_f = [&f, &sigma_guess, &sigma_trial, &plastic_multiplier_guess,
&Ce, &De, &yield_function, &gradient_f,
&delta_inelastic_strain,
&compute_gradient_f](Real & k, Real & alpha) {
// compute gradient
compute_gradient_f(alpha);
// compute yield function
- Matrix<Real> sigma_dev(dim, dim, 0);
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- sigma_dev(i, j) = sigma_guess(i, j);
- }
- }
+ auto sigma_dev = Material::computeDeviatoric<dim>(sigma_guess);
+ auto j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
+ auto sigma_dev_eff = std::sqrt(3. * j2);
- sigma_dev -= Matrix<Real>::eye(dim, sigma_guess.trace() / dim);
-
- Real j2 = (1. / 2.) * sigma_dev.doubleDot(sigma_dev);
- Real sigma_dev_eff = std::sqrt(3. * j2);
-
- Real modified_yield_stress = alpha * sigma_guess.trace() - k;
+ auto modified_yield_stress = alpha * sigma_guess.trace() - k;
yield_function = sigma_dev_eff + modified_yield_stress;
// compute increment strain
auto sigma_trial_voigt = voigt_h::matrixToVoigt(sigma_trial);
auto sigma_guess_voigt = voigt_h::matrixToVoigt(sigma_guess);
auto tmp = sigma_trial_voigt - sigma_guess_voigt;
- delta_inelastic_strain.mul<false>(Ce, tmp);
+ delta_inelastic_strain = Ce * tmp;
// compute objective function
- f.mul<false>(De, gradient_f, plastic_multiplier_guess);
+ f = De * gradient_f * plastic_multiplier_guess;
f = tmp - f;
// compute error
- auto error = std::max(f.norm<L_2>(), std::abs(yield_function));
+ auto error = std::max(f.norm(), std::abs(yield_function));
return error;
};
Real alpha_tmp{alpha};
Real k_tmp{k};
if (radial_return_mapping) {
alpha_tmp = 0;
k_tmp = std::abs(alpha * sigma_guess.trace() - k);
}
auto projection_error = update_f(k_tmp, alpha_tmp);
/* --------------------------- */
/* iteration loop */
/* --------------------------- */
+ Matrix<Real, size, size> xi;
+ Matrix<Real, size, size> xi_inv;
+ Vector<Real, size> tmp;
+ Vector<Real, size> tmp1;
+ Matrix<Real, size, size> tmp2;
- Matrix<Real> xi(size, size);
-
- Matrix<Real> xi_inv(size, size);
-
- Vector<Real> tmp(size);
-
- Vector<Real> tmp1(size);
-
- Matrix<Real> tmp2(size, size);
-
- UInt iterations{0};
+ Int iterations{0};
while (tolerance < projection_error and iterations < max_iterations) {
// compute hessian at previous step
compute_hessian_f();
// compute inverse matrix Xi
xi = Ce + plastic_multiplier_guess * hessian_f;
- // compute inverse matrix Xi
- xi_inv.inverse(xi);
-
- tmp.mul<false>(xi_inv, gradient_f);
+ xi_inv = xi.inverse();
+ tmp = xi_inv * gradient_f;
auto denominator = gradient_f.dot(tmp);
// compute plastic multplier guess
- tmp1.mul<false>(xi_inv, delta_inelastic_strain);
- plastic_multiplier_guess = gradient_f.dot(tmp1);
- plastic_multiplier_guess += yield_function;
- plastic_multiplier_guess /= denominator;
+ tmp1 = xi_inv * delta_inelastic_strain;
+ plastic_multiplier_guess =
+ (gradient_f.dot(tmp1) + yield_function) / denominator;
// compute delta sigma
- tmp2.outerProduct(tmp, tmp);
- tmp2 /= denominator;
-
- tmp2 = xi_inv - tmp2;
- delta_sigma.mul<false>(tmp2, delta_inelastic_strain);
-
- delta_sigma -= tmp * yield_function / denominator;
+ tmp2 = xi_inv - tmp * tmp.transpose() / denominator;
+ delta_sigma =
+ tmp2 * delta_inelastic_strain - tmp * yield_function / denominator;
// compute sigma_guess
- Matrix<Real> delta_sigma_mat(dim, dim);
+ Matrix<Real, dim, dim> delta_sigma_mat;
voigt_h::voigtToMatrix(delta_sigma, delta_sigma_mat);
sigma_guess += delta_sigma_mat;
projection_error = update_f(k_tmp, alpha_tmp);
iterations++;
}
}
/* -------------------------------------------------------------------------- */
/// Infinitesimal deformations
-template <UInt dim>
-inline void MaterialDruckerPrager<dim>::computeStressOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain, const Real & sigma_th,
- const Real & previous_sigma_th) {
+template <Int dim>
+template <class Args>
+inline void MaterialDruckerPrager<dim>::computeStressOnQuad(Args && args) {
+ const auto & grad_u = args["grad_u"_n];
+ const auto & previous_grad_u = args["previous_grad_u"_n];
+ const auto & previous_sigma = args["previous_sigma"_n];
+ const auto & sigma_th = args["sigma_th"_n];
+ const auto & previous_sigma_th = args["previous_sigma_th"_n];
Real delta_sigma_th = sigma_th - previous_sigma_th;
Matrix<Real> grad_delta_u(grad_u);
grad_delta_u -= previous_grad_u;
// Compute trial stress, sigma_tr
Matrix<Real> sigma_tr(dim, dim);
- MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr,
- delta_sigma_th);
+ MaterialElastic<dim>::computeStressOnQuad(
+ tuple::make_named_tuple("grad_u"_n = grad_delta_u, "sigma"_n = sigma_tr,
+ "sigma_th"_n = delta_sigma_th));
sigma_tr += previous_sigma;
- // Compute the yielding sress
- /*Real yield_stress = computeYieldStress(sigma_tr);
-
- Matrix<Real> sigma_tr_dev(dim, dim, 0);
- this->computeDeviatoricStress(sigma_tr, sigma_tr_dev);
-
- Real j2 = (1./ 2.) * sigma_tr_dev.doubleDot(sigma_tr_dev);
- Real sigma_tr_dev_eff = std::sqrt(3. * j2);
-
- bool initial_yielding = ((sigma_tr_dev_eff + yield_stress) > 0);*/
-
bool initial_yielding = (this->computeYieldFunction(sigma_tr) > 0);
// use closet point projection to compute the plastic multiplier and
// gradient and inealstic strain at the surface for the given trial stress
// state
- Matrix<Real> delta_inelastic_strain(dim, dim, 0.);
+ Matrix<Real, dim, dim> delta_inelastic_strain;
+ delta_inelastic_strain.zero();
if (initial_yielding) {
-
- UInt size = voigt_h::size;
+ constexpr auto size = voigt_h::size;
// plastic multiplier
Real dp{0.};
// gradient of yield surface in voigt notation
- Vector<Real> gradient_f(size, 0.);
+ Vector<Real, size> gradient_f;
// inelastic strain in voigt notation
- Vector<Real> delta_inelastic_strain_voigt(size, 0.);
+ Vector<Real, size> delta_inelastic_strain_voigt;
// compute using closet-point projection
this->computeGradientAndPlasticMultplier(sigma_tr, dp, gradient_f,
delta_inelastic_strain_voigt);
for (auto i : arange(dim, size)) {
delta_inelastic_strain_voigt[i] /= 2.;
}
voigt_h::voigtToMatrix(delta_inelastic_strain_voigt,
delta_inelastic_strain);
}
// Compute the increment in inelastic strain
-
MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(
- grad_delta_u, sigma, previous_sigma, inelastic_strain,
- previous_inelastic_strain, delta_inelastic_strain);
+ tuple::append(args, "delta_grad_u"_n = grad_delta_u,
+ "delta_inelastic_strain"_n = delta_inelastic_strain));
}
-/* -------------------------------------------------------------------------- */
-/// Finite deformations
-template <UInt dim>
-inline void MaterialDruckerPrager<dim>::computeStressOnQuad(
- __attribute__((unused)) const Matrix<Real> & grad_u,
- __attribute__((unused)) const Matrix<Real> & previous_grad_u,
- __attribute__((unused)) Matrix<Real> & sigma,
- __attribute__((unused)) const Matrix<Real> & previous_sigma,
- __attribute__((unused)) Matrix<Real> & inelastic_strain,
- __attribute__((unused)) const Matrix<Real> & previous_inelastic_strain,
- __attribute__((unused)) const Real & sigma_th,
- __attribute__((unused)) const Real & previous_sigma_th,
- __attribute__((unused)) const Matrix<Real> & F_tensor) {}
-
-/* -------------------------------------------------------------------------- */
-
-template <UInt dim>
-inline void MaterialDruckerPrager<dim>::computeTangentModuliOnQuad(
- __attribute__((unused)) Matrix<Real> & tangent,
- __attribute__((unused)) const Matrix<Real> & grad_u,
- __attribute__((unused)) const Matrix<Real> & previous_grad_u,
- __attribute__((unused)) const Matrix<Real> & sigma_tensor,
- __attribute__((unused)) const Matrix<Real> & previous_sigma_tensor) const {}
-
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
index 610229436..9a9397ae4 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
@@ -1,204 +1,107 @@
/**
* @file material_linear_isotropic_hardening.cc
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Benjamin Paccaud <benjamin.paccaud@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Apr 07 2014
* @date last modification: Fri Apr 09 2021
*
* @brief Specialization of the material class for isotropic finite deformation
* linear hardening plasticity
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_linear_isotropic_hardening.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-MaterialLinearIsotropicHardening<dim>::MaterialLinearIsotropicHardening(
- SolidMechanicsModel & model, const ID & id)
- : MaterialPlastic<dim>(model, id) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialLinearIsotropicHardening<spatial_dimension>::
- MaterialLinearIsotropicHardening(SolidMechanicsModel & model, UInt dim,
- const Mesh & mesh, FEEngine & fe_engine,
- const ID & id)
- : MaterialPlastic<spatial_dimension>(model, dim, mesh, fe_engine, id) {}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialLinearIsotropicHardening<spatial_dimension>::computeStress(
+template <Int dim>
+void MaterialLinearIsotropicHardening<dim>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
// NOLINTNEXTLINE(bugprone-parent-virtual-call)
- MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type);
-
- // infinitesimal and finite deformation
- auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
-
- auto previous_sigma_th_it =
- this->sigma_th.previous(el_type, ghost_type).begin();
-
- auto previous_gradu_it = this->gradu.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_stress_it = this->stress.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto inelastic_strain_it = this->inelastic_strain(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_inelastic_strain_it =
- this->inelastic_strain.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto iso_hardening_it = this->iso_hardening(el_type, ghost_type).begin();
-
- auto previous_iso_hardening_it =
- this->iso_hardening.previous(el_type, ghost_type).begin();
-
- //
- // Finite Deformations
- //
- if (this->finite_deformation) {
- auto previous_piola_kirchhoff_2_it =
- this->piola_kirchhoff_2.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto green_strain_it = this->green_strain(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- auto & inelastic_strain_tensor = *inelastic_strain_it;
- auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
- auto & previous_grad_u = *previous_gradu_it;
- auto & previous_sigma = *previous_piola_kirchhoff_2_it;
-
- auto & green_strain = *green_strain_it;
- this->template gradUToE<spatial_dimension>(grad_u, green_strain);
- Matrix<Real> previous_green_strain(spatial_dimension, spatial_dimension);
- this->template gradUToE<spatial_dimension>(previous_grad_u,
- previous_green_strain);
- Matrix<Real> F_tensor(spatial_dimension, spatial_dimension);
- this->template gradUToF<spatial_dimension>(grad_u, F_tensor);
-
- computeStressOnQuad(green_strain, previous_green_strain, sigma,
- previous_sigma, inelastic_strain_tensor,
- previous_inelastic_strain_tensor, *iso_hardening_it,
- *previous_iso_hardening_it, *sigma_th_it,
- *previous_sigma_th_it, F_tensor);
-
- ++sigma_th_it;
- ++inelastic_strain_it;
- ++iso_hardening_it;
- ++previous_sigma_th_it;
- //++previous_stress_it;
- ++previous_gradu_it;
- ++green_strain_it;
- ++previous_inelastic_strain_it;
- ++previous_iso_hardening_it;
- ++previous_piola_kirchhoff_2_it;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- }
- // Infinitesimal deformations
- else {
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- auto & inelastic_strain_tensor = *inelastic_strain_it;
- auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
- auto & previous_grad_u = *previous_gradu_it;
- auto & previous_sigma = *previous_stress_it;
-
- computeStressOnQuad(
- grad_u, previous_grad_u, sigma, previous_sigma, inelastic_strain_tensor,
- previous_inelastic_strain_tensor, *iso_hardening_it,
- *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it);
- ++sigma_th_it;
- ++inelastic_strain_it;
- ++iso_hardening_it;
- ++previous_sigma_th_it;
- ++previous_stress_it;
- ++previous_gradu_it;
- ++previous_inelastic_strain_it;
- ++previous_iso_hardening_it;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ MaterialThermal<dim>::computeStress(el_type, ghost_type);
+
+ if (this->finite_deformation) { // Finite deformation
+ for (auto && data :
+ zip(Parent::getArguments(el_type, ghost_type),
+ make_view<dim, dim>(this->green_strain(el_type, ghost_type)))) {
+ auto && args = std::get<0>(data);
+ auto & green_strain = std::get<1>(data);
+ auto & grad_u = args["grad_u"_n];
+ auto & previous_grad_u = args["previous_grad_u"_n];
+
+ Material::gradUToE<dim>(grad_u, green_strain);
+ Matrix<Real, dim, dim> previous_green_strain =
+ Material::gradUToE<dim>(previous_grad_u);
+ Matrix<Real, dim, dim> F_tensor = Material::gradUToF<dim>(grad_u);
+
+ computeStressOnQuad(tuple::append(
+ tuple::replace(tuple::replace(args, "grad_u"_n = green_strain),
+ "previous_grad_u"_n = previous_green_strain),
+ "F"_n = F_tensor));
+
+ computeStressOnQuad(args);
+ }
+ } else { // Infinitesimal deformations
+ for (auto && args : Parent::getArguments(el_type, ghost_type)) {
+ computeStressOnQuad(args);
+ }
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialLinearIsotropicHardening<spatial_dimension>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- auto previous_gradu_it = this->gradu.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_stress_it = this->stress.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
-
- auto iso_hardening = this->iso_hardening(el_type, ghost_type).begin();
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
-
- computeTangentModuliOnQuad(tangent, grad_u, *previous_gradu_it, sigma,
- *previous_stress_it, *iso_hardening);
-
- ++previous_gradu_it;
- ++previous_stress_it;
- ++iso_hardening;
-
- MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
+ for (auto && args :
+ Parent::getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
+ computeTangentModuliOnQuad(args);
+ }
this->was_stiffness_assembled = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(plastic_linear_isotropic_hardening,
- MaterialLinearIsotropicHardening);
+template class MaterialLinearIsotropicHardening<1>;
+template class MaterialLinearIsotropicHardening<2>;
+template class MaterialLinearIsotropicHardening<3>;
+static bool material_is_allocated_plastic_linear_isotropic_hardening =
+ instantiateMaterial<MaterialLinearIsotropicHardening>(
+ "plastic_linear_isotropic_hardening");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
index ca0eba853..8e907c8d7 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
@@ -1,115 +1,93 @@
/**
* @file material_linear_isotropic_hardening.hh
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Benjamin Paccaud <benjamin.paccaud@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Specialization of the material class for isotropic finite deformation
* linear hardening plasticity
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_voigthelper.hh"
#include "material_plastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH_
#define AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH_
namespace akantu {
/**
* Material plastic with a linear evolution of the yielding stress
*/
-template <UInt spatial_dimension>
-class MaterialLinearIsotropicHardening
- : public MaterialPlastic<spatial_dimension> {
+template <Int dim>
+class MaterialLinearIsotropicHardening : public MaterialPlastic<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
+ using Parent = MaterialPlastic<dim>;
+
public:
- MaterialLinearIsotropicHardening(SolidMechanicsModel & model,
- const ID & id = "");
- MaterialLinearIsotropicHardening(SolidMechanicsModel & model, UInt dim,
- const Mesh & mesh, FEEngine & fe_engine,
- const ID & id = "");
+ using Parent::Parent;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
protected:
/// Infinitesimal deformations
- inline void
- computeStressOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain,
- Real & iso_hardening, const Real & previous_iso_hardening,
- const Real & sigma_th, const Real & previous_sigma_th);
- /// Finite deformations
- inline void computeStressOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain, Real & iso_hardening,
- const Real & previous_iso_hardening, const Real & sigma_th,
- const Real & previous_sigma_th, const Matrix<Real> & F_tensor);
+ template <class Args,
+ std::enable_if_t<not named_tuple_t<Args>::has("F"_n)> * = nullptr>
+ inline void computeStressOnQuad(Args && arguments);
- inline void computeTangentModuliOnQuad(
- Matrix<Real> & tangent, const Matrix<Real> & grad_u,
- const Matrix<Real> & previous_grad_u, const Matrix<Real> & sigma_tensor,
- const Matrix<Real> & previous_sigma_tensor,
- const Real & iso_hardening) const;
+ /// Finite deformations
+ template <class Args,
+ std::enable_if_t<named_tuple_t<Args>::has("F"_n)> * = nullptr>
+ inline void computeStressOnQuad(Args && arguments);
- /* ------------------------------------------------------------------------ */
- /* Class Members */
- /* ------------------------------------------------------------------------ */
-private:
+ template <class Args>
+ inline void computeTangentModuliOnQuad(Args && arguments) const;
};
-/* -------------------------------------------------------------------------- */
-/* inline functions */
-/* -------------------------------------------------------------------------- */
} // namespace akantu
#include "material_linear_isotropic_hardening_inline_impl.hh"
#endif /* AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh
index ce203ae52..d4d209d1d 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh
@@ -1,302 +1,212 @@
/**
* @file material_linear_isotropic_hardening_inline_impl.hh
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Benjamin Paccaud <benjamin.paccaud@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Apr 07 2014
* @date last modification: Thu Feb 20 2020
*
* @brief Implementation of the inline functions of the material plasticity
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "material_linear_isotropic_hardening.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/// Infinitesimal deformations
-template <UInt dim>
-inline void MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain, Real & iso_hardening,
- const Real & previous_iso_hardening, const Real & sigma_th,
- const Real & previous_sigma_th) {
+template <Int dim>
+template <class Args, std::enable_if_t<not named_tuple_t<Args>::has("F"_n)> *>
+inline void
+MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(Args && args) {
+
+ Real delta_sigma_th = 0.;
+ if constexpr (named_tuple_t<Args>::has("sigma_th"_n)) {
+ delta_sigma_th = args["previous_sigma_th"_n] - args["sigma_th"_n];
+ }
- Real delta_sigma_th = sigma_th - previous_sigma_th;
+ auto && grad_u = args["grad_u"_n];
+ auto && previous_grad_u = args["previous_grad_u"_n];
+ auto && grad_delta_u = grad_u - previous_grad_u;
- Matrix<Real> grad_delta_u(grad_u);
- grad_delta_u -= previous_grad_u;
+ Matrix<Real, dim, dim> sigma_tr;
// Compute trial stress, sigma_tr
- Matrix<Real> sigma_tr(dim, dim);
- MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr,
- delta_sigma_th);
+ MaterialElastic<dim>::computeStressOnQuad(
+ tuple::make_named_tuple("grad_u"_n = grad_delta_u, "sigma"_n = sigma_tr,
+ "sigma_th"_n = delta_sigma_th));
+
+ auto && previous_sigma = args["previous_sigma"_n];
sigma_tr += previous_sigma;
// We need a full stress tensor, otherwise the VM stress is messed up
- Matrix<Real> sigma_tr_dev(3, 3, 0);
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- sigma_tr_dev(i, j) = sigma_tr(i, j);
- }
- }
+ Matrix<Real, 3, 3> sigma_tr_dev = Matrix<Real, 3, 3>::Zero();
+ sigma_tr_dev.block<dim, dim>(0, 0) = sigma_tr;
- sigma_tr_dev -= Matrix<Real>::eye(3, sigma_tr.trace() / 3.0);
+ sigma_tr_dev -= Matrix<Real, 3, 3>::Identity() * sigma_tr.trace() / 3.0;
// Compute effective deviatoric trial stress
- Real s = sigma_tr_dev.doubleDot(sigma_tr_dev);
- Real sigma_tr_dev_eff = std::sqrt(3. / 2. * s);
+ auto s = sigma_tr_dev.doubleDot(sigma_tr_dev);
+ auto sigma_tr_dev_eff = std::sqrt(3. / 2. * s);
- bool initial_yielding =
+ auto && iso_hardening = args["iso_hardening"_n];
+ auto initial_yielding =
((sigma_tr_dev_eff - iso_hardening - this->sigma_y) > 0);
- Real dp = (initial_yielding)
+ auto && previous_iso_hardening = args["previous_iso_hardening"_n];
+ auto dp = (initial_yielding)
? (sigma_tr_dev_eff - this->sigma_y - previous_iso_hardening) /
(3 * this->mu + this->h)
: 0;
iso_hardening = previous_iso_hardening + this->h * dp;
// Compute inelastic strain (ignore last components in 1-2D)
- Matrix<Real> delta_inelastic_strain(dim, dim, 0.);
- if (std::abs(sigma_tr_dev_eff) >
- sigma_tr_dev.norm<L_inf>() * Math::getTolerance()) {
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- delta_inelastic_strain(i, j) = sigma_tr_dev(i, j);
- }
- }
- delta_inelastic_strain *= 3. / 2. * dp / sigma_tr_dev_eff;
+ Matrix<Real, dim, dim> delta_inelastic_strain =
+ Matrix<Real, dim, dim>::Zero();
+ if (std::abs(sigma_tr_dev_eff) > sigma_tr_dev.norm() * Math::getTolerance()) {
+ delta_inelastic_strain =
+ sigma_tr_dev.block<dim, dim>(0, 0) * 3. / 2. * dp / sigma_tr_dev_eff;
}
MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(
- grad_delta_u, sigma, previous_sigma, inelastic_strain,
- previous_inelastic_strain, delta_inelastic_strain);
+ tuple::append(args, "delta_inelastic_strain"_n = delta_inelastic_strain));
}
/* -------------------------------------------------------------------------- */
/// Finite deformations
-template <UInt dim>
-inline void MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain, Real & iso_hardening,
- const Real & previous_iso_hardening, const Real & sigma_th,
- const Real & previous_sigma_th, const Matrix<Real> & F_tensor) {
+template <Int dim>
+template <class Args, std::enable_if_t<named_tuple_t<Args>::has("F"_n)> *>
+inline void
+MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(Args && args) {
// Finite plasticity
Real dp = 0.0;
Real d_dp = 0.0;
UInt n = 0;
- Real delta_sigma_th = sigma_th - previous_sigma_th;
+ Real delta_sigma_th = 0.;
+ if constexpr (named_tuple_t<Args>::has("sigma_th"_n)) {
+ delta_sigma_th = args["previous_sigma_th"_n] - args["sigma_th"_n];
+ }
- Matrix<Real> grad_delta_u(grad_u);
- grad_delta_u -= previous_grad_u;
+ auto && grad_u = args["grad_u"_n];
+ auto && previous_grad_u = args["previous_grad_u"_n];
+ auto && grad_delta_u = grad_u - previous_grad_u;
// Compute trial stress, sigma_tr
- Matrix<Real> sigma_tr(dim, dim);
- MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr,
- delta_sigma_th);
+ Matrix<Real, dim, dim> sigma_tr;
+ MaterialElastic<dim>::computeStressOnQuad(
+ tuple::make_named_tuple("grad_u"_n = grad_delta_u, "sigma"_n = sigma_tr,
+ "sigma_th"_n = delta_sigma_th));
+
+ auto && previous_sigma = args["previous_sigma"_n];
sigma_tr += previous_sigma;
// Compute deviatoric trial stress, sigma_tr_dev
- Matrix<Real> sigma_tr_dev(sigma_tr);
- sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0);
+ auto && sigma_tr_dev =
+ sigma_tr - Matrix<Real, dim, dim>::Identity() * sigma_tr.trace() / 3.0;
// Compute effective deviatoric trial stress
Real s = sigma_tr_dev.doubleDot(sigma_tr_dev);
Real sigma_tr_dev_eff = std::sqrt(3. / 2. * s);
+ auto && F = args["F"_n];
+
// compute the cauchy stress to apply the Von-Mises criterion
- Matrix<Real> cauchy_stress(dim, dim);
- Material::StoCauchy<dim>(F_tensor, sigma_tr, cauchy_stress);
- Matrix<Real> cauchy_stress_dev(cauchy_stress);
- cauchy_stress_dev -= Matrix<Real>::eye(dim, cauchy_stress.trace() / 3.0);
+ auto cauchy_stress = Material::StoCauchy<dim>(F, sigma_tr);
+
+ auto && cauchy_stress_dev =
+ cauchy_stress -
+ Matrix<Real, dim, dim>::Identity() * cauchy_stress.trace() / 3.0;
Real c = cauchy_stress_dev.doubleDot(cauchy_stress_dev);
Real cauchy_stress_dev_eff = std::sqrt(3. / 2. * c);
+ auto && iso_hardening = args["iso_hardening"_n];
+ auto && previous_iso_hardening = args["previous_iso_hardening"_n];
+
const Real iso_hardening_t = previous_iso_hardening;
iso_hardening = iso_hardening_t;
- // Loop for correcting stress based on yield function
-
- // F is written in terms of S
- // bool initial_yielding = ( (sigma_tr_dev_eff - iso_hardening -
- // this->sigma_y) > 0) ;
- // while ( initial_yielding && std::abs(sigma_tr_dev_eff - iso_hardening -
- // this->sigma_y) > Math::getTolerance() ) {
-
- // d_dp = (sigma_tr_dev_eff - 3. * this->mu *dp - iso_hardening -
- // this->sigma_y)
- // / (3. * this->mu + this->h);
-
- // //r = r + h * dp;
- // dp = dp + d_dp;
- // iso_hardening = iso_hardening_t + this->h * dp;
-
- // ++n;
-
- // /// TODO : explicit this criterion with an error message
- // if ((std::abs(d_dp) < 1e-9) || (n>50)){
- // AKANTU_DEBUG_INFO("convergence of increment of plastic strain. d_dp:"
- // << d_dp << "\tNumber of iteration:"<<n);
- // break;
- // }
- // }
// F is written in terms of cauchy stress
bool initial_yielding =
((cauchy_stress_dev_eff - iso_hardening - this->sigma_y) > 0);
while (initial_yielding && std::abs(cauchy_stress_dev_eff - iso_hardening -
this->sigma_y) > Math::getTolerance()) {
d_dp = (cauchy_stress_dev_eff - 3. * this->mu * dp - iso_hardening -
this->sigma_y) /
(3. * this->mu + this->h);
// r = r + h * dp;
dp = dp + d_dp;
iso_hardening = iso_hardening_t + this->h * dp;
++n;
/// TODO : explicit this criterion with an error message
if ((d_dp < 1e-5) || (n > 50)) {
AKANTU_DEBUG_INFO("convergence of increment of plastic strain. d_dp:"
<< d_dp << "\tNumber of iteration:" << n);
break;
}
}
// Update internal variable
- Matrix<Real> delta_inelastic_strain(dim, dim, 0.);
- if (std::abs(sigma_tr_dev_eff) >
- sigma_tr_dev.norm<L_inf>() * Math::getTolerance()) {
+ Matrix<Real, dim, dim> delta_inelastic_strain;
+ if (std::abs(sigma_tr_dev_eff) > sigma_tr_dev.norm() * Math::getTolerance()) {
// /// compute the direction of the plastic strain as \frac{\partial
// F}{\partial S} = \frac{3}{2J\sigma_{effective}}} Ft \sigma_{dev} F
- Matrix<Real> cauchy_dev_F(dim, dim);
- cauchy_dev_F.mul<false, false>(F_tensor, cauchy_stress_dev);
- Real J = F_tensor.det();
+ Matrix<Real, dim, dim> cauchy_dev_F;
+ cauchy_dev_F = F * cauchy_stress_dev;
+ Real J = F.determinant();
Real constant = not Math::are_float_equal(J, 0.) ? 1. / J : 0;
constant *= 3. * dp / (2. * cauchy_stress_dev_eff);
- delta_inelastic_strain.mul<true, false>(F_tensor, cauchy_dev_F, constant);
+ delta_inelastic_strain = F.transpose() * cauchy_dev_F * constant;
// Direction given by the piola kirchhoff deviatoric tensor \frac{\partial
// F}{\partial S} = \frac{3}{2\sigma_{effective}}}S_{dev}
// delta_inelastic_strain.copy(sigma_tr_dev);
// delta_inelastic_strain *= 3./2. * dp / sigma_tr_dev_eff;
+ } else {
+ delta_inelastic_strain.zero();
}
MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(
- grad_delta_u, sigma, previous_sigma, inelastic_strain,
- previous_inelastic_strain, delta_inelastic_strain);
+ tuple::append(args, "delta_inelastic_strain"_n = delta_inelastic_strain));
}
/* -------------------------------------------------------------------------- */
-
-template <UInt dim>
+template <Int dim>
+template <class Args>
inline void MaterialLinearIsotropicHardening<dim>::computeTangentModuliOnQuad(
- Matrix<Real> & tangent, __attribute__((unused)) const Matrix<Real> & grad_u,
- __attribute__((unused)) const Matrix<Real> & previous_grad_u,
- __attribute__((unused)) const Matrix<Real> & sigma_tensor,
- __attribute__((unused)) const Matrix<Real> & previous_sigma_tensor,
- __attribute__((unused)) const Real & iso_hardening) const {
- // Real r=iso_hardening;
-
- // Matrix<Real> grad_delta_u(grad_u);
- // grad_delta_u -= previous_grad_u;
-
- // //Compute trial stress, sigma_tr
- // Matrix<Real> sigma_tr(dim, dim);
- // MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr);
- // sigma_tr += previous_sigma_tensor;
-
- // // Compute deviatoric trial stress, sigma_tr_dev
- // Matrix<Real> sigma_tr_dev(sigma_tr);
- // sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0);
-
- // // Compute effective deviatoric trial stress
- // Real s = sigma_tr_dev.doubleDot(sigma_tr_dev);
- // Real sigma_tr_dev_eff=std::sqrt(3./2. * s);
-
- // // Compute deviatoric stress, sigma_dev
- // Matrix<Real> sigma_dev(sigma_tensor);
- // sigma_dev -= Matrix<Real>::eye(dim, sigma_tensor.trace() / 3.0);
-
- // // Compute effective deviatoric stress
- // s = sigma_dev.doubleDot(sigma_dev);
- // Real sigma_dev_eff = std::sqrt(3./2. * s);
-
- // Real xr = 0.0;
- // if(sigma_tr_dev_eff > sigma_dev_eff * Math::getTolerance())
- // xr = sigma_dev_eff / sigma_tr_dev_eff;
-
- // Real __attribute__((unused)) q = 1.5 * (1. / (1. + 3. * this->mu /
- // this->h) - xr);
-
- /*
- UInt cols = tangent.cols();
- UInt rows = tangent.rows();
-
- for (UInt m = 0; m < rows; ++m) {
- UInt i = VoigtHelper<dim>::vec[m][0];
- UInt j = VoigtHelper<dim>::vec[m][1];
-
- for (UInt n = 0; n < cols; ++n) {
- UInt k = VoigtHelper<dim>::vec[n][0];
- UInt l = VoigtHelper<dim>::vec[n][1];
- */
-
- // This section of the code is commented
- // There were some problems with the convergence of plastic-coupled
- // simulations with thermal expansion
- // XXX: DO NOT REMOVE
- /*if (((sigma_tr_dev_eff-iso_hardening-sigmay) > 0) && (xr > 0)) {
- tangent(m,n) =
- 2. * this->mu * q * (sigma_tr_dev (i,j) / sigma_tr_dev_eff) * (sigma_tr_dev
- (k,l) / sigma_tr_dev_eff) +
- (i==k) * (j==l) * 2. * this->mu * xr +
- (i==j) * (k==l) * (this->kpa - 2./3. * this->mu * xr);
- if ((m == n) && (m>=dim))
- tangent(m, n) = tangent(m, n) - this->mu * xr;
- } else {*/
- /*
- tangent(m,n) = (i==k) * (j==l) * 2. * this->mu +
- (i==j) * (k==l) * this->lambda;
- tangent(m,n) -= (m==n) * (m>=dim) * this->mu;
- */
- //}
- // correct tangent stiffness for shear component
- //}
- //}
- MaterialElastic<dim>::computeTangentModuliOnQuad(tangent);
+ Args && args) const {
+ // Initial tangent
+ MaterialElastic<dim>::computeTangentModuliOnQuad(args);
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
index 6148a975f..4868067a0 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
@@ -1,202 +1,162 @@
/**
* @file material_plastic.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Apr 07 2014
* @date last modification: Fri Apr 09 2021
*
* @brief Implemantation of the akantu::MaterialPlastic class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_plastic.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model,
const ID & id)
: MaterialElastic<spatial_dimension>(model, id),
iso_hardening("iso_hardening", *this),
inelastic_strain("inelastic_strain", *this),
plastic_energy("plastic_energy", *this),
d_plastic_energy("d_plastic_energy", *this) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model,
UInt dim, const Mesh & mesh,
FEEngine & fe_engine,
const ID & id)
: MaterialElastic<spatial_dimension>(model, dim, mesh, fe_engine, id),
iso_hardening("iso_hardening", *this, dim, fe_engine,
this->element_filter),
inelastic_strain("inelastic_strain", *this, dim, fe_engine,
this->element_filter),
plastic_energy("plastic_energy", *this, dim, fe_engine,
this->element_filter),
d_plastic_energy("d_plastic_energy", *this, dim, fe_engine,
this->element_filter) {
AKANTU_DEBUG_IN();
this->initialize();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialPlastic<spatial_dimension>::initialize() {
this->registerParam("h", h, Real(0.), _pat_parsable | _pat_modifiable,
"Hardening modulus");
this->registerParam("sigma_y", sigma_y, Real(0.),
_pat_parsable | _pat_modifiable, "Yield stress");
this->iso_hardening.initialize(1);
this->iso_hardening.initializeHistory();
this->plastic_energy.initialize(1);
this->d_plastic_energy.initialize(1);
this->use_previous_stress = true;
this->use_previous_gradu = true;
- this->use_previous_stress_thermal = true;
this->inelastic_strain.initialize(spatial_dimension * spatial_dimension);
this->inelastic_strain.initializeHistory();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
Real MaterialPlastic<spatial_dimension>::getEnergy(const std::string & type) {
if (type == "plastic") {
return getPlasticEnergy();
}
return MaterialElastic<spatial_dimension>::getEnergy(type);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
Real MaterialPlastic<spatial_dimension>::getPlasticEnergy() {
AKANTU_DEBUG_IN();
Real penergy = 0.;
- for (auto & type :
+ for (const auto & type :
this->element_filter.elementTypes(spatial_dimension, _not_ghost)) {
penergy +=
this->fem.integrate(plastic_energy(type, _not_ghost), type, _not_ghost,
this->element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return penergy;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialPlastic<spatial_dimension>::computePotentialEnergy(
- ElementType el_type) {
- AKANTU_DEBUG_IN();
-
- Array<Real>::scalar_iterator epot = this->potential_energy(el_type).begin();
-
- Array<Real>::const_iterator<Matrix<Real>> inelastic_strain_it =
- this->inelastic_strain(el_type).begin(spatial_dimension,
- spatial_dimension);
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
-
- Matrix<Real> elastic_strain(spatial_dimension, spatial_dimension);
- elastic_strain.copy(grad_u);
- elastic_strain -= *inelastic_strain_it;
-
- MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad(
- elastic_strain, sigma, *epot);
+template <Int dim>
+void MaterialPlastic<dim>::computePotentialEnergy(ElementType el_type) {
+ auto epot = this->potential_energy(el_type).begin();
- ++epot;
- ++inelastic_strain_it;
+ for (auto && args : getArguments(el_type)) {
+ Matrix<Real, dim, dim> elastic_strain =
+ args["grad_u"_n] - args["inelastic_strain"_n];
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ MaterialElastic<dim>::computePotentialEnergyOnQuad(
+ tuple::replace(args, "grad_u"_n = elastic_strain), *epot);
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialPlastic<spatial_dimension>::updateEnergies(ElementType el_type) {
- AKANTU_DEBUG_IN();
-
- MaterialElastic<spatial_dimension>::updateEnergies(el_type);
+template <Int dim>
+void MaterialPlastic<dim>::updateEnergies(ElementType el_type) {
+ MaterialElastic<dim>::updateEnergies(el_type);
- Array<Real>::iterator<> pe_it = this->plastic_energy(el_type).begin();
+ for (auto && args : zip_append(getArguments(el_type),
+ "pe"_n = this->plastic_energy(el_type),
+ "wp"_n = this->d_plastic_energy(el_type))) {
- Array<Real>::iterator<> wp_it = this->d_plastic_energy(el_type).begin();
+ Matrix<Real, dim, dim> delta_strain_it =
+ args["inelastic_strain"_n] - args["previous_inelastic_strain"_n];
- Array<Real>::iterator<Matrix<Real>> inelastic_strain_it =
- this->inelastic_strain(el_type).begin(spatial_dimension,
- spatial_dimension);
+ Matrix<Real, dim, dim> sigma_h = args["sigma"_n] + args["previous_sigma"_n];
- Array<Real>::iterator<Matrix<Real>> previous_inelastic_strain_it =
- this->inelastic_strain.previous(el_type).begin(spatial_dimension,
- spatial_dimension);
+ auto && wp = args["wp"_n];
+ wp = .5 * sigma_h.doubleDot(delta_strain_it);
- Array<Real>::matrix_iterator previous_sigma =
- this->stress.previous(el_type).begin(spatial_dimension,
- spatial_dimension);
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
-
- Matrix<Real> delta_strain_it(*inelastic_strain_it);
- delta_strain_it -= *previous_inelastic_strain_it;
-
- Matrix<Real> sigma_h(sigma);
- sigma_h += *previous_sigma;
-
- *wp_it = .5 * sigma_h.doubleDot(delta_strain_it);
-
- *pe_it += *wp_it;
-
- ++pe_it;
- ++wp_it;
- ++inelastic_strain_it;
- ++previous_inelastic_strain_it;
- ++previous_sigma;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ args["pe"_n] += wp;
+ }
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL_ONLY(MaterialPlastic);
+template class MaterialPlastic<1>;
+template class MaterialPlastic<2>;
+template class MaterialPlastic<3>;
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
index 7fc2c8357..6c5610c72 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
@@ -1,134 +1,159 @@
/**
* @file material_plastic.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Common interface for plastic materials
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_PLASTIC_HH_
#define AKANTU_MATERIAL_PLASTIC_HH_
namespace akantu {
/**
* Parent class for the plastic constitutive laws
* parameters in the material files :
* - h : Hardening parameter (default: 0)
* - sigmay : Yield stress
*/
-template <UInt dim> class MaterialPlastic : public MaterialElastic<dim> {
+template <Int dim> class MaterialPlastic : public MaterialElastic<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialPlastic(SolidMechanicsModel & model, const ID & id = "");
MaterialPlastic(SolidMechanicsModel & model, UInt a_dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id = "");
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/**
* @brief Return potential or plastic energy
*
* Plastic dissipated energy is integrated over time.
*/
Real getEnergy(const std::string & type) override;
/// Update the plastic energy for the current timestep
void updateEnergies(ElementType el_type) override;
/// Compute the true potential energy (w/ elastic strain)
void computePotentialEnergy(ElementType el_type) override;
protected:
/// compute the stress and inelastic strain for the quadrature point
- inline void computeStressAndInelasticStrainOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain,
- const Matrix<Real> & delta_inelastic_strain) const;
-
- inline void computeStressAndInelasticStrainOnQuad(
- const Matrix<Real> & delta_grad_u, Matrix<Real> & sigma,
- const Matrix<Real> & previous_sigma, Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain,
- const Matrix<Real> & delta_inelastic_strain) const;
+ template <class Args, std::enable_if_t<named_tuple_t<Args>::has(
+ "delta_grad_u"_n)> * = nullptr>
+ inline void computeStressAndInelasticStrainOnQuad(Args && args) const {
+ Matrix<Real, dim, dim> delta_grad_u_elastic =
+ args["delta_grad_u"_n] - args["delta_inelastic_strain"_n];
+
+ Matrix<Real, dim, dim> sigma_elastic;
+ MaterialElastic<dim>::computeStressOnQuad(tuple::make_named_tuple(
+ "grad_u"_n = delta_grad_u_elastic, "sigma"_n = sigma_elastic));
+
+ args["sigma"_n] = args["previous_sigma"_n] + sigma_elastic;
+
+ args["inelastic_strain"_n] =
+ args["previous_inelastic_strain"_n] + args["delta_inelastic_strain"_n];
+ }
+
+ template <class Args, std::enable_if_t<not named_tuple_t<Args>::has(
+ "delta_grad_u"_n)> * = nullptr>
+ inline void computeStressAndInelasticStrainOnQuad(Args && args) const {
+ Matrix<Real, dim, dim> delta_grad_u =
+ args["grad_u"_n] - args["previous_grad_u"_n];
+
+ computeStressAndInelasticStrainOnQuad(
+ tuple::append(args, "delta_grad_u"_n = delta_grad_u));
+ }
/// Get the integrated plastic energy for the time step
Real getPlasticEnergy();
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ MaterialElastic<dim>::getArguments(el_type, ghost_type),
+ "iso_hardening"_n = make_view(this->iso_hardening(el_type, ghost_type)),
+ "previous_iso_hardening"_n =
+ make_view(this->iso_hardening.previous(el_type, ghost_type)),
+ "inelastic_strain"_n =
+ make_view<dim, dim>(this->inelastic_strain(el_type, ghost_type)),
+ "previous_inelastic_strain"_n = make_view<dim, dim>(
+ this->inelastic_strain.previous(el_type, ghost_type)));
+ }
+
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// Yield stresss
Real sigma_y;
/// hardening modulus
Real h;
/// isotropic hardening, r
InternalField<Real> iso_hardening;
/// inelastic strain arrays ordered by element types (inelastic deformation)
InternalField<Real> inelastic_strain;
/// Plastic energy
InternalField<Real> plastic_energy;
/// @todo : add a coefficient beta that will multiply the plastic energy
/// increment
/// to compute the energy converted to heat
/// Plastic energy increment
InternalField<Real> d_plastic_energy;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
} // namespace akantu
-#include "material_plastic_inline_impl.hh"
#endif /* AKANTU_MATERIAL_PLASTIC_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.hh b/src/model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.hh
index e73b95db3..ef3ad38f2 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.hh
@@ -1,77 +1,42 @@
/**
* @file material_plastic_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Apr 07 2014
* @date last modification: Thu Feb 20 2020
*
* @brief Implementation of the inline functions of akantu::MaterialPlastic
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef MATERIAL_PLASTIC_INLINE_IMPL_H
#define MATERIAL_PLASTIC_INLINE_IMPL_H
#include "material_plastic.hh"
-namespace akantu {
-
-template <UInt dim>
-inline void MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(
- const Matrix<Real> & delta_grad_u, Matrix<Real> & sigma,
- const Matrix<Real> & previous_sigma, Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain,
- const Matrix<Real> & delta_inelastic_strain) const {
- Matrix<Real> grad_u_elastic(dim, dim);
- grad_u_elastic.copy(delta_grad_u);
- grad_u_elastic -= delta_inelastic_strain;
- Matrix<Real> sigma_elastic(dim, dim);
- MaterialElastic<dim>::computeStressOnQuad(grad_u_elastic, sigma_elastic);
- sigma.copy(previous_sigma);
- sigma += sigma_elastic;
- inelastic_strain.copy(previous_inelastic_strain);
- inelastic_strain += delta_inelastic_strain;
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, const Matrix<Real> & previous_sigma,
- Matrix<Real> & inelastic_strain,
- const Matrix<Real> & previous_inelastic_strain,
- const Matrix<Real> & delta_inelastic_strain) const {
- Matrix<Real> delta_grad_u(grad_u);
- delta_grad_u -= previous_grad_u;
-
- computeStressAndInelasticStrainOnQuad(
- delta_grad_u, sigma, previous_sigma, inelastic_strain,
- previous_inelastic_strain, delta_inelastic_strain);
-}
-
-} // namespace akantu
+namespace akantu {} // namespace akantu
#endif /* MATERIAL_PLASTIC_INLINE_IMPL_H */
diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc
index 4de1e3844..9f9316a14 100644
--- a/src/model/solid_mechanics/materials/material_thermal.cc
+++ b/src/model/solid_mechanics/materials/material_thermal.cc
@@ -1,97 +1,96 @@
/**
* @file material_thermal.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Specialization of the material class for the thermal material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_thermal.hh"
+/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialThermal<dim>::MaterialThermal(SolidMechanicsModel & model,
const ID & id)
: Material(model, id), delta_T("delta_T", *this),
- sigma_th("sigma_th", *this), use_previous_stress_thermal(false) {
+ sigma_th("sigma_th", *this) {
this->initialize();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialThermal<dim>::MaterialThermal(SolidMechanicsModel & model,
- UInt spatial_dimension, const Mesh & mesh,
+ Int spatial_dimension, const Mesh & mesh,
FEEngine & fe_engine, const ID & id)
: Material(model, spatial_dimension, mesh, fe_engine, id),
delta_T("delta_T", *this, dim, fe_engine, this->element_filter),
- sigma_th("sigma_th", *this, dim, fe_engine, this->element_filter),
- use_previous_stress_thermal(false) {
+ sigma_th("sigma_th", *this, dim, fe_engine, this->element_filter) {
this->initialize();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialThermal<dim>::initialize() {
+template <Int dim> void MaterialThermal<dim>::initialize() {
this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable,
"Young's modulus");
this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable,
"Poisson's ratio");
this->registerParam("alpha", alpha, Real(0.), _pat_parsable | _pat_modifiable,
"Thermal expansion coefficient");
this->registerParam("delta_T", delta_T, _pat_parsable | _pat_modifiable,
"Uniform temperature field");
delta_T.initialize(1);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void MaterialThermal<dim>::initMaterial() {
+template <Int dim> void MaterialThermal<dim>::initMaterial() {
sigma_th.initialize(1);
-
- if (use_previous_stress_thermal) {
- sigma_th.initializeHistory();
- }
+ sigma_th.initializeHistory();
Material::initMaterial();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialThermal<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
- for (auto && tuple : zip(this->delta_T(el_type, ghost_type),
- this->sigma_th(el_type, ghost_type))) {
- computeStressOnQuad(std::get<1>(tuple), std::get<0>(tuple));
+ auto && arguments = getArguments(el_type, ghost_type);
+ for (auto && args : arguments) {
+ computeStressOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
-INSTANTIATE_MATERIAL_ONLY(MaterialThermal);
+template class MaterialThermal<1>;
+template class MaterialThermal<2>;
+template class MaterialThermal<3>;
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_thermal.hh b/src/model/solid_mechanics/materials/material_thermal.hh
index d29b54b03..c45bdbf8c 100644
--- a/src/model/solid_mechanics/materials/material_thermal.hh
+++ b/src/model/solid_mechanics/materials/material_thermal.hh
@@ -1,110 +1,125 @@
/**
* @file material_thermal.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Material isotropic thermo-elastic
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_THERMAL_HH_
#define AKANTU_MATERIAL_THERMAL_HH_
namespace akantu {
-template <UInt dim> class MaterialThermal : public Material {
+template <Int dim> class MaterialThermal : public Material {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialThermal(SolidMechanicsModel & model, const ID & id = "");
- MaterialThermal(SolidMechanicsModel & model, UInt spatial_dimension,
+ MaterialThermal(SolidMechanicsModel & model, Int spatial_dimension,
const Mesh & mesh, FEEngine & fe_engine, const ID & id = "");
~MaterialThermal() override = default;
protected:
void initialize();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type, GhostType ghost_type) override;
/// local computation of thermal stress
- inline void computeStressOnQuad(Real & sigma, const Real & deltaT);
+ template <class Args> inline void computeStressOnQuad(Args && args);
/* ------------------------------------------------------------------------ */
+ decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) {
+ return zip_append(
+ Material::getArguments<dim>(el_type, ghost_type),
+ "delta_T"_n = make_view(this->delta_T(el_type, ghost_type)),
+ "sigma_th"_n = make_view(this->sigma_th(el_type, ghost_type)),
+ "previous_sigma_th"_n =
+ make_view(this->sigma_th.previous(el_type, ghost_type)));
+ }
+
+ decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrices,
+ ElementType el_type,
+ GhostType ghost_type) {
+ return Material::getArgumentsTangent<dim>(tangent_matrices, el_type,
+ ghost_type);
+ }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// Young modulus
Real E;
/// Poisson ratio
Real nu;
/// Thermal expansion coefficient
/// TODO : implement alpha as a matrix
Real alpha;
/// Temperature field
InternalField<Real> delta_T;
/// Current thermal stress
InternalField<Real> sigma_th;
-
- /// Tell if we need to use the previous thermal stress
- bool use_previous_stress_thermal;
};
/* ------------------------------------------------------------------------ */
/* Inline impl */
/* ------------------------------------------------------------------------ */
-template <UInt dim>
-inline void MaterialThermal<dim>::computeStressOnQuad(Real & sigma,
- const Real & deltaT) {
+template <Int dim>
+template <class Args>
+inline void MaterialThermal<dim>::computeStressOnQuad(Args && args) {
+ auto && sigma = args["sigma_th"_n];
+ auto && deltaT = args["delta_T"_n];
sigma = -this->E / (1. - 2. * this->nu) * this->alpha * deltaT;
}
template <>
-inline void MaterialThermal<1>::computeStressOnQuad(Real & sigma,
- const Real & deltaT) {
+template <class Args>
+inline void MaterialThermal<1>::computeStressOnQuad(Args && args) {
+ auto && sigma = args["sigma_th"_n];
+ auto && deltaT = args["delta_T"_n];
sigma = -this->E * this->alpha * deltaT;
}
} // namespace akantu
#endif /* AKANTU_MATERIAL_THERMAL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
index fec98196a..eacf7428b 100644
--- a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
+++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
@@ -1,318 +1,253 @@
/**
* @file material_standard_linear_solid_deviatoric.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Vladislav Yastrebov <vladislav.yastrebov@epfl.ch>
*
* @date creation: Wed May 04 2011
* @date last modification: Fri Apr 09 2021
*
* @brief Material Visco-elastic
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_standard_linear_solid_deviatoric.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
MaterialStandardLinearSolidDeviatoric<
dim>::MaterialStandardLinearSolidDeviatoric(SolidMechanicsModel & model,
const ID & id)
: MaterialElastic<dim>(model, id), stress_dev("stress_dev", *this),
history_integral("history_integral", *this),
dissipated_energy("dissipated_energy", *this) {
AKANTU_DEBUG_IN();
this->registerParam("Eta", eta, Real(1.), _pat_parsable | _pat_modifiable,
"Viscosity");
this->registerParam("Ev", Ev, Real(1.), _pat_parsable | _pat_modifiable,
"Stiffness of the viscous element");
this->registerParam("Einf", E_inf, Real(1.), _pat_readable,
"Stiffness of the elastic element");
- UInt stress_size = dim * dim;
+ auto stress_size = dim * dim;
this->stress_dev.initialize(stress_size);
this->history_integral.initialize(stress_size);
this->dissipated_energy.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::initMaterial() {
AKANTU_DEBUG_IN();
updateInternalParameters();
MaterialElastic<dim>::initMaterial();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::updateInternalParameters() {
MaterialElastic<dim>::updateInternalParameters();
E_inf = this->E - this->Ev;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::setToSteadyState(
ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type);
- Array<Real> & history_int_vect = history_integral(el_type, ghost_type);
-
- Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(dim, dim);
- Array<Real>::matrix_iterator history_int = history_int_vect.begin(dim, dim);
-
/// Loop on all quadrature points
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- Matrix<Real> & dev_s = *stress_d;
- Matrix<Real> & h = *history_int;
+ for (auto && args : this->getArguments(el_type, ghost_type)) {
+ const auto & grad_u = args["grad_u"_n];
+ auto & dev_s = args["sigma_dev"_n];
+ auto & h = args["history"_n];
- /// Compute the first invariant of strain
- Real Theta = grad_u.trace();
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- dev_s(i, j) = 2 * this->mu *
- (.5 * (grad_u(i, j) + grad_u(j, i)) -
- 1. / 3. * Theta * Math::kronecker(i, j));
- h(i, j) = 0.;
- }
- }
-
- /// Save the deviator of stress
- ++stress_d;
- ++history_int;
+ /// Compute the first invariant of strain
+ Real Theta = grad_u.trace();
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ dev_s = 2 * this->mu *
+ ((grad_u + grad_u.transpose()) / 2. -
+ Theta * Matrix<Real, dim, dim>::Identity() / 3.);
- AKANTU_DEBUG_OUT();
+ h.zero();
+ }
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::computeStress(
ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- Real tau = 0.;
- // if(std::abs(Ev) > std::numeric_limits<Real>::epsilon())
- tau = eta / Ev;
-
- Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type);
- Array<Real> & history_int_vect = history_integral(el_type, ghost_type);
-
- Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(dim, dim);
- Array<Real>::matrix_iterator history_int = history_int_vect.begin(dim, dim);
-
- Matrix<Real> s(dim, dim);
+ Real tau = eta / Ev;
Real dt = this->model.getTimeStep();
Real exp_dt_tau = exp(-dt / tau);
Real exp_dt_tau_2 = exp(-.5 * dt / tau);
- Matrix<Real> epsilon_v(dim, dim);
-
- /// Loop on all quadrature points
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- Matrix<Real> & dev_s = *stress_d;
- Matrix<Real> & h = *history_int;
-
- s.zero();
- sigma.zero();
+ Matrix<Real, dim, dim> s;
+ Matrix<Real, dim, dim> epsilon_d;
+ Matrix<Real, dim, dim> U_rond_prim;
/// Compute the first invariant of strain
- Real gamma_inf = E_inf / this->E;
- Real gamma_v = Ev / this->E;
+ auto gamma_inf = E_inf / this->E;
+ auto gamma_v = Ev / this->E;
- auto epsilon_d = this->template gradUToEpsilon<dim>(grad_u);
- Real Theta = epsilon_d.trace();
- epsilon_v.eye(Theta / Real(3.));
- epsilon_d -= epsilon_v;
+ auto && arguments = this->getArguments(el_type, ghost_type);
+ /// Loop on all quadrature points
+ for (auto && args : arguments) {
+ auto && grad_u = args["grad_u"_n];
+ auto && sigma = args["sigma"_n];
+ auto && dev_s = args["sigma_dev"_n];
+ auto && h = args["history"_n];
- Matrix<Real> U_rond_prim(dim, dim);
+ s.zero();
+ sigma.zero();
- U_rond_prim.eye(gamma_inf * this->kpa * Theta);
+ epsilon_d = this->template gradUToEpsilon<dim>(grad_u);
+ auto Theta = epsilon_d.trace();
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- s(i, j) = 2 * this->mu * epsilon_d(i, j);
- h(i, j) = exp_dt_tau * h(i, j) + exp_dt_tau_2 * (s(i, j) - dev_s(i, j));
- dev_s(i, j) = s(i, j);
- sigma(i, j) = U_rond_prim(i, j) + gamma_inf * s(i, j) + gamma_v * h(i, j);
- }
- }
+ epsilon_d -= Matrix<Real, dim, dim>::Identity() * Theta / 3.;
- /// Save the deviator of stress
- ++stress_d;
- ++history_int;
+ U_rond_prim =
+ Matrix<Real, dim, dim>::Identity() * gamma_inf * this->kpa * Theta;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ s = 2 * this->mu * epsilon_d;
+ h = exp_dt_tau * h + exp_dt_tau_2 * (s - dev_s);
+ dev_s = s;
+ sigma = U_rond_prim + gamma_inf * s + gamma_v * h;
+ }
this->updateDissipatedEnergy(el_type, ghost_type);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::updateDissipatedEnergy(
ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
+ Real tau = eta / Ev;
- // if(ghost_type == _ghost) return 0.;
+ Matrix<Real, dim, dim> q;
+ Matrix<Real, dim, dim> q_rate;
+ Matrix<Real, dim, dim> epsilon_d;
- Real tau = 0.;
- tau = eta / Ev;
- Real * dis_energy = dissipated_energy(el_type, ghost_type).storage();
+ auto dt = this->model.getTimeStep();
- Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type);
- Array<Real> & history_int_vect = history_integral(el_type, ghost_type);
+ auto gamma_v = Ev / this->E;
+ auto alpha = 1. / (2. * this->mu * gamma_v);
- Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(dim, dim);
- Array<Real>::matrix_iterator history_int = history_int_vect.begin(dim, dim);
+ for (auto && data : zip(this->getArguments(el_type, ghost_type),
+ dissipated_energy(el_type, ghost_type))) {
+ auto && args = std::get<0>(data);
+ auto & dis_energy = std::get<1>(data);
+ const auto & grad_u = args["grad_u"_n];
+ auto & dev_s = args["sigma_dev"_n];
+ auto & h = args["history"_n];
- Matrix<Real> q(dim, dim);
- Matrix<Real> q_rate(dim, dim);
- Matrix<Real> epsilon_d(dim, dim);
- Matrix<Real> epsilon_v(dim, dim);
+ /// Compute the first invariant of strain
+ epsilon_d = Material::gradUToEpsilon<dim>(grad_u);
- Real dt = this->model.getTimeStep();
-
- Real gamma_v = Ev / this->E;
- Real alpha = 1. / (2. * this->mu * gamma_v);
+ auto Theta = epsilon_d.trace();
+ epsilon_d -= Matrix<Real, dim, dim>::Identity() * Theta / 3.;
- /// Loop on all quadrature points
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
+ q = (dev_s - h) * gamma_v;
+ q_rate = (dev_s * gamma_v - q) / tau;
- Matrix<Real> & dev_s = *stress_d;
- Matrix<Real> & h = *history_int;
-
- /// Compute the first invariant of strain
- this->template gradUToEpsilon<dim>(grad_u, epsilon_d);
-
- Real Theta = epsilon_d.trace();
- epsilon_v.eye(Theta / Real(3.));
- epsilon_d -= epsilon_v;
-
- q.copy(dev_s);
- q -= h;
- q *= gamma_v;
-
- q_rate.copy(dev_s);
- q_rate *= gamma_v;
- q_rate -= q;
- q_rate /= tau;
-
- for (UInt i = 0; i < dim; ++i) {
- for (UInt j = 0; j < dim; ++j) {
- *dis_energy += (epsilon_d(i, j) - alpha * q(i, j)) * q_rate(i, j) * dt;
- }
+ dis_energy += ((epsilon_d - alpha * q) * q_rate * dt).sum();
}
-
- /// Save the deviator of stress
- ++stress_d;
- ++history_int;
- ++dis_energy;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
Real MaterialStandardLinearSolidDeviatoric<dim>::getDissipatedEnergy() const {
AKANTU_DEBUG_IN();
Real de = 0.;
/// integrate the dissipated energy for each type of elements
- for (auto & type : this->element_filter.elementTypes(dim, _not_ghost)) {
+ for (const auto & type : this->element_filter.elementTypes(dim, _not_ghost)) {
de +=
this->fem.integrate(dissipated_energy(type, _not_ghost), type,
_not_ghost, this->element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return de;
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
Real MaterialStandardLinearSolidDeviatoric<dim>::getDissipatedEnergy(
- ElementType type, UInt index) const {
+ const Element & element) const {
AKANTU_DEBUG_IN();
- UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
- auto it =
- this->dissipated_energy(type, _not_ghost).begin(nb_quadrature_points);
- UInt gindex = (this->element_filter(type, _not_ghost))(index);
+ auto nb_quadrature_points = this->fem.getNbIntegrationPoints(element.type);
+ auto it = this->dissipated_energy(element.type, _not_ghost)
+ .begin(nb_quadrature_points);
AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[index], type, gindex);
+ return this->fem.integrate(it[element.element], element);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
Real MaterialStandardLinearSolidDeviatoric<dim>::getEnergy(
const std::string & type) {
if (type == "dissipated") {
return getDissipatedEnergy();
}
if (type == "dissipated_sls_deviatoric") {
return getDissipatedEnergy();
}
return MaterialElastic<dim>::getEnergy(type);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
Real MaterialStandardLinearSolidDeviatoric<dim>::getEnergy(
- const std::string & energy_id, ElementType type, UInt index) {
+ const std::string & energy_id, const Element & element) {
if (energy_id == "dissipated") {
- return getDissipatedEnergy(type, index);
+ return getDissipatedEnergy(element);
}
if (energy_id == "dissipated_sls_deviatoric") {
- return getDissipatedEnergy(type, index);
+ return getDissipatedEnergy(element);
}
- return MaterialElastic<dim>::getEnergy(energy_id, type, index);
+ return Parent::getEnergy(energy_id, element);
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(sls_deviatoric, MaterialStandardLinearSolidDeviatoric);
+template class MaterialStandardLinearSolidDeviatoric<1>;
+template class MaterialStandardLinearSolidDeviatoric<2>;
+template class MaterialStandardLinearSolidDeviatoric<3>;
+static bool material_is_allocated_sls_deviatoric =
+ instantiateMaterial<MaterialStandardLinearSolidDeviatoric>(
+ "sls_deviatoric");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh
index d3799030b..0b14bd9c4 100644
--- a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh
+++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh
@@ -1,138 +1,148 @@
/**
* @file material_standard_linear_solid_deviatoric.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Vladislav Yastrebov <vladislav.yastrebov@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Feb 20 2020
*
* @brief Material Visco-elastic, based on Standard Solid rheological model,
* see
* [] J.C. Simo, T.J.R. Hughes, "Computational Inelasticity", Springer (1998),
* see Sections 10.2 and 10.3
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_STANDARD_LINEAR_SOLID_DEVIATORIC_HH_
#define AKANTU_MATERIAL_STANDARD_LINEAR_SOLID_DEVIATORIC_HH_
namespace akantu {
/**
* Material standard linear solid deviatoric
*
*
* @verbatim
E_\inf
------|\/\/\|------
| |
---| |---
| |
----|\/\/\|--[|----
E_v \eta
@endverbatim
*
* keyword : sls_deviatoric
*
* parameters in the material files :
* - E : Initial Young's modulus @f$ E = E_i + E_v @f$
* - eta : viscosity
* - Ev : stiffness of the viscous element
*/
-template <UInt spatial_dimension>
-class MaterialStandardLinearSolidDeviatoric
- : public MaterialElastic<spatial_dimension> {
+template <Int dim>
+class MaterialStandardLinearSolidDeviatoric : public MaterialElastic<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
+ using Parent = MaterialElastic<dim>;
+
public:
MaterialStandardLinearSolidDeviatoric(SolidMechanicsModel & model,
const ID & id = "");
~MaterialStandardLinearSolidDeviatoric() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material computed parameter
void initMaterial() override;
/// update the internal parameters (for modifiable parameters)
void updateInternalParameters() override;
/// set material to steady state
void setToSteadyState(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
+ inline decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ Parent::getArguments(el_type, ghost_type),
+ "sigma_dev"_n = make_view<dim, dim>(stress_dev(el_type, ghost_type)),
+ "history"_n =
+ make_view<dim, dim>(history_integral(el_type, ghost_type)));
+ }
+
protected:
/// update the dissipated energy, is called after the stress have been
/// computed
void updateDissipatedEnergy(ElementType el_type, GhostType ghost_type);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// give the dissipated energy for the time step
Real getDissipatedEnergy() const;
- Real getDissipatedEnergy(ElementType type, UInt index) const;
+ Real getDissipatedEnergy(const Element & element) const;
/// get the energy using an energy type string for the time step
Real getEnergy(const std::string & type) override;
- Real getEnergy(const std::string & energy_id, ElementType type,
- UInt index) override;
+ Real getEnergy(const std::string & energy_id,
+ const Element & element) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// viscosity, viscous elastic modulus
Real eta, Ev, E_inf;
Vector<Real> etas;
/// history of deviatoric stress
InternalField<Real> stress_dev;
/// Internal variable: history integral
InternalField<Real> history_integral;
/// Dissipated energy
InternalField<Real> dissipated_energy;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_STANDARD_LINEAR_SOLID_DEVIATORIC_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc b/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc
index 76dd3274c..bb794b1fc 100644
--- a/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc
+++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc
@@ -1,736 +1,633 @@
/**
* @file material_viscoelastic_maxwell.cc
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
*
* @date creation: Mon Jun 04 2018
* @date last modification: Fri Apr 09 2021
*
* @brief Material Visco-elastic, based on Maxwell chain,
* see
* [] R. de Borst and A.H. van den Boogaard "Finite-element modeling of
* deformation and cracking in early-age concrete", J.Eng.Mech., 1994
* as well as
* [] Manual of DIANA FEA Theory manual v.10.2 Section 37.6
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_viscoelastic_maxwell.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialViscoelasticMaxwell<spatial_dimension>::MaterialViscoelasticMaxwell(
+template <Int dim>
+MaterialViscoelasticMaxwell<dim>::MaterialViscoelasticMaxwell(
SolidMechanicsModel & model, const ID & id)
- : MaterialElastic<spatial_dimension>(model, id),
- C(voigt_h::size, voigt_h::size), D(voigt_h::size, voigt_h::size),
- sigma_v("sigma_v", *this), epsilon_v("epsilon_v", *this),
+ : MaterialElastic<dim>(model, id), C(voigt_h::size, voigt_h::size),
+ D(voigt_h::size, voigt_h::size), sigma_v("sigma_v", *this),
+ epsilon_v("epsilon_v", *this),
dissipated_energy("dissipated_energy", *this),
mechanical_work("mechanical_work", *this) {
AKANTU_DEBUG_IN();
this->registerParam("Einf", Einf, Real(1.), _pat_parsable | _pat_modifiable,
"Stiffness of the elastic element");
this->registerParam("previous_dt", previous_dt, Real(0.), _pat_readable,
"Time step of previous solveStep");
this->registerParam("Eta", Eta, _pat_parsable | _pat_modifiable,
"Viscosity of a Maxwell element");
this->registerParam("Ev", Ev, _pat_parsable | _pat_modifiable,
"Stiffness of a Maxwell element");
this->update_variable_flag = true;
this->use_previous_stress = true;
this->use_previous_gradu = true;
- this->use_previous_stress_thermal = true;
this->dissipated_energy.initialize(1);
this->mechanical_work.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::initMaterial() {
+template <Int dim> void MaterialViscoelasticMaxwell<dim>::initMaterial() {
AKANTU_DEBUG_IN();
- this->E = Einf + Ev.norm<L_1>();
+ this->E = Einf + Ev.lpNorm<1>();
// this->E = std::min(this->Einf, this->Ev(0));
- MaterialElastic<spatial_dimension>::initMaterial();
+ MaterialElastic<dim>::initMaterial();
+
AKANTU_DEBUG_ASSERT(this->Eta.size() == this->Ev.size(),
"Eta and Ev have different dimensions! Please correct.");
AKANTU_DEBUG_ASSERT(
!this->finite_deformation,
"Current material works only in infinitesimal deformations.");
- UInt stress_size = spatial_dimension * spatial_dimension;
+ UInt stress_size = dim * dim;
this->sigma_v.initialize(stress_size * this->Ev.size());
this->epsilon_v.initialize(stress_size * this->Ev.size());
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<
- spatial_dimension>::updateInternalParameters() {
- MaterialElastic<spatial_dimension>::updateInternalParameters();
-
- Real pre_mult = 1 / (1 + this->nu) / (1 - 2 * this->nu);
- UInt n = voigt_h::size;
- Real Miiii = pre_mult * (1 - this->nu);
- Real Miijj = pre_mult * this->nu;
- Real Mijij = pre_mult * 0.5 * (1 - 2 * this->nu);
-
- Real Diiii = 1;
- Real Diijj = -this->nu;
- Real Dijij = (2 + 2 * this->nu);
-
- if (spatial_dimension == 1) {
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::updateInternalParameters() {
+ MaterialElastic<dim>::updateInternalParameters();
+
+ [[maybe_unused]] auto pre_mult = 1 / (1 + this->nu) / (1 - 2 * this->nu);
+
+ [[maybe_unused]] auto Miiii = pre_mult * (1 - this->nu);
+ [[maybe_unused]] auto Miijj = pre_mult * this->nu;
+ [[maybe_unused]] auto Mijij = pre_mult * 0.5 * (1 - 2 * this->nu);
+
+ [[maybe_unused]] auto Diiii = 1;
+ [[maybe_unused]] auto Diijj = -this->nu;
+ [[maybe_unused]] auto Dijij = (2 + 2 * this->nu);
+
+ C.zero();
+ D.zero();
+
+ if constexpr (dim == 1) {
C(0, 0) = 1;
D(0, 0) = 1;
} else {
C(0, 0) = Miiii;
D(0, 0) = Diiii;
}
- if (spatial_dimension >= 2) {
+ if constexpr (dim >= 2) {
+ auto n = voigt_h::size;
C(1, 1) = Miiii;
C(0, 1) = Miijj;
C(1, 0) = Miijj;
C(n - 1, n - 1) = Mijij;
D(1, 1) = Diiii;
D(0, 1) = Diijj;
D(1, 0) = Diijj;
D(n - 1, n - 1) = Dijij;
}
- if (spatial_dimension == 3) {
+ if constexpr (dim == 3) {
C(2, 2) = Miiii;
C(0, 2) = Miijj;
C(1, 2) = Miijj;
C(2, 0) = Miijj;
C(2, 1) = Miijj;
C(3, 3) = Mijij;
C(4, 4) = Mijij;
D(2, 2) = Diiii;
D(0, 2) = Diijj;
D(1, 2) = Diijj;
D(2, 0) = Diijj;
D(2, 1) = Diijj;
D(3, 3) = Dijij;
D(4, 4) = Dijij;
}
}
/* -------------------------------------------------------------------------- */
-template <> void MaterialViscoelasticMaxwell<2>::updateInternalParameters() {
- MaterialElastic<2>::updateInternalParameters();
-
- Real pre_mult = 1 / (1 + this->nu) / (1 - 2 * this->nu);
- UInt n = voigt_h::size;
- Real Miiii = pre_mult * (1 - this->nu);
- Real Miijj = pre_mult * this->nu;
- Real Mijij = pre_mult * 0.5 * (1 - 2 * this->nu);
-
- Real Diiii = 1;
- Real Diijj = -this->nu;
- Real Dijij = (2 + 2 * this->nu);
-
- C(0, 0) = Miiii;
- C(1, 1) = Miiii;
- C(0, 1) = Miijj;
- C(1, 0) = Miijj;
- C(n - 1, n - 1) = Mijij;
-
- D(0, 0) = Diiii;
- D(1, 1) = Diiii;
- D(0, 1) = Diijj;
- D(1, 0) = Diijj;
- D(n - 1, n - 1) = Dijij;
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::computeStress(
- ElementType el_type, GhostType ghost_type) {
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::computeStress(ElementType el_type,
+ GhostType ghost_type) {
AKANTU_DEBUG_IN();
// NOLINTNEXTLINE(bugprone-parent-virtual-call)
- MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type);
+ MaterialThermal<dim>::computeStress(el_type, ghost_type);
auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
- auto previous_gradu_it = this->gradu.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
+ auto previous_gradu_it =
+ make_view<dim, dim>(this->gradu.previous(el_type, ghost_type)).begin();
- auto previous_stress_it = this->stress.previous(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension);
+ auto previous_stress_it =
+ make_view<dim, dim>(this->stress.previous(el_type, ghost_type)).begin();
auto sigma_v_it =
- this->sigma_v(el_type, ghost_type)
- .begin(spatial_dimension, spatial_dimension, this->Eta.size());
+ make_view(this->sigma_v(el_type, ghost_type), dim, dim, this->Eta.size())
+ .begin();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
computeStressOnQuad(grad_u, *previous_gradu_it, sigma, *sigma_v_it,
*sigma_th_it);
+
++sigma_th_it;
++previous_gradu_it;
++sigma_v_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::computeStressOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, Tensor3<Real> & sigma_v, const Real & sigma_th) {
-
+template <Int dim>
+template <typename D1, typename D2, typename D3>
+void MaterialViscoelasticMaxwell<dim>::computeStressOnQuad(
+ const Eigen::MatrixBase<D1> & grad_u,
+ const Eigen::MatrixBase<D2> & previous_grad_u,
+ Eigen::MatrixBase<D3> & sigma, Tensor3Proxy<Real> & sigma_v,
+ const Real & sigma_th) {
+ Real dt = this->model.getTimeStep();
// Wikipedia convention:
// 2*eps_ij (i!=j) = voigt_eps_I
// http://en.wikipedia.org/wiki/Voigt_notation
- Vector<Real> voigt_current_strain(voigt_h::size);
- Vector<Real> voigt_previous_strain(voigt_h::size);
- Vector<Real> voigt_stress(voigt_h::size);
- Vector<Real> voigt_sigma_v(voigt_h::size);
-
- for (UInt I = 0; I < voigt_h::size; ++I) {
- Real voigt_factor = voigt_h::factors[I];
- UInt i = voigt_h::vec[I][0];
- UInt j = voigt_h::vec[I][1];
-
- voigt_current_strain(I) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.;
- voigt_previous_strain(I) =
- voigt_factor * (previous_grad_u(i, j) + previous_grad_u(j, i)) / 2.;
- }
+ auto voigt_current_strain =
+ Material::strainToVoigt<dim>(Material::gradUToEpsilon<dim>(grad_u));
+ auto voigt_previous_strain = Material::strainToVoigt<dim>(
+ Material::gradUToEpsilon<dim>(previous_grad_u));
- voigt_stress = this->Einf * this->C * voigt_current_strain;
- Real dt = this->model.getTimeStep();
+ Vector<Real, voigt_h::size> voigt_stress =
+ this->Einf * this->C * voigt_current_strain;
- for (UInt k = 0; k < Eta.size(); ++k) {
- Real lambda = this->Eta(k) / this->Ev(k);
- Real exp_dt_lambda = exp(-dt / lambda);
+ Vector<Real, voigt_h::size> stress =
+ this->C * (voigt_current_strain - voigt_previous_strain);
+
+ for (auto && [Eta, Ev, sigma] : zip(this->Eta, this->Ev, sigma_v)) {
+ auto lambda = Eta / Ev;
+ auto exp_dt_lambda = exp(-dt / lambda);
Real E_additional;
if (exp_dt_lambda == 1) {
- E_additional = this->Ev(k);
+ E_additional = Ev;
} else {
- E_additional = (1 - exp_dt_lambda) * this->Ev(k) * lambda / dt;
+ E_additional = (1 - exp_dt_lambda) * Ev * lambda / dt;
}
- for (UInt I = 0; I < voigt_h::size; ++I) {
- UInt i = voigt_h::vec[I][0];
- UInt j = voigt_h::vec[I][1];
-
- voigt_sigma_v(I) = sigma_v(i, j, k);
- }
-
- voigt_stress += E_additional * this->C *
- (voigt_current_strain - voigt_previous_strain) +
- exp_dt_lambda * voigt_sigma_v;
+ voigt_stress += E_additional * stress +
+ exp_dt_lambda * Material::stressToVoigt<dim>(sigma);
}
- for (UInt I = 0; I < voigt_h::size; ++I) {
- UInt i = voigt_h::vec[I][0];
- UInt j = voigt_h::vec[I][1];
+ for (Int I = 0; I < voigt_h::size; ++I) {
+ auto i = voigt_h::vec[I][0];
+ auto j = voigt_h::vec[I][1];
sigma(i, j) = sigma(j, i) =
voigt_stress(I) + Math::kronecker(i, j) * sigma_th;
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::computePotentialEnergy(
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::computePotentialEnergy(
ElementType el_type) {
AKANTU_DEBUG_IN();
auto epot = this->potential_energy(el_type).begin();
- auto sigma_v_it = this->sigma_v(el_type).begin(
- spatial_dimension, spatial_dimension, this->Eta.size());
- auto epsilon_v_it = this->epsilon_v(el_type).begin(
- spatial_dimension, spatial_dimension, this->Eta.size());
+ auto sigma_v_it = this->sigma_v(el_type).begin(dim, dim, this->Eta.size());
+ auto epsilon_v_it =
+ this->epsilon_v(el_type).begin(dim, dim, this->Eta.size());
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
this->computePotentialEnergyOnQuad(grad_u, *epot, *sigma_v_it, *epsilon_v_it);
+
++epot;
++sigma_v_it;
++epsilon_v_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::
- computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, Real & epot,
- Tensor3<Real> & sigma_v,
- Tensor3<Real> & epsilon_v) {
-
- Vector<Real> voigt_strain(voigt_h::size);
- Vector<Real> voigt_stress(voigt_h::size);
- Vector<Real> voigt_sigma_v(voigt_h::size);
-
- for (UInt I = 0; I < voigt_h::size; ++I) {
- Real voigt_factor = voigt_h::factors[I];
- UInt i = voigt_h::vec[I][0];
- UInt j = voigt_h::vec[I][1];
-
- voigt_strain(I) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.;
- }
+template <Int dim>
+template <typename D1>
+void MaterialViscoelasticMaxwell<dim>::computePotentialEnergyOnQuad(
+ const Eigen::MatrixBase<D1> & grad_u, Real & epot,
+ Tensor3Proxy<Real> & sigma_v, Tensor3Proxy<Real> & epsilon_v) {
+
+ auto voigt_strain =
+ Material::strainToVoigt<dim>(Material::gradUToEpsilon<dim>(grad_u));
+ Vector<Real, voigt_h::size> voigt_stress =
+ this->Einf * this->C * voigt_strain;
- voigt_stress = this->Einf * this->C * voigt_strain;
epot = 0.5 * voigt_stress.dot(voigt_strain);
- for (UInt k = 0; k < this->Eta.size(); ++k) {
+ for (Int k = 0; k < this->Eta.size(); ++k) {
Matrix<Real> stress_v = sigma_v(k);
Matrix<Real> strain_v = epsilon_v(k);
epot += 0.5 * stress_v.doubleDot(strain_v);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::afterSolveStep(
- bool converged) {
-
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::afterSolveStep(bool converged) {
Material::afterSolveStep(converged);
if (not converged) {
return;
}
- for (auto & el_type : this->element_filter.elementTypes(
+ for (const auto & el_type : this->element_filter.elementTypes(
_all_dimensions, _not_ghost, _ek_not_defined)) {
if (this->update_variable_flag) {
- auto previous_gradu_it = this->gradu.previous(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension);
+ auto previous_gradu_it =
+ this->gradu.previous(el_type, _not_ghost).begin(dim, dim);
auto sigma_v_it =
- this->sigma_v(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension, this->Eta.size());
+ this->sigma_v(el_type, _not_ghost).begin(dim, dim, this->Eta.size());
- auto epsilon_v_it =
- this->epsilon_v(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension, this->Eta.size());
+ auto epsilon_v_it = this->epsilon_v(el_type, _not_ghost)
+ .begin(dim, dim, this->Eta.size());
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
updateIntVarOnQuad(grad_u, *previous_gradu_it, *sigma_v_it,
*epsilon_v_it);
++previous_gradu_it;
++sigma_v_it;
++epsilon_v_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
}
this->updateDissipatedEnergy(el_type);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::updateIntVarOnQuad(
- const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u,
- Tensor3<Real> & sigma_v, Tensor3<Real> & epsilon_v) {
+template <Int dim>
+template <typename D1, typename D2>
+void MaterialViscoelasticMaxwell<dim>::updateIntVarOnQuad(
+ const Eigen::MatrixBase<D1> & grad_u,
+ const Eigen::MatrixBase<D2> & previous_grad_u, Tensor3Proxy<Real> & sigma_v,
+ Tensor3Proxy<Real> & epsilon_v) {
- Matrix<Real> grad_delta_u(grad_u);
- grad_delta_u -= previous_grad_u;
+ Matrix<Real, dim, dim> grad_delta_u = grad_u - previous_grad_u;
Real dt = this->model.getTimeStep();
- Vector<Real> voigt_delta_strain(voigt_h::size);
- for (UInt I = 0; I < voigt_h::size; ++I) {
- Real voigt_factor = voigt_h::factors[I];
- UInt i = voigt_h::vec[I][0];
- UInt j = voigt_h::vec[I][1];
-
- voigt_delta_strain(I) =
- voigt_factor * (grad_delta_u(i, j) + grad_delta_u(j, i)) / 2.;
- }
- for (UInt k = 0; k < this->Eta.size(); ++k) {
- Real lambda = this->Eta(k) / this->Ev(k);
- Real exp_dt_lambda = exp(-dt / lambda);
+ auto voigt_delta_strain =
+ Material::strainToVoigt<dim>(Material::gradUToEpsilon<dim>(grad_delta_u));
+
+ for (Idx k = 0; k < this->Eta.size(); ++k) {
+ auto lambda = this->Eta(k) / this->Ev(k);
+ auto exp_dt_lambda = exp(-dt / lambda);
Real E_ef_v;
if (exp_dt_lambda == 1) {
E_ef_v = this->Ev(k);
} else {
E_ef_v = (1 - exp_dt_lambda) * this->Ev(k) * lambda / dt;
}
- Vector<Real> voigt_sigma_v(voigt_h::size);
- Vector<Real> voigt_epsilon_v(voigt_h::size);
-
- for (UInt I = 0; I < voigt_h::size; ++I) {
- UInt i = voigt_h::vec[I][0];
- UInt j = voigt_h::vec[I][1];
+ auto voigt_sigma_v = Material::stressToVoigt<dim>(sigma_v(k));
- voigt_sigma_v(I) = sigma_v(i, j, k);
- }
-
- voigt_sigma_v =
+ Vector<Real, voigt_h::size> voigt_epsilon_v =
exp_dt_lambda * voigt_sigma_v + E_ef_v * this->C * voigt_delta_strain;
voigt_epsilon_v = 1 / Ev(k) * this->D * voigt_sigma_v;
- for (UInt I = 0; I < voigt_h::size; ++I) {
- UInt i = voigt_h::vec[I][0];
- UInt j = voigt_h::vec[I][1];
+ for (Int I = 0; I < voigt_h::size; ++I) {
+ auto i = voigt_h::vec[I][0];
+ auto j = voigt_h::vec[I][1];
sigma_v(i, j, k) = sigma_v(j, i, k) = voigt_sigma_v(I);
epsilon_v(i, j, k) = epsilon_v(j, i, k) = voigt_epsilon_v(I);
}
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::computeTangentModuli(
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Real dt = this->model.getTimeStep();
Real E_ef = this->Einf;
- for (UInt k = 0; k < Eta.size(); ++k) {
+ for (Int k = 0; k < Eta.size(); ++k) {
Real lambda = this->Eta(k) / this->Ev(k);
Real exp_dt_lambda = exp(-dt / lambda);
if (exp_dt_lambda == 1) {
E_ef += this->Ev(k);
} else {
E_ef += (1 - exp_dt_lambda) * this->Ev(k) * lambda / dt;
}
}
this->previous_dt = dt;
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
this->computeTangentModuliOnQuad(tangent);
MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
tangent_matrix *= E_ef;
this->was_stiffness_assembled = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::computeTangentModuliOnQuad(
- Matrix<Real> & tangent) {
+template <Int dim>
+template <typename D1>
+void MaterialViscoelasticMaxwell<dim>::computeTangentModuliOnQuad(
+ Eigen::MatrixBase<D1> & tangent) {
- tangent.copy(C);
+ tangent = C;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::savePreviousState() {
+template <Int dim> void MaterialViscoelasticMaxwell<dim>::updateIntVariables() {
- for (auto & el_type : this->element_filter.elementTypes(
+ for (const auto & el_type : this->element_filter.elementTypes(
_all_dimensions, _not_ghost, _ek_not_defined)) {
- auto sigma_th_it = this->sigma_th(el_type, _not_ghost).begin();
-
- auto previous_sigma_th_it =
- this->sigma_th.previous(el_type, _not_ghost).begin();
-
- auto previous_gradu_it = this->gradu.previous(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension);
-
- auto previous_sigma_it = this->stress.previous(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension);
+ auto previous_gradu_it =
+ this->gradu.previous(el_type, _not_ghost).begin(dim, dim);
auto sigma_v_it =
- this->sigma_v(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension, this->Eta.size());
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
- auto & previous_grad_u = *previous_gradu_it;
- auto & previous_sigma = *previous_sigma_it;
-
- previous_grad_u.copy(grad_u);
- previous_sigma.copy(sigma);
- *previous_sigma_th_it = *sigma_th_it;
-
- ++previous_gradu_it, ++previous_sigma_it, ++previous_sigma_th_it,
- ++sigma_v_it, ++sigma_th_it;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
- }
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::updateIntVariables() {
-
- for (auto & el_type : this->element_filter.elementTypes(
- _all_dimensions, _not_ghost, _ek_not_defined)) {
-
- auto previous_gradu_it = this->gradu.previous(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension);
- auto previous_sigma_it = this->stress.previous(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension);
-
- auto sigma_v_it =
- this->sigma_v(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension, this->Eta.size());
+ this->sigma_v(el_type, _not_ghost).begin(dim, dim, this->Eta.size());
auto epsilon_v_it =
- this->epsilon_v(el_type, _not_ghost)
- .begin(spatial_dimension, spatial_dimension, this->Eta.size());
+ this->epsilon_v(el_type, _not_ghost).begin(dim, dim, this->Eta.size());
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
updateIntVarOnQuad(grad_u, *previous_gradu_it, *sigma_v_it, *epsilon_v_it);
++previous_gradu_it;
++sigma_v_it;
++epsilon_v_it;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::updateDissipatedEnergy(
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::updateDissipatedEnergy(
ElementType el_type) {
AKANTU_DEBUG_IN();
this->computePotentialEnergy(el_type);
auto epot = this->potential_energy(el_type).begin();
auto dis_energy = this->dissipated_energy(el_type).begin();
auto mech_work = this->mechanical_work(el_type).begin();
- auto sigma_v_it = this->sigma_v(el_type).begin(
- spatial_dimension, spatial_dimension, this->Eta.size());
- auto epsilon_v_it = this->epsilon_v(el_type).begin(
- spatial_dimension, spatial_dimension, this->Eta.size());
- auto previous_gradu_it =
- this->gradu.previous(el_type).begin(spatial_dimension, spatial_dimension);
- auto previous_sigma_it = this->stress.previous(el_type).begin(
- spatial_dimension, spatial_dimension);
+ auto sigma_v_it = this->sigma_v(el_type).begin(dim, dim, this->Eta.size());
+ auto epsilon_v_it =
+ this->epsilon_v(el_type).begin(dim, dim, this->Eta.size());
+ auto previous_gradu_it = this->gradu.previous(el_type).begin(dim, dim);
+ auto previous_sigma_it = this->stress.previous(el_type).begin(dim, dim);
/// Loop on all quadrature points
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
updateDissipatedEnergyOnQuad(grad_u, *previous_gradu_it, sigma,
*previous_sigma_it, *dis_energy, *mech_work,
*epot);
++previous_gradu_it;
++previous_sigma_it;
++dis_energy;
++mech_work;
++epot;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::
- updateDissipatedEnergyOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & previous_grad_u,
- const Matrix<Real> & sigma,
- const Matrix<Real> & previous_sigma,
- Real & dis_energy, Real & mech_work,
- const Real & pot_energy) {
+template <Int dim>
+template <typename D1, typename D2, typename D3, typename D4>
+void MaterialViscoelasticMaxwell<dim>::updateDissipatedEnergyOnQuad(
+ const Eigen::MatrixBase<D1> & grad_u,
+ const Eigen::MatrixBase<D2> & previous_grad_u,
+ const Eigen::MatrixBase<D3> & sigma,
+ const Eigen::MatrixBase<D4> & previous_sigma, Real & dis_energy,
+ Real & mech_work, const Real & pot_energy) {
Real dt = this->model.getTimeStep();
Matrix<Real> strain_rate = grad_u;
strain_rate -= previous_grad_u;
strain_rate /= dt;
Matrix<Real> av_stress = sigma;
av_stress += previous_sigma;
av_stress /= 2;
mech_work += av_stress.doubleDot(strain_rate) * dt;
dis_energy = mech_work - pot_energy;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getDissipatedEnergy()
- const {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getDissipatedEnergy() const {
AKANTU_DEBUG_IN();
Real de = 0.;
/// integrate the dissipated energy for each type of elements
- for (auto & type :
- this->element_filter.elementTypes(spatial_dimension, _not_ghost)) {
+ for (const auto & type : this->element_filter.elementTypes(dim, _not_ghost)) {
de +=
this->fem.integrate(this->dissipated_energy(type, _not_ghost), type,
_not_ghost, this->element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return de;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getDissipatedEnergy(
- ElementType type, UInt index) const {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getDissipatedEnergy(
+ const Element & element) const {
AKANTU_DEBUG_IN();
- UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
- auto it =
- this->dissipated_energy(type, _not_ghost).begin(nb_quadrature_points);
- UInt gindex = (this->element_filter(type, _not_ghost))(index);
+ auto nb_quadrature_points = this->fem.getNbIntegrationPoints(element.type);
+ auto it = this->dissipated_energy(element.type, _not_ghost)
+ .begin(nb_quadrature_points);
+ auto gindex = this->element_filter(element);
AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[index], type, gindex);
+ return this->fem.integrate(it[element.element],
+ {element.type, gindex, _not_ghost});
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getMechanicalWork() const {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getMechanicalWork() const {
AKANTU_DEBUG_IN();
Real mw = 0.;
/// integrate the dissipated energy for each type of elements
- for (auto & type :
- this->element_filter.elementTypes(spatial_dimension, _not_ghost)) {
+ for (const auto & type : this->element_filter.elementTypes(dim, _not_ghost)) {
mw +=
this->fem.integrate(this->mechanical_work(type, _not_ghost), type,
_not_ghost, this->element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return mw;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getMechanicalWork(
- ElementType type, UInt index) const {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getMechanicalWork(
+ const Element & element) const {
AKANTU_DEBUG_IN();
- UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
- auto it = this->mechanical_work(type, _not_ghost).begin(nb_quadrature_points);
- UInt gindex = (this->element_filter(type, _not_ghost))(index);
+ auto nb_quadrature_points = this->fem.getNbIntegrationPoints(element.type);
+ auto it = this->mechanical_work(element.type, _not_ghost)
+ .begin(nb_quadrature_points);
+ auto gindex = this->element_filter(element);
AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[index], type, gindex);
+ return this->fem.integrate(it[element.element],
+ {element.type, gindex, _not_ghost});
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getPotentialEnergy()
- const {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getPotentialEnergy() const {
AKANTU_DEBUG_IN();
Real epot = 0.;
/// integrate the dissipated energy for each type of elements
- for (auto & type :
- this->element_filter.elementTypes(spatial_dimension, _not_ghost)) {
+ for (const auto & type : this->element_filter.elementTypes(dim, _not_ghost)) {
epot +=
this->fem.integrate(this->potential_energy(type, _not_ghost), type,
_not_ghost, this->element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return epot;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getPotentialEnergy(
- ElementType type, UInt index) const {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getPotentialEnergy(
+ const Element & element) const {
AKANTU_DEBUG_IN();
- UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
- auto it =
- this->potential_energy(type, _not_ghost).begin(nb_quadrature_points);
- UInt gindex = (this->element_filter(type, _not_ghost))(index);
+ auto nb_quadrature_points = this->fem.getNbIntegrationPoints(element.type);
+ auto it = this->potential_energy(element.type, _not_ghost)
+ .begin(nb_quadrature_points);
+ auto gindex = this->element_filter(element);
AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[index], type, gindex);
+ return this->fem.integrate(it[element.element],
+ {element.type, gindex, _not_ghost});
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getEnergy(
- const std::string & type) {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getEnergy(const std::string & type) {
if (type == "dissipated") {
return getDissipatedEnergy();
}
if (type == "potential") {
return getPotentialEnergy();
}
if (type == "work") {
return getMechanicalWork();
}
- return MaterialElastic<spatial_dimension>::getEnergy(type);
+ return MaterialElastic<dim>::getEnergy(type);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-Real MaterialViscoelasticMaxwell<spatial_dimension>::getEnergy(
- const std::string & energy_id, ElementType type, UInt index) {
+template <Int dim>
+Real MaterialViscoelasticMaxwell<dim>::getEnergy(const std::string & energy_id,
+ const Element & element) {
if (energy_id == "dissipated") {
- return getDissipatedEnergy(type, index);
+ return getDissipatedEnergy(element);
}
if (energy_id == "potential") {
- return getPotentialEnergy(type, index);
+ return getPotentialEnergy(element);
}
if (energy_id == "work") {
- return getMechanicalWork(type, index);
+ return getMechanicalWork(element);
}
- return MaterialElastic<spatial_dimension>::getEnergy(energy_id, type, index);
+ return MaterialElastic<dim>::getEnergy(energy_id, element);
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::forceUpdateVariable() {
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::forceUpdateVariable() {
update_variable_flag = true;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialViscoelasticMaxwell<spatial_dimension>::forceNotUpdateVariable() {
+template <Int dim>
+void MaterialViscoelasticMaxwell<dim>::forceNotUpdateVariable() {
update_variable_flag = false;
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(viscoelastic_maxwell, MaterialViscoelasticMaxwell);
+template class MaterialViscoelasticMaxwell<1>;
+template class MaterialViscoelasticMaxwell<2>;
+template class MaterialViscoelasticMaxwell<3>;
+static bool material_is_allocated_viscoelastic_maxwell =
+ instantiateMaterial<MaterialViscoelasticMaxwell>("viscoelastic_maxwell");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh b/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh
index df2503b0a..ad62175fc 100644
--- a/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh
+++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh
@@ -1,228 +1,232 @@
/**
* @file material_viscoelastic_maxwell.hh
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
*
* @date creation: Mon Jun 04 2018
* @date last modification: Wed Dec 09 2020
*
* @brief Material Visco-elastic, based on Maxwell chain,
* see
* [] R. de Borst and A.H. van den Boogaard "Finite-element modeling of
* deformation and cracking in early-age concrete", J.Eng.Mech., 1994
* as well as
* [] Manual of DIANA FEA Theory manual v.10.2 Section 37.6
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_voigthelper.hh"
#include "material_elastic.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_VISCOELASTIC_MAXWELL_HH_
#define AKANTU_MATERIAL_VISCOELASTIC_MAXWELL_HH_
namespace akantu {
/**
* Material Viscoelastic based on Maxwell chain
*
*
* @verbatim
E_0
------|\/\/\|-------
| |
---| |---
| |
----|\/\/\|--[|-----
| E_v1 \Eta_1|
---| |---
| |
----|\/\/\|--[|-----
| E_v2 \Eta_2 |
---| |---
| |
----|\/\/\|--[|----
E_vN \Eta_N
@endverbatim
*
* keyword : viscoelastic_maxwell
*
* parameters in the material files :
* - N : number of Maxwell elements
* - Einf : one spring element stiffness
* - Ev1 : stiffness of the 1st viscous element
* - Eta1: viscosity of the 1st Maxwell element
* ...
* - Ev<N> : stiffness of the Nst viscous element
* - Eta<N>: viscosity of the Nst Maxwell element
*/
-template <UInt spatial_dimension>
-class MaterialViscoelasticMaxwell : public MaterialElastic<spatial_dimension> {
+template <Int dim>
+class MaterialViscoelasticMaxwell : public MaterialElastic<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialViscoelasticMaxwell(SolidMechanicsModel & model, const ID & id = "");
~MaterialViscoelasticMaxwell() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material computed parameter
void initMaterial() override;
/// recompute the lame coefficient and effective tangent moduli
void updateInternalParameters() override;
/// update internal variable on a converged Newton
void afterSolveStep(bool converged) override;
/// update internal variable based on previous and current strain values
void updateIntVariables();
/// update the internal variable sigma_v on quadrature point
- void updateIntVarOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & previous_grad_u,
- Tensor3<Real> & sigma_v, Tensor3<Real> & epsilon_v);
+ template <typename D1, typename D2>
+ void updateIntVarOnQuad(const Eigen::MatrixBase<D1> & grad_u,
+ const Eigen::MatrixBase<D2> & previous_grad_u,
+ Tensor3Proxy<Real> & sigma_v,
+ Tensor3Proxy<Real> & epsilon_v);
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the tangent stiffness matrix for an element type
void computeTangentModuli(ElementType el_type, Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override;
- /// save previous stress and strain values into "previous" arrays
- void savePreviousState() override;
-
/// change flag of updateIntVar to true
void forceUpdateVariable();
/// change flag of updateIntVar to false
void forceNotUpdateVariable();
/// compute the elastic potential energy
void computePotentialEnergy(ElementType el_type) override;
protected:
- void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, Real & epot,
- Tensor3<Real> & sigma_v,
- Tensor3<Real> & epsilon_v);
+ template <typename D>
+ void computePotentialEnergyOnQuad(const Eigen::MatrixBase<D> & grad_u,
+ Real & epot, Tensor3Proxy<Real> & sigma_v,
+ Tensor3Proxy<Real> & epsilon_v);
/// update the dissipated energy, is called after the stress have been
/// computed
void updateDissipatedEnergy(ElementType el_type);
- void updateDissipatedEnergyOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & previous_grad_u,
- const Matrix<Real> & sigma,
- const Matrix<Real> & previous_sigma,
- Real & dis_energy, Real & mech_work,
- const Real & pot_energy);
+ template <typename D1, typename D2, typename D3, typename D4>
+ void
+ updateDissipatedEnergyOnQuad(const Eigen::MatrixBase<D1> & grad_u,
+ const Eigen::MatrixBase<D2> & previous_grad_u,
+ const Eigen::MatrixBase<D3> & sigma,
+ const Eigen::MatrixBase<D4> & previous_sigma,
+ Real & dis_energy, Real & mech_work,
+ const Real & pot_energy);
/// compute stresses on a quadrature point
- void computeStressOnQuad(const Matrix<Real> & grad_u,
- const Matrix<Real> & previous_grad_u,
- Matrix<Real> & sigma, Tensor3<Real> & sigma_v,
- const Real & sigma_th);
+ template <typename D1, typename D2, typename D3>
+ void computeStressOnQuad(const Eigen::MatrixBase<D1> & grad_u,
+ const Eigen::MatrixBase<D2> & previous_grad_u,
+ Eigen::MatrixBase<D3> & sigma,
+ Tensor3Proxy<Real> & sigma_v, const Real & sigma_th);
/// compute tangent moduli on a quadrature point
- void computeTangentModuliOnQuad(Matrix<Real> & tangent);
+ template <typename D1>
+ void computeTangentModuliOnQuad(Eigen::MatrixBase<D1> & tangent);
bool hasStiffnessMatrixChanged() override {
Real dt = this->model.getTimeStep();
return ((this->previous_dt == dt)
? (!(this->previous_dt == dt)) * (this->was_stiffness_assembled)
: (!(this->previous_dt == dt)));
// return (!(this->previous_dt == dt));
}
MatrixType getTangentType() override { return _symmetric; }
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// give the dissipated energy
Real getDissipatedEnergy() const;
- Real getDissipatedEnergy(ElementType type, UInt index) const;
+ Real getDissipatedEnergy(const Element & element) const;
/// get the potential energy
Real getPotentialEnergy() const;
- Real getPotentialEnergy(ElementType type, UInt index) const;
+ Real getPotentialEnergy(const Element & element) const;
/// get the potential energy
Real getMechanicalWork() const;
- Real getMechanicalWork(ElementType type, UInt index) const;
+ Real getMechanicalWork(const Element & element) const;
/// get the energy using an energy type string for the time step
Real getEnergy(const std::string & type) override;
- Real getEnergy(const std::string & energy_id, ElementType type,
- UInt index) override;
+ Real getEnergy(const std::string & energy_id,
+ const Element & element) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
- using voigt_h = VoigtHelper<spatial_dimension>;
+ using voigt_h = VoigtHelper<dim>;
/// Vectors of viscosity, viscous elastic modulus, one spring element elastic
/// modulus
Vector<Real> Eta;
Vector<Real> Ev;
Real Einf;
/// time step from previous solveStep
Real previous_dt;
/// Stiffness matrix template
Matrix<Real> C;
/// Compliance matrix template
Matrix<Real> D;
/// Internal variable: viscous_stress
InternalField<Real> sigma_v;
/// Internal variable: spring strain in Maxwell element
InternalField<Real> epsilon_v;
/// Dissipated energy
InternalField<Real> dissipated_energy;
/// Mechanical work
InternalField<Real> mechanical_work;
/// Update internal variable after solve step or not
bool update_variable_flag;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_VISCOELASTIC_MAXWELL_HH_ */
diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
index e57e42092..8df547fac 100644
--- a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
+++ b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
@@ -1,105 +1,105 @@
/**
* @file plane_stress_toolbox.hh
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Sep 16 2014
* @date last modification: Fri Apr 09 2021
*
* @brief Tools to implement the plane stress behavior in a material
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PLANE_STRESS_TOOLBOX_HH_
#define AKANTU_PLANE_STRESS_TOOLBOX_HH_
namespace akantu {
class SolidMechanicsModel;
class FEEngine;
} // namespace akantu
namespace akantu {
/**
* Empty class in dimensions different from 2
* This class is only specialized for 2D in the tmpl file
*/
-template <UInt dim, class ParentMaterial = Material>
+template <Int dim, class ParentMaterial = Material>
class PlaneStressToolbox : public ParentMaterial {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "")
: ParentMaterial(model, id) {}
- PlaneStressToolbox(SolidMechanicsModel & model, UInt spatial_dimension,
+ PlaneStressToolbox(SolidMechanicsModel & model, Int spatial_dimension,
const Mesh & mesh, FEEngine & fe_engine,
const ID & id = "")
: ParentMaterial(model, spatial_dimension, mesh, fe_engine, id) {}
~PlaneStressToolbox() override = default;
protected:
void initialize();
public:
void computeAllCauchyStresses(GhostType ghost_type = _not_ghost) override {
ParentMaterial::computeAllCauchyStresses(ghost_type);
}
virtual void computeCauchyStressPlaneStress(ElementType /*el_type*/,
GhostType /*ghost_type*/) {
AKANTU_DEBUG_IN();
AKANTU_ERROR("The function \"computeCauchyStressPlaneStress\" can "
"only be used in 2D Plane stress problems, which means "
"that you made a mistake somewhere!! ");
AKANTU_DEBUG_OUT();
}
virtual void computeThirdAxisDeformation(ElementType /*unused*/,
GhostType /*unused*/) {}
protected:
bool initialize_third_axis_deformation{false};
};
#define AKANTU_PLANE_STRESS_TOOL_SPEC(dim) \
template <> \
inline PlaneStressToolbox<dim, Material>::PlaneStressToolbox( \
SolidMechanicsModel & model, const ID & id) \
: Material(model, id) {}
AKANTU_PLANE_STRESS_TOOL_SPEC(1)
AKANTU_PLANE_STRESS_TOOL_SPEC(3)
} // namespace akantu
#include "plane_stress_toolbox_tmpl.hh"
#endif /* AKANTU_PLANE_STRESS_TOOLBOX_HH_ */
diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
index 5ba800474..8c26ea626 100644
--- a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
+++ b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
@@ -1,167 +1,167 @@
/**
* @file plane_stress_toolbox_tmpl.hh
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
*
* @date creation: Tue Sep 16 2014
* @date last modification: Fri Apr 09 2021
*
* @brief 2D specialization of the akantu::PlaneStressToolbox class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH_
#define AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class ParentMaterial>
class PlaneStressToolbox<2, ParentMaterial> : public ParentMaterial {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "");
- PlaneStressToolbox(SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
+ PlaneStressToolbox(SolidMechanicsModel & model, Int dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id = "");
~PlaneStressToolbox() override = default;
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ThirdAxisDeformation,
third_axis_deformation, Real);
protected:
void initialize() {
this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod,
"Is plane stress");
}
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
void initMaterial() override {
ParentMaterial::initMaterial();
if (this->plane_stress && this->initialize_third_axis_deformation) {
this->third_axis_deformation.initialize(1);
this->third_axis_deformation.resize();
}
}
/* ------------------------------------------------------------------------ */
void computeStress(ElementType el_type, GhostType ghost_type) override {
ParentMaterial::computeStress(el_type, ghost_type);
if (this->plane_stress) {
computeThirdAxisDeformation(el_type, ghost_type);
}
}
/* ------------------------------------------------------------------------ */
virtual void computeThirdAxisDeformation(ElementType /*unused*/,
GhostType /*unused*/) {}
/// Computation of Cauchy stress tensor in the case of finite deformation
void computeAllCauchyStresses(GhostType ghost_type = _not_ghost) override {
AKANTU_DEBUG_IN();
if (this->plane_stress) {
AKANTU_DEBUG_ASSERT(this->finite_deformation,
"The Cauchy stress can only be computed if you are "
"working in finite deformation.");
- for (auto & type : this->fem.getMesh().elementTypes(2, ghost_type)) {
+ for (auto && type : this->fem.getMesh().elementTypes(2, ghost_type)) {
this->computeCauchyStressPlaneStress(type, ghost_type);
}
} else {
ParentMaterial::computeAllCauchyStresses(ghost_type);
}
AKANTU_DEBUG_OUT();
}
virtual void
computeCauchyStressPlaneStress(__attribute__((unused)) ElementType el_type,
__attribute__((unused))
GhostType ghost_type = _not_ghost){};
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// third axis strain measure value
InternalField<Real> third_axis_deformation;
/// Plane stress or plane strain
bool plane_stress;
/// For non linear materials, the \f[\epsilon_{zz}\f] might be required
bool initialize_third_axis_deformation;
};
template <class ParentMaterial>
inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox(
SolidMechanicsModel & model, const ID & id)
: ParentMaterial(model, id),
third_axis_deformation("third_axis_deformation", *this),
plane_stress(false), initialize_third_axis_deformation(false) {
/// @todo Plane_Stress should not be possible to be modified after
/// initMaterial (but before)
this->initialize();
}
template <class ParentMaterial>
inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox(
- SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
+ SolidMechanicsModel & model, Int dim, const Mesh & mesh,
FEEngine & fe_engine, const ID & id)
: ParentMaterial(model, dim, mesh, fe_engine, id),
third_axis_deformation("third_axis_deformation", *this, dim, fe_engine,
this->element_filter),
plane_stress(false), initialize_third_axis_deformation(false) {
this->initialize();
}
template <>
inline PlaneStressToolbox<2, Material>::PlaneStressToolbox(
SolidMechanicsModel & model, const ID & id)
: Material(model, id),
third_axis_deformation("third_axis_deformation", *this),
plane_stress(false), initialize_third_axis_deformation(false) {
/// @todo Plane_Stress should not be possible to be modified after
/// initMaterial (but before)
this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod,
"Is plane stress");
}
} // namespace akantu
#endif /* AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH_ */
diff --git a/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.cc b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.cc
new file mode 100644
index 000000000..44fd35754
--- /dev/null
+++ b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.cc
@@ -0,0 +1,37 @@
+/**
+ * @file damaged_weight_function.cc
+ *
+ * @author Nicolas Richart
+ *
+ * @date creation sam jan 22 2022
+ *
+ * @brief A Documented file.
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+
+#include "damaged_weight_function.hh"
+
+namespace akantu {
+
+INSTANTIATE_NL_NEIGHBORHOOD(damage_wf, DamagedWeightFunction);
+
+} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh
index ee342f289..1dbd730c6 100644
--- a/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh
+++ b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh
@@ -1,81 +1,78 @@
/**
* @file damaged_weight_function.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Nov 08 2017
*
* @brief Damaged weight function for non local materials
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "base_weight_function.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DAMAGED_WEIGHT_FUNCTION_HH_
#define AKANTU_DAMAGED_WEIGHT_FUNCTION_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Damage weight function */
/* -------------------------------------------------------------------------- */
class DamagedWeightFunction : public BaseWeightFunction {
public:
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
DamagedWeightFunction(NonLocalManager & manager)
- : BaseWeightFunction(manager, "damaged"), damage(nullptr) {
+ : BaseWeightFunction(manager, "damaged") {
this->init();
}
- /* --------------------------------------------------------------------------
- */
- /* Base Weight Function inherited methods */
- /* --------------------------------------------------------------------------
- */
-
+ /* ------------------------------------------------------------------------ */
+ /* Base Weight Function inherited methods */
+ /* ------------------------------------------------------------------------ */
/// set the pointers of internals to the right flattend version
void init() override;
inline Real operator()(Real r,
const __attribute__((unused)) IntegrationPoint & q1,
const IntegrationPoint & q2);
private:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
/// internal pointer to the current damage vector
- ElementTypeMapReal * damage;
+ ElementTypeMapReal * damage{nullptr};
};
} // namespace akantu
#include "damaged_weight_function_inline_impl.hh"
#endif /* AKANTU_DAMAGED_WEIGHT_FUNCTION_HH_ */
diff --git a/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh
index 3921bad6f..b101ee66c 100644
--- a/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh
@@ -1,84 +1,85 @@
/**
* @file damaged_weight_function_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Mon Aug 24 2015
* @date last modification: Fri Jan 15 2016
*
* @brief Implementation of inline function of damaged weight function
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "damaged_weight_function.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
inline Real DamagedWeightFunction::operator()(Real r,
const __attribute__((unused))
IntegrationPoint & q1,
const IntegrationPoint & q2) {
/// compute the weight
UInt quad = q2.global_num;
Array<Real> & dam_array = (*this->damage)(q2.type, q2.ghost_type);
Real D = dam_array(quad);
Real Radius_t = 0;
Real Radius_init = this->R2;
// if(D <= 0.5)
// {
// Radius_t = 2*D*Radius_init;
// }
// else
// {
// Radius_t = 2*Radius_init*(1-D);
// }
//
Radius_t = Radius_init * (1 - D);
Radius_init *= Radius_init;
Radius_t *= Radius_t;
if (Radius_t < Math::getTolerance()) {
Radius_t = 0.001 * Radius_init;
}
Real expb =
(2 * std::log(0.51)) / (std::log(1.0 - 0.49 * Radius_t / Radius_init));
Int expb_floor = std::floor(expb);
Real b = expb_floor + expb_floor % 2;
Real alpha = std::max(0., 1. - r * r / Radius_init);
Real w = std::pow(alpha, b);
return w;
}
/* -------------------------------------------------------------------------- */
inline void DamagedWeightFunction::init() {
this->damage = &(this->manager.registerWeightFunctionInternal("damage"));
}
+
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.cc b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.cc
new file mode 100644
index 000000000..2a0501d9a
--- /dev/null
+++ b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.cc
@@ -0,0 +1,37 @@
+/**
+ * @file remove_damaged_weight_function.cc
+ *
+ * @author Nicolas Richart
+ *
+ * @date creation sam jan 22 2022
+ *
+ * @brief A Documented file.
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+
+#include "remove_damaged_weight_function.hh"
+
+namespace akantu {
+
+INSTANTIATE_NL_NEIGHBORHOOD(remove_wf, RemoveDamagedWeightFunction);
+
+} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh
index fc940b2bc..22de2ecc8 100644
--- a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh
+++ b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh
@@ -1,98 +1,99 @@
/**
* @file remove_damaged_weight_function.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Mon Aug 24 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Removed damaged weight function for non local materials
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "base_weight_function.hh"
+
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_HH_
#define AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Remove damaged weight function */
/* -------------------------------------------------------------------------- */
class RemoveDamagedWeightFunction : public BaseWeightFunction {
public:
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
RemoveDamagedWeightFunction(NonLocalManager & manager)
: BaseWeightFunction(manager, "remove_damaged"), damage(nullptr) {
this->registerParam("damage_limit", this->damage_limit, 1., _pat_parsable,
"Damage Threshold");
this->init();
}
/* --------------------------------------------------------------------------
*/
/* Base Weight Function inherited methods */
/* --------------------------------------------------------------------------
*/
inline void init() override;
inline Real operator()(Real r, const IntegrationPoint & q1,
const IntegrationPoint & q2);
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
private:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
/// limit at which a point is considered as complitely broken
Real damage_limit;
/// internal pointer to the current damage vector
ElementTypeMapReal * damage;
};
} // namespace akantu
#include "remove_damaged_weight_function_inline_impl.hh"
#endif /* AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_HH_ */
diff --git a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh
index b11d2132e..054646c9f 100644
--- a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh
@@ -1,108 +1,108 @@
/**
* @file remove_damaged_weight_function_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Mon Aug 24 2015
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of inline function of remove damaged weight function
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "remove_damaged_weight_function.hh"
+//#include "remove_damaged_weight_function.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_INLINE_IMPL_HH_
#define AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline Real RemoveDamagedWeightFunction::operator()(
Real r, const __attribute__((unused)) IntegrationPoint & q1,
const IntegrationPoint & q2) {
/// compute the weight
UInt quad = q2.global_num;
if (q1 == q2) {
return 1.;
}
Array<Real> & dam_array = (*this->damage)(q2.type, q2.ghost_type);
Real D = dam_array(quad);
Real w = 0.;
if (D < damage_limit * (1 - Math::getTolerance())) {
Real alpha = std::max(0., 1. - r * r / this->R2);
w = alpha * alpha;
}
return w;
}
/* -------------------------------------------------------------------------- */
inline void RemoveDamagedWeightFunction::init() {
this->damage = &(this->manager.registerWeightFunctionInternal("damage"));
}
/* -------------------------------------------------------------------------- */
-inline UInt
+inline Int
RemoveDamagedWeightFunction::getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const {
if (tag == SynchronizationTag::_mnl_weight) {
return this->manager.getModel().getNbIntegrationPoints(elements) *
sizeof(Real);
}
return 0;
}
/* -------------------------------------------------------------------------- */
inline void
RemoveDamagedWeightFunction::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
if (tag == SynchronizationTag::_mnl_weight) {
DataAccessor<Element>::packElementalDataHelper<Real>(
*damage, buffer, elements, true,
this->manager.getModel().getFEEngine());
}
}
/* -------------------------------------------------------------------------- */
inline void
RemoveDamagedWeightFunction::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
if (tag == SynchronizationTag::_mnl_weight) {
DataAccessor<Element>::unpackElementalDataHelper<Real>(
*damage, buffer, elements, true,
this->manager.getModel().getFEEngine());
}
}
} // namespace akantu
#endif /* AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_INLINE_IMPL_HH_ */
diff --git a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh
index b5b88850a..fd1443845 100644
--- a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh
+++ b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh
@@ -1,85 +1,85 @@
/**
* @file remove_damaged_with_damage_rate_weight_function.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Removed damaged weight function for non local materials
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
/* -------------------------------------------------------------------------- */
#include "base_weight_function.hh"
+
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_REMOVE_DAMAGED_WITH_DAMAGE_RATE_WEIGHT_FUNCTION_HH_
#define AKANTU_REMOVE_DAMAGED_WITH_DAMAGE_RATE_WEIGHT_FUNCTION_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Remove damaged with damage rate weight function */
/* -------------------------------------------------------------------------- */
class RemoveDamagedWithDamageRateWeightFunction : public BaseWeightFunction {
public:
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
RemoveDamagedWithDamageRateWeightFunction(NonLocalManager & manager)
: BaseWeightFunction(manager, "remove_damage_with_damage_rate"),
damage_with_damage_rate(nullptr) {
this->registerParam<Real>("damage_limit",
this->damage_limit_with_damage_rate, 1,
_pat_parsable, "Damage Threshold");
this->init();
}
/* --------------------------------------------------------------------------
*/
/* Base Weight Function inherited methods */
/* --------------------------------------------------------------------------
*/
- inline Real operator()(Real r,
- const __attribute__((unused)) IntegrationPoint & q1,
- const IntegrationPoint & q2);
+ inline auto operator()(Real r,
+ const IntegrationPoint & q1,
+ const IntegrationPoint & q2) -> Real;
inline void init() override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// limit at which a point is considered as complitely broken
Real damage_limit_with_damage_rate;
/// internal pointer to the current damage vector
ElementTypeMapReal * damage_with_damage_rate;
};
} // namespace akantu
#include "remove_damaged_with_damage_rate_weight_function_inline_impl.hh"
#endif /* AKANTU_REMOVE_DAMAGED_WITH_DAMAGE_WEIGHT_FUNCTION_HH_ */
diff --git a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh
index c1ab81375..e5e4c3c7b 100644
--- a/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh
@@ -1,71 +1,71 @@
/**
* @file remove_damaged_with_damage_rate_weight_function_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Mon Aug 24 2015
* @date last modification: Fri Jan 15 2016
*
* @brief Implementation of inline function of remove damaged with
* damage rate weight function
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
/* -------------------------------------------------------------------------- */
#include "remove_damaged_with_damage_rate_weight_function.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
+
/* -------------------------------------------------------------------------- */
inline void RemoveDamagedWithDamageRateWeightFunction::init() {
this->damage_with_damage_rate =
&(this->manager.registerWeightFunctionInternal("damage-rate"));
}
/* -------------------------------------------------------------------------- */
inline Real RemoveDamagedWithDamageRateWeightFunction::operator()(
- Real r, const __attribute__((unused)) IntegrationPoint & q1,
+ Real r, const IntegrationPoint & q1, const IntegrationPoint & q2) {
- const IntegrationPoint & q2) {
/// compute the weight
- UInt quad = q2.global_num;
+ auto quad = q2.global_num;
if (q1.global_num == quad) {
return 1.;
}
Array<Real> & dam_array =
(*this->damage_with_damage_rate)(q2.type, q2.ghost_type);
Real D = dam_array(quad);
Real w = 0.;
Real alphaexp = 1.;
Real betaexp = 2.;
if (D < damage_limit_with_damage_rate) {
Real alpha = std::max(0., 1. - pow((r * r / this->R2), alphaexp));
w = pow(alpha, betaexp);
}
return w;
}
+
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc
index f3084b52e..f834c282d 100644
--- a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc
+++ b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc
@@ -1,125 +1,124 @@
/**
* @file stress_based_weight_function.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Aug 24 2015
* @date last modification: Thu Feb 20 2020
*
* @brief implementation of the stres based weight function classes
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "stress_based_weight_function.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
StressBasedWeightFunction::StressBasedWeightFunction(NonLocalManager & manager)
: BaseWeightFunction(manager, "stress_based")
// stress_diag("stress_diag", material), selected_stress_diag(NULL),
// stress_base("stress_base", material), selected_stress_base(NULL),
// characteristic_size("lc", material), selected_characteristic_size(NULL)
{
-
// this->registerParam("ft", this->ft, 0., _pat_parsable, "Tensile strength");
// stress_diag.initialize(spatial_dimension);
// stress_base.initialize(spatial_dimension * spatial_dimension);
// characteristic_size.initialize(1);
}
/* -------------------------------------------------------------------------- */
/// During intialization the characteristic sizes for all quadrature
/// points are computed
void StressBasedWeightFunction::init() {
// const Mesh & mesh = this->material.getModel().getFEEngine().getMesh();
- // for (UInt g = _not_ghost; g <= _ghost; ++g) {
+ // for (Int g = _not_ghost; g <= _ghost; ++g) {
// GhostType gt = GhostType(g);
// Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt);
// Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, gt);
// for(; it != last_type; ++it) {
// UInt nb_quadrature_points =
// this->material.getModel().getFEEngine().getNbQuadraturePoints(*it, gt);
- // const Array<UInt> & element_filter =
+ // const Array<Int> & element_filter =
// this->material.getElementFilter(*it, gt);
// UInt nb_element = element_filter.size();
// Array<Real> ones(nb_element*nb_quadrature_points, 1, 1.);
// Array<Real> & lc = characteristic_size(*it, gt);
// this->material.getModel().getFEEngine().integrateOnQuadraturePoints(ones,
// lc,
// 1,
// *it,
// gt,
// element_filter);
- // for (UInt q = 0; q < nb_quadrature_points * nb_element; q++) {
+ // for (Int q = 0; q < nb_quadrature_points * nb_element; q++) {
// lc(q) = pow(lc(q), 1./ Real(spatial_dimension));
// }
// }
// }
}
/* -------------------------------------------------------------------------- */
/// computation of principals stresses and principal directions
void StressBasedWeightFunction::updatePrincipalStress(__attribute__((unused))
GhostType ghost_type) {
// AKANTU_DEBUG_IN();
// const Mesh & mesh = this->material.getModel().getFEEngine().getMesh();
// Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
// Mesh::type_iterator last_type = mesh.lastType(spatial_dimension,
// ghost_type);
// for(; it != last_type; ++it) {
// Array<Real>::const_matrix_iterator sigma =
// this->material.getStress(*it, ghost_type).begin(spatial_dimension,
// spatial_dimension);
// auto eigenvalues =
// stress_diag(*it, ghost_type).begin(spatial_dimension);
// auto eigenvalues_end =
// stress_diag(*it, ghost_type).end(spatial_dimension);
// Array<Real>::matrix_iterator eigenvector =
// stress_base(*it, ghost_type).begin(spatial_dimension,
// spatial_dimension);
// #ifndef __trick__
// auto cl = characteristic_size(*it, ghost_type).begin();
// #endif
// UInt q = 0;
// for(;eigenvalues != eigenvalues_end; ++sigma, ++eigenvalues,
// ++eigenvector, ++cl, ++q) {
// sigma->eig(*eigenvalues, *eigenvector);
// *eigenvalues /= ft;
// #ifndef __trick__
// // specify a lower bound for principal stress based on the size of
// the element
- // for (UInt i = 0; i < spatial_dimension; ++i) {
+ // for (Int i = 0; i < spatial_dimension; ++i) {
// (*eigenvalues)(i) = std::max(*cl / this->R, (*eigenvalues)(i));
// }
// #endif
// }
// }
// AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.hh b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.hh
index df4a5b24a..1b2d97860 100644
--- a/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.hh
@@ -1,198 +1,198 @@
/**
* @file stress_based_weight_function_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Fri Apr 13 2012
* @date last modification: Tue Dec 04 2018
*
* @brief Implementation of inline function of remove damaged with
* damage rate weight function
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "stress_based_weight_function.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
inline void StressBasedWeightFunction::updateInternals() {
// updatePrincipalStress(_not_ghost);
// updatePrincipalStress(_ghost);
}
/* -------------------------------------------------------------------------- */
// inline void StressBasedWeightFunction::selectType(ElementType type1,
// GhostType ghost_type1,
// ElementType type2,
// GhostType ghost_type2) {
// selected_stress_diag = &stress_diag(type2, ghost_type2);
// selected_stress_base = &stress_base(type2, ghost_type2);
// selected_characteristic_size = &characteristic_size(type1, ghost_type1);
// }
/* -------------------------------------------------------------------------- */
inline Real StressBasedWeightFunction::
computeRhoSquare( // NOLINT(readability-convert-member-functions-to-static)
Real /*r*/, Vector<Real> & /*eigs*/, Matrix<Real> & /*eigenvects*/,
Vector<Real> & /*x_s*/) {
// if (spatial_dimension == 1)
// return eigs[0];
// else if (spatial_dimension == 2) {
- // Vector<Real> u1(eigenvects.storage(), 2);
+ // Vector<Real> u1(eigenvects.data(), 2);
// Real cos_t = x_s.dot(u1) / (x_s.norm() * u1.norm());
// Real cos_t_2;
// Real sin_t_2;
// Real sigma1_2 = eigs[0]*eigs[0];
// Real sigma2_2 = eigs[1]*eigs[1];
// #ifdef __trick__
// Real zero = std::numeric_limits<Real>::epsilon();
// if(std::abs(cos_t) < zero) {
// cos_t_2 = 0;
// sin_t_2 = 1;
// } else {
// cos_t_2 = cos_t * cos_t;
// sin_t_2 = (1 - cos_t_2);
// }
// Real rhop1 = std::max(0., cos_t_2 / sigma1_2);
// Real rhop2 = std::max(0., sin_t_2 / sigma2_2);
// #else
// cos_t_2 = cos_t * cos_t;
// sin_t_2 = (1 - cos_t_2);
// Real rhop1 = cos_t_2 / sigma1_2;
// Real rhop2 = sin_t_2 / sigma2_2;
// #endif
// return 1./ (rhop1 + rhop2);
// } else if (spatial_dimension == 3) {
- // Vector<Real> u1(eigenvects.storage() + 0*3, 3);
- // //Vector<Real> u2(eigenvects.storage() + 1*3, 3);
- // Vector<Real> u3(eigenvects.storage() + 2*3, 3);
+ // Vector<Real> u1(eigenvects.data() + 0*3, 3);
+ // //Vector<Real> u2(eigenvects.data() + 1*3, 3);
+ // Vector<Real> u3(eigenvects.data() + 2*3, 3);
// Real zero = std::numeric_limits<Real>::epsilon();
// Vector<Real> tmp(3);
// tmp.crossProduct(x_s, u3);
// Vector<Real> u3_C_x_s_C_u3(3);
// u3_C_x_s_C_u3.crossProduct(u3, tmp);
// Real norm_u3_C_x_s_C_u3 = u3_C_x_s_C_u3.norm();
// Real cos_t = 0.;
// if(std::abs(norm_u3_C_x_s_C_u3) > zero) {
// Real inv_norm_u3_C_x_s_C_u3 = 1. / norm_u3_C_x_s_C_u3;
// cos_t = u1.dot(u3_C_x_s_C_u3) * inv_norm_u3_C_x_s_C_u3;
// }
// Real cos_p = u3.dot(x_s) / r;
// Real cos_t_2;
// Real sin_t_2;
// Real cos_p_2;
// Real sin_p_2;
// Real sigma1_2 = eigs[0]*eigs[0];
// Real sigma2_2 = eigs[1]*eigs[1];
// Real sigma3_2 = eigs[2]*eigs[2];
// #ifdef __trick__
// if(std::abs(cos_t) < zero) {
// cos_t_2 = 0;
// sin_t_2 = 1;
// } else {
// cos_t_2 = cos_t * cos_t;
// sin_t_2 = (1 - cos_t_2);
// }
// if(std::abs(cos_p) < zero) {
// cos_p_2 = 0;
// sin_p_2 = 1;
// } else {
// cos_p_2 = cos_p * cos_p;
// sin_p_2 = (1 - cos_p_2);
// }
// Real rhop1 = std::max(0., sin_p_2 * cos_t_2 / sigma1_2);
// Real rhop2 = std::max(0., sin_p_2 * sin_t_2 / sigma2_2);
// Real rhop3 = std::max(0., cos_p_2 / sigma3_2);
// #else
// cos_t_2 = cos_t * cos_t;
// sin_t_2 = (1 - cos_t_2);
// cos_p_2 = cos_p * cos_p;
// sin_p_2 = (1 - cos_p_2);
// Real rhop1 = sin_p_2 * cos_t_2 / sigma1_2;
// Real rhop2 = sin_p_2 * sin_t_2 / sigma2_2;
// Real rhop3 = cos_p_2 / sigma3_2;
// #endif
// return 1./ (rhop1 + rhop2 + rhop3);
// }
return 0.;
}
/* -------------------------------------------------------------------------- */
inline Real
StressBasedWeightFunction::operator()(Real /*r*/,
const IntegrationPoint & /*q1*/,
const IntegrationPoint & /*q2*/) {
// Real zero = std::numeric_limits<Real>::epsilon();
// if(r < zero) return 1.; // means x and s are the same points
// const Vector<Real> & x = q1.getPosition();
// const Vector<Real> & s = q2.getPosition();
// Vector<Real> eigs =
// selected_stress_diag->begin(spatial_dimension)[q2.global_num];
// Matrix<Real> eigenvects =
// selected_stress_base->begin(spatial_dimension,
// spatial_dimension)[q2.global_num];
// Real min_rho_lc = selected_characteristic_size->begin()[q1.global_num];
// Vector<Real> x_s(spatial_dimension);
// x_s = x;
// x_s -= s;
// Real rho_2 = computeRhoSquare(r, eigs, eigenvects, x_s);
// Real rho_lc_2 = std::max(this->R2 * rho_2, min_rho_lc*min_rho_lc);
// // Real w = std::max(0., 1. - r*r / rho_lc_2);
// // w = w*w;
// Real w = exp(- 2*2*r*r / rho_lc_2);
// return w;
return 0.;
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc
index 7136890bb..e9d51d7ef 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model.cc
@@ -1,1259 +1,1251 @@
/**
* @file solid_mechanics_model.cc
*
* @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue Jul 27 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Implementation of the SolidMechanicsModel class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
#include "integrator_gauss.hh"
#include "shape_lagrange.hh"
#include "solid_mechanics_model_tmpl.hh"
#include "communicator.hh"
#include "element_synchronizer.hh"
#include "sparse_matrix.hh"
#include "synchronizer_registry.hh"
#include "dumpable_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
#include "material_non_local.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/**
* A solid mechanics model need a mesh and a dimension to be created. the model
* by it self can not do a lot, the good init functions should be called in
* order to configure the model depending on what we want to do.
*
* @param mesh mesh representing the model we want to simulate
* @param dim spatial dimension of the problem, if dim = 0 (default value) the
* dimension of the problem is assumed to be the on of the mesh
* @param id an id to identify the model
* @param model_type this is an internal parameter for inheritance purposes
*/
SolidMechanicsModel::SolidMechanicsModel(
- Mesh & mesh, UInt dim, const ID & id,
+ Mesh & mesh, Int dim, const ID & id,
std::shared_ptr<DOFManager> dof_manager, const ModelType model_type)
: Model(mesh, model_type, dim, id), material_index("material index", id),
material_local_numbering("material local numbering", id) {
AKANTU_DEBUG_IN();
this->initDOFManager(dof_manager);
this->registerFEEngineObject<MyFEEngineType>("SolidMechanicsFEEngine", mesh,
Model::spatial_dimension);
this->mesh.registerDumper<DumperParaview>("solid_mechanics_model", id, true);
this->mesh.addDumpMesh(mesh, Model::spatial_dimension, _not_ghost,
_ek_regular);
material_selector = std::make_shared<DefaultMaterialSelector>(material_index);
this->registerDataAccessor(*this);
if (this->mesh.isDistributed()) {
auto & synchronizer = this->mesh.getElementSynchronizer();
this->registerSynchronizer(synchronizer, SynchronizationTag::_material_id);
this->registerSynchronizer(synchronizer, SynchronizationTag::_smm_mass);
this->registerSynchronizer(synchronizer, SynchronizationTag::_smm_stress);
this->registerSynchronizer(synchronizer, SynchronizationTag::_for_dump);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
SolidMechanicsModel::~SolidMechanicsModel() = default;
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::setTimeStep(Real time_step, const ID & solver_id) {
Model::setTimeStep(time_step, solver_id);
this->mesh.getDumper().setTimeStep(time_step);
}
/* -------------------------------------------------------------------------- */
/* Initialization */
/* -------------------------------------------------------------------------- */
/**
* This function groups many of the initialization in on function. For most of
* basics case the function should be enough. The functions initialize the
* model, the internal vectors, set them to 0, and depending on the parameters
* it also initialize the explicit or implicit solver.
*
* @param options
* \parblock
* contains the different options to initialize the model
* \li \c analysis_method specify the type of solver to use
* \endparblock
*/
void SolidMechanicsModel::initFullImpl(const ModelOptions & options) {
material_index.initialize(mesh, _element_kind = _ek_not_defined,
- _default_value = UInt(-1), _with_nb_element = true);
+ _default_value = -1, _with_nb_element = true);
material_local_numbering.initialize(mesh, _element_kind = _ek_not_defined,
_with_nb_element = true);
Model::initFullImpl(options);
// initialize the materials
if (not this->parser.getLastParsedFile().empty()) {
this->instantiateMaterials();
this->initMaterials();
}
this->initBC(*this, *displacement, *displacement_increment, *external_force);
}
/* -------------------------------------------------------------------------- */
TimeStepSolverType SolidMechanicsModel::getDefaultSolverType() const {
return TimeStepSolverType::_dynamic_lumped;
}
/* -------------------------------------------------------------------------- */
ModelSolverOptions SolidMechanicsModel::getDefaultSolverOptions(
const TimeStepSolverType & type) const {
ModelSolverOptions options;
switch (type) {
case TimeStepSolverType::_dynamic_lumped: {
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
break;
}
case TimeStepSolverType::_static: {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_pseudo_time;
options.solution_type["displacement"] = IntegrationScheme::_not_defined;
break;
}
case TimeStepSolverType::_dynamic: {
if (this->method == _explicit_consistent_mass) {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
} else {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_trapezoidal_rule_2;
options.solution_type["displacement"] = IntegrationScheme::_displacement;
}
break;
}
default:
AKANTU_EXCEPTION(type << " is not a valid time step solver type");
}
return options;
}
/* -------------------------------------------------------------------------- */
std::tuple<ID, TimeStepSolverType>
SolidMechanicsModel::getDefaultSolverID(const AnalysisMethod & method) {
switch (method) {
case _explicit_lumped_mass: {
return std::make_tuple("explicit_lumped",
TimeStepSolverType::_dynamic_lumped);
}
case _explicit_consistent_mass: {
return std::make_tuple("explicit", TimeStepSolverType::_dynamic);
}
case _static: {
return std::make_tuple("static", TimeStepSolverType::_static);
}
case _implicit_dynamic: {
return std::make_tuple("implicit", TimeStepSolverType::_dynamic);
}
default:
return std::make_tuple("unknown", TimeStepSolverType::_not_defined);
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::initSolver(TimeStepSolverType time_step_solver_type,
NonLinearSolverType /*unused*/) {
auto & dof_manager = this->getDOFManager();
/* ------------------------------------------------------------------------ */
// for alloc type of solvers
this->allocNodalField(this->displacement, spatial_dimension, "displacement");
this->allocNodalField(this->previous_displacement, spatial_dimension,
"previous_displacement");
this->allocNodalField(this->displacement_increment, spatial_dimension,
"displacement_increment");
this->allocNodalField(this->internal_force, spatial_dimension,
"internal_force");
this->allocNodalField(this->external_force, spatial_dimension,
"external_force");
this->allocNodalField(this->blocked_dofs, spatial_dimension, "blocked_dofs");
this->allocNodalField(this->current_position, spatial_dimension,
"current_position");
// initialize the current positions
this->current_position->copy(this->mesh.getNodes());
/* ------------------------------------------------------------------------ */
if (!dof_manager.hasDOFs("displacement")) {
dof_manager.registerDOFs("displacement", *this->displacement, _dst_nodal);
dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs);
dof_manager.registerDOFsIncrement("displacement",
*this->displacement_increment);
dof_manager.registerDOFsPrevious("displacement",
*this->previous_displacement);
}
/* ------------------------------------------------------------------------ */
// for dynamic
if (time_step_solver_type == TimeStepSolverType::_dynamic ||
time_step_solver_type == TimeStepSolverType::_dynamic_lumped) {
this->allocNodalField(this->velocity, spatial_dimension, "velocity");
this->allocNodalField(this->acceleration, spatial_dimension,
"acceleration");
if (!dof_manager.hasDOFsDerivatives("displacement", 1)) {
dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity);
dof_manager.registerDOFsDerivative("displacement", 2,
*this->acceleration);
}
}
}
/* -------------------------------------------------------------------------- */
/**
* Initialize the model,basically it pre-compute the shapes, shapes derivatives
* and jacobian
*/
void SolidMechanicsModel::initModel() {
/// \todo add the current position as a parameter to initShapeFunctions for
/// large deformation
getFEEngine().initShapeFunctions(_not_ghost);
getFEEngine().initShapeFunctions(_ghost);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleResidual() {
AKANTU_DEBUG_IN();
/* ------------------------------------------------------------------------ */
// computes the internal forces
this->assembleInternalForces();
/* ------------------------------------------------------------------------ */
this->getDOFManager().assembleToResidual("displacement",
*this->external_force, 1);
this->getDOFManager().assembleToResidual("displacement",
*this->internal_force, 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleResidual(const ID & residual_part) {
AKANTU_DEBUG_IN();
if ("external" == residual_part) {
this->getDOFManager().assembleToResidual("displacement",
*this->external_force, 1);
AKANTU_DEBUG_OUT();
return;
}
if ("internal" == residual_part) {
this->assembleInternalForces();
this->getDOFManager().assembleToResidual("displacement",
*this->internal_force, 1);
AKANTU_DEBUG_OUT();
return;
}
AKANTU_CUSTOM_EXCEPTION(
debug::SolverCallbackResidualPartUnknown(residual_part));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
MatrixType SolidMechanicsModel::getMatrixType(const ID & matrix_id) const {
// \TODO check the materials to know what is the correct answer
if (matrix_id == "C") {
return _mt_not_defined;
}
if (matrix_id == "K") {
auto matrix_type = _unsymmetric;
for (auto & material : materials) {
matrix_type = std::max(matrix_type, material->getMatrixType(matrix_id));
}
}
return _symmetric;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleMatrix(const ID & matrix_id) {
if (matrix_id == "K") {
this->assembleStiffnessMatrix();
} else if (matrix_id == "M") {
this->assembleMass();
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleLumpedMatrix(const ID & matrix_id) {
if (matrix_id == "M") {
this->assembleMassLumped();
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::beforeSolveStep() {
for (auto & material : materials) {
material->beforeSolveStep();
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::afterSolveStep(bool converged) {
for (auto & material : materials) {
material->afterSolveStep(converged);
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::predictor() { ++displacement_release; }
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::corrector() { ++displacement_release; }
/* -------------------------------------------------------------------------- */
/**
* This function computes the internal forces as \f$F_{int} = \int_{\Omega} N
* \sigma d\Omega@\f$
*/
void SolidMechanicsModel::assembleInternalForces() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the internal forces");
this->internal_force->zero();
// compute the stresses of local elements
AKANTU_DEBUG_INFO("Compute local stresses");
for (auto & material : materials) {
material->computeAllStresses(_not_ghost);
}
/* ------------------------------------------------------------------------ */
/* Computation of the non local part */
if (this->non_local_manager) {
this->non_local_manager->computeAllNonLocalStresses();
}
// communicate the stresses
AKANTU_DEBUG_INFO("Send data for residual assembly");
this->asynchronousSynchronize(SynchronizationTag::_smm_stress);
// assemble the forces due to local stresses
AKANTU_DEBUG_INFO("Assemble residual for local elements");
for (auto & material : materials) {
material->assembleInternalForces(_not_ghost);
}
// finalize communications
AKANTU_DEBUG_INFO("Wait distant stresses");
this->waitEndSynchronize(SynchronizationTag::_smm_stress);
// assemble the stresses due to ghost elements
AKANTU_DEBUG_INFO("Assemble residual for ghost elements");
for (auto & material : materials) {
material->assembleInternalForces(_ghost);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleStiffnessMatrix(bool need_to_reassemble) {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Assemble the new stiffness matrix.");
if (not this->getDOFManager().hasMatrix("K")) {
this->getDOFManager().getNewMatrix("K", this->getMatrixType("K"));
}
// Check if materials need to recompute the matrix
for (auto & material : materials) {
need_to_reassemble |= material->hasMatrixChanged("K");
}
if (need_to_reassemble) {
this->getDOFManager().getMatrix("K").zero();
// call compute stiffness matrix on each local elements
for (auto & material : materials) {
material->assembleStiffnessMatrix(_not_ghost);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::updateCurrentPosition() {
if (this->current_position_release == this->displacement_release) {
return;
}
this->current_position->copy(this->mesh.getNodes());
- auto cpos_it = this->current_position->begin(Model::spatial_dimension);
- auto cpos_end = this->current_position->end(Model::spatial_dimension);
- auto disp_it = this->displacement->begin(Model::spatial_dimension);
-
- for (; cpos_it != cpos_end; ++cpos_it, ++disp_it) {
- *cpos_it += *disp_it;
+ for (auto && data : zip(make_view(*this->current_position, spatial_dimension),
+ make_view(*this->displacement, spatial_dimension))) {
+ std::get<0>(data) += std::get<1>(data);
}
this->current_position_release = this->displacement_release;
}
/* -------------------------------------------------------------------------- */
const Array<Real> & SolidMechanicsModel::getCurrentPosition() {
this->updateCurrentPosition();
return *this->current_position;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::updateDataForNonLocalCriterion(
ElementTypeMapReal & criterion) {
const ID field_name = criterion.getName();
for (auto & material : materials) {
if (!material->isInternal<Real>(field_name, _ek_regular)) {
continue;
}
for (auto ghost_type : ghost_types) {
material->flattenInternal(field_name, criterion, ghost_type, _ek_regular);
}
}
}
/* -------------------------------------------------------------------------- */
/* Information */
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getStableTimeStep() {
AKANTU_DEBUG_IN();
Real min_dt = getStableTimeStep(_not_ghost);
/// reduction min over all processors
mesh.getCommunicator().allReduce(min_dt, SynchronizerOperation::_min);
AKANTU_DEBUG_OUT();
return min_dt;
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getStableTimeStep(GhostType ghost_type) {
AKANTU_DEBUG_IN();
Real min_dt = std::numeric_limits<Real>::max();
this->updateCurrentPosition();
Element elem;
elem.ghost_type = ghost_type;
for (auto type :
mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_regular)) {
elem.type = type;
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- UInt nb_element = mesh.getNbElement(type);
-
- auto mat_indexes = material_index(type, ghost_type).begin();
- auto mat_loc_num = material_local_numbering(type, ghost_type).begin();
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Array<Real> X(0, nb_nodes_per_element * Model::spatial_dimension);
FEEngine::extractNodalToElementField(mesh, *current_position, X, type,
_not_ghost);
- auto X_el = X.begin(Model::spatial_dimension, nb_nodes_per_element);
+ for (auto && data :
+ zip(make_view(X, spatial_dimension, nb_nodes_per_element),
+ make_view(material_index(type, ghost_type)),
+ make_view(material_local_numbering(type, ghost_type)))) {
+ auto && X_el = std::get<0>(data);
+ auto && mat_idx = std::get<1>(data);
+ elem.element = std::get<2>(data);
- for (UInt el = 0; el < nb_element;
- ++el, ++X_el, ++mat_indexes, ++mat_loc_num) {
- elem.element = *mat_loc_num;
- Real el_h = getFEEngine().getElementInradius(*X_el, type);
- Real el_c = this->materials[*mat_indexes]->getCelerity(elem);
- Real el_dt = el_h / el_c;
+ auto el_h = getFEEngine().getElementInradius(X_el, type);
+ auto el_c = this->materials[mat_idx]->getCelerity(elem);
+ auto el_dt = el_h / el_c;
min_dt = std::min(min_dt, el_dt);
}
}
AKANTU_DEBUG_OUT();
return min_dt;
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getKineticEnergy() {
AKANTU_DEBUG_IN();
Real ekin = 0.;
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
if (this->getDOFManager().hasLumpedMatrix("M")) {
this->assembleLumpedMatrix("M");
auto m_it = this->mass->begin(Model::spatial_dimension);
auto m_end = this->mass->end(Model::spatial_dimension);
auto v_it = this->velocity->begin(Model::spatial_dimension);
- for (UInt n = 0; m_it != m_end; ++n, ++m_it, ++v_it) {
+ for (Int n = 0; m_it != m_end; ++n, ++m_it, ++v_it) {
const auto & v = *v_it;
const auto & m = *m_it;
Real mv2 = 0.;
auto is_local_node = mesh.isLocalOrMasterNode(n);
// bool is_not_pbc_slave_node = !isPBCSlaveNode(n);
auto count_node = is_local_node; // && is_not_pbc_slave_node;
if (count_node) {
- for (UInt i = 0; i < Model::spatial_dimension; ++i) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
if (m(i) > std::numeric_limits<Real>::epsilon()) {
mv2 += v(i) * v(i) * m(i);
}
}
}
ekin += mv2;
}
} else if (this->getDOFManager().hasMatrix("M")) {
this->assembleMatrix("M");
Array<Real> Mv(nb_nodes, Model::spatial_dimension);
this->getDOFManager().assembleMatMulVectToArray("displacement", "M",
*this->velocity, Mv);
for (auto && data : zip(arange(nb_nodes), make_view(Mv, spatial_dimension),
make_view(*this->velocity, spatial_dimension))) {
ekin += std::get<2>(data).dot(std::get<1>(data)) *
static_cast<Real>(mesh.isLocalOrMasterNode(std::get<0>(data)));
}
} else {
AKANTU_ERROR("No function called to assemble the mass matrix.");
}
mesh.getCommunicator().allReduce(ekin, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
return ekin * .5;
}
/* -------------------------------------------------------------------------- */
-Real SolidMechanicsModel::getKineticEnergy(ElementType type, UInt index) {
+Real SolidMechanicsModel::getKineticEnergy(const Element & element) {
AKANTU_DEBUG_IN();
- UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
+ auto nb_quadrature_points =
+ getFEEngine().getNbIntegrationPoints(element.type);
Array<Real> vel_on_quad(nb_quadrature_points, Model::spatial_dimension);
- Array<UInt> filter_element(1, 1, index);
-
- getFEEngine().interpolateOnIntegrationPoints(*velocity, vel_on_quad,
- Model::spatial_dimension, type,
- _not_ghost, filter_element);
-
- auto vit = vel_on_quad.begin(Model::spatial_dimension);
- auto vend = vel_on_quad.end(Model::spatial_dimension);
+ Array<Idx> filter_element(1, 1, element.element);
+ getFEEngine().interpolateOnIntegrationPoints(
+ *velocity, vel_on_quad, Model::spatial_dimension, element.type,
+ _not_ghost, filter_element);
Vector<Real> rho_v2(nb_quadrature_points);
+ Real rho = materials[material_index(element)]->getRho();
- Real rho = materials[material_index(type)(index)]->getRho();
-
- for (UInt q = 0; vit != vend; ++vit, ++q) {
- rho_v2(q) = rho * vit->dot(*vit);
+ for (auto && data : enumerate(make_view(vel_on_quad, spatial_dimension))) {
+ auto && vel = std::get<1>(data);
+ rho_v2(std::get<0>(data)) = rho * vel.dot(vel);
}
AKANTU_DEBUG_OUT();
- return .5 * getFEEngine().integrate(rho_v2, type, index);
+ return .5 * getFEEngine().integrate(rho_v2, element);
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getExternalWork() {
AKANTU_DEBUG_IN();
- auto ext_force_it = external_force->begin(Model::spatial_dimension);
- auto int_force_it = internal_force->begin(Model::spatial_dimension);
- auto boun_it = blocked_dofs->begin(Model::spatial_dimension);
-
- decltype(ext_force_it) incr_or_velo_it;
+ Array<Real> * incrs_or_velos;
if (this->method == _static) {
- incr_or_velo_it =
- this->displacement_increment->begin(Model::spatial_dimension);
+ incrs_or_velos = this->displacement_increment.get();
} else {
- incr_or_velo_it = this->velocity->begin(Model::spatial_dimension);
+ incrs_or_velos = this->velocity.get();
}
Real work = 0.;
- UInt nb_nodes = this->mesh.getNbNodes();
+ auto nb_nodes = this->mesh.getNbNodes();
- for (UInt n = 0; n < nb_nodes;
- ++n, ++ext_force_it, ++int_force_it, ++boun_it, ++incr_or_velo_it) {
- const auto & int_force = *int_force_it;
- const auto & ext_force = *ext_force_it;
- const auto & boun = *boun_it;
- const auto & incr_or_velo = *incr_or_velo_it;
+ for (auto && data :
+ zip(make_view(*external_force, spatial_dimension),
+ make_view(*internal_force, spatial_dimension),
+ make_view(*blocked_dofs, spatial_dimension),
+ make_view(*incrs_or_velos, spatial_dimension), arange(nb_nodes))) {
+ auto && ext_force = std::get<0>(data);
+ auto && int_force = std::get<1>(data);
+ auto && boun = std::get<2>(data);
+ auto && incr_or_velo = std::get<3>(data);
+ auto && n = std::get<4>(data);
- bool is_local_node = this->mesh.isLocalOrMasterNode(n);
+ auto is_local_node = this->mesh.isLocalOrMasterNode(n);
// bool is_not_pbc_slave_node = !this->isPBCSlaveNode(n);
- bool count_node = is_local_node; // && is_not_pbc_slave_node;
+ auto count_node = is_local_node; // && is_not_pbc_slave_node;
if (count_node) {
- for (UInt i = 0; i < Model::spatial_dimension; ++i) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
if (boun(i)) {
work -= int_force(i) * incr_or_velo(i);
} else {
work += ext_force(i) * incr_or_velo(i);
}
}
}
}
mesh.getCommunicator().allReduce(work, SynchronizerOperation::_sum);
if (this->method != _static) {
work *= this->getTimeStep();
}
AKANTU_DEBUG_OUT();
return work;
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getEnergy(const std::string & energy_id) {
AKANTU_DEBUG_IN();
if (energy_id == "kinetic") {
return getKineticEnergy();
}
if (energy_id == "external work") {
return getExternalWork();
}
Real energy = 0.;
for (auto & material : materials) {
energy += material->getEnergy(energy_id);
}
/// reduction sum over all processors
mesh.getCommunicator().allReduce(energy, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
return energy;
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getEnergy(const std::string & energy_id,
- ElementType type, UInt index) {
+ const Element & element) {
AKANTU_DEBUG_IN();
if (energy_id == "kinetic") {
- return getKineticEnergy(type, index);
+ return getKineticEnergy(element);
}
- UInt mat_index = this->material_index(type, _not_ghost)(index);
- UInt mat_loc_num = this->material_local_numbering(type, _not_ghost)(index);
- Real energy =
- this->materials[mat_index]->getEnergy(energy_id, type, mat_loc_num);
+ auto mat_index = this->material_index(element);
+ auto mat_loc_num = this->material_local_numbering(element);
+ auto energy = this->materials[mat_index]->getEnergy(
+ energy_id, {element.type, mat_loc_num, element.ghost_type});
AKANTU_DEBUG_OUT();
return energy;
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getEnergy(const ID & energy_id, const ID & group_id) {
auto && group = mesh.getElementGroup(group_id);
auto energy = 0.;
for (auto && type : group.elementTypes()) {
for (auto el : group.getElementsIterable(type)) {
energy += getEnergy(energy_id, el);
}
}
/// reduction sum over all processors
mesh.getCommunicator().allReduce(energy, SynchronizerOperation::_sum);
return energy;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) {
AKANTU_DEBUG_IN();
this->material_index.initialize(mesh, _element_kind = _ek_not_defined,
- _with_nb_element = true,
- _default_value = UInt(-1));
+ _with_nb_element = true, _default_value = -1);
this->material_local_numbering.initialize(
mesh, _element_kind = _ek_not_defined, _with_nb_element = true,
- _default_value = UInt(-1));
+ _default_value = -1);
- ElementTypeMapArray<UInt> filter("new_element_filter", this->getID());
+ ElementTypeMapArray<Idx> filter("new_element_filter", this->getID());
for (const auto & elem : element_list) {
if (mesh.getSpatialDimension(elem.type) != spatial_dimension) {
continue;
}
if (!filter.exists(elem.type, elem.ghost_type)) {
filter.alloc(0, 1, elem.type, elem.ghost_type);
}
filter(elem.type, elem.ghost_type).push_back(elem.element);
}
// this fails in parallel if the event is sent on facet between constructor
// and initFull \todo: to debug...
this->assignMaterialToElements(&filter);
for (auto & material : materials) {
material->onElementsAdded(element_list, event);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::onElementsRemoved(
const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) {
for (auto & material : materials) {
material->onElementsRemoved(element_list, new_numbering, event);
}
}
/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::onNodesAdded(const Array<UInt> & nodes_list,
+void SolidMechanicsModel::onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) {
AKANTU_DEBUG_IN();
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
if (displacement) {
displacement->resize(nb_nodes, 0.);
++displacement_release;
}
if (mass) {
mass->resize(nb_nodes, 0.);
}
if (velocity) {
velocity->resize(nb_nodes, 0.);
}
if (acceleration) {
acceleration->resize(nb_nodes, 0.);
}
if (external_force) {
external_force->resize(nb_nodes, 0.);
}
if (internal_force) {
internal_force->resize(nb_nodes, 0.);
}
if (blocked_dofs) {
blocked_dofs->resize(nb_nodes, false);
}
if (current_position) {
current_position->resize(nb_nodes, 0.);
}
if (previous_displacement) {
previous_displacement->resize(nb_nodes, 0.);
}
if (displacement_increment) {
displacement_increment->resize(nb_nodes, 0.);
}
for (auto & material : materials) {
material->onNodesAdded(nodes_list, event);
}
need_to_reassemble_lumped_mass = true;
need_to_reassemble_mass = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::onNodesRemoved(const Array<UInt> & /*element_list*/,
- const Array<UInt> & new_numbering,
+void SolidMechanicsModel::onNodesRemoved(const Array<Idx> & /*element_list*/,
+ const Array<Idx> & new_numbering,
const RemovedNodesEvent & /*event*/) {
if (displacement) {
mesh.removeNodesFromArray(*displacement, new_numbering);
++displacement_release;
}
if (mass) {
mesh.removeNodesFromArray(*mass, new_numbering);
}
if (velocity) {
mesh.removeNodesFromArray(*velocity, new_numbering);
}
if (acceleration) {
mesh.removeNodesFromArray(*acceleration, new_numbering);
}
if (internal_force) {
mesh.removeNodesFromArray(*internal_force, new_numbering);
}
if (external_force) {
mesh.removeNodesFromArray(*external_force, new_numbering);
}
if (blocked_dofs) {
mesh.removeNodesFromArray(*blocked_dofs, new_numbering);
}
// if (increment_acceleration)
// mesh.removeNodesFromArray(*increment_acceleration, new_numbering);
if (displacement_increment) {
mesh.removeNodesFromArray(*displacement_increment, new_numbering);
}
if (previous_displacement) {
mesh.removeNodesFromArray(*previous_displacement, new_numbering);
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "Solid Mechanics Model [" << std::endl;
stream << space << " + id : " << id << std::endl;
stream << space << " + spatial dimension : " << Model::spatial_dimension
<< std::endl;
stream << space << " + fem [" << std::endl;
getFEEngine().printself(stream, indent + 2);
stream << space << " ]" << std::endl;
stream << space << " + nodals information [" << std::endl;
displacement->printself(stream, indent + 2);
if (velocity) {
velocity->printself(stream, indent + 2);
}
if (acceleration) {
acceleration->printself(stream, indent + 2);
}
if (mass) {
mass->printself(stream, indent + 2);
}
external_force->printself(stream, indent + 2);
internal_force->printself(stream, indent + 2);
blocked_dofs->printself(stream, indent + 2);
stream << space << " ]" << std::endl;
stream << space << " + material information [" << std::endl;
material_index.printself(stream, indent + 2);
stream << space << " ]" << std::endl;
stream << space << " + materials [" << std::endl;
for (const auto & material : materials) {
material->printself(stream, indent + 2);
}
stream << space << " ]" << std::endl;
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::initializeNonLocal() {
this->non_local_manager->synchronize(*this, SynchronizationTag::_material_id);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::insertIntegrationPointsInNeighborhoods(
GhostType ghost_type) {
for (auto & mat : materials) {
- MaterialNonLocalInterface * mat_non_local;
- if ((mat_non_local =
- dynamic_cast<MaterialNonLocalInterface *>(mat.get())) == nullptr) {
+ if (not aka::is_of_type<MaterialNonLocalInterface>(mat)) {
continue;
}
+ auto && mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat);
+
ElementTypeMapArray<Real> quadrature_points_coordinates(
"quadrature_points_coordinates_tmp_nl", this->id);
quadrature_points_coordinates.initialize(this->getFEEngine(),
_nb_component = spatial_dimension,
_ghost_type = ghost_type);
for (const auto & type : quadrature_points_coordinates.elementTypes(
Model::spatial_dimension, ghost_type)) {
this->getFEEngine().computeIntegrationPointsCoordinates(
quadrature_points_coordinates(type, ghost_type), type, ghost_type);
}
- mat_non_local->initMaterialNonLocal();
+ mat_non_local.initMaterialNonLocal();
- mat_non_local->insertIntegrationPointsInNeighborhoods(
+ mat_non_local.insertIntegrationPointsInNeighborhoods(
ghost_type, quadrature_points_coordinates);
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::computeNonLocalStresses(GhostType ghost_type) {
for (auto & mat : materials) {
if (not aka::is_of_type<MaterialNonLocalInterface>(*mat)) {
continue;
}
auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat);
mat_non_local.computeNonLocalStresses(ghost_type);
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::updateLocalInternal(
ElementTypeMapReal & internal_flat, GhostType ghost_type,
ElementKind kind) {
const ID field_name = internal_flat.getName();
for (auto & material : materials) {
if (material->isInternal<Real>(field_name, kind)) {
material->flattenInternal(field_name, internal_flat, ghost_type, kind);
}
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::updateNonLocalInternal(
ElementTypeMapReal & internal_flat, GhostType ghost_type,
ElementKind kind) {
const ID field_name = internal_flat.getName();
for (auto & mat : materials) {
if (not aka::is_of_type<MaterialNonLocalInterface>(*mat)) {
continue;
}
auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat);
mat_non_local.updateNonLocalInternals(internal_flat, field_name, ghost_type,
kind);
}
}
/* -------------------------------------------------------------------------- */
FEEngine & SolidMechanicsModel::getFEEngineBoundary(const ID & name) {
return getFEEngineClassBoundary<MyFEEngineType>(name);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::splitElementByMaterial(
const Array<Element> & elements,
std::vector<Array<Element>> & elements_per_mat) const {
for (const auto & el : elements) {
Element mat_el = el;
mat_el.element = this->material_local_numbering(el);
+ AKANTU_DEBUG_ASSERT(mat_el.element != -1,
+ "The element" << el << " has no defined material");
elements_per_mat[this->material_index(el)].push_back(mat_el);
}
}
/* -------------------------------------------------------------------------- */
-UInt SolidMechanicsModel::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+Int SolidMechanicsModel::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
- UInt size = 0;
- UInt nb_nodes_per_element = 0;
+ Int size = 0;
+ Int nb_nodes_per_element = 0;
for (const Element & el : elements) {
nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
}
switch (tag) {
case SynchronizationTag::_material_id: {
- size += elements.size() * sizeof(UInt);
+ size += elements.size() * sizeof(decltype(material_index)::value_type);
break;
}
case SynchronizationTag::_smm_mass: {
size += nb_nodes_per_element * sizeof(Real) *
Model::spatial_dimension; // mass vector
break;
}
case SynchronizationTag::_smm_for_gradu: {
size += nb_nodes_per_element * Model::spatial_dimension *
sizeof(Real); // displacement
break;
}
case SynchronizationTag::_smm_boundary: {
// force, displacement, boundary
size += nb_nodes_per_element * Model::spatial_dimension *
(2 * sizeof(Real) + sizeof(bool));
break;
}
case SynchronizationTag::_for_dump: {
// displacement, velocity, acceleration, residual, force
size += nb_nodes_per_element * Model::spatial_dimension * sizeof(Real) * 5;
break;
}
default: {
}
}
if (tag != SynchronizationTag::_material_id) {
splitByMaterial(elements, [&](auto && mat, auto && elements) {
size += mat.getNbData(elements, tag);
});
}
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
switch (tag) {
case SynchronizationTag::_material_id: {
packElementalDataHelper(material_index, buffer, elements, false,
getFEEngine());
break;
}
case SynchronizationTag::_smm_mass: {
packNodalDataHelper(*mass, buffer, elements, mesh);
break;
}
case SynchronizationTag::_smm_for_gradu: {
packNodalDataHelper(*displacement, buffer, elements, mesh);
break;
}
case SynchronizationTag::_for_dump: {
packNodalDataHelper(*displacement, buffer, elements, mesh);
packNodalDataHelper(*velocity, buffer, elements, mesh);
packNodalDataHelper(*acceleration, buffer, elements, mesh);
packNodalDataHelper(*internal_force, buffer, elements, mesh);
packNodalDataHelper(*external_force, buffer, elements, mesh);
break;
}
case SynchronizationTag::_smm_boundary: {
packNodalDataHelper(*external_force, buffer, elements, mesh);
packNodalDataHelper(*velocity, buffer, elements, mesh);
packNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
break;
}
default: {
}
}
if (tag != SynchronizationTag::_material_id) {
splitByMaterial(elements, [&](auto && mat, auto && elements) {
mat.packData(buffer, elements, tag);
});
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
switch (tag) {
case SynchronizationTag::_material_id: {
for (auto && element : elements) {
- UInt recv_mat_index;
+ decltype(material_index)::value_type recv_mat_index;
buffer >> recv_mat_index;
- UInt & mat_index = material_index(element);
- if (mat_index != UInt(-1)) {
+ auto & mat_index = material_index(element);
+ if (mat_index != -1) {
continue;
}
// add ghosts element to the correct material
mat_index = recv_mat_index;
- UInt index = materials[mat_index]->addElement(element);
+ auto index = materials[mat_index]->addElement(element);
material_local_numbering(element) = index;
}
break;
}
case SynchronizationTag::_smm_mass: {
unpackNodalDataHelper(*mass, buffer, elements, mesh);
break;
}
case SynchronizationTag::_smm_for_gradu: {
unpackNodalDataHelper(*displacement, buffer, elements, mesh);
break;
}
case SynchronizationTag::_for_dump: {
unpackNodalDataHelper(*displacement, buffer, elements, mesh);
unpackNodalDataHelper(*velocity, buffer, elements, mesh);
unpackNodalDataHelper(*acceleration, buffer, elements, mesh);
unpackNodalDataHelper(*internal_force, buffer, elements, mesh);
unpackNodalDataHelper(*external_force, buffer, elements, mesh);
break;
}
case SynchronizationTag::_smm_boundary: {
unpackNodalDataHelper(*external_force, buffer, elements, mesh);
unpackNodalDataHelper(*velocity, buffer, elements, mesh);
unpackNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
break;
}
default: {
}
}
if (tag != SynchronizationTag::_material_id) {
splitByMaterial(elements, [&](auto && mat, auto && elements) {
mat.unpackData(buffer, elements, tag);
});
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-UInt SolidMechanicsModel::getNbData(const Array<UInt> & dofs,
- const SynchronizationTag & tag) const {
+Int SolidMechanicsModel::getNbData(const Array<Idx> & dofs,
+ const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
- UInt size = 0;
- // UInt nb_nodes = mesh.getNbNodes();
+ Int size = 0;
switch (tag) {
case SynchronizationTag::_smm_uv: {
size += sizeof(Real) * Model::spatial_dimension * 2;
break;
}
case SynchronizationTag::_smm_res: /* FALLTHRU */
case SynchronizationTag::_smm_mass: {
size += sizeof(Real) * Model::spatial_dimension;
break;
}
case SynchronizationTag::_for_dump: {
size += sizeof(Real) * Model::spatial_dimension * 5;
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
AKANTU_DEBUG_OUT();
return size * dofs.size();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::packData(CommunicationBuffer & buffer,
- const Array<UInt> & dofs,
+ const Array<Idx> & dofs,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
switch (tag) {
case SynchronizationTag::_smm_uv: {
packDOFDataHelper(*displacement, buffer, dofs);
packDOFDataHelper(*velocity, buffer, dofs);
break;
}
case SynchronizationTag::_smm_res: {
packDOFDataHelper(*internal_force, buffer, dofs);
break;
}
case SynchronizationTag::_smm_mass: {
packDOFDataHelper(*mass, buffer, dofs);
break;
}
case SynchronizationTag::_for_dump: {
packDOFDataHelper(*displacement, buffer, dofs);
packDOFDataHelper(*velocity, buffer, dofs);
packDOFDataHelper(*acceleration, buffer, dofs);
packDOFDataHelper(*internal_force, buffer, dofs);
packDOFDataHelper(*external_force, buffer, dofs);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer,
- const Array<UInt> & dofs,
+ const Array<Idx> & dofs,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
switch (tag) {
case SynchronizationTag::_smm_uv: {
unpackDOFDataHelper(*displacement, buffer, dofs);
unpackDOFDataHelper(*velocity, buffer, dofs);
break;
}
case SynchronizationTag::_smm_res: {
unpackDOFDataHelper(*internal_force, buffer, dofs);
break;
}
case SynchronizationTag::_smm_mass: {
unpackDOFDataHelper(*mass, buffer, dofs);
break;
}
case SynchronizationTag::_for_dump: {
unpackDOFDataHelper(*displacement, buffer, dofs);
unpackDOFDataHelper(*velocity, buffer, dofs);
unpackDOFDataHelper(*acceleration, buffer, dofs);
unpackDOFDataHelper(*internal_force, buffer, dofs);
unpackDOFDataHelper(*external_force, buffer, dofs);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh
index c59136979..23adb2914 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model.hh
@@ -1,601 +1,607 @@
/**
* @file solid_mechanics_model.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jul 27 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Model of Solid Mechanics
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "boundary_condition.hh"
#include "data_accessor.hh"
#include "fe_engine.hh"
#include "model.hh"
#include "non_local_manager_callback.hh"
#include "solid_mechanics_model_event_handler.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLID_MECHANICS_MODEL_HH_
#define AKANTU_SOLID_MECHANICS_MODEL_HH_
namespace akantu {
class Material;
class MaterialSelector;
class DumperIOHelper;
class NonLocalManager;
template <ElementKind kind, class IntegrationOrderFunctor>
class IntegratorGauss;
template <ElementKind kind> class ShapeLagrange;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
class SolidMechanicsModel
: public Model,
public DataAccessor<Element>,
- public DataAccessor<UInt>,
+ public DataAccessor<Idx>,
public BoundaryCondition<SolidMechanicsModel>,
public NonLocalManagerCallback,
public EventHandlerManager<SolidMechanicsModelEventHandler> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
class NewMaterialElementsEvent : public NewElementsEvent {
public:
- AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array<UInt> &);
- AKANTU_GET_MACRO(MaterialList, material, const Array<UInt> &);
+ AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array<Int> &);
+ AKANTU_GET_MACRO(MaterialList, material, const Array<Int> &);
protected:
- Array<UInt> material;
+ Array<Int> material;
};
using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
protected:
using EventManager = EventHandlerManager<SolidMechanicsModelEventHandler>;
public:
- SolidMechanicsModel(Mesh & mesh, UInt dim = _all_dimensions,
+ SolidMechanicsModel(Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "solid_mechanics_model",
std::shared_ptr<DOFManager> dof_manager = nullptr,
ModelType model_type = ModelType::_solid_mechanics_model);
~SolidMechanicsModel() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// initialize completely the model
void initFullImpl(
const ModelOptions & options = SolidMechanicsModelOptions()) override;
public:
/// initialize all internal arrays for materials
virtual void initMaterials();
protected:
/// initialize the model
void initModel() override;
/// function to print the containt of the class
void printself(std::ostream & stream, int indent = 0) const override;
/// get some default values for derived classes
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
/* ------------------------------------------------------------------------ */
/* Solver interface */
/* ------------------------------------------------------------------------ */
public:
/// assembles the stiffness matrix,
virtual void assembleStiffnessMatrix(bool need_to_reassemble = false);
/// assembles the internal forces in the array internal_forces
virtual void assembleInternalForces();
protected:
/// callback for the solver, this adds f_{ext} - f_{int} to the residual
void assembleResidual() override;
/// callback for the solver, this adds f_{ext} or f_{int} to the residual
void assembleResidual(const ID & residual_part) override;
bool canSplitResidual() const override { return true; }
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override;
/// callback for the solver, this assembles different matrices
void assembleMatrix(const ID & matrix_id) override;
/// callback for the solver, this assembles the stiffness matrix
void assembleLumpedMatrix(const ID & matrix_id) override;
/// callback for the solver, this is called at beginning of solve
void predictor() override;
/// callback for the solver, this is called at end of solve
void corrector() override;
/// callback for the solver, this is called at beginning of solve
void beforeSolveStep() override;
/// callback for the solver, this is called at end of solve
void afterSolveStep(bool converged = true) override;
/// Callback for the model to instantiate the matricees when needed
void initSolver(TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type) override;
protected:
/* ------------------------------------------------------------------------ */
TimeStepSolverType getDefaultSolverType() const override;
/* ------------------------------------------------------------------------ */
ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
public:
bool isDefaultSolverExplicit() {
return method == _explicit_lumped_mass ||
method == _explicit_consistent_mass;
}
protected:
/// update the current position vector
void updateCurrentPosition();
/* ------------------------------------------------------------------------ */
/* Materials (solid_mechanics_model_material.cc) */
/* ------------------------------------------------------------------------ */
public:
/// register an empty material of a given type
Material & registerNewMaterial(const ID & mat_name, const ID & mat_type,
const ID & opt_param);
/// reassigns materials depending on the material selector
virtual void reassignMaterial();
/// apply a constant eigen_grad_u on all quadrature points of a given material
virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
const ID & material_name,
GhostType ghost_type = _not_ghost);
protected:
/// register a material in the dynamic database
Material & registerNewMaterial(const ParserSection & mat_section);
/// read the material files to instantiate all the materials
void instantiateMaterials();
/// set the element_id_by_material and add the elements to the good materials
virtual void
- assignMaterialToElements(const ElementTypeMapArray<UInt> * filter = nullptr);
+ assignMaterialToElements(const ElementTypeMapArray<Idx> * filter = nullptr);
/* ------------------------------------------------------------------------ */
/* Mass (solid_mechanics_model_mass.cc) */
/* ------------------------------------------------------------------------ */
public:
/// assemble the lumped mass matrix
void assembleMassLumped();
/// assemble the mass matrix for consistent mass resolutions
void assembleMass();
public:
/// assemble the lumped mass matrix for local and ghost elements
void assembleMassLumped(GhostType ghost_type);
/// assemble the mass matrix for either _ghost or _not_ghost elements
void assembleMass(GhostType ghost_type);
protected:
/// fill a vector of rho
void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type);
/// compute the kinetic energy
Real getKineticEnergy();
- Real getKineticEnergy(ElementType type, UInt index);
+
+ [[gnu::deprecated("Use the interface with an Element")]] Real
+ getKineticEnergy(ElementType type, Idx index) {
+ return getKineticEnergy({type, index, _not_ghost});
+ }
+
+ Real getKineticEnergy(const Element & element);
/// compute the external work (for impose displacement, the velocity should be
/// given too)
Real getExternalWork();
/* ------------------------------------------------------------------------ */
/* NonLocalManager inherited members */
/* ------------------------------------------------------------------------ */
protected:
void initializeNonLocal() override;
void updateDataForNonLocalCriterion(ElementTypeMapReal & criterion) override;
void computeNonLocalStresses(GhostType ghost_type) override;
void insertIntegrationPointsInNeighborhoods(GhostType ghost_type) override;
/// update the values of the non local internal
void updateLocalInternal(ElementTypeMapReal & internal_flat,
GhostType ghost_type, ElementKind kind) override;
/// copy the results of the averaging in the materials
void updateNonLocalInternal(ElementTypeMapReal & internal_flat,
GhostType ghost_type, ElementKind kind) override;
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const override;
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) override;
- UInt getNbData(const Array<UInt> & dofs,
- const SynchronizationTag & tag) const override;
+ Int getNbData(const Array<Idx> & dofs,
+ const SynchronizationTag & tag) const override;
- void packData(CommunicationBuffer & buffer, const Array<UInt> & dofs,
+ void packData(CommunicationBuffer & buffer, const Array<Idx> & dofs,
const SynchronizationTag & tag) const override;
- void unpackData(CommunicationBuffer & buffer, const Array<UInt> & dofs,
+ void unpackData(CommunicationBuffer & buffer, const Array<Idx> & dofs,
const SynchronizationTag & tag) override;
protected:
void
splitElementByMaterial(const Array<Element> & elements,
std::vector<Array<Element>> & elements_per_mat) const;
template <typename Operation>
void splitByMaterial(const Array<Element> & elements, Operation && op) const;
/* ------------------------------------------------------------------------ */
/* Mesh Event Handler inherited members */
/* ------------------------------------------------------------------------ */
protected:
- void onNodesAdded(const Array<UInt> & nodes_list,
+ void onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) override;
- void onNodesRemoved(const Array<UInt> & element_list,
- const Array<UInt> & new_numbering,
+ void onNodesRemoved(const Array<Idx> & element_list,
+ const Array<Idx> & new_numbering,
const RemovedNodesEvent & event) override;
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
void onElementsRemoved(const Array<Element> & element_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) override;
- void onElementsChanged(const Array<Element> & /*unused*/,
- const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const ChangedElementsEvent & /*unused*/) override{};
+ void onElementsChanged(const Array<Element> &, const Array<Element> &,
+ const ElementTypeMapArray<Idx> &,
+ const ChangedElementsEvent &) override{};
/* ------------------------------------------------------------------------ */
/* Dumpable interface (kept for convenience) and dumper relative functions */
/* ------------------------------------------------------------------------ */
public:
virtual void onDump();
//! decide wether a field is a material internal or not
bool isInternal(const std::string & field_name, ElementKind element_kind);
//! give the amount of data per element
- virtual ElementTypeMap<UInt>
+ virtual ElementTypeMap<Int>
getInternalDataPerElem(const std::string & field_name, ElementKind kind);
//! flatten a given material internal field
ElementTypeMapArray<Real> &
flattenInternal(const std::string & field_name, ElementKind kind,
GhostType ghost_type = _not_ghost);
//! flatten all the registered material internals
void flattenAllRegisteredInternals(ElementKind kind);
//! inverse operation of the flatten
void inflateInternal(const std::string & field_name,
const ElementTypeMapArray<Real> & field,
ElementKind kind, GhostType ghost_type = _not_ghost);
std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createElementalField(const std::string & field_name,
const std::string & group_name, bool padding_flag,
- UInt spatial_dimension, ElementKind kind) override;
+ Int spatial_dimension, ElementKind kind) override;
void dump(const std::string & dumper_name) override;
- void dump(const std::string & dumper_name, UInt step) override;
- void dump(const std::string & dumper_name, Real time, UInt step) override;
+ void dump(const std::string & dumper_name, Int step) override;
+ void dump(const std::string & dumper_name, Real time, Int step) override;
void dump() override;
- void dump(UInt step) override;
- void dump(Real time, UInt step) override;
+ void dump(Int step) override;
+ void dump(Real time, Int step) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// set the value of the time step
void setTimeStep(Real time_step, const ID & solver_id = "") override;
/// get the value of the conversion from forces/ mass to acceleration
AKANTU_GET_MACRO(F_M2A, f_m2a, Real);
/// set the value of the conversion from forces/ mass to acceleration
AKANTU_SET_MACRO(F_M2A, f_m2a, Real);
/// get the SolidMechanicsModel::displacement array
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Displacement, displacement);
/// get the SolidMechanicsModel::displacement array
AKANTU_GET_MACRO_DEREF_PTR(Displacement, displacement);
/// get the SolidMechanicsModel::previous_displacement array
AKANTU_GET_MACRO_DEREF_PTR(PreviousDisplacement, previous_displacement);
/// get the SolidMechanicsModel::current_position array
const Array<Real> & getCurrentPosition();
/// get the SolidMechanicsModel::displacement_increment array
AKANTU_GET_MACRO_DEREF_PTR(Increment, displacement_increment);
/// get the SolidMechanicsModel::displacement_increment array
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Increment, displacement_increment);
/// get the lumped SolidMechanicsModel::mass array
AKANTU_GET_MACRO_DEREF_PTR(Mass, mass);
/// get the SolidMechanicsModel::velocity array
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Velocity, velocity);
/// get the SolidMechanicsModel::velocity array
AKANTU_GET_MACRO_DEREF_PTR(Velocity, velocity);
/// get the SolidMechanicsModel::acceleration array
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Acceleration, acceleration);
/// get the SolidMechanicsModel::acceleration array
AKANTU_GET_MACRO_DEREF_PTR(Acceleration, acceleration);
/// get the SolidMechanicsModel::external_force array
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(ExternalForce, external_force);
/// get the SolidMechanicsModel::external_force array
AKANTU_GET_MACRO_DEREF_PTR(ExternalForce, external_force);
/// get the SolidMechanicsModel::force array (external forces)
[[deprecated("Use getExternalForce instead of this function")]] Array<Real> &
getForce() {
return getExternalForce();
}
/// get the SolidMechanicsModel::internal_force array (internal forces)
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(InternalForce, internal_force);
/// get the SolidMechanicsModel::internal_force array (internal forces)
AKANTU_GET_MACRO_DEREF_PTR(InternalForce, internal_force);
/// get the SolidMechanicsModel::blocked_dofs array
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(BlockedDOFs, blocked_dofs);
/// get the SolidMechanicsModel::blocked_dofs array
AKANTU_GET_MACRO_DEREF_PTR(BlockedDOFs, blocked_dofs);
+ AKANTU_GET_MACRO_AUTO(DisplacementRelease, displacement_release);
+ AKANTU_GET_MACRO_AUTO(CurrentPositionRelease, current_position_release);
+
/// get an iterable on the materials
inline decltype(auto) getMaterials();
/// get an iterable on the materials
inline decltype(auto) getMaterials() const;
/// get a particular material (by numerical material index)
inline Material & getMaterial(UInt mat_index);
/// get a particular material (by numerical material index)
inline const Material & getMaterial(UInt mat_index) const;
/// get a particular material (by material name)
inline Material & getMaterial(const std::string & name);
/// get a particular material (by material name)
inline const Material & getMaterial(const std::string & name) const;
/// get a particular material (by material name)
inline const Material & getMaterial(const Element & element) const;
/// get a particular material id from is name
- inline UInt getMaterialIndex(const std::string & name) const;
+ inline Int getMaterialIndex(const std::string & name) const;
/// give the number of materials
- inline UInt getNbMaterials() const { return materials.size(); }
+ inline Int getNbMaterials() const { return materials.size(); }
/// give the material internal index from its id
Int getInternalIndexFromID(const ID & id) const;
/// compute the stable time step
Real getStableTimeStep();
/**
* @brief Returns the total energy for a given energy type
*
* Energy types of SolidMechanicsModel expected as argument are:
* - `kinetic`
* - `external work`
*
* Other energy types are passed on to the materials. All materials should
* define a `potential` energy type. For additional energy types, see material
* documentation.
*/
Real getEnergy(const std::string & energy_id);
- /// Compute energy for an element type and material index
- Real getEnergy(const std::string & energy_id, ElementType type, UInt index);
+ /// compute the energy for one element
+ Real getEnergy(const std::string & energy_id, const Element & element);
- /// Compute energy for an individual element
- Real getEnergy(const std::string & energy_id, const Element & element) {
- return getEnergy(energy_id, element.type, element.element);
+ [[gnu::deprecated("Use the interface with an Element")]] Real
+ getEnergy(const std::string & energy_id, ElementType type, Int index) {
+ return getEnergy(energy_id, Element{type, index, _not_ghost});
}
/// Compute energy for an element group
Real getEnergy(const ID & energy_id, const ID & group_id);
- AKANTU_GET_MACRO(MaterialByElement, material_index,
- const ElementTypeMapArray<UInt> &);
- AKANTU_GET_MACRO(MaterialLocalNumbering, material_local_numbering,
- const ElementTypeMapArray<UInt> &);
+ AKANTU_GET_MACRO_AUTO(MaterialByElement, material_index);
+ AKANTU_GET_MACRO_AUTO(MaterialLocalNumbering, material_local_numbering);
/// vectors containing local material element index for each global element
/// index
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index,
- UInt);
- // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt);
+ Int);
+ // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, Int);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering,
- material_local_numbering, UInt);
+ material_local_numbering, Int);
// AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering,
// material_local_numbering, UInt);
AKANTU_GET_MACRO_NOT_CONST(MaterialSelector, material_selector,
std::shared_ptr<MaterialSelector>);
void
setMaterialSelector(std::shared_ptr<MaterialSelector> material_selector) {
this->material_selector = std::move(material_selector);
}
/// Access the non_local_manager interface
AKANTU_GET_MACRO(NonLocalManager, *non_local_manager, NonLocalManager &);
/// get the FEEngine object to integrate or interpolate on the boundary
FEEngine & getFEEngineBoundary(const ID & name = "") override;
protected:
/// compute the stable time step
Real getStableTimeStep(GhostType ghost_type);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// release version of the displacement array
- UInt displacement_release{0};
+ Int displacement_release{0};
/// release version of the current_position array
- UInt current_position_release{0};
+ Int current_position_release{0};
/// Check if materials need to recompute the mass array
bool need_to_reassemble_lumped_mass{true};
/// Check if materials need to recompute the mass matrix
bool need_to_reassemble_mass{true};
/// mapping between material name and material internal id
- std::map<std::string, UInt> materials_names_to_id;
+ std::map<std::string, Int> materials_names_to_id;
protected:
/// conversion coefficient form force/mass to acceleration
Real f_m2a{1.0};
/// displacements array
std::unique_ptr<Array<Real>> displacement;
/// displacements array at the previous time step (used in finite deformation)
std::unique_ptr<Array<Real>> previous_displacement;
/// increment of displacement
std::unique_ptr<Array<Real>> displacement_increment;
/// lumped mass array
std::unique_ptr<Array<Real>> mass;
/// velocities array
std::unique_ptr<Array<Real>> velocity;
/// accelerations array
std::unique_ptr<Array<Real>> acceleration;
/// external forces array
std::unique_ptr<Array<Real>> external_force;
/// internal forces array
std::unique_ptr<Array<Real>> internal_force;
/// array specifing if a degree of freedom is blocked or not
std::unique_ptr<Array<bool>> blocked_dofs;
/// array of current position used during update residual
std::unique_ptr<Array<Real>> current_position;
/// Arrays containing the material index for each element
- ElementTypeMapArray<UInt> material_index;
+ ElementTypeMapArray<Int> material_index;
/// Arrays containing the position in the element filter of the material
/// (material's local numbering)
- ElementTypeMapArray<UInt> material_local_numbering;
+ ElementTypeMapArray<Idx> material_local_numbering;
/// list of used materials
std::vector<std::unique_ptr<Material>> materials;
/// class defining of to choose a material
std::shared_ptr<MaterialSelector> material_selector;
using flatten_internal_map =
std::map<std::pair<std::string, ElementKind>,
std::unique_ptr<ElementTypeMapArray<Real>>>;
/// tells if the material are instantiated
flatten_internal_map registered_internals;
/// non local manager
std::unique_ptr<NonLocalManager> non_local_manager;
/// tells if the material are instantiated
bool are_materials_instantiated{false};
friend class Material;
template <class Model_> friend class CouplerSolidContactTemplate;
};
/* -------------------------------------------------------------------------- */
namespace BC {
namespace Neumann {
using FromStress = FromHigherDim;
using FromTraction = FromSameDim;
} // namespace Neumann
} // namespace BC
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material.hh"
#include "parser.hh"
#include "solid_mechanics_model_inline_impl.hh"
#include "solid_mechanics_model_tmpl.hh"
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_SOLID_MECHANICS_MODEL_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc
index 79b8e1f3b..9208c68e7 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc
@@ -1,547 +1,530 @@
/**
* @file fragment_manager.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Thu Jan 23 2014
* @date last modification: Mon Mar 29 2021
*
* @brief Group manager to handle fragments
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fragment_manager.hh"
#include "aka_iterators.hh"
#include "communicator.hh"
#include "element_synchronizer.hh"
#include "material_cohesive.hh"
#include "mesh_iterators.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <functional>
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
FragmentManager::FragmentManager(SolidMechanicsModelCohesive & model,
bool dump_data, const ID & id)
: GroupManager(model.getMesh(), id), model(model),
- mass_center(0, model.getSpatialDimension(), "mass_center"),
- mass(0, model.getSpatialDimension(), "mass"),
- velocity(0, model.getSpatialDimension(), "velocity"),
+ mass_centers(0, model.getSpatialDimension(), "mass_center"),
+ masses(0, model.getSpatialDimension(), "mass"),
+ velocities(0, model.getSpatialDimension(), "velocity"),
inertia_moments(0, model.getSpatialDimension(), "inertia_moments"),
principal_directions(
0, model.getSpatialDimension() * model.getSpatialDimension(),
"principal_directions"),
quad_coordinates("quad_coordinates", id),
- mass_density("mass_density", id),
+ mass_densities("mass_density", id),
nb_elements_per_fragment(0, 1, "nb_elements_per_fragment"),
dump_data(dump_data) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
/// compute quadrature points' coordinates
quad_coordinates.initialize(mesh, _nb_component = spatial_dimension,
_spatial_dimension = spatial_dimension,
_ghost_type = _not_ghost);
- // mesh.initElementTypeMapArray(quad_coordinates, spatial_dimension,
- // spatial_dimension, _not_ghost);
model.getFEEngine().interpolateOnIntegrationPoints(model.getMesh().getNodes(),
quad_coordinates);
/// store mass density per quadrature point
- mass_density.initialize(mesh, _spatial_dimension = spatial_dimension,
- _ghost_type = _not_ghost);
- // mesh.initElementTypeMapArray(mass_density, 1, spatial_dimension,
- // _not_ghost);
+ mass_densities.initialize(mesh, _spatial_dimension = spatial_dimension,
+ _ghost_type = _not_ghost);
storeMassDensityPerIntegrationPoint();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
class CohesiveElementFilter : public GroupManager::ClusteringFilter {
public:
CohesiveElementFilter(const SolidMechanicsModelCohesive & model,
const Real max_damage = 1.)
- : model(model), is_unbroken(max_damage) {}
+ : model(model), max_damage(max_damage) {}
bool operator()(const Element & el) const override {
if (Mesh::getKind(el.type) == _ek_regular) {
return true;
}
- const Array<UInt> & mat_indexes =
- model.getMaterialByElement(el.type, el.ghost_type);
- const Array<UInt> & mat_loc_num =
- model.getMaterialLocalNumbering(el.type, el.ghost_type);
+ auto mat_indexe = model.getMaterialByElement()(el);
+ auto mat_loc_num = model.getMaterialLocalNumbering()(el);
- const auto & mat = static_cast<const MaterialCohesive &>(
- model.getMaterial(mat_indexes(el.element)));
+ const auto & mat =
+ static_cast<const MaterialCohesive &>(model.getMaterial(mat_indexe));
- UInt el_index = mat_loc_num(el.element);
- UInt nb_quad_per_element =
+ auto el_index = mat_loc_num;
+ auto nb_quad_per_element =
model.getFEEngine("CohesiveFEEngine")
.getNbIntegrationPoints(el.type, el.ghost_type);
- const Array<Real> & damage_array = mat.getDamage(el.type, el.ghost_type);
+ const auto & damage_array = mat.getDamage(el.type, el.ghost_type);
- AKANTU_DEBUG_ASSERT(nb_quad_per_element * el_index < damage_array.size(),
+ AKANTU_DEBUG_ASSERT(Int(nb_quad_per_element * el_index) <
+ damage_array.size(),
"This quadrature point is out of range");
- const Real * element_damage =
- damage_array.storage() + nb_quad_per_element * el_index;
+ const auto * element_damage =
+ damage_array.data() + nb_quad_per_element * el_index;
- UInt unbroken_quads = std::count_if(
- element_damage, element_damage + nb_quad_per_element, is_unbroken);
+ auto nonbroken_quads =
+ std::count_if(element_damage, element_damage + nb_quad_per_element,
+ [&](auto && x) { return x < (max_damage - 1e-14); });
- return (unbroken_quads > 0);
+ return (nonbroken_quads > 0);
}
private:
- struct IsUnbrokenFunctor {
- IsUnbrokenFunctor(const Real & max_damage) : max_damage(max_damage) {}
- bool operator()(const Real & x) const { return x < max_damage; }
- const Real max_damage;
- };
-
const SolidMechanicsModelCohesive & model;
- const IsUnbrokenFunctor is_unbroken;
+ Real max_damage;
};
/* -------------------------------------------------------------------------- */
void FragmentManager::buildFragments(Real damage_limit) {
AKANTU_DEBUG_IN();
if (mesh.isDistributed()) {
auto & cohesive_synchronizer = model.getCohesiveSynchronizer();
cohesive_synchronizer.synchronize(model, SynchronizationTag::_smmc_damage);
}
auto & mesh_facets = mesh.getMeshFacets();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
std::string fragment_prefix("fragment");
/// generate fragments
global_nb_fragment =
createClusters(spatial_dimension, mesh_facets, fragment_prefix,
CohesiveElementFilter(model, damage_limit));
nb_fragment = getNbElementGroups(spatial_dimension);
- fragment_index.resize(nb_fragment);
+ fragment_indexes.resize(nb_fragment);
/// loop over fragments
- for (auto && data : zip(iterateElementGroups(), fragment_index)) {
+ for (auto && data : zip(iterateElementGroups(), fragment_indexes)) {
auto name = std::get<0>(data).getName();
/// get fragment index
std::string fragment_index_string = name.substr(fragment_prefix.size() + 1);
std::get<1>(data) = std::stoul(fragment_index_string);
}
/// compute fragments' mass
computeMass();
if (dump_data) {
- createDumpDataArray(fragment_index, "fragments", true);
- createDumpDataArray(mass, "fragments mass");
+ createDumpDataArray(fragment_indexes, "fragments", true);
+ createDumpDataArray(masses, "fragments mass");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FragmentManager::computeMass() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
/// create a unit field per quadrature point, since to compute mass
/// it's neccessary to integrate only density
ElementTypeMapArray<Real> unit_field("unit_field", id);
unit_field.initialize(model.getFEEngine(), _nb_component = spatial_dimension,
_spatial_dimension = spatial_dimension,
_ghost_type = _not_ghost, _default_value = 1.);
- integrateFieldOnFragments(unit_field, mass);
+ integrateFieldOnFragments(unit_field, masses);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FragmentManager::computeCenterOfMass() {
AKANTU_DEBUG_IN();
/// integrate position multiplied by density
- integrateFieldOnFragments(quad_coordinates, mass_center);
+ integrateFieldOnFragments(quad_coordinates, mass_centers);
/// divide it by the fragments' mass
- Real * mass_storage = mass.storage();
- Real * mass_center_storage = mass_center.storage();
-
- UInt total_components = mass_center.size() * mass_center.getNbComponent();
-
- for (UInt i = 0; i < total_components; ++i) {
- mass_center_storage[i] /= mass_storage[i];
+ for (auto && data : zip(make_view(masses), make_view(mass_centers))) {
+ std::get<1>(data) /= std::get<0>(data);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FragmentManager::computeVelocity() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
/// compute velocity per quadrature point
ElementTypeMapArray<Real> velocity_field("velocity_field", id);
velocity_field.initialize(
model.getFEEngine(), _nb_component = spatial_dimension,
_spatial_dimension = spatial_dimension, _ghost_type = _not_ghost);
model.getFEEngine().interpolateOnIntegrationPoints(model.getVelocity(),
velocity_field);
/// integrate on fragments
- integrateFieldOnFragments(velocity_field, velocity);
+ integrateFieldOnFragments(velocity_field, velocities);
/// divide it by the fragments' mass
- Real * mass_storage = mass.storage();
- Real * velocity_storage = velocity.storage();
-
- UInt total_components = velocity.size() * velocity.getNbComponent();
-
- for (UInt i = 0; i < total_components; ++i) {
- velocity_storage[i] /= mass_storage[i];
+ for (auto && data : zip(make_view(masses), make_view(velocities))) {
+ std::get<1>(data) /= std::get<0>(data);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* Given the distance @f$ \mathbf{r} @f$ between a quadrature point
* and its center of mass, the moment of inertia is computed as \f[
* I_\mathrm{CM} = \mathrm{tr}(\mathbf{r}\mathbf{r}^\mathrm{T})
* \mathbf{I} - \mathbf{r}\mathbf{r}^\mathrm{T} \f] for more
* information check Wikipedia
* (http://en.wikipedia.org/wiki/Moment_of_inertia#Identities_for_a_skew-symmetric_matrix)
*
*/
void FragmentManager::computeInertiaMoments() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
computeCenterOfMass();
/// compute local coordinates products with respect to the center of match
ElementTypeMapArray<Real> moments_coords("moments_coords", id);
moments_coords.initialize(model.getFEEngine(),
_nb_component =
spatial_dimension * spatial_dimension,
_spatial_dimension = spatial_dimension,
_ghost_type = _not_ghost, _default_value = 1.);
/// loop over fragments
- for (auto && data :
- zip(iterateElementGroups(), make_view(mass_center, spatial_dimension))) {
+ for (auto && data : zip(iterateElementGroups(),
+ make_view(mass_centers, spatial_dimension))) {
const auto & el_list = std::get<0>(data).getElements();
auto & mass_center = std::get<1>(data);
/// loop over elements of the fragment
for (auto type :
el_list.elementTypes(spatial_dimension, _not_ghost, _ek_regular)) {
auto nb_quad_per_element =
model.getFEEngine().getNbIntegrationPoints(type);
auto & moments_coords_array = moments_coords(type);
const auto & quad_coordinates_array = quad_coordinates(type);
const auto & el_list_array = el_list(type);
auto moments_begin =
moments_coords_array.begin(spatial_dimension, spatial_dimension);
auto quad_coordinates_begin =
quad_coordinates_array.begin(spatial_dimension);
Vector<Real> relative_coords(spatial_dimension);
- for (UInt el = 0; el < el_list_array.size(); ++el) {
- UInt global_el = el_list_array(el);
+ for (Int el = 0; el < el_list_array.size(); ++el) {
+ auto global_el = el_list_array(el);
/// loop over quadrature points
- for (UInt q = 0; q < nb_quad_per_element; ++q) {
- UInt global_q = global_el * nb_quad_per_element + q;
- Matrix<Real> moments_matrix = moments_begin[global_q];
- const Vector<Real> & quad_coord_vector =
- quad_coordinates_begin[global_q];
+ for (Int q = 0; q < nb_quad_per_element; ++q) {
+ auto global_q = global_el * nb_quad_per_element + q;
+ auto && moments_matrix = moments_begin[global_q];
+ const auto & quad_coord_vector = quad_coordinates_begin[global_q];
/// to understand this read the documentation written just
/// before this function
relative_coords = quad_coord_vector;
relative_coords -= mass_center;
- moments_matrix.outerProduct(relative_coords, relative_coords);
+ moments_matrix = relative_coords * relative_coords.transpose();
Real trace = moments_matrix.trace();
- moments_matrix *= -1.;
- moments_matrix += Matrix<Real>::eye(spatial_dimension, trace);
+ moments_matrix = -1. * moments_matrix +
+ trace * Matrix<Real>::Identity(spatial_dimension,
+ spatial_dimension);
}
}
}
}
/// integrate moments
Array<Real> integrated_moments(global_nb_fragment,
spatial_dimension * spatial_dimension);
integrateFieldOnFragments(moments_coords, integrated_moments);
/// compute and store principal moments
inertia_moments.resize(global_nb_fragment);
principal_directions.resize(global_nb_fragment);
auto integrated_moments_it =
integrated_moments.begin(spatial_dimension, spatial_dimension);
auto inertia_moments_it = inertia_moments.begin(spatial_dimension);
auto principal_directions_it =
principal_directions.begin(spatial_dimension, spatial_dimension);
for (UInt frag = 0; frag < global_nb_fragment; ++frag,
++integrated_moments_it, ++inertia_moments_it,
++principal_directions_it) {
integrated_moments_it->eig(*inertia_moments_it, *principal_directions_it);
}
if (dump_data) {
createDumpDataArray(inertia_moments, "moments of inertia");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FragmentManager::computeAllData(Real damage_limit) {
AKANTU_DEBUG_IN();
buildFragments(damage_limit);
computeVelocity();
computeInertiaMoments();
computeNbElementsPerFragment();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FragmentManager::storeMassDensityPerIntegrationPoint() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ auto spatial_dimension = model.getSpatialDimension();
for (auto type : mesh.elementTypes(_spatial_dimension = spatial_dimension,
_element_kind = _ek_regular)) {
- Array<Real> & mass_density_array = mass_density(type);
+ auto & mass_density_array = mass_densities(type);
- UInt nb_element = mesh.getNbElement(type);
- UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type);
+ auto nb_element = mesh.getNbElement(type);
+ auto nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type);
mass_density_array.resize(nb_element * nb_quad_per_element);
- const Array<UInt> & mat_indexes = model.getMaterialByElement(type);
+ const auto & mat_indexes = model.getMaterialByElement(type);
- Real * mass_density_it = mass_density_array.storage();
+ auto * mass_density_it = mass_density_array.data();
/// store mass_density for each element and quadrature point
- for (UInt el = 0; el < nb_element; ++el) {
- Material & mat = model.getMaterial(mat_indexes(el));
+ for (Int el = 0; el < nb_element; ++el) {
+ auto & mat = model.getMaterial(mat_indexes(el));
- for (UInt q = 0; q < nb_quad_per_element; ++q, ++mass_density_it) {
+ for (Int q = 0; q < nb_quad_per_element; ++q, ++mass_density_it) {
*mass_density_it = mat.getRho();
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FragmentManager::integrateFieldOnFragments(
ElementTypeMapArray<Real> & field, Array<Real> & output) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
- UInt nb_component = output.getNbComponent();
+ auto spatial_dimension = model.getSpatialDimension();
+ auto nb_component = output.getNbComponent();
/// integration part
output.resize(global_nb_fragment);
output.zero();
-
- auto output_begin = output.begin(nb_component);
+ auto output_begin = make_view(output, nb_component).begin();
/// loop over fragments
- for (auto && data : zip(iterateElementGroups(), fragment_index)) {
+ for (auto && data : zip(iterateElementGroups(), fragment_indexes)) {
const auto & el_list = std::get<0>(data).getElements();
- auto fragment_index = std::get<1>(data);
+ auto && fragment_index = std::get<1>(data);
/// loop over elements of the fragment
for (auto type :
el_list.elementTypes(spatial_dimension, _not_ghost, _ek_regular)) {
- UInt nb_quad_per_element =
+ auto nb_quad_per_element =
model.getFEEngine().getNbIntegrationPoints(type);
- const Array<Real> & density_array = mass_density(type);
- Array<Real> & field_array = field(type);
- const Array<UInt> & elements = el_list(type);
+ const auto & density_array = mass_densities(type);
+ auto & field_array = field(type);
+ const auto & elements = el_list(type);
/// generate array to be integrated by filtering fragment's elements
Array<Real> integration_array(elements.size() * nb_quad_per_element,
nb_component);
- auto field_array_begin = field_array.begin_reinterpret(
- nb_quad_per_element, nb_component,
- field_array.size() / nb_quad_per_element);
- auto density_array_begin = density_array.begin_reinterpret(
- nb_quad_per_element, density_array.size() / nb_quad_per_element);
+ auto field_array_begin =
+ make_view(field_array, nb_quad_per_element, nb_component).begin();
+ auto density_array_begin =
+ make_view(density_array, nb_quad_per_element).begin();
for (auto && data : enumerate(make_view(
integration_array, nb_quad_per_element, nb_component))) {
- UInt global_el = elements(std::get<0>(data));
+ auto global_el = elements(std::get<0>(data));
auto & int_array = std::get<1>(data);
int_array = field_array_begin[global_el];
/// multiply field by density
- const Vector<Real> & density_vector = density_array_begin[global_el];
+ const auto & density_vector = density_array_begin[global_el];
- for (UInt i = 0; i < nb_quad_per_element; ++i) {
- for (UInt j = 0; j < nb_component; ++j) {
+ for (Int i = 0; i < nb_quad_per_element; ++i) {
+ for (Int j = 0; j < nb_component; ++j) {
int_array(i, j) *= density_vector(i);
}
}
}
/// integrate the field over the fragment
Array<Real> integrated_array(elements.size(), nb_component);
+ std::cout << "integrated_array 1: " << std::get<0>(data).getName()
+ << " - " << integrated_array.size() << " - " << fragment_index
+ << " - " << type << std::endl;
model.getFEEngine().integrate(integration_array, integrated_array,
nb_component, type, _not_ghost, elements);
+ Vector<Real> zeros = Vector<Real>::Zero(nb_component);
+
/// sum over all elements and store the result
- Vector<Real> output_tmp(output_begin[fragment_index]);
- output_tmp += std::accumulate(integrated_array.begin(nb_component),
- integrated_array.end(nb_component),
- Vector<Real>(nb_component));
+ output_begin[fragment_index] = zeros;
+ for (auto && data : make_view(integrated_array, nb_component)) {
+ output_begin[fragment_index] += data;
+ }
}
}
/// sum output over all processors
- const Communicator & comm = mesh.getCommunicator();
+ const auto & comm = mesh.getCommunicator();
comm.allReduce(output, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void FragmentManager::computeNbElementsPerFragment() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
nb_elements_per_fragment.resize(global_nb_fragment);
nb_elements_per_fragment.zero();
/// loop over fragments
- for (auto && data : zip(iterateElementGroups(), fragment_index)) {
+ for (auto && data : zip(iterateElementGroups(), fragment_indexes)) {
const auto & el_list = std::get<0>(data).getElements();
- auto fragment_index = std::get<1>(data);
+ auto && fragment_index = std::get<1>(data);
/// loop over elements of the fragment
for (auto type :
el_list.elementTypes(spatial_dimension, _not_ghost, _ek_regular)) {
- UInt nb_element = el_list(type).size();
+ auto nb_element = el_list(type).size();
nb_elements_per_fragment(fragment_index) += nb_element;
}
}
/// sum values over all processors
const auto & comm = mesh.getCommunicator();
comm.allReduce(nb_elements_per_fragment, SynchronizerOperation::_sum);
if (dump_data) {
createDumpDataArray(nb_elements_per_fragment, "elements per fragment");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename T>
void FragmentManager::createDumpDataArray(Array<T> & data, std::string name,
bool fragment_index_output) {
AKANTU_DEBUG_IN();
if (data.empty()) {
return;
}
auto & mesh_not_const = const_cast<Mesh &>(mesh);
auto && spatial_dimension = mesh.getSpatialDimension();
auto && nb_component = data.getNbComponent();
auto && data_begin = data.begin(nb_component);
/// loop over fragments
- for (auto && data : zip(iterateElementGroups(), fragment_index)) {
+ for (auto && data : zip(iterateElementGroups(), fragment_indexes)) {
const auto & fragment = std::get<0>(data);
- auto fragment_idx = std::get<1>(data);
+ auto && fragment_idx = std::get<1>(data);
/// loop over cluster types
for (auto && type : fragment.elementTypes(spatial_dimension)) {
/// init mesh data
auto & mesh_data = mesh_not_const.getDataPointer<T>(
name, type, _not_ghost, nb_component);
auto mesh_data_begin = mesh_data.begin(nb_component);
/// fill mesh data
for (const auto & elem : fragment.getElements(type)) {
Vector<T> md_tmp = mesh_data_begin[elem];
if (fragment_index_output) {
md_tmp(0) = fragment_idx;
} else {
md_tmp = data_begin[fragment_idx];
}
}
}
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh
index 887924c82..c46ae2982 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh
@@ -1,169 +1,169 @@
/**
* @file fragment_manager.hh
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Thu Jan 23 2014
* @date last modification: Mon Mar 29 2021
*
* @brief Group manager to handle fragments
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "group_manager.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_FRAGMENT_MANAGER_HH_
#define AKANTU_FRAGMENT_MANAGER_HH_
namespace akantu {
class SolidMechanicsModelCohesive;
}
namespace akantu {
/* -------------------------------------------------------------------------- */
class FragmentManager : public GroupManager {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
FragmentManager(SolidMechanicsModelCohesive & model, bool dump_data = true,
const ID & id = "fragment_manager");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
private:
/// store mass density per integration point
void storeMassDensityPerIntegrationPoint();
/// integrate an elemental field multiplied by density on global
/// fragments
void integrateFieldOnFragments(ElementTypeMapArray<Real> & field,
Array<Real> & output);
/// compute fragments' mass
void computeMass();
/// create dump data for a single array
template <typename T>
void createDumpDataArray(Array<T> & data, std::string name,
bool fragment_index_output = false);
public:
/// build fragment list (cohesive elements are considered broken if
/// damage >= damage_limit)
void buildFragments(Real damage_limit = 1.);
/// compute fragments' center of mass
void computeCenterOfMass();
/// compute fragments' velocity
void computeVelocity();
/// computes principal moments of inertia with respect to the center
/// of mass of each fragment
void computeInertiaMoments();
/// compute all fragments' data
void computeAllData(Real damage_limit = 1.);
/// compute number of elements per fragment
void computeNbElementsPerFragment();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get number of fragments
AKANTU_GET_MACRO(NbFragment, global_nb_fragment, UInt);
/// get fragments' mass
- AKANTU_GET_MACRO(Mass, mass, const Array<Real> &);
+ AKANTU_GET_MACRO(Mass, masses, const Array<Real> &);
/// get fragments' center of mass
- AKANTU_GET_MACRO(CenterOfMass, mass_center, const Array<Real> &);
+ AKANTU_GET_MACRO(CenterOfMass, mass_centers, const Array<Real> &);
/// get fragments' velocity
- AKANTU_GET_MACRO(Velocity, velocity, const Array<Real> &);
+ AKANTU_GET_MACRO(Velocity, velocities, const Array<Real> &);
/// get fragments' principal moments of inertia
AKANTU_GET_MACRO(MomentsOfInertia, inertia_moments, const Array<Real> &);
/// get fragments' principal directions
AKANTU_GET_MACRO(PrincipalDirections, principal_directions,
const Array<Real> &);
/// get number of elements per fragment
AKANTU_GET_MACRO(NbElementsPerFragment, nb_elements_per_fragment,
const Array<UInt> &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// local_fragment index
- Array<UInt> fragment_index;
+ Array<UInt> fragment_indexes;
/// global number of fragments (parallel simulations)
UInt global_nb_fragment;
/// number of fragments
UInt nb_fragment;
/// cohesive solid mechanics model associated
SolidMechanicsModelCohesive & model;
/// fragments' center of mass
- Array<Real> mass_center;
+ Array<Real> mass_centers;
/// fragments' mass
- Array<Real> mass;
+ Array<Real> masses;
/// fragments' velocity
- Array<Real> velocity;
+ Array<Real> velocities;
/// fragments' principal moments of inertia with respect to the
/// center of mass
Array<Real> inertia_moments;
/// fragments' principal directions
Array<Real> principal_directions;
/// quadrature points' coordinates
ElementTypeMapArray<Real> quad_coordinates;
/// mass density per quadrature point
- ElementTypeMapArray<Real> mass_density;
+ ElementTypeMapArray<Real> mass_densities;
/// fragment filter
Array<UInt> nb_elements_per_fragment;
/// dump data
bool dump_data;
};
} // namespace akantu
#endif /* AKANTU_FRAGMENT_MANAGER_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc
index d96583923..13faf653e 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc
@@ -1,167 +1,166 @@
/**
* @file material_selector_cohesive.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Dec 11 2015
* @date last modification: Fri Apr 09 2021
*
* @brief Material selector for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_selector_cohesive.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
DefaultMaterialCohesiveSelector::DefaultMaterialCohesiveSelector(
const SolidMechanicsModelCohesive & model)
: facet_material(model.getFacetMaterial()), mesh(model.getMesh()) {
// backward compatibility v3: to get the former behavior back when the user
// creates its own selector
this->fallback_selector =
std::make_shared<DefaultMaterialSelector>(model.getMaterialByElement());
}
/* -------------------------------------------------------------------------- */
-UInt DefaultMaterialCohesiveSelector::operator()(const Element & element) {
+Int DefaultMaterialCohesiveSelector::operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_cohesive) {
try {
const Array<Element> & cohesive_el_to_facet =
mesh.getMeshFacets().getSubelementToElement(element.type,
element.ghost_type);
bool third_dimension = (mesh.getSpatialDimension() == 3);
const Element & facet =
cohesive_el_to_facet(element.element, UInt(third_dimension));
if (facet_material.exists(facet.type, facet.ghost_type)) {
return facet_material(facet.type, facet.ghost_type)(facet.element);
}
return fallback_value;
} catch (...) {
return fallback_value;
}
} else if (Mesh::getSpatialDimension(element.type) ==
mesh.getSpatialDimension() - 1) {
return facet_material(element.type, element.ghost_type)(element.element);
} else {
return MaterialSelector::operator()(element);
}
}
/* -------------------------------------------------------------------------- */
MeshDataMaterialCohesiveSelector::MeshDataMaterialCohesiveSelector(
const SolidMechanicsModelCohesive & model)
: model(model), mesh_facets(model.getMeshFacets()),
material_index(mesh_facets.getData<std::string>("physical_names")) {
third_dimension = (model.getSpatialDimension() == 3);
// backward compatibility v3: to get the former behavior back when the user
// creates its own selector
this->fallback_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
}
/* -------------------------------------------------------------------------- */
-UInt MeshDataMaterialCohesiveSelector::operator()(const Element & element) {
+Int MeshDataMaterialCohesiveSelector::operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_cohesive or
Mesh::getSpatialDimension(element.type) ==
mesh_facets.getSpatialDimension() - 1) {
Element facet;
if (Mesh::getKind(element.type) == _ek_cohesive) {
facet =
mesh_facets.getSubelementToElement(element.type, element.ghost_type)(
element.element, UInt(third_dimension));
} else {
facet = element;
}
try {
std::string material_name = this->material_index(facet);
return this->model.getMaterialIndex(material_name);
} catch (...) {
return fallback_value;
}
}
return MaterialSelector::operator()(element);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
MaterialCohesiveRulesSelector::MaterialCohesiveRulesSelector(
const SolidMechanicsModelCohesive & model,
const MaterialCohesiveRules & rules,
ID mesh_data_id) // what we have here is the name of model and also
// the name of different materials
: model(model), mesh_data_id(std::move(mesh_data_id)),
mesh(model.getMesh()), mesh_facets(model.getMeshFacets()),
spatial_dimension(model.getSpatialDimension()), rules(rules) {
// cohesive fallback
this->fallback_selector =
std::make_shared<DefaultMaterialCohesiveSelector>(model);
// non cohesive fallback
this->fallback_selector->setFallback(
std::make_shared<MeshDataMaterialSelector<std::string>>(
this->mesh_data_id, model));
}
/* -------------------------------------------------------------------------- */
-UInt MaterialCohesiveRulesSelector::operator()(const Element & element) {
+Int MaterialCohesiveRulesSelector::operator()(const Element & element) {
if (mesh_facets.getSpatialDimension(element.type) ==
(spatial_dimension - 1)) {
- const std::vector<Element> & element_to_subelement =
- mesh_facets.getElementToSubelement(element.type,
- element.ghost_type)(element.element);
- const Element & el1 = element_to_subelement[0];
- const Element & el2 = element_to_subelement[1];
+ const auto & element_to_subelement = mesh_facets.getElementToSubelement(
+ element.type, element.ghost_type)(element.element);
+ const auto & el1 = element_to_subelement[0];
+ const auto & el2 = element_to_subelement[1];
- ID id1 = mesh.getData<std::string>(mesh_data_id, el1.type,
- el1.ghost_type)(el1.element);
+ auto id1 = mesh.getData<std::string>(mesh_data_id, el1.type,
+ el1.ghost_type)(el1.element);
- ID id2 = id1;
+ auto id2 = id1;
if (el2 != ElementNull) {
id2 = mesh.getData<std::string>(mesh_data_id, el2.type,
el2.ghost_type)(el2.element);
}
auto rit = rules.find(std::make_pair(id1, id2));
if (rit == rules.end()) {
rit = rules.find(std::make_pair(id2, id1));
}
if (rit != rules.end()) {
return model.getMaterialIndex(rit->second);
}
}
return MaterialSelector::operator()(element);
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh
index 09e1175a9..a073ad0c7 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh
@@ -1,100 +1,100 @@
/**
* @file material_selector_cohesive.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Dec 11 2015
* @date last modification: Fri Apr 09 2021
*
* @brief Material selectors for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_selector.hh"
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
namespace akantu {
class SolidMechanicsModelCohesive;
}
namespace akantu {
#ifndef AKANTU_MATERIAL_SELECTOR_COHESIVE_HH_
#define AKANTU_MATERIAL_SELECTOR_COHESIVE_HH_
/* -------------------------------------------------------------------------- */
/**
* class that assigns the first cohesive material by default to the
* cohesive elements
*/
class DefaultMaterialCohesiveSelector : public MaterialSelector {
public:
DefaultMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model);
- UInt operator()(const Element & element) override;
+ Int operator()(const Element & element) override;
private:
- const ElementTypeMapArray<UInt> & facet_material;
+ const ElementTypeMapArray<Idx> & facet_material;
const Mesh & mesh;
};
/* -------------------------------------------------------------------------- */
/// To be used with intrinsic elements inserted along mesh physical surfaces
class MeshDataMaterialCohesiveSelector : public MaterialSelector {
public:
MeshDataMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model);
- UInt operator()(const Element & element) override;
+ Int operator()(const Element & element) override;
protected:
const SolidMechanicsModelCohesive & model;
const Mesh & mesh_facets;
const ElementTypeMapArray<std::string> & material_index;
bool third_dimension;
};
/// bulk1, bulk2 -> cohesive
using MaterialCohesiveRules = std::map<std::pair<ID, ID>, ID>;
/* -------------------------------------------------------------------------- */
class MaterialCohesiveRulesSelector : public MaterialSelector {
public:
MaterialCohesiveRulesSelector(const SolidMechanicsModelCohesive & model,
const MaterialCohesiveRules & rules,
ID mesh_data_id = "physical_names");
- UInt operator()(const Element & element) override;
+ Int operator()(const Element & element) override;
private:
const SolidMechanicsModelCohesive & model;
ID mesh_data_id;
const Mesh & mesh;
const Mesh & mesh_facets;
- UInt spatial_dimension;
+ Int spatial_dimension;
MaterialCohesiveRules rules;
};
#endif /* AKANTU_MATERIAL_SELECTOR_COHESIVE_HH_ */
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc
index 1853dbb2d..ebd9a2875 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc
@@ -1,215 +1,209 @@
/**
* @file material_cohesive_bilinear.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Feb 22 2012
* @date last modification: Sat Dec 19 2020
*
* @brief Bilinear cohesive constitutive law
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_bilinear.hh"
//#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialCohesiveBilinear<spatial_dimension>::MaterialCohesiveBilinear(
SolidMechanicsModel & model, const ID & id)
: MaterialCohesiveLinear<spatial_dimension>(model, id) {
AKANTU_DEBUG_IN();
this->registerParam("delta_0", delta_0, Real(0.),
_pat_parsable | _pat_readable,
"Elastic limit displacement");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialCohesiveBilinear<spatial_dimension>::initMaterial() {
AKANTU_DEBUG_IN();
this->sigma_c_eff.setRandomDistribution(this->sigma_c.getRandomParameter());
MaterialCohesiveLinear<spatial_dimension>::initMaterial();
this->delta_max.setDefaultValue(delta_0);
this->insertion_stress.setDefaultValue(0);
this->delta_max.reset();
this->insertion_stress.reset();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialCohesiveBilinear<spatial_dimension>::onElementsAdded(
const Array<Element> & element_list, const NewElementsEvent & event) {
AKANTU_DEBUG_IN();
MaterialCohesiveLinear<spatial_dimension>::onElementsAdded(element_list,
event);
bool scale_traction = false;
// don't scale sigma_c if volume_s hasn't been specified by the user
if (!Math::are_float_equal(this->volume_s, 0.)) {
scale_traction = true;
}
- Array<Element>::const_scalar_iterator el_it = element_list.begin();
- Array<Element>::const_scalar_iterator el_end = element_list.end();
-
- for (; el_it != el_end; ++el_it) {
+ for (auto && el : element_list) {
// filter not ghost cohesive elements
- if ((el_it->ghost_type != _not_ghost) or
- (Mesh::getKind(el_it->type) != _ek_cohesive)) {
+ if ((el.ghost_type != _not_ghost) or
+ (Mesh::getKind(el.type) != _ek_cohesive)) {
continue;
}
- UInt index = el_it->element;
- ElementType type = el_it->type;
- UInt nb_element = this->model->getMesh().getNbElement(type);
- UInt nb_quad_per_element = this->fem_cohesive.getNbIntegrationPoints(type);
+ auto index = el.element;
+ auto type = el.type;
+ auto nb_quad_per_element = this->fem_cohesive.getNbIntegrationPoints(type);
- auto sigma_c_begin = this->sigma_c_eff(type).begin_reinterpret(
- nb_quad_per_element, nb_element);
- Vector<Real> sigma_c_vec = sigma_c_begin[index];
+ auto sigma_c_begin =
+ make_view(this->sigma_c_eff(type), nb_quad_per_element).begin();
+ auto && sigma_c_vec = sigma_c_begin[index];
- auto delta_c_begin = this->delta_c_eff(type).begin_reinterpret(
- nb_quad_per_element, nb_element);
- Vector<Real> delta_c_vec = delta_c_begin[index];
+ auto delta_c_begin =
+ make_view(this->delta_c_eff(type), nb_quad_per_element).begin();
+ auto && delta_c_vec = delta_c_begin[index];
if (scale_traction) {
- scaleTraction(*el_it, sigma_c_vec);
+ scaleTraction(el, sigma_c_vec);
}
/**
* Recompute sigma_c as
* @f$ {\sigma_c}_\textup{new} =
* \frac{{\sigma_c}_\textup{old} \delta_c} {\delta_c - \delta_0} @f$
*/
- for (UInt q = 0; q < nb_quad_per_element; ++q) {
+ for (Int q = 0; q < nb_quad_per_element; ++q) {
delta_c_vec(q) = 2 * this->G_c / sigma_c_vec(q);
if (delta_c_vec(q) - delta_0 < Math::getTolerance()) {
AKANTU_ERROR("delta_0 = " << delta_0 << " must be lower than delta_c = "
<< delta_c_vec(q)
<< ", modify your material file");
}
sigma_c_vec(q) *= delta_c_vec(q) / (delta_c_vec(q) - delta_0);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
+template <typename D1>
void MaterialCohesiveBilinear<spatial_dimension>::scaleTraction(
- const Element & el, Vector<Real> & sigma_c_vec) {
+ const Element & el, Eigen::MatrixBase<D1> & sigma_c_vec) {
AKANTU_DEBUG_IN();
- Real base_sigma_c = this->sigma_c_eff;
+ auto base_sigma_c = Real(this->sigma_c_eff);
- const Mesh & mesh_facets = this->model->getMeshFacets();
- const FEEngine & fe_engine = this->model->getFEEngine();
+ const auto & mesh_facets = this->model->getMeshFacets();
+ const auto & fe_engine = this->model->getFEEngine();
auto coh_element_to_facet_begin =
mesh_facets.getSubelementToElement(el.type).begin(2);
- const Vector<Element> & coh_element_to_facet =
- coh_element_to_facet_begin[el.element];
+ const auto & coh_element_to_facet = coh_element_to_facet_begin[el.element];
// compute bounding volume
- Real volume = 0;
+ Real volume = 0.;
// loop over facets
- for (UInt f = 0; f < 2; ++f) {
- const Element & facet = coh_element_to_facet(f);
+ for (Int f = 0; f < 2; ++f) {
+ const auto & facet = coh_element_to_facet(f);
- const Array<std::vector<Element>> & facet_to_element =
+ const auto & facet_to_element =
mesh_facets.getElementToSubelement(facet.type, facet.ghost_type);
- const std::vector<Element> & element_list = facet_to_element(facet.element);
-
- auto elem = element_list.begin();
- auto elem_end = element_list.end();
-
// loop over elements connected to each facet
- for (; elem != elem_end; ++elem) {
+ for (auto && elem : facet_to_element(facet.element)) {
// skip cohesive elements and dummy elements
- if (*elem == ElementNull || Mesh::getKind(elem->type) == _ek_cohesive) {
+ if (elem == ElementNull || Mesh::getKind(elem.type) == _ek_cohesive) {
continue;
}
// unit vector for integration in order to obtain the volume
- UInt nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem->type);
- Vector<Real> unit_vector(nb_quadrature_points, 1);
+ auto nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem.type);
+ Vector<Real> unit_vector(nb_quadrature_points);
+ unit_vector.fill(1);
- volume += fe_engine.integrate(unit_vector, elem->type, elem->element,
- elem->ghost_type);
+ volume += fe_engine.integrate(unit_vector, elem);
}
}
// scale sigma_c
- sigma_c_vec -= base_sigma_c;
- sigma_c_vec *= std::pow(this->volume_s / volume, 1. / this->m_s);
- sigma_c_vec += base_sigma_c;
+ sigma_c_vec = (sigma_c_vec.array() - base_sigma_c) *
+ std::pow(this->volume_s / volume, 1. / this->m_s) +
+ base_sigma_c;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialCohesiveBilinear<spatial_dimension>::computeTraction(
- const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
+ ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- MaterialCohesiveLinear<spatial_dimension>::computeTraction(normal, el_type,
+ MaterialCohesiveLinear<spatial_dimension>::computeTraction(el_type,
ghost_type);
// adjust damage
- auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
- auto delta_max_it = this->delta_max(el_type, ghost_type).begin();
- auto damage_it = this->damage(el_type, ghost_type).begin();
- auto damage_end = this->damage(el_type, ghost_type).end();
-
- for (; damage_it != damage_end; ++damage_it, ++delta_max_it, ++delta_c_it) {
- *damage_it =
- std::max((*delta_max_it - delta_0) / (*delta_c_it - delta_0), Real(0.));
- *damage_it = std::min(*damage_it, Real(1.));
+ for (auto && data : zip(this->damage(el_type, ghost_type),
+ this->delta_max(el_type, ghost_type),
+ this->delta_c_eff(el_type, ghost_type))) {
+ auto & dam = std::get<0>(data);
+ auto & delta_max = std::get<1>(data);
+ auto & delta_c = std::get<2>(data);
+
+ dam = std::max((delta_max - delta_0) / (delta_c - delta_0), Real(0.));
+ dam = std::min(dam, Real(1.));
}
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(cohesive_bilinear, MaterialCohesiveBilinear);
+template class MaterialCohesiveBilinear<1>;
+template class MaterialCohesiveBilinear<2>;
+template class MaterialCohesiveBilinear<3>;
+static bool material_is_alocated_cohesive_bilinear =
+ instantiateMaterial<MaterialCohesiveBilinear>("cohesive_bilinear");
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.hh
index 74a2fa5c8..a90873509 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.hh
@@ -1,106 +1,107 @@
/**
* @file material_cohesive_bilinear.hh
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Feb 20 2020
*
* @brief Bilinear cohesive constitutive law
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
#ifndef AKANTU_MATERIAL_COHESIVE_BILINEAR_HH_
#define AKANTU_MATERIAL_COHESIVE_BILINEAR_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* Cohesive material bilinear
*
* parameters in the material files :
* - delta_0 : elastic limit displacement (default: 0)
* - sigma_c : critical stress sigma_c (default: 0)
* - beta : weighting parameter for sliding and normal opening (default:
* 0)
* - G_cI : fracture energy for mode I (default: 0)
* - G_cII : fracture energy for mode II (default: 0)
* - penalty : stiffness in compression to prevent penetration
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialCohesiveBilinear
: public MaterialCohesiveLinear<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialCohesiveBilinear(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material computed parameter
void initMaterial() override;
/// set material parameters for new elements
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
protected:
/// constitutive law
- void computeTraction(const Array<Real> & normal, ElementType el_type,
+ void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/**
* Scale traction sigma_c according to the volume of the
* two elements surrounding an element
*/
- void scaleTraction(const Element & el, Vector<Real> & sigma_c_vec);
+ template <typename D1>
+ void scaleTraction(const Element & el, Eigen::MatrixBase<D1> & sigma_c_vec);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// elastic limit displacement
Real delta_0;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
//#include "material_cohesive_elastic_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_COHESIVE_BILINEAR_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc
index f9ce8ee20..39f3dcafe 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc
@@ -1,345 +1,310 @@
/**
* @file material_cohesive_exponential.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Mon Jul 09 2012
* @date last modification: Thu Feb 20 2020
*
* @brief Exponential irreversible cohesive law of mixed mode loading
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_exponential.hh"
#include "dof_synchronizer.hh"
#include "solid_mechanics_model.hh"
#include "sparse_matrix.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialCohesiveExponential<spatial_dimension>::MaterialCohesiveExponential(
+template <Int dim>
+MaterialCohesiveExponential<dim>::MaterialCohesiveExponential(
SolidMechanicsModel & model, const ID & id)
: MaterialCohesive(model, id) {
AKANTU_DEBUG_IN();
this->registerParam("beta", beta, Real(0.), _pat_parsable, "Beta parameter");
this->registerParam("exponential_penalty", exp_penalty, true, _pat_parsable,
"Is contact penalty following the exponential law?");
this->registerParam(
"contact_tangent", contact_tangent, Real(1.0), _pat_parsable,
"Ratio of contact tangent over the initial exponential tangent");
// this->initInternalArray(delta_max, 1, _ek_cohesive);
use_previous_delta_max = true;
AKANTU_DEBUG_OUT();
}
+
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveExponential<spatial_dimension>::initMaterial() {
+template <Int dim> void MaterialCohesiveExponential<dim>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialCohesive::initMaterial();
if ((exp_penalty) && (contact_tangent != 1)) {
contact_tangent = 1;
AKANTU_DEBUG_WARNING("The parsed paramter <contact_tangent> is forced to "
"1.0 when the contact penalty follows the exponential "
"law");
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveExponential<spatial_dimension>::computeTraction(
- const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
+template <Int dim>
+void MaterialCohesiveExponential<dim>::computeTraction(ElementType el_type,
+ GhostType ghost_type) {
AKANTU_DEBUG_IN();
- /// define iterators
- auto traction_it = tractions(el_type, ghost_type).begin(spatial_dimension);
- auto opening_it = opening(el_type, ghost_type).begin(spatial_dimension);
- auto normal_it = normal.begin(spatial_dimension);
- auto traction_end = tractions(el_type, ghost_type).end(spatial_dimension);
- auto delta_max_it = delta_max(el_type, ghost_type).begin();
- auto delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin();
-
/// compute scalars
Real beta2 = beta * beta;
/// loop on each quadrature point
- for (; traction_it != traction_end; ++traction_it, ++opening_it, ++normal_it,
- ++delta_max_it, ++delta_max_prev_it) {
+ for (auto && data : zip(make_view<dim>(tractions(el_type, ghost_type)),
+ make_view<dim>(opening(el_type, ghost_type)),
+ make_view<dim>(normals(el_type, ghost_type)),
+ delta_max(el_type, ghost_type),
+ delta_max.previous(el_type, ghost_type))) {
+ auto & traction = std::get<0>(data);
+ auto & opening = std::get<1>(data);
+ auto & normal = std::get<2>(data);
+ auto & delta_max = std::get<3>(data);
+ auto & delta_max_prev = std::get<4>(data);
/// compute normal and tangential opening vectors
- Real normal_opening_norm = opening_it->dot(*normal_it);
- Vector<Real> normal_opening(spatial_dimension);
- normal_opening = (*normal_it);
- normal_opening *= normal_opening_norm;
-
- Vector<Real> tangential_opening(spatial_dimension);
- tangential_opening = *opening_it;
- tangential_opening -= normal_opening;
+ Real normal_opening_norm = opening.dot(normal);
+ auto && normal_opening = normal * normal_opening_norm;
+ auto && tangential_opening = opening - normal_opening;
Real tangential_opening_norm = tangential_opening.norm();
/**
* compute effective opening displacement
* @f$ \delta = \sqrt{
* \beta^2 \Delta_t^2 + \Delta_n^2 } @f$
*/
- Real delta = tangential_opening_norm;
- delta *= delta * beta2;
- delta += normal_opening_norm * normal_opening_norm;
-
- delta = sqrt(delta);
+ Real delta =
+ std::sqrt(tangential_opening_norm * tangential_opening_norm * beta2 +
+ normal_opening_norm * normal_opening_norm);
if ((normal_opening_norm < 0) &&
(std::abs(normal_opening_norm) > Math::getTolerance())) {
- Vector<Real> op_n(*normal_it);
- op_n *= normal_opening_norm;
- Vector<Real> delta_s(*opening_it);
- delta_s -= op_n;
+ auto && delta_s = opening - normal_opening;
delta = tangential_opening_norm * beta;
- computeCoupledTraction(*traction_it, *normal_it, delta, delta_s,
- *delta_max_it, *delta_max_prev_it);
+ computeCoupledTraction(traction, normal, delta, delta_s, delta_max,
+ delta_max_prev);
- computeCompressiveTraction(*traction_it, *normal_it, normal_opening_norm,
- *opening_it);
+ computeCompressiveTraction(traction, normal, normal_opening_norm,
+ opening);
- } else {
- computeCoupledTraction(*traction_it, *normal_it, delta, *opening_it,
- *delta_max_it, *delta_max_prev_it);
- }
+ } else
+ computeCoupledTraction(traction, normal, delta, opening, delta_max,
+ delta_max_prev);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTraction(
- Vector<Real> & tract, const Vector<Real> & normal, Real delta,
- const Vector<Real> & opening, Real & delta_max_new, Real delta_max) {
- AKANTU_DEBUG_IN();
-
+template <Int dim>
+template <class D1, class D2, class D3>
+void MaterialCohesiveExponential<dim>::computeCoupledTraction(
+ Eigen::MatrixBase<D1> & tract, const Eigen::MatrixBase<D2> & normal,
+ Real delta, const Eigen::MatrixBase<D3> & opening, Real & delta_max_new,
+ Real delta_max) {
/// full damage case
if (std::abs(delta) < Math::getTolerance()) {
/// set traction to zero
tract.zero();
- } else { /// element not fully damaged
- /**
- * Compute traction loading @f$ \mathbf{T} =
- * e \sigma_c \frac{\delta}{\delta_c} e^{-\delta/ \delta_c}@f$
- */
- /**
- * Compute traction unloading @f$ \mathbf{T} =
- * \frac{t_{max}}{\delta_{max}} \delta @f$
- */
- Real beta2 = beta * beta;
- Real normal_open_norm = opening.dot(normal);
- Vector<Real> op_n_n(spatial_dimension);
- op_n_n = normal;
- op_n_n *= (1 - beta2);
- op_n_n *= normal_open_norm;
- tract = beta2 * opening;
- tract += op_n_n;
-
- delta_max_new = std::max(delta_max, delta);
- tract *=
- std::exp(1.) * sigma_c * std::exp(-delta_max_new / delta_c) / delta_c;
+ return;
}
- AKANTU_DEBUG_OUT();
+
+ /// element not fully damaged
+ /**
+ * Compute traction loading @f$ \mathbf{T} =
+ * e \sigma_c \frac{\delta}{\delta_c} e^{-\delta/ \delta_c}@f$
+ */
+ /**
+ * Compute traction unloading @f$ \mathbf{T} =
+ * \frac{t_{max}}{\delta_{max}} \delta @f$
+ */
+ Real beta2 = beta * beta;
+ Real normal_open_norm = opening.dot(normal);
+
+ delta_max_new = std::max(delta_max, delta);
+ auto && op_n_n = normal * (1 - beta2) * normal_open_norm;
+ tract = (beta2 * opening + op_n_n) * std::exp(1.) * sigma_c *
+ std::exp(-delta_max_new / delta_c) / delta_c;
}
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveExponential<spatial_dimension>::computeCompressiveTraction(
- Vector<Real> & tract, const Vector<Real> & normal, Real delta_n,
- __attribute__((unused)) const Vector<Real> & opening) {
+/* ------------------------------------------------------------------------- */
+template <Int dim>
+template <class D1, class D2, class D3>
+void MaterialCohesiveExponential<dim>::computeCompressiveTraction(
+ Eigen::MatrixBase<D1> & tract, const Eigen::MatrixBase<D2> & normal,
+ Real delta_n, const Eigen::MatrixBase<D3> & /*opening*/) {
Vector<Real> temp_tract(normal);
if (exp_penalty) {
temp_tract *= delta_n * std::exp(1) * sigma_c *
std::exp(-delta_n / delta_c) / delta_c;
} else {
Real initial_tg =
contact_tangent * std::exp(1.) * sigma_c * delta_n / delta_c;
temp_tract *= initial_tg;
}
tract += temp_tract;
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveExponential<spatial_dimension>::computeTangentTraction(
- ElementType el_type, Array<Real> & tangent_matrix,
- const Array<Real> & normal, GhostType ghost_type) {
+template <Int dim>
+void MaterialCohesiveExponential<dim>::computeTangentTraction(
+ ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- auto tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension);
- auto tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension);
- auto normal_it = normal.begin(spatial_dimension);
- auto opening_it = opening(el_type, ghost_type).begin(spatial_dimension);
- auto delta_max_it = delta_max.previous(el_type, ghost_type).begin();
-
Real beta2 = beta * beta;
/**
* compute tangent matrix @f$ \frac{\partial \mathbf{t}}
* {\partial \delta} = \hat{\mathbf{t}} \otimes
* \frac{\partial (t/\delta)}{\partial \delta}
* \frac{\hat{\mathbf{t}}}{\delta}+ \frac{t}{\delta} [ \beta^2 \mathbf{I} +
* (1-\beta^2) (\mathbf{n} \otimes \mathbf{n})] @f$
**/
/**
* In which @f$
* \frac{\partial(t/ \delta)}{\partial \delta} =
* \left\{\begin{array} {l l}
* -e \frac{\sigma_c}{\delta_c^2 }e^{-\delta / \delta_c} & \quad if
* \delta \geq \delta_{max} \\
* 0 & \quad if \delta < \delta_{max}, \delta_n > 0
* \end{array}\right. @f$
**/
- for (; tangent_it != tangent_end;
- ++tangent_it, ++normal_it, ++opening_it, ++delta_max_it) {
+ for (auto && data : zip(make_view<dim, dim>(tangent_matrix),
+ make_view<dim>(opening(el_type, ghost_type)),
+ make_view<dim>(normals(el_type, ghost_type)),
+ delta_max.previous(el_type, ghost_type))) {
+ auto && tangent = std::get<0>(data);
+ auto && opening = std::get<1>(data);
+ auto && normal = std::get<2>(data);
+ auto && delta_max_prev = std::get<3>(data);
- Real normal_opening_norm = opening_it->dot(*normal_it);
- Vector<Real> normal_opening(spatial_dimension);
- normal_opening = (*normal_it);
- normal_opening *= normal_opening_norm;
+ Real normal_opening_norm = opening.dot(normal);
- Vector<Real> tangential_opening(spatial_dimension);
- tangential_opening = *opening_it;
- tangential_opening -= normal_opening;
+ auto && normal_opening = normal * normal_opening_norm;
+ auto && tangential_opening = opening - normal_opening;
Real tangential_opening_norm = tangential_opening.norm();
- Real delta = tangential_opening_norm;
- delta *= delta * beta2;
- delta += normal_opening_norm * normal_opening_norm;
- delta = sqrt(delta);
+ auto delta =
+ std::sqrt(tangential_opening_norm * tangential_opening_norm * beta2 +
+ normal_opening_norm * normal_opening_norm);
if ((normal_opening_norm < 0) &&
(std::abs(normal_opening_norm) > Math::getTolerance())) {
- Vector<Real> op_n(*normal_it);
- op_n *= normal_opening_norm;
- Vector<Real> delta_s(*opening_it);
- delta_s -= op_n;
+ auto && delta_s = opening - normal_opening;
delta = tangential_opening_norm * beta;
- computeCoupledTangent(*tangent_it, *normal_it, delta, delta_s,
- *delta_max_it);
+ computeCoupledTangent(tangent, normal, delta, delta_s, delta_max_prev);
- computeCompressivePenalty(*tangent_it, *normal_it, normal_opening_norm);
-
- } else {
- computeCoupledTangent(*tangent_it, *normal_it, delta, *opening_it,
- *delta_max_it);
- }
+ computeCompressivePenalty(tangent, normal, normal_opening_norm);
+ } else
+ computeCoupledTangent(tangent, normal, delta, opening, delta_max_prev);
}
AKANTU_DEBUG_OUT();
}
+
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTangent(
- Matrix<Real> & tangent, const Vector<Real> & normal, Real delta,
- const Vector<Real> & opening, Real /*unused*/) {
+template <Int dim>
+template <class D1, class D2, class D3>
+void MaterialCohesiveExponential<dim>::computeCoupledTangent(
+ Eigen::MatrixBase<D1> & tangent, const Eigen::MatrixBase<D2> & normal,
+ Real delta, const Eigen::MatrixBase<D3> & opening,
+ Real /* delta_max_new */) {
AKANTU_DEBUG_IN();
- Real beta2 = beta * beta;
- Matrix<Real> J(spatial_dimension, spatial_dimension);
- J.eye(beta2);
+ auto beta2 = beta * beta;
+ auto J = Matrix<Real, dim, dim>::Identity() * beta2;
if (std::abs(delta) < Math::getTolerance()) {
delta = Math::getTolerance();
}
- Real opening_normal;
- opening_normal = opening.dot(normal);
+ auto opening_normal = opening.dot(normal);
- Vector<Real> delta_e(normal);
- delta_e *= opening_normal;
- delta_e *= (1. - beta2);
- delta_e += (beta2 * opening);
+ auto && delta_e = normal * opening_normal * (1. - beta2) + beta2 * opening;
- Real exponent = std::exp(1. - delta / delta_c) * sigma_c / delta_c;
+ auto exponent = std::exp(1. - delta / delta_c) * sigma_c / delta_c;
- Matrix<Real> first_term(spatial_dimension, spatial_dimension);
- first_term.outerProduct(normal, normal);
- first_term *= (1. - beta2);
- first_term += J;
+ auto && first_term = normal * normal.transpose() * (1. - beta2) + J;
- Matrix<Real> second_term(spatial_dimension, spatial_dimension);
- second_term.outerProduct(delta_e, delta_e);
- second_term /= delta;
- second_term /= delta_c;
+ auto && second_term = delta_e * delta_e.transpose() / delta / delta_c;
- Matrix<Real> diff(first_term);
- diff -= second_term;
-
- tangent = diff;
- tangent *= exponent;
+ tangent = (first_term - second_term) * exponent;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveExponential<spatial_dimension>::computeCompressivePenalty(
- Matrix<Real> & tangent, const Vector<Real> & normal, Real delta_n) {
+template <Int dim>
+template <class D1, class D2>
+void MaterialCohesiveExponential<dim>::computeCompressivePenalty(
+ Eigen::MatrixBase<D1> & tangent, const Eigen::MatrixBase<D2> & normal,
+ Real delta_n) {
- if (!exp_penalty) {
+ if (not exp_penalty) {
delta_n = 0.;
}
- Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
- n_outer_n.outerProduct(normal, normal);
+ auto && n_outer_n = normal * normal.transpose();
- Real normal_tg = contact_tangent * std::exp(1.) * sigma_c *
+ auto normal_tg = contact_tangent * std::exp(1.) * sigma_c *
std::exp(-delta_n / delta_c) * (1. - delta_n / delta_c) /
delta_c;
- n_outer_n *= normal_tg;
-
- tangent += n_outer_n;
+ tangent = tangent + n_outer_n * normal_tg;
}
-INSTANTIATE_MATERIAL(cohesive_exponential, MaterialCohesiveExponential);
+/* -------------------------------------------------------------------------- */
+template class MaterialCohesiveExponential<1>;
+template class MaterialCohesiveExponential<2>;
+template class MaterialCohesiveExponential<3>;
+static bool material_is_alocated_cohesive_exponential =
+ instantiateMaterial<MaterialCohesiveExponential>("cohesive_exponential");
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.hh
index 69c889175..9fde9b79f 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.hh
@@ -1,122 +1,129 @@
/**
* @file material_cohesive_exponential.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Feb 20 2020
*
* @brief Exponential irreversible cohesive law of mixed mode loading
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material_cohesive.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_COHESIVE_EXPONENTIAL_HH_
#define AKANTU_MATERIAL_COHESIVE_EXPONENTIAL_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* Cohesive material Exponential damage
*
* parameters in the material files :
* - sigma_c : critical stress sigma_c (default: 0)
* - beta : weighting parameter for sliding and normal opening (default:
* 0)
* - delta_c : critical opening (default: 0)
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialCohesiveExponential : public MaterialCohesive {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialCohesiveExponential(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// Initialization
void initMaterial() override;
/// constitutive law
- void computeTraction(const Array<Real> & normal, ElementType el_type,
+ void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute the tangent stiffness matrix for an element type
void computeTangentTraction(ElementType el_type, Array<Real> & tangent_matrix,
- const Array<Real> & normal,
GhostType ghost_type = _not_ghost) override;
private:
- void computeCoupledTraction(Vector<Real> & tract, const Vector<Real> & normal,
- Real delta, const Vector<Real> & opening,
+ template <class D1, class D2, class D3>
+ void computeCoupledTraction(Eigen::MatrixBase<D1> & tract,
+ const Eigen::MatrixBase<D2> & normal, Real delta,
+ const Eigen::MatrixBase<D3> & opening,
Real & delta_max_new, Real delta_max);
- void computeCompressiveTraction(Vector<Real> & tract,
- const Vector<Real> & normal, Real delta_n,
- const Vector<Real> & opening);
-
- void computeCoupledTangent(Matrix<Real> & tangent,
- const Vector<Real> & normal, Real delta,
- const Vector<Real> & opening, Real delta_max_new);
-
- void computeCompressivePenalty(Matrix<Real> & tangent,
- const Vector<Real> & normal, Real delta_n);
+ template <class D1, class D2, class D3>
+ void computeCompressiveTraction(Eigen::MatrixBase<D1> & tract,
+ const Eigen::MatrixBase<D2> & normal,
+ Real delta_n,
+ const Eigen::MatrixBase<D3> & opening);
+
+ template <class D1, class D2, class D3>
+ void computeCoupledTangent(Eigen::MatrixBase<D1> & tangent,
+ const Eigen::MatrixBase<D2> & normal, Real delta,
+ const Eigen::MatrixBase<D3> & opening,
+ Real delta_max_new);
+
+ template <class D1, class D2>
+ void computeCompressivePenalty(Eigen::MatrixBase<D1> & tangent,
+ const Eigen::MatrixBase<D2> & normal,
+ Real delta_n);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// beta parameter
Real beta;
/// contact penalty = initial slope ?
bool exp_penalty;
/// Ratio of contact tangent over the initial exponential tangent
Real contact_tangent;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
// #include "material_cohesive_exponential_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_MATERIAL_COHESIVE_EXPONENTIAL_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
index 7ecd9b191..b9aa6c2f0 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
@@ -1,433 +1,348 @@
/**
* @file material_cohesive_linear.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Feb 22 2012
* @date last modification: Thu Jan 14 2021
*
* @brief Linear irreversible cohesive law of mixed mode loading with
* random stress definition for extrinsic type
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
#include "dof_synchronizer.hh"
#include "solid_mechanics_model_cohesive.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialCohesiveLinear<spatial_dimension>::MaterialCohesiveLinear(
- SolidMechanicsModel & model, const ID & id)
+template <Int dim>
+MaterialCohesiveLinear<dim>::MaterialCohesiveLinear(SolidMechanicsModel & model,
+ const ID & id)
: MaterialCohesive(model, id), sigma_c_eff("sigma_c_eff", *this),
delta_c_eff("delta_c_eff", *this),
insertion_stress("insertion_stress", *this) {
AKANTU_DEBUG_IN();
this->registerParam("beta", beta, Real(0.), _pat_parsable | _pat_readable,
"Beta parameter");
this->registerParam("G_c", G_c, Real(0.), _pat_parsable | _pat_readable,
"Mode I fracture energy");
this->registerParam("penalty", penalty, Real(0.),
_pat_parsable | _pat_readable, "Penalty coefficient");
this->registerParam("volume_s", volume_s, Real(0.),
_pat_parsable | _pat_readable,
"Reference volume for sigma_c scaling");
this->registerParam("m_s", m_s, Real(1.), _pat_parsable | _pat_readable,
"Weibull exponent for sigma_c scaling");
this->registerParam("kappa", kappa, Real(1.), _pat_parsable | _pat_readable,
"Kappa parameter");
this->registerParam(
"contact_after_breaking", contact_after_breaking, false,
_pat_parsable | _pat_readable,
"Activation of contact when the elements are fully damaged");
this->registerParam("max_quad_stress_insertion", max_quad_stress_insertion,
false, _pat_parsable | _pat_readable,
"Insertion of cohesive element when stress is high "
"enough just on one quadrature point");
this->registerParam("recompute", recompute, false,
_pat_parsable | _pat_modifiable, "recompute solution");
this->use_previous_delta_max = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinear<spatial_dimension>::initMaterial() {
+template <Int dim> void MaterialCohesiveLinear<dim>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialCohesive::initMaterial();
sigma_c_eff.initialize(1);
delta_c_eff.initialize(1);
- insertion_stress.initialize(spatial_dimension);
+ insertion_stress.initialize(dim);
if (not Math::are_float_equal(delta_c, 0.)) {
delta_c_eff.setDefaultValue(delta_c);
} else {
delta_c_eff.setDefaultValue(2 * G_c / sigma_c);
}
if (model->getIsExtrinsic()) {
scaleInsertionTraction();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinear<spatial_dimension>::updateInternalParameters() {
+template <Int dim>
+void MaterialCohesiveLinear<dim>::updateInternalParameters() {
/// compute scalars
beta2_kappa2 = beta * beta / kappa / kappa;
beta2_kappa = beta * beta / kappa;
if (Math::are_float_equal(beta, 0)) {
beta2_inv = 0;
} else {
beta2_inv = 1. / beta / beta;
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinear<spatial_dimension>::scaleInsertionTraction() {
+template <Int dim> void MaterialCohesiveLinear<dim>::scaleInsertionTraction() {
AKANTU_DEBUG_IN();
// do nothing if volume_s hasn't been specified by the user
if (Math::are_float_equal(volume_s, 0.)) {
return;
}
- const Mesh & mesh_facets = model->getMeshFacets();
+ const auto & mesh_facets = model->getMeshFacets();
const auto & fe_engine = model->getFEEngine();
const auto & fe_engine_facet = model->getFEEngine("FacetsFEEngine");
- Real base_sigma_c = sigma_c;
-
- for (auto && type_facet : mesh_facets.elementTypes(spatial_dimension - 1)) {
- const Array<std::vector<Element>> & facet_to_element =
+ for (const auto & type_facet : mesh_facets.elementTypes(dim - 1)) {
+ const auto & facet_to_element =
mesh_facets.getElementToSubelement(type_facet);
- UInt nb_facet = facet_to_element.size();
- UInt nb_quad_per_facet = fe_engine_facet.getNbIntegrationPoints(type_facet);
-
- // iterator to modify sigma_c for all the quadrature points of a facet
- auto sigma_c_iterator =
- sigma_c(type_facet).begin_reinterpret(nb_quad_per_facet, nb_facet);
+ auto nb_quad_per_facet = fe_engine_facet.getNbIntegrationPoints(type_facet);
- for (UInt f = 0; f < nb_facet; ++f, ++sigma_c_iterator) {
-
- const std::vector<Element> & element_list = facet_to_element(f);
+ for (auto data :
+ enumerate(make_view(sigma_c(type_facet), nb_quad_per_facet))) {
+ auto f = std::get<0>(data);
+ auto && sigma_c = std::get<1>(data);
// compute bounding volume
Real volume = 0;
- auto elem = element_list.begin();
- auto elem_end = element_list.end();
-
- for (; elem != elem_end; ++elem) {
- if (*elem == ElementNull) {
+ for (auto && elem : facet_to_element(f)) {
+ if (elem == ElementNull) {
continue;
}
// unit vector for integration in order to obtain the volume
- UInt nb_quadrature_points =
- fe_engine.getNbIntegrationPoints(elem->type);
- Vector<Real> unit_vector(nb_quadrature_points, 1);
+ auto nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem.type);
+ Vector<Real> unit_vector(nb_quadrature_points);
+ unit_vector.fill(1);
- volume += fe_engine.integrate(unit_vector, elem->type, elem->element,
- elem->ghost_type);
+ volume += fe_engine.integrate(unit_vector, elem);
}
// scale sigma_c
- *sigma_c_iterator -= base_sigma_c;
- *sigma_c_iterator *= std::pow(volume_s / volume, 1. / m_s);
- *sigma_c_iterator += base_sigma_c;
+ Vector<Real> base_sigma_c_v(sigma_c.rows());
+ sigma_c = (sigma_c.colwise() - base_sigma_c_v) *
+ std::pow(volume_s / volume, 1. / m_s) +
+ base_sigma_c_v;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinear<spatial_dimension>::checkInsertion(
- bool check_only) {
+template <Int dim>
+void MaterialCohesiveLinear<dim>::checkInsertion(bool check_only) {
AKANTU_DEBUG_IN();
- const Mesh & mesh_facets = model->getMeshFacets();
- CohesiveElementInserter & inserter = model->getElementInserter();
+ const auto & mesh_facets = model->getMeshFacets();
+ auto & inserter = model->getElementInserter();
+
+ for (const auto & type_facet : mesh_facets.elementTypes(dim - 1)) {
+ auto type_cohesive = FEEngine::getCohesiveElementType(type_facet);
- for (auto && type_facet : mesh_facets.elementTypes(spatial_dimension - 1)) {
- ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
const auto & facets_check = inserter.getCheckFacets(type_facet);
auto & f_insertion = inserter.getInsertionFacets(type_facet);
- auto & f_filter = facet_filter(type_facet);
auto & sig_c_eff = sigma_c_eff(type_cohesive);
auto & del_c = delta_c_eff(type_cohesive);
auto & ins_stress = insertion_stress(type_cohesive);
auto & trac_old = tractions.previous(type_cohesive);
const auto & f_stress = model->getStressOnFacets(type_facet);
- const auto & sigma_lim = sigma_c(type_facet);
- UInt nb_quad_facet =
+ const auto & facet_filter_array = facet_filter(type_facet);
+ const auto & sigma_limit_array = sigma_c(type_facet);
+
+ auto nb_quad_facet =
model->getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
#ifndef AKANTU_NDEBUG
- UInt nb_quad_cohesive = model->getFEEngine("CohesiveFEEngine")
+ auto nb_quad_cohesive = model->getFEEngine("CohesiveFEEngine")
.getNbIntegrationPoints(type_cohesive);
AKANTU_DEBUG_ASSERT(nb_quad_cohesive == nb_quad_facet,
"The cohesive element and the corresponding facet do "
"not have the same numbers of integration points");
#endif
- UInt nb_facet = f_filter.size();
- // if (nb_facet == 0) continue;
-
- auto sigma_lim_it = sigma_lim.begin();
-
- Matrix<Real> stress_tmp(spatial_dimension, spatial_dimension);
- Matrix<Real> normal_traction(spatial_dimension, nb_quad_facet);
+ Matrix<Real, dim, dim> stress_tmp;
+ Matrix<Real> normal_traction(dim, nb_quad_facet);
Vector<Real> stress_check(nb_quad_facet);
- UInt sp2 = spatial_dimension * spatial_dimension;
const auto & tangents = model->getTangents(type_facet);
const auto & normals = model->getFEEngine("FacetsFEEngine")
.getNormalsOnIntegrationPoints(type_facet);
- auto normal_begin = normals.begin(spatial_dimension);
- auto tangent_begin = tangents.begin(tangents.getNbComponent());
- auto facet_stress_begin =
- f_stress.begin(spatial_dimension, spatial_dimension * 2);
+ auto normal_begin = make_view<dim>(normals).begin();
+ auto tangent_begin = make_view<dim, (dim == 3 ? 2 : 1)>(tangents).begin();
+ auto facet_stress_begin = make_view(f_stress, dim, dim, 2).begin();
std::vector<Real> new_sigmas;
std::vector<Vector<Real>> new_normal_traction;
std::vector<Real> new_delta_c;
// loop over each facet belonging to this material
- for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it) {
- UInt facet = f_filter(f);
+ for (auto && [facet, sigma_limit] :
+ zip(facet_filter_array, sigma_limit_array)) {
// skip facets where check shouldn't be realized
if (!facets_check(facet)) {
continue;
}
// compute the effective norm on each quadrature point of the facet
- for (UInt q = 0; q < nb_quad_facet; ++q) {
- UInt current_quad = facet * nb_quad_facet + q;
- const Vector<Real> & normal = normal_begin[current_quad];
- const Vector<Real> & tangent = tangent_begin[current_quad];
- const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad];
+ for (Int q = 0; q < nb_quad_facet; ++q) {
+ auto current_quad = facet * nb_quad_facet + q;
+ auto && normal = normal_begin[current_quad];
+ auto && tangent = tangent_begin[current_quad];
+ auto && facet_stress = facet_stress_begin[current_quad];
// compute average stress on the current quadrature point
- Matrix<Real> stress_1(facet_stress_it.storage(), spatial_dimension,
- spatial_dimension);
+ auto && stress_1 = facet_stress(0);
+ auto && stress_2 = facet_stress(1);
- Matrix<Real> stress_2(facet_stress_it.storage() + sp2,
- spatial_dimension, spatial_dimension);
-
- stress_tmp.copy(stress_1);
- stress_tmp += stress_2;
- stress_tmp /= 2.;
-
- Vector<Real> normal_traction_vec(normal_traction(q));
+ auto && stress_avg = (stress_1 + stress_2) / 2.;
// compute normal and effective stress
- stress_check(q) = computeEffectiveNorm(stress_tmp, normal, tangent,
- normal_traction_vec);
+ stress_check(q) = computeEffectiveNorm(stress_avg, normal, tangent,
+ normal_traction(q));
}
// verify if the effective stress overcomes the threshold
- Real final_stress = stress_check.mean();
+ auto final_stress = stress_check.mean();
if (max_quad_stress_insertion) {
- final_stress = *std::max_element(
- stress_check.storage(), stress_check.storage() + nb_quad_facet);
+ final_stress = *std::max_element(stress_check.data(),
+ stress_check.data() + nb_quad_facet);
}
- if (final_stress > *sigma_lim_it) {
+ if (final_stress > sigma_limit) {
f_insertion(facet) = true;
if (check_only) {
continue;
}
// store the new cohesive material parameters for each quadrature
// point
- for (UInt q = 0; q < nb_quad_facet; ++q) {
- Real new_sigma = stress_check(q);
- Vector<Real> normal_traction_vec(normal_traction(q));
+ for (Int q = 0; q < nb_quad_facet; ++q) {
+ auto new_sigma = stress_check(q);
+ auto && normal_traction_vec = normal_traction(q);
- if (spatial_dimension != 3) {
+ if (dim != 3) {
normal_traction_vec *= -1.;
}
new_sigmas.push_back(new_sigma);
new_normal_traction.push_back(normal_traction_vec);
Real new_delta;
// set delta_c in function of G_c or a given delta_c value
if (Math::are_float_equal(delta_c, 0.)) {
new_delta = 2 * G_c / new_sigma;
} else {
- new_delta = (*sigma_lim_it) / new_sigma * delta_c;
+ new_delta = sigma_limit / new_sigma * delta_c;
}
new_delta_c.push_back(new_delta);
}
}
}
// update material data for the new elements
- UInt old_nb_quad_points = sig_c_eff.size();
- UInt new_nb_quad_points = new_sigmas.size();
+ auto old_nb_quad_points = sig_c_eff.size();
+ Int new_nb_quad_points = new_sigmas.size();
sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points);
ins_stress.resize(old_nb_quad_points + new_nb_quad_points);
trac_old.resize(old_nb_quad_points + new_nb_quad_points);
del_c.resize(old_nb_quad_points + new_nb_quad_points);
- for (UInt q = 0; q < new_nb_quad_points; ++q) {
+ for (Int q = 0; q < new_nb_quad_points; ++q) {
sig_c_eff(old_nb_quad_points + q) = new_sigmas[q];
del_c(old_nb_quad_points + q) = new_delta_c[q];
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
- ins_stress(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
- trac_old(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
+ for (Int d = 0; d < dim; ++d) {
+ ins_stress(old_nb_quad_points + q, d) = new_normal_traction[q](d);
+ trac_old(old_nb_quad_points + q, d) = new_normal_traction[q](d);
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinear<spatial_dimension>::computeTraction(
- const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- /// define iterators
- auto traction_it = tractions(el_type, ghost_type).begin(spatial_dimension);
- auto opening_it = opening(el_type, ghost_type).begin(spatial_dimension);
- auto contact_traction_it =
- contact_tractions(el_type, ghost_type).begin(spatial_dimension);
- auto contact_opening_it =
- contact_opening(el_type, ghost_type).begin(spatial_dimension);
-
- auto normal_it = normal.begin(spatial_dimension);
- auto traction_end = tractions(el_type, ghost_type).end(spatial_dimension);
- auto sigma_c_it = sigma_c_eff(el_type, ghost_type).begin();
- auto delta_max_it = delta_max(el_type, ghost_type).begin();
- auto delta_c_it = delta_c_eff(el_type, ghost_type).begin();
- auto damage_it = damage(el_type, ghost_type).begin();
- auto insertion_stress_it =
- insertion_stress(el_type, ghost_type).begin(spatial_dimension);
-
- Vector<Real> normal_opening(spatial_dimension);
- Vector<Real> tangential_opening(spatial_dimension);
-
- /// loop on each quadrature point
- for (; traction_it != traction_end;
- ++traction_it, ++opening_it, ++normal_it, ++sigma_c_it, ++delta_max_it,
- ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it,
- ++contact_opening_it) {
- Real normal_opening_norm{0};
- Real tangential_opening_norm{0};
- bool penetration{false};
- this->computeTractionOnQuad(
- *traction_it, *opening_it, *normal_it, *delta_max_it, *delta_c_it,
- *insertion_stress_it, *sigma_c_it, normal_opening, tangential_opening,
- normal_opening_norm, tangential_opening_norm, *damage_it, penetration,
- *contact_traction_it, *contact_opening_it);
+template <Int dim>
+void MaterialCohesiveLinear<dim>::computeTraction(ElementType el_type,
+ GhostType ghost_type) {
+ for (auto && args : getArguments(el_type, ghost_type)) {
+ this->computeTractionOnQuad(args);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinear<spatial_dimension>::computeTangentTraction(
- ElementType el_type, Array<Real> & tangent_matrix,
- const Array<Real> & normal, GhostType ghost_type) {
+template <Int dim>
+void MaterialCohesiveLinear<dim>::computeTangentTraction(
+ ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- /// define iterators
- auto tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension);
-
- auto tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension);
-
- auto normal_it = normal.begin(spatial_dimension);
-
- auto opening_it = opening(el_type, ghost_type).begin(spatial_dimension);
-
- /// NB: delta_max_it points on delta_max_previous, i.e. the
- /// delta_max related to the solution of the previous incremental
- /// step
- auto delta_max_it = delta_max.previous(el_type, ghost_type).begin();
- auto sigma_c_it = sigma_c_eff(el_type, ghost_type).begin();
- auto delta_c_it = delta_c_eff(el_type, ghost_type).begin();
- auto damage_it = damage(el_type, ghost_type).begin();
- auto contact_opening_it =
- contact_opening(el_type, ghost_type).begin(spatial_dimension);
-
- Vector<Real> normal_opening(spatial_dimension);
- Vector<Real> tangential_opening(spatial_dimension);
-
- for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it,
- ++delta_max_it, ++sigma_c_it, ++delta_c_it,
- ++damage_it, ++contact_opening_it) {
- Real normal_opening_norm{0};
- Real tangential_opening_norm{0};
- bool penetration{false};
- this->computeTangentTractionOnQuad(
- *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it,
- *normal_it, normal_opening, tangential_opening, normal_opening_norm,
- tangential_opening_norm, *damage_it, penetration, *contact_opening_it);
+ for (auto && [args, tangent] : zip(getArguments(el_type, ghost_type),
+ make_view<dim, dim>(tangent_matrix))) {
+ computeTangentTractionOnQuad(tangent, args);
}
AKANTU_DEBUG_OUT();
}
-/* -------------------------------------------------------------------------- */
-INSTANTIATE_MATERIAL(cohesive_linear, MaterialCohesiveLinear);
+/* -------------------------------------------------------------------------- */
+template class MaterialCohesiveLinear<1>;
+template class MaterialCohesiveLinear<2>;
+template class MaterialCohesiveLinear<3>;
+static bool material_is_alocated_cohesive_linear =
+ instantiateMaterial<MaterialCohesiveLinear>("cohesive_linear");
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
index c590830d2..a82f1e9c4 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
@@ -1,188 +1,194 @@
/**
* @file material_cohesive_linear.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Mon Sep 14 2020
*
* @brief Linear irreversible cohesive law of mixed mode loading with
* random stress definition for extrinsic type
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_COHESIVE_LINEAR_HH_
#define AKANTU_MATERIAL_COHESIVE_LINEAR_HH_
namespace akantu {
/**
* Cohesive material linear damage for extrinsic case
*
* parameters in the material files :
* - sigma_c : critical stress sigma_c (default: 0)
* - beta : weighting parameter for sliding and normal opening (default:
* 0)
* - G_cI : fracture energy for mode I (default: 0)
* - G_cII : fracture energy for mode II (default: 0)
* - penalty : stiffness in compression to prevent penetration
*/
-template <UInt spatial_dimension>
-class MaterialCohesiveLinear : public MaterialCohesive {
+template <Int dim> class MaterialCohesiveLinear : public MaterialCohesive {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialCohesiveLinear(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material parameters
void initMaterial() override;
void updateInternalParameters() override;
/// check stress for cohesive elements' insertion
void checkInsertion(bool check_only = false) override;
/// compute effective stress norm for insertion check
- Real computeEffectiveNorm(const Matrix<Real> & stress,
- const Vector<Real> & normal,
- const Vector<Real> & tangent,
- Vector<Real> & normal_traction) const;
+ template <class D1, class D2, class D3, class D4>
+ Real computeEffectiveNorm(const Eigen::MatrixBase<D1> & stress,
+ const Eigen::MatrixBase<D2> & normal,
+ const Eigen::MatrixBase<D3> & tangent,
+ const Eigen::MatrixBase<D4> & normal_stress) const;
protected:
/// constitutive law
- void computeTraction(const Array<Real> & normal, ElementType el_type,
+ void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute tangent stiffness matrix
void computeTangentTraction(ElementType el_type, Array<Real> & tangent_matrix,
- const Array<Real> & normal,
GhostType ghost_type) override;
/**
* Scale insertion traction sigma_c according to the volume of the
* two elements surrounding a facet
*
* see the article: F. Zhou and J. F. Molinari "Dynamic crack
* propagation with cohesive elements: a methodology to address mesh
* dependency" International Journal for Numerical Methods in
* Engineering (2004)
*/
void scaleInsertionTraction();
+ inline decltype(auto) getArguments(ElementType element_type,
+ GhostType ghost_type) {
+ using namespace tuple;
+ return zip_append(
+ MaterialCohesive::getArguments<dim>(element_type, ghost_type),
+ "sigma_c"_n = this->sigma_c_eff(element_type, ghost_type),
+ "delta_c"_n = this->delta_c_eff(element_type, ghost_type),
+ "insertion_stress"_n =
+ make_view<dim>(this->insertion_stress(element_type, ghost_type)));
+ }
+
/// compute the traction for a given quadrature point
- inline void computeTractionOnQuad(
- Vector<Real> & traction, Vector<Real> & opening,
- const Vector<Real> & normal, Real & delta_max, const Real & delta_c,
- const Vector<Real> & insertion_stress, const Real & sigma_c,
- Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
- Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
- bool & penetration, Vector<Real> & contact_traction,
- Vector<Real> & contact_opening);
-
- inline void computeTangentTractionOnQuad(
- Matrix<Real> & tangent, Real & delta_max, const Real & delta_c,
- const Real & sigma_c, Vector<Real> & opening, const Vector<Real> & normal,
- Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
- Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
- bool & penetration, Vector<Real> & contact_opening);
+ template <typename Args> inline void computeTractionOnQuad(Args && args);
+
+ template <class Derived, class Args>
+ inline void computeTangentTractionOnQuad(Eigen::MatrixBase<Derived> & tangent,
+ Args && args);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get sigma_c_eff
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(InsertionTraction, sigma_c_eff, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// beta parameter
Real beta;
/// beta square inverse to compute effective norm
Real beta2_inv;
/// mode I fracture energy
Real G_c;
/// kappa parameter
Real kappa;
/// constitutive law scalar to compute delta
Real beta2_kappa2;
/// constitutive law scalar to compute traction
Real beta2_kappa;
/// penalty coefficient
Real penalty;
/// reference volume used to scale sigma_c
Real volume_s;
/// weibull exponent used to scale sigma_c
Real m_s;
/// variable defining if we are recomputing the last loading step
/// after load_reduction
bool recompute;
/// critical effective stress
RandomInternalField<Real, CohesiveInternalField> sigma_c_eff;
/// effective critical displacement (each element can have a
/// different value)
CohesiveInternalField<Real> delta_c_eff;
/// stress at insertion
CohesiveInternalField<Real> insertion_stress;
/// variable saying if there should be penalty contact also after
/// breaking the cohesive elements
bool contact_after_breaking;
/// insertion of cohesive element when stress is high enough just on
/// one quadrature point
bool max_quad_stress_insertion;
+
+ Vector<Real, dim> normal_opening;
+ Vector<Real, dim> tangential_opening;
+ Real normal_opening_norm{0.};
+ Real tangential_opening_norm{0.};
+ bool penetration{false};
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
} // namespace akantu
#include "material_cohesive_linear_inline_impl.hh"
#endif /* AKANTU_MATERIAL_COHESIVE_LINEAR_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc
index 69046e2f3..80737b4aa 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc
@@ -1,306 +1,307 @@
/**
* @file material_cohesive_linear_fatigue.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Feb 20 2015
* @date last modification: Thu Feb 20 2020
*
* @brief See material_cohesive_linear_fatigue.hh for information
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear_fatigue.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
MaterialCohesiveLinearFatigue<spatial_dimension>::MaterialCohesiveLinearFatigue(
SolidMechanicsModel & model, const ID & id)
: MaterialCohesiveLinear<spatial_dimension>(model, id),
delta_prec("delta_prec", *this), K_plus("K_plus", *this),
K_minus("K_minus", *this), T_1d("T_1d", *this),
switches("switches", *this), delta_dot_prec("delta_dot_prec", *this),
normal_regime("normal_regime", *this) {
this->registerParam("delta_f", delta_f, Real(-1.),
_pat_parsable | _pat_readable, "delta_f");
this->registerParam("progressive_delta_f", progressive_delta_f, false,
_pat_parsable | _pat_readable,
"Whether or not delta_f is equal to delta_max");
this->registerParam("count_switches", count_switches, false,
_pat_parsable | _pat_readable,
"Count the opening/closing switches per element");
this->registerParam(
"fatigue_ratio", fatigue_ratio, Real(1.), _pat_parsable | _pat_readable,
"What portion of the cohesive law is subjected to fatigue");
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialCohesiveLinearFatigue<spatial_dimension>::initMaterial() {
MaterialCohesiveLinear<spatial_dimension>::initMaterial();
// check that delta_f has a proper value or assign a defaul value
if (delta_f < 0) {
delta_f = this->delta_c_eff;
} else if (delta_f < this->delta_c_eff) {
AKANTU_ERROR("Delta_f must be greater or equal to delta_c");
}
delta_prec.initialize(1);
K_plus.initialize(1);
K_minus.initialize(1);
T_1d.initialize(1);
normal_regime.initialize(1);
if (count_switches) {
switches.initialize(1);
delta_dot_prec.initialize(1);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
void MaterialCohesiveLinearFatigue<spatial_dimension>::computeTraction(
- const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
+ ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// define iterators
auto traction_it =
this->tractions(el_type, ghost_type).begin(spatial_dimension);
auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
auto contact_traction_it =
this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
auto contact_opening_it =
this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
- auto normal_it = normal.begin(spatial_dimension);
+ auto normal_it = this->normals(el_type, ghost_type).begin(spatial_dimension);
auto traction_end =
this->tractions(el_type, ghost_type).end(spatial_dimension);
const Array<Real> & sigma_c_array = this->sigma_c_eff(el_type, ghost_type);
Array<Real> & delta_max_array = this->delta_max(el_type, ghost_type);
const Array<Real> & delta_c_array = this->delta_c_eff(el_type, ghost_type);
Array<Real> & damage_array = this->damage(el_type, ghost_type);
auto insertion_stress_it =
this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
Array<Real> & delta_prec_array = delta_prec(el_type, ghost_type);
Array<Real> & K_plus_array = K_plus(el_type, ghost_type);
Array<Real> & K_minus_array = K_minus(el_type, ghost_type);
Array<Real> & T_1d_array = T_1d(el_type, ghost_type);
Array<bool> & normal_regime_array = normal_regime(el_type, ghost_type);
Array<UInt> * switches_array = nullptr;
Array<Real> * delta_dot_prec_array = nullptr;
if (count_switches) {
switches_array = &switches(el_type, ghost_type);
delta_dot_prec_array = &delta_dot_prec(el_type, ghost_type);
}
- auto * memory_space = new Real[2 * spatial_dimension];
- Vector<Real> normal_opening(memory_space, spatial_dimension);
- Vector<Real> tangential_opening(memory_space + spatial_dimension,
- spatial_dimension);
+ Vector<Real, spatial_dimension> normal_opening;
+ Vector<Real, spatial_dimension> tangential_opening;
Real tolerance = Math::getTolerance();
/// loop on each quadrature point
- for (UInt q = 0; traction_it != traction_end; ++traction_it, ++opening_it,
- ++normal_it, ++contact_traction_it, ++insertion_stress_it,
- ++contact_opening_it, ++q) {
+ for (Int q = 0; traction_it != traction_end; ++traction_it, ++opening_it,
+ ++normal_it, ++contact_traction_it, ++insertion_stress_it,
+ ++contact_opening_it, ++q) {
/// compute normal and tangential opening vectors
Real normal_opening_norm = opening_it->dot(*normal_it);
normal_opening = (*normal_it);
normal_opening *= normal_opening_norm;
tangential_opening = *opening_it;
tangential_opening -= normal_opening;
Real tangential_opening_norm = tangential_opening.norm();
/**
* compute effective opening displacement
* @f$ \delta = \sqrt{
* \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$
*/
Real delta =
tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
bool penetration = normal_opening_norm < -tolerance;
if (not this->contact_after_breaking and
Math::are_float_equal(damage_array(q), 1.)) {
penetration = false;
}
if (penetration) {
/// use penalty coefficient in case of penetration
*contact_traction_it = normal_opening;
*contact_traction_it *= this->penalty;
*contact_opening_it = normal_opening;
/// don't consider penetration contribution for delta
*opening_it = tangential_opening;
normal_opening.zero();
} else {
delta += normal_opening_norm * normal_opening_norm;
contact_traction_it->zero();
contact_opening_it->zero();
}
delta = std::sqrt(delta);
/**
* Compute traction @f$ \mathbf{T} = \left(
* \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n
* \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1-
* \frac{\delta}{\delta_c} \right)@f$
*/
// update maximum displacement and damage
delta_max_array(q) = std::max(delta, delta_max_array(q));
damage_array(q) = std::min(delta_max_array(q) / delta_c_array(q), Real(1.));
Real delta_dot = delta - delta_prec_array(q);
// count switches if asked
if (count_switches) {
if ((delta_dot > 0. && (*delta_dot_prec_array)(q) <= 0.) ||
(delta_dot < 0. && (*delta_dot_prec_array)(q) >= 0.)) {
++((*switches_array)(q));
}
(*delta_dot_prec_array)(q) = delta_dot;
}
// set delta_f equal to delta_max if desired
if (progressive_delta_f) {
delta_f = delta_max_array(q);
}
// broken element case
if (Math::are_float_equal(damage_array(q), 1.)) {
traction_it->zero();
// just inserted element case
} else if (Math::are_float_equal(damage_array(q), 0.)) {
if (penetration) {
traction_it->zero();
} else {
*traction_it = *insertion_stress_it;
}
// initialize the 1d traction to sigma_c
T_1d_array(q) = sigma_c_array(q);
}
// normal case
else {
// if element is closed then there are zero tractions
if (delta <= tolerance) {
traction_it->zero();
// otherwise compute new tractions if the new delta is different
// than the previous one
} else if (std::abs(delta_dot) > tolerance) {
// loading case
if (delta_dot > 0.) {
if (!normal_regime_array(q)) {
// equation (4) of the article
K_plus_array(q) *= 1. - delta_dot / delta_f;
// equivalent to equation (2) of the article
T_1d_array(q) += K_plus_array(q) * delta_dot;
// in case of reloading, traction must not exceed that of the
// envelop of the cohesive law
Real max_traction =
sigma_c_array(q) * (1 - delta / delta_c_array(q));
bool max_traction_exceeded = T_1d_array(q) > max_traction;
if (max_traction_exceeded) {
T_1d_array(q) = max_traction;
}
// switch to standard linear cohesive law
if (delta_max_array(q) > fatigue_ratio * delta_c_array(q)) {
// reset delta_max to avoid big jumps in the traction
delta_max_array(q) =
sigma_c_array(q) /
(T_1d_array(q) / delta + sigma_c_array(q) / delta_c_array(q));
damage_array(q) =
std::min(delta_max_array(q) / delta_c_array(q), Real(1.));
K_minus_array(q) = sigma_c_array(q) / delta_max_array(q) *
(1. - damage_array(q));
normal_regime_array(q) = true;
} else {
// equation (3) of the article
K_minus_array(q) = T_1d_array(q) / delta;
// if the traction is following the cohesive envelop, then
// K_plus has to be reset
if (max_traction_exceeded) {
K_plus_array(q) = K_minus_array(q);
}
}
} else {
// compute stiffness according to the standard law
K_minus_array(q) =
sigma_c_array(q) / delta_max_array(q) * (1. - damage_array(q));
}
}
// unloading case
else if (!normal_regime_array(q)) {
// equation (4) of the article
K_plus_array(q) +=
(K_plus_array(q) - K_minus_array(q)) * delta_dot / delta_f;
// equivalent to equation (2) of the article
T_1d_array(q) = K_minus_array(q) * delta;
}
// applying the actual stiffness
*traction_it = tangential_opening;
*traction_it *= this->beta2_kappa;
*traction_it += normal_opening;
*traction_it *= K_minus_array(q);
}
}
// update precendent delta
delta_prec_array(q) = delta;
}
- delete[] memory_space;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(cohesive_linear_fatigue, MaterialCohesiveLinearFatigue);
+template class MaterialCohesiveLinearFatigue<1>;
+template class MaterialCohesiveLinearFatigue<2>;
+template class MaterialCohesiveLinearFatigue<3>;
+static bool material_is_alocated_cohesive_linear_fatigue =
+ instantiateMaterial<MaterialCohesiveLinearFatigue>(
+ "cohesive_linear_fatigue");
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.hh
index ec7a93cfd..980c39711 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.hh
@@ -1,133 +1,133 @@
/**
* @file material_cohesive_linear_fatigue.hh
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Feb 20 2020
*
* @brief Linear irreversible cohesive law with dissipative
* unloading-reloading cycles
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_COHESIVE_LINEAR_FATIGUE_HH_
#define AKANTU_MATERIAL_COHESIVE_LINEAR_FATIGUE_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* Linear irreversible cohesive law with dissipative
* unloading-reloading cycles
*
* This law uses two different stiffnesses during unloading and
* reloading. The implementation is based on the article entitled "A
* cohesive model for fatigue crack growth" by Nguyen, Repetto, Ortiz
* and Radovitzky (2001). This law is identical to the
* MaterialCohesiveLinear one except for the unloading-reloading
* phase.
*
* input parameter:
*
* - delta_f : it must be greater than delta_c and it is inversely
* proportional to the dissipation in the unloading-reloading
* cycles (default: delta_c)
*/
-template <UInt spatial_dimension>
+template <Int spatial_dimension>
class MaterialCohesiveLinearFatigue
: public MaterialCohesiveLinear<spatial_dimension> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
MaterialCohesiveLinearFatigue(SolidMechanicsModel & model,
const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material parameters
void initMaterial() override;
protected:
/// constitutive law
- void computeTraction(const Array<Real> & normal, ElementType el_type,
+ void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the switches
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Switches, switches, UInt);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// delta_f parameter
Real delta_f;
/// variable saying if delta_f is equal to delta_max for each
/// element when the traction is computed
bool progressive_delta_f;
/// count the opening/closing switches per element
bool count_switches;
/// delta of the previous step
CohesiveInternalField<Real> delta_prec;
/// stiffness for reloading
CohesiveInternalField<Real> K_plus;
/// stiffness for unloading
CohesiveInternalField<Real> K_minus;
/// 1D traction in the cohesive law
CohesiveInternalField<Real> T_1d;
/// Number of opening/closing switches
CohesiveInternalField<UInt> switches;
/// delta increment of the previous time step
CohesiveInternalField<Real> delta_dot_prec;
/// has the element passed to normal regime (not in fatigue anymore)
CohesiveInternalField<bool> normal_regime;
/// ratio indicating until what point fatigue is applied in the cohesive law
Real fatigue_ratio;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_COHESIVE_LINEAR_FATIGUE_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc
index 9c5f940be..3d18042ad 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc
@@ -1,282 +1,188 @@
/**
* @file material_cohesive_linear_friction.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
*
* @date creation: Tue Jan 12 2016
* @date last modification: Fri Dec 11 2020
*
* @brief Linear irreversible cohesive law of mixed mode loading with
* random stress definition for extrinsic type
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear_friction.hh"
#include "solid_mechanics_model_cohesive.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialCohesiveLinearFriction<spatial_dimension>::
- MaterialCohesiveLinearFriction(SolidMechanicsModel & model, const ID & id)
+template <Int dim>
+MaterialCohesiveLinearFriction<dim>::MaterialCohesiveLinearFriction(
+ SolidMechanicsModel & model, const ID & id)
: MaterialParent(model, id), residual_sliding("residual_sliding", *this),
friction_force("friction_force", *this) {
AKANTU_DEBUG_IN();
this->registerParam("mu", mu_max, Real(0.), _pat_parsable | _pat_readable,
"Maximum value of the friction coefficient");
this->registerParam("penalty_for_friction", friction_penalty, Real(0.),
_pat_parsable | _pat_readable,
"Penalty parameter for the friction behavior");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearFriction<spatial_dimension>::initMaterial() {
+template <Int dim> void MaterialCohesiveLinearFriction<dim>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialParent::initMaterial();
- friction_force.initialize(spatial_dimension);
+ friction_force.initialize(dim);
residual_sliding.initialize(1);
residual_sliding.initializeHistory();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearFriction<spatial_dimension>::computeTraction(
- __attribute__((unused)) const Array<Real> & normal, ElementType el_type,
- GhostType ghost_type) {
- AKANTU_DEBUG_IN();
+template <Int dim>
+template <typename Args>
+void MaterialCohesiveLinearFriction<dim>::computeTractionOnQuad(Args && args) {
+ MaterialParent::computeTractionOnQuad(args);
+ using namespace tuple;
+
+ auto && res_sliding_prev = args["previous_residual_sliding"_n];
+ auto && res_sliding = args["residual_sliding"_n];
+
+ if (not this->penetration) {
+ args["friction_force"_n].zero();
+ return;
+ }
+
+ /// the friction coefficient mu increases with the damage. It
+ /// equals the maximum value when damage = 1.
+ // Real damage = std::min(*delta_max_prev_it / *delta_c_it,
+ // Real(1.));
+ Real mu = mu_max; // * damage;
+
+ /// the definition of tau_max refers to the opening
+ /// (penetration) of the previous incremental step
+
+ Real tau_max = mu * this->penalty * (std::abs(this->normal_opening_norm));
+ Real delta_sliding_norm =
+ std::abs(this->tangential_opening_norm - res_sliding_prev);
+
+ /// tau is the norm of the friction force, acting tangentially to the
+ /// surface
+ Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max);
+
+ if ((this->tangential_opening_norm - res_sliding_prev) < 0.0) {
+ tau = -tau;
+ }
+
+ /// from tau get the x and y components of friction, to be added in the
+ /// force vector
+ args["friction_force"_n] =
+ tau * this->tangential_opening / this->tangential_opening_norm;
+
+ /// update residual_sliding
+ if (friction_penalty == 0.) {
+ res_sliding = this->tangential_opening_norm;
+ } else {
+ res_sliding =
+ this->tangential_opening_norm - (std::abs(tau) / friction_penalty);
+ }
- residual_sliding.resize();
- friction_force.resize();
-
- /// define iterators
- auto traction_it =
- this->tractions(el_type, ghost_type).begin(spatial_dimension);
- auto traction_end =
- this->tractions(el_type, ghost_type).end(spatial_dimension);
- auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
- auto previous_opening_it =
- this->opening.previous(el_type, ghost_type).begin(spatial_dimension);
- auto contact_traction_it =
- this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
- auto contact_opening_it =
- this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
- auto normal_it = this->normal.begin(spatial_dimension);
- auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
- auto delta_max_it = this->delta_max(el_type, ghost_type).begin();
- auto delta_max_prev_it =
- this->delta_max.previous(el_type, ghost_type).begin();
- auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
- auto damage_it = this->damage(el_type, ghost_type).begin();
- auto insertion_stress_it =
- this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
- auto res_sliding_it = this->residual_sliding(el_type, ghost_type).begin();
- auto res_sliding_prev_it =
- this->residual_sliding.previous(el_type, ghost_type).begin();
- auto friction_force_it =
- this->friction_force(el_type, ghost_type).begin(spatial_dimension);
-
- Vector<Real> normal_opening(spatial_dimension);
- Vector<Real> tangential_opening(spatial_dimension);
+ args["traction"_n] += args["friction_force"_n];
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+void MaterialCohesiveLinearFriction<dim>::computeTraction(
+ ElementType el_type, GhostType ghost_type) {
+ AKANTU_DEBUG_IN();
+ using namespace tuple;
if (not this->model->isDefaultSolverExplicit()) {
this->delta_max(el_type, ghost_type)
.copy(this->delta_max.previous(el_type, ghost_type));
}
- /// loop on each quadrature point
- for (; traction_it != traction_end;
- ++traction_it, ++opening_it, ++normal_it, ++sigma_c_it, ++delta_max_it,
- ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it,
- ++contact_opening_it, ++delta_max_prev_it, ++res_sliding_it,
- ++res_sliding_prev_it, ++friction_force_it, ++previous_opening_it) {
-
- Real normal_opening_norm;
- Real tangential_opening_norm;
- bool penetration;
- this->computeTractionOnQuad(
- *traction_it, *opening_it, *normal_it, *delta_max_it, *delta_c_it,
- *insertion_stress_it, *sigma_c_it, normal_opening, tangential_opening,
- normal_opening_norm, tangential_opening_norm, *damage_it, penetration,
- *contact_traction_it, *contact_opening_it);
-
- if (penetration) {
- /// the friction coefficient mu increases with the damage. It
- /// equals the maximum value when damage = 1.
- // Real damage = std::min(*delta_max_prev_it / *delta_c_it,
- // Real(1.));
- Real mu = mu_max; // * damage;
-
- /// the definition of tau_max refers to the opening
- /// (penetration) of the previous incremental step
-
- Real tau_max = mu * this->penalty * (std::abs(normal_opening_norm));
- Real delta_sliding_norm =
- std::abs(tangential_opening_norm - *res_sliding_prev_it);
-
- /// tau is the norm of the friction force, acting tangentially to the
- /// surface
- Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max);
-
- if ((tangential_opening_norm - *res_sliding_prev_it) < 0.0) {
- tau = -tau;
- }
-
- /// from tau get the x and y components of friction, to be added in the
- /// force vector
- Vector<Real> tangent_unit_vector(spatial_dimension);
- tangent_unit_vector = tangential_opening / tangential_opening_norm;
- *friction_force_it = tau * tangent_unit_vector;
-
- /// update residual_sliding
- if (friction_penalty == 0.) {
- *res_sliding_it = tangential_opening_norm;
- } else {
- *res_sliding_it =
- tangential_opening_norm - (std::abs(tau) / friction_penalty);
- }
- } else {
- friction_force_it->zero();
- }
-
- *traction_it += *friction_force_it;
+ for (auto && args : getArguments(el_type, ghost_type)) {
+ computeTractionOnQuad(args);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearFriction<spatial_dimension>::computeTangentTraction(
- ElementType el_type, Array<Real> & tangent_matrix,
- __attribute__((unused)) const Array<Real> & normal, GhostType ghost_type) {
+template <Int dim>
+void MaterialCohesiveLinearFriction<dim>::computeTangentTraction(
+ ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- /// define iterators
- auto tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension);
- auto tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension);
-
- auto normal_it = this->normal.begin(spatial_dimension);
-
- auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
- auto previous_opening_it =
- this->opening.previous(el_type, ghost_type).begin(spatial_dimension);
-
- /**
- * NB: delta_max_it points on delta_max_previous, i.e. the
- * delta_max related to the solution of the previous incremental
- * step
- */
- auto delta_max_it = this->delta_max.previous(el_type, ghost_type).begin();
- auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
- auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
- auto damage_it = this->damage(el_type, ghost_type).begin();
-
- auto contact_opening_it =
- this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
-
- auto res_sliding_prev_it =
- this->residual_sliding.previous(el_type, ghost_type).begin();
-
- Vector<Real> normal_opening(spatial_dimension);
- Vector<Real> tangential_opening(spatial_dimension);
-
- for (; tangent_it != tangent_end;
- ++tangent_it, ++normal_it, ++opening_it, ++previous_opening_it,
- ++delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it,
- ++contact_opening_it, ++res_sliding_prev_it) {
-
- Real normal_opening_norm;
- Real tangential_opening_norm;
- bool penetration;
- this->computeTangentTractionOnQuad(
- *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it,
- *normal_it, normal_opening, tangential_opening, normal_opening_norm,
- tangential_opening_norm, *damage_it, penetration, *contact_opening_it);
-
- if (penetration) {
- // Real damage = std::min(*delta_max_it / *delta_c_it, Real(1.));
- Real mu = mu_max; // * damage;
-
- Real normal_opening_prev_norm =
- std::min(previous_opening_it->dot(*normal_it), Real(0.));
- // Vector<Real> normal_opening_prev = (*normal_it);
- // normal_opening_prev *= normal_opening_prev_norm;
-
- Real tau_max = mu * this->penalty * (std::abs(normal_opening_prev_norm));
- Real delta_sliding_norm =
- std::abs(tangential_opening_norm - *res_sliding_prev_it);
-
- // tau is the norm of the friction force, acting tangentially to the
- // surface
- Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max);
-
- if (tau < tau_max && tau_max > Math::getTolerance()) {
- Matrix<Real> I(spatial_dimension, spatial_dimension);
- I.eye(1.);
-
- Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
- n_outer_n.outerProduct(*normal_it, *normal_it);
-
- Matrix<Real> nn(n_outer_n);
- I -= nn;
- *tangent_it += I * friction_penalty;
- }
- }
+ for (auto && [args, tangent] : zip(getArguments(el_type, ghost_type),
+ make_view<dim, dim>(tangent_matrix))) {
+ this->computeTangentTractionOnQuad(tangent, args);
- // check if the tangential stiffness matrix is symmetric
- // for (UInt h = 0; h < spatial_dimension; ++h){
- // for (UInt l = h; l < spatial_dimension; ++l){
- // if (l > h){
- // Real k_ls = (*tangent_it)[spatial_dimension*h+l];
- // Real k_us = (*tangent_it)[spatial_dimension*l+h];
- // // std::cout << "k_ls = " << k_ls << std::endl;
- // // std::cout << "k_us = " << k_us << std::endl;
- // if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){
- // Real error = std::abs((k_ls - k_us) / k_us);
- // if (error > 1e-10){
- // std::cout << "non symmetric cohesive matrix" << std::endl;
- // // std::cout << "error " << error << std::endl;
- // }
- // }
- // }
- // }
- // }
+ if (not this->penetration) {
+ continue;
+ }
+ // Real damage = std::min(*delta_max_it / *delta_c_it, Real(1.));
+ Real mu = mu_max; // * damage;
+
+ Real previous_normal_opening_norm =
+ std::min(args["previous_opening"_n].dot(args["normal"_n]), Real(0.));
+ // Vector<Real> normal_opening_prev = (*normal_it);
+ // normal_opening_prev *= normal_opening_prev_norm;
+
+ Real tau_max =
+ mu * this->penalty * (std::abs(previous_normal_opening_norm));
+ Real delta_sliding_norm = std::abs(this->tangential_opening_norm -
+ args["previous_residual_sliding"_n]);
+
+ // tau is the norm of the friction force, acting tangentially to the
+ // surface
+ Real tau = std::min(this->friction_penalty * delta_sliding_norm, tau_max);
+
+ if (tau < tau_max && tau_max > Math::getTolerance()) {
+ auto && I = Matrix<Real, dim, dim>::Identity();
+ auto && n = args["normal"_n];
+ tangent += (I - n * n.transpose()) * friction_penalty;
+ }
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(cohesive_linear_friction, MaterialCohesiveLinearFriction);
+template class MaterialCohesiveLinearFriction<1>;
+template class MaterialCohesiveLinearFriction<2>;
+template class MaterialCohesiveLinearFriction<3>;
+static bool material_is_allocated_cohesive_linear_friction =
+ instantiateMaterial<MaterialCohesiveLinearFriction>(
+ "cohesive_linear_friction");
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
index d19e561df..2995070f8 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
@@ -1,105 +1,117 @@
/**
* @file material_cohesive_linear_friction.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Tue Apr 28 2020
*
* @brief Linear irreversible cohesive law of mixed mode loading with
* random stress definition for extrinsic type
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH_
#define AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* Cohesive material linear with friction force
*
* parameters in the material files :
* - mu : friction coefficient
* - penalty_for_friction : Penalty parameter for the friction behavior
*/
-template <UInt spatial_dimension>
-class MaterialCohesiveLinearFriction
- : public MaterialCohesiveLinear<spatial_dimension> {
+template <Int dim>
+class MaterialCohesiveLinearFriction : public MaterialCohesiveLinear<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
- using MaterialParent = MaterialCohesiveLinear<spatial_dimension>;
+ using MaterialParent = MaterialCohesiveLinear<dim>;
public:
MaterialCohesiveLinearFriction(SolidMechanicsModel & model,
const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material parameters
void initMaterial() override;
protected:
/// constitutive law
- void computeTraction(const Array<Real> & normal, ElementType el_type,
+ void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute tangent stiffness matrix
void computeTangentTraction(ElementType el_type, Array<Real> & tangent_matrix,
- const Array<Real> & normal,
GhostType ghost_type) override;
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ using namespace tuple;
+ return zip_append(MaterialParent::getArguments(el_type, ghost_type),
+ "residual_sliding"_n =
+ residual_sliding(el_type, ghost_type),
+ "friction_force"_n =
+ make_view<dim>(friction_force(el_type, ghost_type)),
+ "previous_residual_sliding"_n =
+ residual_sliding.previous(el_type, ghost_type));
+ }
+
+ template <typename Args> void computeTractionOnQuad(Args && args);
+
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// maximum value of the friction coefficient
Real mu_max;
/// penalty parameter for the friction law
Real friction_penalty;
/// history parameter for the friction law
CohesiveInternalField<Real> residual_sliding;
/// friction force
CohesiveInternalField<Real> friction_force;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh
index 6e8609fe8..81e277966 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh
@@ -1,269 +1,265 @@
/**
* @file material_cohesive_linear_inline_impl.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Apr 22 2015
* @date last modification: Thu Jan 14 2021
*
* @brief Inline functions of the MaterialCohesiveLinear
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "material_cohesive_linear.hh"
+//#include "material_cohesive_linear.hh"
+#include "aka_static_if.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_HH_
#define AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline Real MaterialCohesiveLinear<dim>::computeEffectiveNorm(
- const Matrix<Real> & stress, const Vector<Real> & normal,
- const Vector<Real> & tangent, Vector<Real> & normal_traction) const {
- normal_traction.mul<false>(stress, normal);
+template <Int dim>
+template <class D1, class D2, class D3, class D4>
+Real MaterialCohesiveLinear<dim>::computeEffectiveNorm(
+ const Eigen::MatrixBase<D1> & stress, const Eigen::MatrixBase<D2> & normal,
+ const Eigen::MatrixBase<D3> & tangent,
+ const Eigen::MatrixBase<D4> & normal_traction_) const {
+ Eigen::MatrixBase<D4> & normal_traction =
+ const_cast<Eigen::MatrixBase<D4> &>(normal_traction_);
+ normal_traction = stress * normal;
Real normal_contrib = normal_traction.dot(normal);
/// in 3D tangential components must be summed
Real tangent_contrib = 0;
- if (dim == 2) {
+ if constexpr (dim == 2) {
Real tangent_contrib_tmp = normal_traction.dot(tangent);
tangent_contrib += tangent_contrib_tmp * tangent_contrib_tmp;
- } else if (dim == 3) {
- for (UInt s = 0; s < dim - 1; ++s) {
- const Vector<Real> tangent_v(tangent.storage() + s * dim, dim);
+ } else if constexpr (dim == 3) {
+ for (auto && tangent_v : tangent) {
Real tangent_contrib_tmp = normal_traction.dot(tangent_v);
tangent_contrib += tangent_contrib_tmp * tangent_contrib_tmp;
}
}
tangent_contrib = std::sqrt(tangent_contrib);
normal_contrib = std::max(Real(0.), normal_contrib);
return std::sqrt(normal_contrib * normal_contrib +
tangent_contrib * tangent_contrib * beta2_inv);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
-inline void MaterialCohesiveLinear<dim>::computeTractionOnQuad(
- Vector<Real> & traction, Vector<Real> & opening,
- const Vector<Real> & normal, Real & delta_max, const Real & delta_c,
- const Vector<Real> & insertion_stress, const Real & sigma_c,
- Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
- Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
- bool & penetration, Vector<Real> & contact_traction,
- Vector<Real> & contact_opening) {
+template <Int dim>
+template <typename Args>
+inline void MaterialCohesiveLinear<dim>::computeTractionOnQuad(Args && args) {
+ auto && delta_c = args["delta_c"_n];
+ auto && sigma_c = args["sigma_c"_n];
+ auto && delta_max = args["delta_max"_n];
+
+ auto && normal = args["normal"_n];
+ auto && opening = args["opening"_n];
+ auto && traction = args["traction"_n];
+
+ auto && damage = args["damage"_n];
+ auto && insertion_stress = args["insertion_stress"_n];
/// compute normal and tangential opening vectors
- normal_opening_norm = opening.dot(normal);
- normal_opening = normal;
- normal_opening *= normal_opening_norm;
+ auto norm = opening.dot(normal);
+ this->normal_opening_norm = norm;
+ this->normal_opening = normal * this->normal_opening_norm;
- tangential_opening = opening;
- tangential_opening -= normal_opening;
- tangential_opening_norm = tangential_opening.norm();
+ this->tangential_opening = opening - normal_opening;
+ this->tangential_opening_norm = this->tangential_opening.norm();
/**
* compute effective opening displacement
* @f$ \delta = \sqrt{
* \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$
*/
- Real delta =
- tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
+ auto delta = this->tangential_opening_norm * this->tangential_opening_norm *
+ this->beta2_kappa2;
+
+ penetration = this->normal_opening_norm / delta_c < -Math::getTolerance();
- penetration = normal_opening_norm / delta_c < -Math::getTolerance();
// penetration = normal_opening_norm < 0.;
if (not this->contact_after_breaking and Math::are_float_equal(damage, 1.)) {
penetration = false;
}
+ auto && contact_traction = args.get("contact_traction"_n);
+ auto && contact_opening = args.get("contact_opening"_n);
+
if (penetration) {
/// use penalty coefficient in case of penetration
- contact_traction = normal_opening;
- contact_traction *= this->penalty;
- contact_opening = normal_opening;
+ contact_traction = this->normal_opening * this->penalty;
+ contact_opening = this->normal_opening;
/// don't consider penetration contribution for delta
opening = tangential_opening;
- normal_opening.zero();
+ this->normal_opening.zero();
} else {
- delta += normal_opening_norm * normal_opening_norm;
+ delta += this->normal_opening_norm * this->normal_opening_norm;
contact_traction.zero();
contact_opening.zero();
}
delta = std::sqrt(delta);
/// update maximum displacement and damage
delta_max = std::max(delta_max, delta);
damage = std::min(delta_max / delta_c, Real(1.));
/**
* Compute traction @f$ \mathbf{T} = \left(
* \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n
* \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1-
* \frac{\delta}{\delta_c} \right)@f$
*/
if (Math::are_float_equal(damage, 1.)) {
traction.zero();
} else if (Math::are_float_equal(damage, 0.)) {
if (penetration) {
traction.zero();
} else {
traction = insertion_stress;
}
} else {
- traction = tangential_opening;
- traction *= this->beta2_kappa;
- traction += normal_opening;
-
AKANTU_DEBUG_ASSERT(delta_max != 0.,
"Division by zero, tolerance might be too low");
- traction *= sigma_c / delta_max * (1. - damage);
+ traction =
+ (this->tangential_opening * this->beta2_kappa + this->normal_opening) *
+ sigma_c / delta_max * (1. - damage);
}
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
+template <class Derived, class Args>
inline void MaterialCohesiveLinear<dim>::computeTangentTractionOnQuad(
- Matrix<Real> & tangent, Real & delta_max, const Real & delta_c,
- const Real & sigma_c, Vector<Real> & opening, const Vector<Real> & normal,
- Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
- Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
- bool & penetration, Vector<Real> & contact_opening) {
-
+ Eigen::MatrixBase<Derived> & tangent, Args && args) {
/**
* During the update of the residual the interpenetrations are
* stored in the array "contact_opening", therefore, in the case
* of penetration, in the array "opening" there are only the
* tangential components.
*/
+
+ auto && delta_c = args["delta_c"_n];
+ auto && delta_max = args["delta_max"_n];
+
+ auto && normal = args["normal"_n];
+ auto && opening = args["opening"_n];
+ auto && contact_opening = args["contact_opening"_n];
+
+ auto && damage = args["damage"_n];
+
opening += contact_opening;
/// compute normal and tangential opening vectors
- normal_opening_norm = opening.dot(normal);
- normal_opening = normal;
- normal_opening *= normal_opening_norm;
+ this->normal_opening_norm = opening.dot(normal);
+ this->normal_opening = normal * normal_opening_norm;
- tangential_opening = opening;
- tangential_opening -= normal_opening;
- tangential_opening_norm = tangential_opening.norm();
+ this->tangential_opening = opening - normal_opening;
+ this->tangential_opening_norm = tangential_opening.norm();
- Real delta =
- tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
+ auto delta = this->tangential_opening_norm * this->tangential_opening_norm *
+ this->beta2_kappa2;
penetration = normal_opening_norm < 0.0;
if (not this->contact_after_breaking and Math::are_float_equal(damage, 1.)) {
penetration = false;
}
Real derivative = 0; // derivative = d(t/delta)/ddelta
Real t = 0;
- Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
- n_outer_n.outerProduct(normal, normal);
+ auto && n_outer_n = normal * normal.transpose();
if (penetration) {
/// stiffness in compression given by the penalty parameter
- tangent += n_outer_n;
- tangent *= penalty;
+ tangent = penalty * (tangent + n_outer_n);
opening = tangential_opening;
+
normal_opening_norm = opening.dot(normal);
- normal_opening = normal;
- normal_opening *= normal_opening_norm;
+ normal_opening = normal * normal_opening_norm;
} else {
delta += normal_opening_norm * normal_opening_norm;
}
delta = std::sqrt(delta);
/**
* Delta has to be different from 0 to have finite values of
* tangential stiffness. At the element insertion, delta =
* 0. Therefore, a fictictious value is defined, for the
* evaluation of the first value of K.
*/
if (delta < Math::getTolerance()) {
delta = delta_c / 1000.;
}
if (delta >= delta_max) {
if (delta <= delta_c) {
derivative = -sigma_c / (delta * delta);
t = sigma_c * (1 - delta / delta_c);
} else {
derivative = 0.;
t = 0.;
}
} else if (delta < delta_max) {
Real tmax = sigma_c * (1 - delta_max / delta_c);
t = tmax / delta_max * delta;
}
/// computation of the derivative of the constitutive law (dT/ddelta)
- Matrix<Real> I(spatial_dimension, spatial_dimension);
- I.eye(this->beta2_kappa);
-
- Matrix<Real> nn(n_outer_n);
- nn *= (1. - this->beta2_kappa);
- nn += I;
- nn *= t / delta;
-
- Vector<Real> t_tilde(normal_opening);
- t_tilde *= (1. - this->beta2_kappa2);
+ auto && I = Eigen::Matrix<Real, dim, dim>::Identity() * this->beta2_kappa;
- Vector<Real> mm(opening);
- mm *= this->beta2_kappa2;
- t_tilde += mm;
+ auto && nn = (n_outer_n * (1. - this->beta2_kappa) + I) * t / delta;
+ auto && mm = opening * this->beta2_kappa2;
- Vector<Real> t_hat(normal_opening);
- t_hat += this->beta2_kappa * tangential_opening;
+ auto && t_tilde = normal_opening * (1. - this->beta2_kappa2) + mm;
+ auto && t_hat = normal_opening + this->beta2_kappa * tangential_opening;
- Matrix<Real> prov(spatial_dimension, spatial_dimension);
- prov.outerProduct(t_hat, t_tilde);
- prov *= derivative / delta;
- prov += nn;
+ auto && prov = t_hat * t_tilde.transpose() * derivative / delta + nn;
- Matrix<Real> prov_t = prov.transpose();
- tangent += prov_t;
+ tangent += prov.transpose();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
/* -------------------------------------------------------------------------- */
#endif // AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_HH_
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc
index 950eb4e64..47e1e7eb7 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc
@@ -1,420 +1,387 @@
/**
* @file material_cohesive_linear_uncoupled.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
*
* @date creation: Mon Jul 25 2016
* @date last modification: Thu Feb 20 2020
*
* @brief Linear irreversible cohesive law of mixed mode loading with
* random stress definition for extrinsic type
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <numeric>
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear_uncoupled.hh"
#include "solid_mechanics_model_cohesive.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialCohesiveLinearUncoupled<spatial_dimension>::
- MaterialCohesiveLinearUncoupled(SolidMechanicsModel & model, const ID & id)
- : MaterialCohesiveLinear<spatial_dimension>(model, id),
- delta_n_max("delta_n_max", *this), delta_t_max("delta_t_max", *this),
- damage_n("damage_n", *this), damage_t("damage_t", *this) {
+template <Int dim>
+MaterialCohesiveLinearUncoupled<dim>::MaterialCohesiveLinearUncoupled(
+ SolidMechanicsModel & model, const ID & id)
+ : MaterialCohesiveLinear<dim>(model, id), delta_n_max("delta_n_max", *this),
+ delta_t_max("delta_t_max", *this), damage_n("damage_n", *this),
+ damage_t("damage_t", *this) {
AKANTU_DEBUG_IN();
this->registerParam(
"roughness", R, Real(1.), _pat_parsable | _pat_readable,
"Roughness to define coupling between mode II and mode I");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearUncoupled<spatial_dimension>::initMaterial() {
+template <Int dim> void MaterialCohesiveLinearUncoupled<dim>::initMaterial() {
AKANTU_DEBUG_IN();
- MaterialCohesiveLinear<spatial_dimension>::initMaterial();
+ MaterialCohesiveLinear<dim>::initMaterial();
delta_n_max.initialize(1);
delta_t_max.initialize(1);
damage_n.initialize(1);
damage_t.initialize(1);
delta_n_max.initializeHistory();
delta_t_max.initializeHistory();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTraction(
- const Array<Real> & /*unused*/, ElementType el_type, GhostType ghost_type) {
+template <Int dim>
+void MaterialCohesiveLinearUncoupled<dim>::computeTraction(
+ ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
delta_n_max.resize();
delta_t_max.resize();
damage_n.resize();
damage_t.resize();
/// define iterators
- auto traction_it =
- this->tractions(el_type, ghost_type).begin(spatial_dimension);
+ auto traction_it = this->tractions(el_type, ghost_type).begin(dim);
- auto traction_end =
- this->tractions(el_type, ghost_type).end(spatial_dimension);
+ auto traction_end = this->tractions(el_type, ghost_type).end(dim);
- auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
+ auto opening_it = this->opening(el_type, ghost_type).begin(dim);
auto contact_traction_it =
- this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
+ this->contact_tractions(el_type, ghost_type).begin(dim);
auto contact_opening_it =
- this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
+ this->contact_opening(el_type, ghost_type).begin(dim);
- auto normal_it = this->normal.begin(spatial_dimension);
+ auto normal_it = this->normals(el_type, ghost_type).begin(dim);
auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
auto delta_n_max_it = delta_n_max(el_type, ghost_type).begin();
auto delta_t_max_it = delta_t_max(el_type, ghost_type).begin();
auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
auto damage_n_it = damage_n(el_type, ghost_type).begin();
auto damage_t_it = damage_t(el_type, ghost_type).begin();
auto insertion_stress_it =
- this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
+ this->insertion_stress(el_type, ghost_type).begin(dim);
- Vector<Real> normal_opening(spatial_dimension);
- Vector<Real> tangential_opening(spatial_dimension);
+ Vector<Real, dim> normal_opening;
+ Vector<Real, dim> tangential_opening;
/// loop on each quadrature point
for (; traction_it != traction_end;
++traction_it, ++opening_it, ++contact_traction_it, ++contact_opening_it,
++normal_it, ++sigma_c_it, ++delta_n_max_it, ++delta_t_max_it,
++delta_c_it, ++damage_n_it, ++damage_t_it, ++insertion_stress_it) {
Real normal_opening_norm;
Real tangential_opening_norm;
bool penetration;
Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R;
/// compute normal and tangential opening vectors
normal_opening_norm = opening_it->dot(*normal_it);
- Vector<Real> normal_opening = *normal_it;
- normal_opening *= normal_opening_norm;
+ normal_opening = *normal_it * normal_opening_norm;
- // std::cout<< "normal_opening_norm = " << normal_opening_norm
- // <<std::endl;
-
- Vector<Real> tangential_opening = *opening_it;
- tangential_opening -= normal_opening;
+ tangential_opening = *opening_it - normal_opening;
tangential_opening_norm = tangential_opening.norm();
/// compute effective opening displacement
Real delta_n =
tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
Real delta_t =
tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
penetration = normal_opening_norm < 0.0;
if (not this->contact_after_breaking and
Math::are_float_equal(*damage_n_it, 1.)) {
penetration = false;
}
if (penetration) {
/// use penalty coefficient in case of penetration
- *contact_traction_it = normal_opening;
- *contact_traction_it *= this->penalty;
+ *contact_traction_it = normal_opening * this->penalty;
*contact_opening_it = normal_opening;
/// don't consider penetration contribution for delta
//*opening_it = tangential_opening;
normal_opening.zero();
} else {
delta_n += normal_opening_norm * normal_opening_norm;
delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2;
contact_traction_it->zero();
contact_opening_it->zero();
}
delta_n = std::sqrt(delta_n);
delta_t = std::sqrt(delta_t);
/// update maximum displacement and damage
*delta_n_max_it = std::max(*delta_n_max_it, delta_n);
*damage_n_it = std::min(*delta_n_max_it / *delta_c_it, Real(1.));
*delta_t_max_it = std::max(*delta_t_max_it, delta_t);
*damage_t_it = std::min(*delta_t_max_it / *delta_c_it, Real(1.));
- Vector<Real> normal_traction(spatial_dimension);
- Vector<Real> shear_traction(spatial_dimension);
+ Vector<Real, dim> normal_traction;
+ Vector<Real, dim> shear_traction;
/// NORMAL TRACTIONS
if (Math::are_float_equal(*damage_n_it, 1.)) {
normal_traction.zero();
} else if (Math::are_float_equal(*damage_n_it, 0.)) {
if (penetration) {
normal_traction.zero();
} else {
normal_traction = *insertion_stress_it;
}
} else {
// the following formulation holds both in loading and in
// unloading-reloading
- normal_traction = normal_opening;
-
AKANTU_DEBUG_ASSERT(*delta_n_max_it != 0.,
"Division by zero, tolerance might be too low");
- normal_traction *= *sigma_c_it / (*delta_n_max_it) * (1. - *damage_n_it);
+ normal_traction = normal_opening * *sigma_c_it / (*delta_n_max_it) *
+ (1. - *damage_n_it);
}
/// SHEAR TRACTIONS
if (Math::are_float_equal(*damage_t_it, 1.) or
Math::are_float_equal(*damage_t_it, 0.)) {
shear_traction.zero();
} else {
- shear_traction = tangential_opening;
-
AKANTU_DEBUG_ASSERT(*delta_t_max_it != 0.,
"Division by zero, tolerance might be too low");
- shear_traction *= this->beta2_kappa;
- shear_traction *= *sigma_c_it / (*delta_t_max_it) * (1. - *damage_t_it);
+ shear_traction = tangential_opening * this->beta2_kappa * *sigma_c_it /
+ (*delta_t_max_it) * (1. - *damage_t_it);
}
- *traction_it = normal_traction;
- *traction_it += shear_traction;
+ *traction_it = normal_traction + shear_traction;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTangentTraction(
- ElementType el_type, Array<Real> & tangent_matrix,
- const Array<Real> & /*unused*/, GhostType ghost_type) {
+template <Int dim>
+void MaterialCohesiveLinearUncoupled<dim>::computeTangentTraction(
+ ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// define iterators
- auto tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension);
- auto tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension);
- auto normal_it = this->normal.begin(spatial_dimension);
- auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
+ auto tangent_it = tangent_matrix.begin(dim, dim);
+ auto tangent_end = tangent_matrix.end(dim, dim);
+ auto normal_it = this->normals(el_type, ghost_type).begin(dim);
+ auto opening_it = this->opening(el_type, ghost_type).begin(dim);
/// NB: delta_max_it points on delta_max_previous, i.e. the
/// delta_max related to the solution of the previous incremental
/// step
auto delta_n_max_it = delta_n_max.previous(el_type, ghost_type).begin();
auto delta_t_max_it = delta_t_max.previous(el_type, ghost_type).begin();
auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
auto damage_n_it = damage_n(el_type, ghost_type).begin();
auto contact_opening_it =
- this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
+ this->contact_opening(el_type, ghost_type).begin(dim);
- Vector<Real> normal_opening(spatial_dimension);
- Vector<Real> tangential_opening(spatial_dimension);
+ Vector<Real, dim> normal_opening;
+ Vector<Real, dim> tangential_opening;
for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it,
++sigma_c_it, ++delta_c_it,
++delta_n_max_it, ++delta_t_max_it,
++damage_n_it, ++contact_opening_it) {
Real normal_opening_norm;
Real tangential_opening_norm;
bool penetration;
Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R;
/**
* During the update of the residual the interpenetrations are
* stored in the array "contact_opening", therefore, in the case
* of penetration, in the array "opening" there are only the
* tangential components.
*/
*opening_it += *contact_opening_it;
/// compute normal and tangential opening vectors
normal_opening_norm = opening_it->dot(*normal_it);
- Vector<Real> normal_opening = *normal_it;
- normal_opening *= normal_opening_norm;
+ normal_opening = *normal_it * normal_opening_norm;
- Vector<Real> tangential_opening = *opening_it;
- tangential_opening -= normal_opening;
+ tangential_opening = *opening_it - normal_opening;
tangential_opening_norm = tangential_opening.norm();
Real delta_n =
tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
Real delta_t =
tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
penetration = normal_opening_norm < 0.0;
if (not this->contact_after_breaking and
Math::are_float_equal(*damage_n_it, 1.)) {
penetration = false;
}
Real derivative = 0; // derivative = d(t/delta)/ddelta
Real T = 0;
/// TANGENT STIFFNESS FOR NORMAL TRACTIONS
- Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
- n_outer_n.outerProduct(*normal_it, *normal_it);
+ Matrix<Real, dim, dim> n_outer_n = *normal_it * (*normal_it).transpose();
if (penetration) {
/// stiffness in compression given by the penalty parameter
- *tangent_it = n_outer_n;
- *tangent_it *= this->penalty;
+ *tangent_it = n_outer_n * this->penalty;
//*opening_it = tangential_opening;
normal_opening.zero();
} else {
delta_n += normal_opening_norm * normal_opening_norm;
delta_n = std::sqrt(delta_n);
delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2;
/**
* Delta has to be different from 0 to have finite values of
* tangential stiffness. At the element insertion, delta =
* 0. Therefore, a fictictious value is defined, for the
* evaluation of the first value of K.
*/
if (delta_n < Math::getTolerance()) {
delta_n = *delta_c_it / 1000.;
}
// loading
if (delta_n >= *delta_n_max_it) {
if (delta_n <= *delta_c_it) {
derivative = -(*sigma_c_it) / (delta_n * delta_n);
T = *sigma_c_it * (1 - delta_n / *delta_c_it);
} else {
derivative = 0.;
T = 0.;
}
// unloading-reloading
} else if (delta_n < *delta_n_max_it) {
Real T_max = *sigma_c_it * (1 - *delta_n_max_it / *delta_c_it);
derivative = 0.;
T = T_max / *delta_n_max_it * delta_n;
}
/// computation of the derivative of the constitutive law (dT/ddelta)
- Matrix<Real> nn(n_outer_n);
- nn *= T / delta_n;
+ Matrix<Real, dim, dim> nn = n_outer_n * T / delta_n;
- Vector<Real> Delta_tilde(normal_opening);
- Delta_tilde *= (1. - this->beta2_kappa2);
- Vector<Real> mm(*opening_it);
- mm *= this->beta2_kappa2;
- Delta_tilde += mm;
+ Vector<Real, dim> Delta_tilde =
+ normal_opening * (1. - this->beta2_kappa2) +
+ *opening_it * this->beta2_kappa2;
- const Vector<Real> & Delta_hat(normal_opening);
- Matrix<Real> prov(spatial_dimension, spatial_dimension);
- prov.outerProduct(Delta_hat, Delta_tilde);
- prov *= derivative / delta_n;
- prov += nn;
+ Matrix<Real, dim, dim> prov =
+ normal_opening * Delta_tilde.transpose() * derivative / delta_n + nn;
- Matrix<Real> prov_t = prov.transpose();
-
- *tangent_it = prov_t;
+ *tangent_it = prov.transpose();
}
derivative = 0.;
T = 0.;
/// TANGENT STIFFNESS FOR SHEAR TRACTIONS
delta_t = std::sqrt(delta_t);
/**
* Delta has to be different from 0 to have finite values of
* tangential stiffness. At the element insertion, delta =
* 0. Therefore, a fictictious value is defined, for the
* evaluation of the first value of K.
*/
if (delta_t < Math::getTolerance()) {
delta_t = *delta_c_it / 1000.;
}
// loading
if (delta_t >= *delta_t_max_it) {
if (delta_t <= *delta_c_it) {
derivative = -(*sigma_c_it) / (delta_t * delta_t);
T = *sigma_c_it * (1 - delta_t / *delta_c_it);
} else {
derivative = 0.;
T = 0.;
}
// unloading-reloading
} else if (delta_t < *delta_t_max_it) {
Real T_max = *sigma_c_it * (1 - *delta_t_max_it / *delta_c_it);
derivative = 0.;
T = T_max / *delta_t_max_it * delta_t;
}
/// computation of the derivative of the constitutive law (dT/ddelta)
- Matrix<Real> I(spatial_dimension, spatial_dimension);
- I.eye();
- Matrix<Real> nn(n_outer_n);
- I -= nn;
- I *= T / delta_t;
-
- Vector<Real> Delta_tilde(normal_opening);
- Delta_tilde *= (delta_c2_R2 - this->beta2_kappa2);
- Vector<Real> mm(*opening_it);
- mm *= this->beta2_kappa2;
- Delta_tilde += mm;
-
- Vector<Real> Delta_hat(tangential_opening);
- Delta_hat *= this->beta2_kappa;
- Matrix<Real> prov(spatial_dimension, spatial_dimension);
- prov.outerProduct(Delta_hat, Delta_tilde);
- prov *= derivative / delta_t;
- prov += I;
-
- Matrix<Real> prov_t = prov.transpose();
-
- *tangent_it += prov_t;
+ auto I = (Matrix<Real, dim, dim>::Identity() - n_outer_n) * (T / delta_t);
+
+ auto && Delta_tilde = normal_opening * (delta_c2_R2 - this->beta2_kappa2) +
+ *opening_it * this->beta2_kappa2;
+
+ auto && Delta_hat = tangential_opening * this->beta2_kappa;
+
+ auto && prov =
+ Delta_hat * Delta_tilde.transpose() * derivative / delta_t + I;
+
+ *tangent_it += prov.transpose();
}
AKANTU_DEBUG_OUT();
}
-/* -------------------------------------------------------------------------- */
-INSTANTIATE_MATERIAL(cohesive_linear_uncoupled,
- MaterialCohesiveLinearUncoupled);
+/* -------------------------------------------------------------------------- */
+template class MaterialCohesiveLinearUncoupled<1>;
+template class MaterialCohesiveLinearUncoupled<2>;
+template class MaterialCohesiveLinearUncoupled<3>;
+static bool material_is_allocated_cohesive_linear_uncoupled =
+ instantiateMaterial<MaterialCohesiveLinearUncoupled>(
+ "cohesive_linear_uncoupled");
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.hh
index cd5350fbe..7439e7ab4 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.hh
@@ -1,102 +1,100 @@
/**
* @file material_cohesive_linear_uncoupled.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Feb 20 2020
*
* @brief Linear irreversible cohesive law of mixed mode loading with
* random stress definition for extrinsic type
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_COHESIVE_LINEAR_UNCOUPLED_HH_
#define AKANTU_MATERIAL_COHESIVE_LINEAR_UNCOUPLED_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* Cohesive material linear with two different laws for mode I and
* mode II, for extrinsic case
*
* parameters in the material files :
* - roughness : define the interaction between mode I and mode II (default: 0)
*/
-template <UInt spatial_dimension>
-class MaterialCohesiveLinearUncoupled
- : public MaterialCohesiveLinear<spatial_dimension> {
+template <Int dim>
+class MaterialCohesiveLinearUncoupled : public MaterialCohesiveLinear<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
// typedef MaterialCohesiveLinear<spatial_dimension> MaterialParent;
public:
MaterialCohesiveLinearUncoupled(SolidMechanicsModel & model,
const ID & id = "");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material parameters
void initMaterial() override;
protected:
/// constitutive law
- void computeTraction(const Array<Real> & normal, ElementType el_type,
+ void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute tangent stiffness matrix
void computeTangentTraction(ElementType el_type, Array<Real> & tangent_matrix,
- const Array<Real> & normal,
GhostType ghost_type) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// parameter to tune the interaction between mode II and mode I
Real R;
/// maximum normal displacement
CohesiveInternalField<Real> delta_n_max;
/// maximum tangential displacement
CohesiveInternalField<Real> delta_t_max;
/// damage associated to normal tractions
CohesiveInternalField<Real> damage_n;
/// damage associated to shear tractions
CohesiveInternalField<Real> damage_t;
};
} // namespace akantu
#endif /* AKANTU_MATERIAL_COHESIVE_LINEAR_UNCOUPLED_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
index e96efb926..071ee2fee 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
@@ -1,559 +1,518 @@
/**
* @file material_cohesive.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Feb 22 2012
* @date last modification: Thu Jan 14 2021
*
* @brief Specialization of the material class for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive.hh"
#include "aka_random_generator.hh"
#include "dof_synchronizer.hh"
#include "fe_engine_template.hh"
#include "integrator_gauss.hh"
#include "shape_cohesive.hh"
-#include "solid_mechanics_model_cohesive.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
MaterialCohesive::MaterialCohesive(SolidMechanicsModel & model, const ID & id)
: Material(model, id), facet_filter("facet_filter", id),
fem_cohesive(
model.getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine")),
reversible_energy("reversible_energy", *this),
total_energy("total_energy", *this), opening("opening", *this),
tractions("tractions", *this),
contact_tractions("contact_tractions", *this),
contact_opening("contact_opening", *this), delta_max("delta max", *this),
use_previous_delta_max(false), use_previous_opening(false),
damage("damage", *this), sigma_c("sigma_c", *this),
- normal(0, spatial_dimension, "normal") {
+ normals("normal", *this) {
AKANTU_DEBUG_IN();
this->model = dynamic_cast<SolidMechanicsModelCohesive *>(&model);
this->registerParam("sigma_c", sigma_c, _pat_parsable | _pat_readable,
"Critical stress");
this->registerParam("delta_c", delta_c, Real(0.),
_pat_parsable | _pat_readable, "Critical displacement");
this->element_filter.initialize(this->model->getMesh(),
_spatial_dimension = spatial_dimension,
_element_kind = _ek_cohesive);
- // this->model->getMesh().initElementTypeMapArray(
- // this->element_filter, 1, spatial_dimension, false, _ek_cohesive);
if (this->model->getIsExtrinsic()) {
this->facet_filter.initialize(this->model->getMeshFacets(),
_spatial_dimension = spatial_dimension - 1,
_element_kind = _ek_regular);
}
- // this->model->getMeshFacets().initElementTypeMapArray(facet_filter, 1,
- // spatial_dimension -
- // 1);
this->reversible_energy.initialize(1);
this->total_energy.initialize(1);
this->tractions.initialize(spatial_dimension);
this->tractions.initializeHistory();
this->contact_tractions.initialize(spatial_dimension);
this->contact_opening.initialize(spatial_dimension);
this->opening.initialize(spatial_dimension);
this->opening.initializeHistory();
+ this->normals.initialize(spatial_dimension);
+
this->delta_max.initialize(1);
this->damage.initialize(1);
if (this->model->getIsExtrinsic()) {
this->sigma_c.initialize(1);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
MaterialCohesive::~MaterialCohesive() = default;
/* -------------------------------------------------------------------------- */
void MaterialCohesive::initMaterial() {
AKANTU_DEBUG_IN();
Material::initMaterial();
if (this->use_previous_delta_max) {
this->delta_max.initializeHistory();
}
if (this->use_previous_opening) {
this->opening.initializeHistory();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MaterialCohesive::assembleInternalForces(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & internal_force = const_cast<Array<Real> &>(model->getInternalForce());
for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type,
_ek_cohesive)) {
auto & elem_filter = element_filter(type, ghost_type);
- UInt nb_element = elem_filter.size();
+ auto nb_element = elem_filter.size();
if (nb_element == 0) {
continue;
}
const auto & shapes = fem_cohesive.getShapes(type, ghost_type);
auto & traction = tractions(type, ghost_type);
auto & contact_traction = contact_tractions(type, ghost_type);
- UInt size_of_shapes = shapes.getNbComponent();
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- UInt nb_quadrature_points =
+ auto size_of_shapes = shapes.getNbComponent();
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_quadrature_points =
fem_cohesive.getNbIntegrationPoints(type, ghost_type);
/// compute @f$t_i N_a@f$
- auto * traction_cpy = new Array<Real>(nb_element * nb_quadrature_points,
- spatial_dimension * size_of_shapes);
+ auto traction_cpy = std::make_shared<Array<Real>>(
+ nb_element * nb_quadrature_points, spatial_dimension * size_of_shapes);
auto traction_it = traction.begin(spatial_dimension, 1);
auto contact_traction_it = contact_traction.begin(spatial_dimension, 1);
auto shapes_filtered_begin = shapes.begin(1, size_of_shapes);
auto traction_cpy_it =
traction_cpy->begin(spatial_dimension, size_of_shapes);
Matrix<Real> traction_tmp(spatial_dimension, 1);
- for (UInt el = 0; el < nb_element; ++el) {
-
- UInt current_quad = elem_filter(el) * nb_quadrature_points;
-
- for (UInt q = 0; q < nb_quadrature_points; ++q, ++traction_it,
- ++contact_traction_it, ++current_quad, ++traction_cpy_it) {
+ for (Int el = 0; el < nb_element; ++el) {
+ auto current_quad = elem_filter(el) * nb_quadrature_points;
- const Matrix<Real> & shapes_filtered =
- shapes_filtered_begin[current_quad];
+ for (Int q = 0; q < nb_quadrature_points; ++q, ++traction_it,
+ ++contact_traction_it, ++current_quad, ++traction_cpy_it) {
- traction_tmp.copy(*traction_it);
- traction_tmp += *contact_traction_it;
+ auto && shapes_filtered = shapes_filtered_begin[current_quad];
- traction_cpy_it->mul<false, false>(traction_tmp, shapes_filtered);
+ *traction_cpy_it =
+ (*traction_it + *contact_traction_it) * shapes_filtered;
}
}
/**
* compute @f$\int t \cdot N\, dS@f$ by @f$ \sum_q \mathbf{N}^t
* \mathbf{t}_q \overline w_q J_q@f$
*/
- auto * partial_int_t_N = new Array<Real>(
+ auto partial_int_t_N = std::make_shared<Array<Real>>(
nb_element, spatial_dimension * size_of_shapes, "int_t_N");
fem_cohesive.integrate(*traction_cpy, *partial_int_t_N,
spatial_dimension * size_of_shapes, type, ghost_type,
elem_filter);
- delete traction_cpy;
-
- auto * int_t_N = new Array<Real>(
+ auto int_t_N = std::make_shared<Array<Real>>(
nb_element, 2 * spatial_dimension * size_of_shapes, "int_t_N");
- Real * int_t_N_val = int_t_N->storage();
- Real * partial_int_t_N_val = partial_int_t_N->storage();
- for (UInt el = 0; el < nb_element; ++el) {
+ auto * int_t_N_val = int_t_N->data();
+ auto * partial_int_t_N_val = partial_int_t_N->data();
+ for (Int el = 0; el < nb_element; ++el) {
std::copy_n(partial_int_t_N_val, size_of_shapes * spatial_dimension,
int_t_N_val);
std::copy_n(partial_int_t_N_val, size_of_shapes * spatial_dimension,
int_t_N_val + size_of_shapes * spatial_dimension);
- for (UInt n = 0; n < size_of_shapes * spatial_dimension; ++n) {
+ for (Int n = 0; n < size_of_shapes * spatial_dimension; ++n) {
int_t_N_val[n] *= -1.;
}
int_t_N_val += nb_nodes_per_element * spatial_dimension;
partial_int_t_N_val += size_of_shapes * spatial_dimension;
}
- delete partial_int_t_N;
-
/// assemble
model->getDOFManager().assembleElementalArrayLocalArray(
*int_t_N, internal_force, type, ghost_type, 1, elem_filter);
-
- delete int_t_N;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MaterialCohesive::assembleStiffnessMatrix(GhostType ghost_type) {
AKANTU_DEBUG_IN();
for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type,
_ek_cohesive)) {
- UInt nb_quadrature_points =
+ auto nb_quadrature_points =
fem_cohesive.getNbIntegrationPoints(type, ghost_type);
- UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- const Array<Real> & shapes = fem_cohesive.getShapes(type, ghost_type);
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
-
- UInt nb_element = elem_filter.size();
+ const auto & shapes = fem_cohesive.getShapes(type, ghost_type);
+ auto & elem_filter = element_filter(type, ghost_type);
+ auto nb_element = elem_filter.size();
if (nb_element == 0U) {
continue;
}
- UInt size_of_shapes = shapes.getNbComponent();
+ auto size_of_shapes = shapes.getNbComponent();
- auto * shapes_filtered = new Array<Real>(nb_element * nb_quadrature_points,
- size_of_shapes, "filtered shapes");
+ auto shapes_filtered = std::make_shared<Array<Real>>(
+ nb_element * nb_quadrature_points, size_of_shapes, "filtered shapes");
- Real * shapes_filtered_val = shapes_filtered->storage();
- UInt * elem_filter_val = elem_filter.storage();
-
- for (UInt el = 0; el < nb_element; ++el) {
- auto * shapes_val = shapes.storage() + elem_filter_val[el] *
- size_of_shapes *
- nb_quadrature_points;
- memcpy(shapes_filtered_val, shapes_val,
- size_of_shapes * nb_quadrature_points * sizeof(Real));
- shapes_filtered_val += size_of_shapes * nb_quadrature_points;
+ for (auto && data :
+ zip(filter(elem_filter,
+ make_view(shapes, size_of_shapes, nb_quadrature_points)),
+ make_view(*shapes_filtered, size_of_shapes,
+ nb_quadrature_points))) {
+ std::get<1>(data) = std::get<0>(data);
}
Matrix<Real> A(spatial_dimension * size_of_shapes,
spatial_dimension * nb_nodes_per_element);
- for (UInt i = 0; i < spatial_dimension * size_of_shapes; ++i) {
+ for (Int i = 0; i < spatial_dimension * size_of_shapes; ++i) {
A(i, i) = 1;
A(i, i + spatial_dimension * size_of_shapes) = -1;
}
/// get the tangent matrix @f$\frac{\partial{(t/\delta)}}{\partial{\delta}}
/// @f$
- auto * tangent_stiffness_matrix = new Array<Real>(
+ auto tangent_stiffness_matrix = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points,
spatial_dimension * spatial_dimension, "tangent_stiffness_matrix");
- // Array<Real> * normal = new Array<Real>(nb_element *
- // nb_quadrature_points, spatial_dimension, "normal");
- normal.resize(nb_quadrature_points);
-
- computeNormal(model->getCurrentPosition(), normal, type, ghost_type);
+ computeNormal(model->getCurrentPosition(), normals(type, ghost_type), type,
+ ghost_type);
/// compute openings @f$\mathbf{\delta}@f$
// computeOpening(model->getDisplacement(), opening(type, ghost_type), type,
// ghost_type);
tangent_stiffness_matrix->zero();
- computeTangentTraction(type, *tangent_stiffness_matrix, normal, ghost_type);
-
- // delete normal;
+ computeTangentTraction(type, *tangent_stiffness_matrix, ghost_type);
UInt size_at_nt_d_n_a = spatial_dimension * nb_nodes_per_element *
spatial_dimension * nb_nodes_per_element;
- auto * at_nt_d_n_a = new Array<Real>(nb_element * nb_quadrature_points,
- size_at_nt_d_n_a, "A^t*N^t*D*N*A");
+ auto at_nt_d_n_a = std::make_unique<Array<Real>>(
+ nb_element * nb_quadrature_points, size_at_nt_d_n_a, "A^t*N^t*D*N*A");
- Array<Real>::iterator<Vector<Real>> shapes_filt_it =
- shapes_filtered->begin(size_of_shapes);
+ Matrix<Real> N(spatial_dimension, spatial_dimension * nb_nodes_per_element);
- Array<Real>::matrix_iterator D_it =
- tangent_stiffness_matrix->begin(spatial_dimension, spatial_dimension);
+ for (auto && data :
+ zip(make_view(*at_nt_d_n_a, spatial_dimension * nb_nodes_per_element,
+ spatial_dimension * nb_nodes_per_element),
+ make_view(*tangent_stiffness_matrix, spatial_dimension,
+ spatial_dimension),
+ make_view(*shapes_filtered, size_of_shapes))) {
- Array<Real>::matrix_iterator At_Nt_D_N_A_it =
- at_nt_d_n_a->begin(spatial_dimension * nb_nodes_per_element,
- spatial_dimension * nb_nodes_per_element);
-
- Array<Real>::matrix_iterator At_Nt_D_N_A_end =
- at_nt_d_n_a->end(spatial_dimension * nb_nodes_per_element,
- spatial_dimension * nb_nodes_per_element);
-
- Matrix<Real> N(spatial_dimension, spatial_dimension * size_of_shapes);
- Matrix<Real> N_A(spatial_dimension,
- spatial_dimension * nb_nodes_per_element);
- Matrix<Real> D_N_A(spatial_dimension,
- spatial_dimension * nb_nodes_per_element);
-
- for (; At_Nt_D_N_A_it != At_Nt_D_N_A_end;
- ++At_Nt_D_N_A_it, ++D_it, ++shapes_filt_it) {
+ auto && At_Nt_D_N_A = std::get<0>(data);
+ auto && D = std::get<1>(data);
+ auto && shapes = std::get<2>(data);
N.zero();
/**
* store the shapes in voigt notations matrix @f$\mathbf{N} =
* \begin{array}{cccccc} N_0(\xi) & 0 & N_1(\xi) &0 & N_2(\xi) & 0 \\
* 0 & * N_0(\xi)& 0 &N_1(\xi)& 0 & N_2(\xi) \end{array} @f$
**/
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt n = 0; n < size_of_shapes; ++n) {
- N(i, i + spatial_dimension * n) = (*shapes_filt_it)(n);
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int n = 0; n < size_of_shapes; ++n) {
+ N(i, i + spatial_dimension * n) = shapes(n);
}
}
/**
- * compute stiffness matrix @f$ \mathbf{K} = \delta \mathbf{U}^T
- * \int_{\Gamma_c} {\mathbf{P}^t \frac{\partial{\mathbf{t}}}
+ * compute stiffness matrix @f$ \mathbf{K} = \delta
+ *\mathbf{U}^T \int_{\Gamma_c} {\mathbf{P}^t
+ *\frac{\partial{\mathbf{t}}}
*{\partial{\delta}}
* \mathbf{P} d\Gamma \Delta \mathbf{U}} @f$
**/
- N_A.mul<false, false>(N, A);
- D_N_A.mul<false, false>(*D_it, N_A);
- (*At_Nt_D_N_A_it).mul<true, false>(D_N_A, N_A);
+ auto && NA = N * A;
+ At_Nt_D_N_A = (D * NA).transpose() * NA;
}
- delete tangent_stiffness_matrix;
- delete shapes_filtered;
-
- auto * K_e = new Array<Real>(nb_element, size_at_nt_d_n_a, "K_e");
+ auto K_e =
+ std::make_unique<Array<Real>>(nb_element, size_at_nt_d_n_a, "K_e");
fem_cohesive.integrate(*at_nt_d_n_a, *K_e, size_at_nt_d_n_a, type,
ghost_type, elem_filter);
- delete at_nt_d_n_a;
-
model->getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _unsymmetric, elem_filter);
-
- delete K_e;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- *
* Compute traction from displacements
*
* @param[in] ghost_type compute the residual for _ghost or _not_ghost element
*/
void MaterialCohesive::computeTraction(GhostType ghost_type) {
AKANTU_DEBUG_IN();
for (const auto & type : element_filter.elementTypes(
spatial_dimension, ghost_type, _ek_cohesive)) {
- Array<UInt> & elem_filter = element_filter(type, ghost_type);
-
- UInt nb_element = elem_filter.size();
+ auto & elem_filter = element_filter(type, ghost_type);
+ auto nb_element = elem_filter.size();
if (nb_element == 0) {
continue;
}
- UInt nb_quadrature_points =
- nb_element * fem_cohesive.getNbIntegrationPoints(type, ghost_type);
-
- normal.resize(nb_quadrature_points);
-
/// compute normals @f$\mathbf{n}@f$
- computeNormal(model->getCurrentPosition(), normal, type, ghost_type);
+ computeNormal(model->getCurrentPosition(), normals(type, ghost_type), type,
+ ghost_type);
/// compute openings @f$\mathbf{\delta}@f$
computeOpening(model->getDisplacement(), opening(type, ghost_type), type,
ghost_type);
/// compute traction @f$\mathbf{t}@f$
- computeTraction(normal, type, ghost_type);
+ computeTraction(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MaterialCohesive::computeNormal(const Array<Real> & position,
Array<Real> & normal, ElementType type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & fem_cohesive =
this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
normal.zero();
-#define COMPUTE_NORMAL(type) \
- fem_cohesive.getShapeFunctions() \
- .computeNormalsOnIntegrationPoints<type, CohesiveReduceFunctionMean>( \
- position, normal, ghost_type, element_filter(type, ghost_type));
-
- AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_NORMAL);
-#undef COMPUTE_NORMAL
+ tuple_dispatch<ElementTypes_t<_ek_cohesive>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ fem_cohesive.getShapeFunctions()
+ .computeNormalsOnIntegrationPoints<type,
+ CohesiveReduceFunctionMean>(
+ position, normal, ghost_type, element_filter(type, ghost_type));
+ },
+ type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MaterialCohesive::computeOpening(const Array<Real> & displacement,
Array<Real> & opening, ElementType type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & fem_cohesive =
this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
-#define COMPUTE_OPENING(type) \
- fem_cohesive.getShapeFunctions() \
- .interpolateOnIntegrationPoints<type, CohesiveReduceFunctionOpening>( \
- displacement, opening, spatial_dimension, ghost_type, \
- element_filter(type, ghost_type));
-
- AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_OPENING);
-#undef COMPUTE_OPENING
+ tuple_dispatch<ElementTypes_t<_ek_cohesive>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ fem_cohesive.getShapeFunctions()
+ .interpolateOnIntegrationPoints<type,
+ CohesiveReduceFunctionOpening>(
+ displacement, opening, spatial_dimension, ghost_type,
+ element_filter(type, ghost_type));
+ },
+ type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MaterialCohesive::updateEnergies(ElementType type) {
AKANTU_DEBUG_IN();
if (Mesh::getKind(type) != _ek_cohesive) {
return;
}
Vector<Real> b(spatial_dimension);
Vector<Real> h(spatial_dimension);
auto erev = reversible_energy(type).begin();
auto etot = total_energy(type).begin();
auto traction_it = tractions(type).begin(spatial_dimension);
auto traction_old_it = tractions.previous(type).begin(spatial_dimension);
auto opening_it = opening(type).begin(spatial_dimension);
auto opening_old_it = opening.previous(type).begin(spatial_dimension);
auto traction_end = tractions(type).end(spatial_dimension);
/// loop on each quadrature point
for (; traction_it != traction_end; ++traction_it, ++traction_old_it,
++opening_it, ++opening_old_it, ++erev,
++etot) {
/// trapezoidal integration
b = *opening_it;
b -= *opening_old_it;
h = *traction_old_it;
h += *traction_it;
*etot += .5 * b.dot(h);
*erev = .5 * traction_it->dot(*opening_it);
}
/// update old values
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Real MaterialCohesive::getReversibleEnergy() {
AKANTU_DEBUG_IN();
Real erev = 0.;
/// integrate reversible energy for each type of elements
for (const auto & type : element_filter.elementTypes(
spatial_dimension, _not_ghost, _ek_cohesive)) {
erev +=
fem_cohesive.integrate(reversible_energy(type, _not_ghost), type,
_not_ghost, element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return erev;
}
/* -------------------------------------------------------------------------- */
Real MaterialCohesive::getDissipatedEnergy() {
AKANTU_DEBUG_IN();
Real edis = 0.;
/// integrate dissipated energy for each type of elements
for (const auto & type : element_filter.elementTypes(
spatial_dimension, _not_ghost, _ek_cohesive)) {
Array<Real> dissipated_energy(total_energy(type, _not_ghost));
dissipated_energy -= reversible_energy(type, _not_ghost);
edis += fem_cohesive.integrate(dissipated_energy, type, _not_ghost,
element_filter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return edis;
}
/* -------------------------------------------------------------------------- */
Real MaterialCohesive::getContactEnergy() {
AKANTU_DEBUG_IN();
Real econ = 0.;
/// integrate contact energy for each type of elements
for (const auto & type : element_filter.elementTypes(
spatial_dimension, _not_ghost, _ek_cohesive)) {
auto & el_filter = element_filter(type, _not_ghost);
- UInt nb_quad_per_el = fem_cohesive.getNbIntegrationPoints(type, _not_ghost);
- UInt nb_quad_points = el_filter.size() * nb_quad_per_el;
+ auto nb_quad_per_el = fem_cohesive.getNbIntegrationPoints(type, _not_ghost);
+ auto nb_quad_points = el_filter.size() * nb_quad_per_el;
Array<Real> contact_energy(nb_quad_points);
auto contact_traction_it =
contact_tractions(type, _not_ghost).begin(spatial_dimension);
auto contact_opening_it =
contact_opening(type, _not_ghost).begin(spatial_dimension);
/// loop on each quadrature point
- for (UInt q = 0; q < nb_quad_points;
+ for (Int q = 0; q < nb_quad_points;
++contact_traction_it, ++contact_opening_it, ++q) {
contact_energy(q) = .5 * contact_traction_it->dot(*contact_opening_it);
}
econ += fem_cohesive.integrate(contact_energy, type, _not_ghost, el_filter);
}
AKANTU_DEBUG_OUT();
return econ;
}
/* -------------------------------------------------------------------------- */
Real MaterialCohesive::getEnergy(const std::string & type) {
if (type == "reversible") {
return getReversibleEnergy();
}
if (type == "dissipated") {
return getDissipatedEnergy();
}
if (type == "cohesive contact") {
return getContactEnergy();
}
return 0.;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
index c3155d2d4..69301a12d 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
@@ -1,236 +1,255 @@
/**
* @file material_cohesive.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Thu Jan 14 2021
*
* @brief Specialization of the material class for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material.hh"
+#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include "cohesive_internal_field.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_COHESIVE_HH_
#define AKANTU_MATERIAL_COHESIVE_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class SolidMechanicsModelCohesive;
}
namespace akantu {
class MaterialCohesive : public Material {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using MyFEEngineCohesiveType =
FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive>;
public:
MaterialCohesive(SolidMechanicsModel & model, const ID & id = "");
~MaterialCohesive() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the material computed parameter
void initMaterial() override;
/// compute tractions (including normals and openings)
void computeTraction(GhostType ghost_type = _not_ghost);
/// assemble residual
void assembleInternalForces(GhostType ghost_type = _not_ghost) override;
/// check stress for cohesive elements' insertion, by default it
/// also updates the cohesive elements' data
virtual void checkInsertion(bool /*check_only*/ = false) {
AKANTU_TO_IMPLEMENT();
}
/// interpolate stress on given positions for each element (empty
/// implemantation to avoid the generic call to be done on cohesive elements)
virtual void interpolateStress(const ElementType /*type*/,
Array<Real> & /*result*/) {}
/// compute the stresses
void computeAllStresses(GhostType /*ghost_type*/ = _not_ghost) final{};
// add the facet to be handled by the material
- UInt addFacet(const Element & element);
+ Idx addFacet(const Element & element);
+
+ template <Int dim>
+ inline decltype(auto) getArguments(ElementType element_type,
+ GhostType ghost_type) {
+ return zip(
+ "normal"_n = make_view<dim>(this->normals(element_type, ghost_type)),
+ "opening"_n = make_view<dim>(this->opening(element_type, ghost_type)),
+ "traction"_n =
+ make_view<dim>(this->tractions(element_type, ghost_type)),
+ "contact_opening"_n =
+ make_view<dim>(this->contact_opening(element_type, ghost_type)),
+ "contact_traction"_n =
+ make_view<dim>(this->contact_tractions(element_type, ghost_type)),
+ "previous_opening"_n =
+ make_view<dim>(this->opening.previous(element_type, ghost_type)),
+ "previous_traction"_n =
+ make_view<dim>(this->tractions.previous(element_type, ghost_type)),
+ "delta_max"_n = this->delta_max(element_type, ghost_type),
+ "damage"_n = this->damage(element_type, ghost_type));
+ }
protected:
virtual void computeTangentTraction(ElementType /*el_type*/,
Array<Real> & /*tangent_matrix*/,
- const Array<Real> & /*normal*/,
GhostType /*ghost_type*/ = _not_ghost) {
AKANTU_TO_IMPLEMENT();
}
/// compute the normal
void computeNormal(const Array<Real> & position, Array<Real> & normal,
ElementType type, GhostType ghost_type);
/// compute the opening
void computeOpening(const Array<Real> & displacement, Array<Real> & opening,
ElementType type, GhostType ghost_type);
template <ElementType type>
void computeNormal(const Array<Real> & position, Array<Real> & normal,
GhostType ghost_type);
/// assemble stiffness
void assembleStiffnessMatrix(GhostType ghost_type) override;
/// constitutive law
- virtual void computeTraction(const Array<Real> & normal, ElementType el_type,
+ virtual void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) = 0;
/// parallelism functions
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const override;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) override;
protected:
void updateEnergies(ElementType el_type) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the opening
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Opening, opening, Real);
/// get the traction
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Traction, tractions, Real);
/// get damage
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real);
/// get facet filter
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetFilter, facet_filter, UInt);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetFilter, facet_filter, UInt);
- AKANTU_GET_MACRO(FacetFilter, facet_filter,
- const ElementTypeMapArray<UInt> &);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetFilter, facet_filter, Idx);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetFilter, facet_filter, Idx);
+ AKANTU_GET_MACRO_AUTO(FacetFilter, facet_filter);
// AKANTU_GET_MACRO(ElementFilter, element_filter, const
// ElementTypeMapArray<UInt> &);
/// compute reversible energy
- Real getReversibleEnergy();
+ auto getReversibleEnergy() -> Real;
/// compute dissipated energy
- Real getDissipatedEnergy();
+ auto getDissipatedEnergy() -> Real;
/// compute contact energy
- Real getContactEnergy();
+ auto getContactEnergy() -> Real;
/// get energy
- Real getEnergy(const std::string & type) override;
+ auto getEnergy(const std::string & type) -> Real override;
/// return the energy (identified by id) for the provided element
- Real getEnergy(const std::string & energy_id, ElementType type,
- UInt index) override {
- return Material::getEnergy(energy_id, type, index);
- }
+ // Real getEnergy(const std::string & energy_id, const Element & element
+ // ) override {
+ // return Material::getEnergy(energy_id, element);
+ // }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// list of facets assigned to this material
- ElementTypeMapArray<UInt> facet_filter;
+ ElementTypeMapArray<Idx> facet_filter;
/// Link to the cohesive fem object in the model
FEEngine & fem_cohesive;
private:
/// reversible energy by quadrature point
CohesiveInternalField<Real> reversible_energy;
/// total energy by quadrature point
CohesiveInternalField<Real> total_energy;
protected:
/// opening in all elements and quadrature points
CohesiveInternalField<Real> opening;
/// traction in all elements and quadrature points
CohesiveInternalField<Real> tractions;
/// traction due to contact
CohesiveInternalField<Real> contact_tractions;
/// normal openings for contact tractions
CohesiveInternalField<Real> contact_opening;
/// maximum displacement
CohesiveInternalField<Real> delta_max;
/// tell if the previous delta_max state is needed (in iterative schemes)
bool use_previous_delta_max;
/// tell if the previous opening state is needed (in iterative schemes)
bool use_previous_opening;
/// damage
CohesiveInternalField<Real> damage;
/// pointer to the solid mechanics model for cohesive elements
SolidMechanicsModelCohesive * model;
/// critical stress
RandomInternalField<Real, FacetInternalField> sigma_c;
/// critical displacement
Real delta_c;
/// array to temporarily store the normals
- Array<Real> normal;
+ CohesiveInternalField<Real> normals;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "cohesive_internal_field_tmpl.hh"
#include "material_cohesive_inline_impl.hh"
#endif /* AKANTU_MATERIAL_COHESIVE_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.hh
index b7dc0f5b2..96fd3cd62 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.hh
@@ -1,110 +1,110 @@
/**
* @file material_cohesive_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Fri Apr 09 2021
*
* @brief MaterialCohesive inline implementation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt MaterialCohesive::addFacet(const Element & element) {
- Array<UInt> & f_filter = facet_filter(element.type, element.ghost_type);
+inline Int MaterialCohesive::addFacet(const Element & element) {
+ auto & f_filter = facet_filter(element.type, element.ghost_type);
f_filter.push_back(element.element);
return f_filter.size() - 1;
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void MaterialCohesive::computeNormal(const Array<Real> & /*position*/,
Array<Real> & /*normal*/,
GhostType /*ghost_type*/) {}
/* -------------------------------------------------------------------------- */
-inline UInt MaterialCohesive::getNbData(const Array<Element> & elements,
+inline Int MaterialCohesive::getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const {
switch (tag) {
case SynchronizationTag::_smm_stress: {
return 2 * spatial_dimension * sizeof(Real) *
this->getModel().getNbIntegrationPoints(elements,
"CohesiveFEEngine");
}
case SynchronizationTag::_smmc_damage: {
return sizeof(Real) * this->getModel().getNbIntegrationPoints(
elements, "CohesiveFEEngine");
}
default: {
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
inline void MaterialCohesive::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
switch (tag) {
case SynchronizationTag::_smm_stress: {
packElementDataHelper(tractions, buffer, elements, "CohesiveFEEngine");
packElementDataHelper(contact_tractions, buffer, elements,
"CohesiveFEEngine");
break;
}
case SynchronizationTag::_smmc_damage:
packElementDataHelper(damage, buffer, elements, "CohesiveFEEngine");
break;
default: {
}
}
}
/* -------------------------------------------------------------------------- */
inline void MaterialCohesive::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
switch (tag) {
case SynchronizationTag::_smm_stress: {
unpackElementDataHelper(tractions, buffer, elements, "CohesiveFEEngine");
unpackElementDataHelper(contact_tractions, buffer, elements,
"CohesiveFEEngine");
break;
}
case SynchronizationTag::_smmc_damage:
unpackElementDataHelper(damage, buffer, elements, "CohesiveFEEngine");
break;
default: {
}
}
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
index d2a57ed48..2eb338854 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
@@ -1,692 +1,675 @@
/**
* @file solid_mechanics_model_cohesive.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue May 08 2012
* @date last modification: Fri Apr 09 2021
*
* @brief Solid mechanics model for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
#include "aka_iterators.hh"
#include "cohesive_element_inserter.hh"
#include "element_synchronizer.hh"
#include "facet_synchronizer.hh"
#include "fe_engine_template.hh"
#include "global_ids_updater.hh"
#include "integrator_gauss.hh"
#include "material_cohesive.hh"
#include "mesh_accessor.hh"
#include "mesh_global_data_updater.hh"
#include "parser.hh"
#include "shape_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
namespace akantu {
class CohesiveMeshGlobalDataUpdater : public MeshGlobalDataUpdater {
public:
CohesiveMeshGlobalDataUpdater(SolidMechanicsModelCohesive & model)
: model(model), mesh(model.getMesh()),
- global_ids_updater(model.getMesh(), *model.cohesive_synchronizer) {}
+ global_ids_updater(model.getMesh(), model.cohesive_synchronizer.get()) {
+ }
/* ------------------------------------------------------------------------ */
std::tuple<UInt, UInt>
updateData(NewNodesEvent & nodes_event,
NewElementsEvent & elements_event) override {
auto * cohesive_nodes_event =
dynamic_cast<CohesiveNewNodesEvent *>(&nodes_event);
if (cohesive_nodes_event == nullptr) {
return std::make_tuple(nodes_event.getList().size(),
elements_event.getList().size());
}
/// update nodes type
auto & new_nodes = cohesive_nodes_event->getList();
auto & old_nodes = cohesive_nodes_event->getOldNodesList();
auto local_nb_new_nodes = new_nodes.size();
auto nb_new_nodes = local_nb_new_nodes;
if (mesh.isDistributed()) {
MeshAccessor mesh_accessor(mesh);
auto & nodes_flags = mesh_accessor.getNodesFlags();
auto nb_old_nodes = nodes_flags.size();
nodes_flags.resize(nb_old_nodes + local_nb_new_nodes);
for (auto && data : zip(old_nodes, new_nodes)) {
UInt old_node;
UInt new_node;
std::tie(old_node, new_node) = data;
nodes_flags(new_node) = nodes_flags(old_node);
}
model.updateCohesiveSynchronizers(elements_event);
nb_new_nodes = global_ids_updater.updateGlobalIDs(new_nodes.size());
}
auto nb_new_elements = elements_event.getList().size();
const auto & comm = mesh.getCommunicator();
comm.allReduce(nb_new_elements, SynchronizerOperation::_sum);
if (nb_new_elements > 0) {
mesh.sendEvent(elements_event);
}
if (nb_new_nodes > 0) {
mesh.sendEvent(nodes_event);
}
return std::make_tuple(nb_new_nodes, nb_new_elements);
}
private:
SolidMechanicsModelCohesive & model;
Mesh & mesh;
GlobalIdsUpdater global_ids_updater;
};
/* -------------------------------------------------------------------------- */
SolidMechanicsModelCohesive::SolidMechanicsModelCohesive(
- Mesh & mesh, UInt dim, const ID & id,
+ Mesh & mesh, Int dim, const ID & id,
std::shared_ptr<DOFManager> dof_manager)
: SolidMechanicsModel(mesh, dim, id, dof_manager,
ModelType::_solid_mechanics_model_cohesive),
tangents("tangents", id), facet_stress("facet_stress", id),
facet_material("facet_material", id) {
AKANTU_DEBUG_IN();
registerFEEngineObject<MyFEEngineCohesiveType>("CohesiveFEEngine", mesh,
Model::spatial_dimension);
auto && tmp_material_selector =
std::make_shared<DefaultMaterialCohesiveSelector>(*this);
tmp_material_selector->setFallback(this->material_selector);
this->material_selector = tmp_material_selector;
this->mesh.registerDumper<DumperParaview>("cohesive elements", id);
this->mesh.addDumpMeshToDumper("cohesive elements", mesh,
Model::spatial_dimension, _not_ghost,
_ek_cohesive);
if (this->mesh.isDistributed()) {
/// create the distributed synchronizer for cohesive elements
this->cohesive_synchronizer = std::make_unique<ElementSynchronizer>(
mesh, "cohesive_distributed_synchronizer");
auto & synchronizer = mesh.getElementSynchronizer();
this->cohesive_synchronizer->split(synchronizer, [](auto && el) {
return Mesh::getKind(el.type) == _ek_cohesive;
});
this->registerSynchronizer(*cohesive_synchronizer,
SynchronizationTag::_material_id);
this->registerSynchronizer(*cohesive_synchronizer,
SynchronizationTag::_smm_stress);
this->registerSynchronizer(*cohesive_synchronizer,
SynchronizationTag::_smm_boundary);
}
this->inserter = std::make_unique<CohesiveElementInserter>(
this->mesh, id + ":cohesive_element_inserter");
registerFEEngineObject<MyFEEngineFacetType>(
"FacetsFEEngine", mesh.getMeshFacets(), Model::spatial_dimension - 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() = default;
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::setTimeStep(Real time_step,
const ID & solver_id) {
SolidMechanicsModel::setTimeStep(time_step, solver_id);
this->mesh.getDumper("cohesive elements").setTimeStep(time_step);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::initFullImpl(const ModelOptions & options) {
AKANTU_DEBUG_IN();
const auto & smmc_options =
aka::as_type<SolidMechanicsModelCohesiveOptions>(options);
this->is_extrinsic = smmc_options.is_extrinsic;
inserter->setIsExtrinsic(is_extrinsic);
if (mesh.isDistributed()) {
auto & mesh_facets = inserter->getMeshFacets();
auto & synchronizer =
aka::as_type<FacetSynchronizer>(mesh_facets.getElementSynchronizer());
// synchronizeGhostFacetsConnectivity();
/// create the facet synchronizer for extrinsic simulations
if (is_extrinsic) {
facet_stress_synchronizer = std::make_unique<ElementSynchronizer>(
synchronizer, id + ":facet_stress_synchronizer");
facet_stress_synchronizer->swapSendRecv();
this->registerSynchronizer(*facet_stress_synchronizer,
SynchronizationTag::_smmc_facets_stress);
}
}
MeshAccessor mesh_accessor(mesh);
mesh_accessor.registerGlobalDataUpdater(
std::make_unique<CohesiveMeshGlobalDataUpdater>(*this));
ParserSection section;
bool is_empty;
std::tie(section, is_empty) = this->getParserSection();
if (not is_empty) {
auto inserter_section =
section.getSubSections(ParserType::_cohesive_inserter);
if (inserter_section.begin() != inserter_section.end()) {
inserter->parseSection(*inserter_section.begin());
}
}
SolidMechanicsModel::initFullImpl(options);
AKANTU_DEBUG_OUT();
} // namespace akantu
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::initMaterials() {
AKANTU_DEBUG_IN();
// make sure the material are instantiated
if (not are_materials_instantiated) {
instantiateMaterials();
}
/// find the first cohesive material
UInt cohesive_index = UInt(-1);
for (auto && material : enumerate(materials)) {
if (dynamic_cast<MaterialCohesive *>(std::get<1>(material).get()) !=
nullptr) {
cohesive_index = std::get<0>(material);
break;
}
}
if (cohesive_index == UInt(-1)) {
AKANTU_EXCEPTION("No cohesive materials in the material input file");
}
material_selector->setFallback(cohesive_index);
// set the facet information in the material in case of dynamic insertion
// to know what material to call for stress checks
const Mesh & mesh_facets = inserter->getMeshFacets();
facet_material.initialize(
mesh_facets, _spatial_dimension = spatial_dimension - 1,
_with_nb_element = true,
_default_value = material_selector->getFallbackValue());
for_each_element(
mesh_facets,
[&](auto && element) {
auto mat_index = (*material_selector)(element);
auto & mat = aka::as_type<MaterialCohesive>(*materials[mat_index]);
facet_material(element) = mat_index;
if (is_extrinsic) {
mat.addFacet(element);
}
},
_spatial_dimension = spatial_dimension - 1, _ghost_type = _not_ghost);
SolidMechanicsModel::initMaterials();
if (is_extrinsic) {
this->initAutomaticInsertion();
} else {
this->insertIntrinsicElements();
}
AKANTU_DEBUG_OUT();
} // namespace akantu
/* -------------------------------------------------------------------------- */
/**
* Initialize the model,basically it pre-compute the shapes, shapes derivatives
* and jacobian
*/
void SolidMechanicsModelCohesive::initModel() {
AKANTU_DEBUG_IN();
SolidMechanicsModel::initModel();
/// add cohesive type connectivity
ElementType type = _not_defined;
for (auto && type_ghost : ghost_types) {
for (const auto & tmp_type :
mesh.elementTypes(spatial_dimension, type_ghost)) {
const auto & connectivity = mesh.getConnectivity(tmp_type, type_ghost);
if (connectivity.empty()) {
continue;
}
type = tmp_type;
auto type_facet = Mesh::getFacetType(type);
auto type_cohesive = FEEngine::getCohesiveElementType(type_facet);
+ AKANTU_DEBUG_ASSERT(Mesh::getKind(type_cohesive) == _ek_cohesive,
+ "The element type " << type_cohesive
+ << " is not a cohesive type");
mesh.addConnectivityType(type_cohesive, type_ghost);
}
}
AKANTU_DEBUG_ASSERT(type != _not_defined, "No elements in the mesh");
getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost);
getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost);
if (is_extrinsic) {
getFEEngine("FacetsFEEngine").initShapeFunctions(_not_ghost);
getFEEngine("FacetsFEEngine").initShapeFunctions(_ghost);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::insertIntrinsicElements() {
AKANTU_DEBUG_IN();
inserter->insertIntrinsicElements();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::initAutomaticInsertion() {
AKANTU_DEBUG_IN();
this->inserter->limitCheckFacets();
this->updateFacetStressSynchronizer();
this->resizeFacetStress();
/// compute normals on facets
this->computeNormals();
this->initStressInterpolation();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::updateAutomaticInsertion() {
AKANTU_DEBUG_IN();
this->inserter->limitCheckFacets();
this->updateFacetStressSynchronizer();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::initStressInterpolation() {
Mesh & mesh_facets = inserter->getMeshFacets();
/// compute quadrature points coordinates on facets
Array<Real> & position = mesh.getNodes();
ElementTypeMapArray<Real> quad_facets("quad_facets", id);
quad_facets.initialize(mesh_facets, _nb_component = Model::spatial_dimension,
_spatial_dimension = Model::spatial_dimension - 1);
// mesh_facets.initElementTypeMapArray(quad_facets, Model::spatial_dimension,
// Model::spatial_dimension - 1);
getFEEngine("FacetsFEEngine")
.interpolateOnIntegrationPoints(position, quad_facets);
/// compute elements quadrature point positions and build
/// element-facet quadrature points data structure
ElementTypeMapArray<Real> elements_quad_facets("elements_quad_facets", id);
elements_quad_facets.initialize(
mesh, _nb_component = Model::spatial_dimension,
_spatial_dimension = Model::spatial_dimension);
// mesh.initElementTypeMapArray(elements_quad_facets,
// Model::spatial_dimension,
// Model::spatial_dimension);
for (auto elem_gt : ghost_types) {
for (const auto & type :
mesh.elementTypes(Model::spatial_dimension, elem_gt)) {
UInt nb_element = mesh.getNbElement(type, elem_gt);
if (nb_element == 0) {
continue;
}
/// compute elements' quadrature points and list of facet
/// quadrature points positions by element
const auto & facet_to_element =
mesh_facets.getSubelementToElement(type, elem_gt);
auto & el_q_facet = elements_quad_facets(type, elem_gt);
auto facet_type = Mesh::getFacetType(type);
auto nb_quad_per_facet =
getFEEngine("FacetsFEEngine").getNbIntegrationPoints(facet_type);
auto nb_facet_per_elem = facet_to_element.getNbComponent();
// small hack in the loop to skip boundary elements, they are silently
// initialized to NaN to see if this causes problems
el_q_facet.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet,
std::numeric_limits<Real>::quiet_NaN());
for (auto && data :
zip(make_view(facet_to_element),
make_view(el_q_facet, spatial_dimension, nb_quad_per_facet))) {
const auto & global_facet = std::get<0>(data);
auto & el_q = std::get<1>(data);
if (global_facet == ElementNull) {
continue;
}
- Matrix<Real> quad_f =
+ auto && quad_f =
make_view(quad_facets(global_facet.type, global_facet.ghost_type),
spatial_dimension, nb_quad_per_facet)
.begin()[global_facet.element];
el_q = quad_f;
}
}
}
/// loop over non cohesive materials
for (auto && material : materials) {
if (aka::is_of_type<MaterialCohesive>(material)) {
continue;
}
/// initialize the interpolation function
material->initElementalFieldInterpolation(elements_quad_facets);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::assembleInternalForces() {
AKANTU_DEBUG_IN();
// f_int += f_int_cohe
for (auto & material : this->materials) {
try {
auto & mat = aka::as_type<MaterialCohesive>(*material);
mat.computeTraction(_not_ghost);
} catch (std::bad_cast & bce) {
}
}
SolidMechanicsModel::assembleInternalForces();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::computeNormals() {
AKANTU_DEBUG_IN();
Mesh & mesh_facets = this->inserter->getMeshFacets();
this->getFEEngine("FacetsFEEngine")
.computeNormalsOnIntegrationPoints(_not_ghost);
/**
* @todo store tangents while computing normals instead of
* recomputing them as follows:
*/
/* ------------------------------------------------------------------------ */
UInt tangent_components =
Model::spatial_dimension * (Model::spatial_dimension - 1);
tangents.initialize(mesh_facets, _nb_component = tangent_components,
_spatial_dimension = Model::spatial_dimension - 1);
- // mesh_facets.initElementTypeMapArray(tangents, tangent_components,
- // Model::spatial_dimension - 1);
for (auto facet_type :
mesh_facets.elementTypes(Model::spatial_dimension - 1)) {
const Array<Real> & normals =
this->getFEEngine("FacetsFEEngine")
.getNormalsOnIntegrationPoints(facet_type);
Array<Real> & tangents = this->tangents(facet_type);
Math::compute_tangents(normals, tangents);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::interpolateStress() {
ElementTypeMapArray<Real> by_elem_result("temporary_stress_by_facets", id);
for (auto & material : materials) {
if (not aka::is_of_type<MaterialCohesive>(material)) {
/// interpolate stress on facet quadrature points positions
material->interpolateStressOnFacets(facet_stress, by_elem_result);
}
}
this->synchronize(SynchronizationTag::_smmc_facets_stress);
}
/* -------------------------------------------------------------------------- */
UInt SolidMechanicsModelCohesive::checkCohesiveStress() {
AKANTU_DEBUG_IN();
if (not is_extrinsic) {
AKANTU_EXCEPTION(
"This function can only be used for extrinsic cohesive elements");
}
interpolateStress();
for (auto & mat : materials) {
if (aka::is_of_type<MaterialCohesive>(mat)) {
/// check which not ghost cohesive elements are to be created
auto * mat_cohesive = aka::as_type<MaterialCohesive>(mat.get());
mat_cohesive->checkInsertion();
}
}
- /// communicate data among processors
- // this->synchronize(SynchronizationTag::_smmc_facets);
-
/// insert cohesive elements
UInt nb_new_elements = inserter->insertElements();
- // if (nb_new_elements > 0) {
- // this->reinitializeSolver();
- // }
-
AKANTU_DEBUG_OUT();
return nb_new_elements;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::onElementsAdded(
const Array<Element> & element_list, const NewElementsEvent & event) {
AKANTU_DEBUG_IN();
SolidMechanicsModel::onElementsAdded(element_list, event);
if (is_extrinsic) {
resizeFacetStress();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void SolidMechanicsModelCohesive::onNodesAdded(const Array<UInt> & new_nodes,
+void SolidMechanicsModelCohesive::onNodesAdded(const Array<Idx> & new_nodes,
const NewNodesEvent & event) {
AKANTU_DEBUG_IN();
SolidMechanicsModel::onNodesAdded(new_nodes, event);
const CohesiveNewNodesEvent * cohesive_event;
if ((cohesive_event = dynamic_cast<const CohesiveNewNodesEvent *>(&event)) ==
nullptr) {
return;
}
const auto & old_nodes = cohesive_event->getOldNodesList();
auto copy = [this, &new_nodes, &old_nodes](auto & arr) {
- UInt new_node;
- UInt old_node;
-
- auto view = make_view(arr, spatial_dimension);
- auto begin = view.begin();
-
- for (auto && pair : zip(new_nodes, old_nodes)) {
- std::tie(new_node, old_node) = pair;
-
- auto old_ = begin + old_node;
- auto new_ = begin + new_node;
-
- *new_ = *old_;
+ auto it = make_view(arr, spatial_dimension).begin();
+ for (auto [new_node, old_node] : zip(new_nodes, old_nodes)) {
+ it[new_node] = it[old_node];
}
};
copy(*displacement);
copy(*blocked_dofs);
if (velocity) {
copy(*velocity);
}
if (acceleration) {
copy(*acceleration);
}
if (current_position) {
copy(*current_position);
}
if (previous_displacement) {
copy(*previous_displacement);
}
if (displacement_increment) {
copy(*displacement_increment);
}
copy(getDOFManager().getSolution("displacement"));
- // this->assembleMassLumped();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::afterSolveStep(bool converged) {
AKANTU_DEBUG_IN();
/*
* This is required because the Cauchy stress is the stress measure that
* is used to check the insertion of cohesive elements
*/
if (converged) {
for (auto & mat : materials) {
if (mat->isFiniteDeformation()) {
mat->computeAllCauchyStresses(_not_ghost);
}
}
}
SolidMechanicsModel::afterSolveStep(converged);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::printself(std::ostream & stream,
int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "SolidMechanicsModelCohesive ["
<< "\n";
SolidMechanicsModel::printself(stream, indent + 2);
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::resizeFacetStress() {
AKANTU_DEBUG_IN();
this->facet_stress.initialize(getFEEngine("FacetsFEEngine"),
_nb_component =
2 * spatial_dimension * spatial_dimension,
_spatial_dimension = spatial_dimension - 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::addDumpGroupFieldToDumper(
const std::string & dumper_name, const std::string & field_id,
const std::string & group_name, ElementKind element_kind,
bool padding_flag) {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = Model::spatial_dimension;
+ Int spatial_dimension = Model::spatial_dimension;
ElementKind _element_kind = element_kind;
if (dumper_name == "cohesive elements") {
_element_kind = _ek_cohesive;
} else if (dumper_name == "facets") {
spatial_dimension = Model::spatial_dimension - 1;
}
SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, field_id,
group_name, spatial_dimension,
_element_kind, padding_flag);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-
void SolidMechanicsModelCohesive::onDump() {
this->flattenAllRegisteredInternals(_ek_cohesive);
SolidMechanicsModel::onDump();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
index 6b83bacd6..3b783fca5 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
@@ -1,311 +1,310 @@
/**
* @file solid_mechanics_model_cohesive.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue May 08 2012
* @date last modification: Fri Apr 09 2021
*
* @brief Solid mechanics model for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "cohesive_element_inserter.hh"
#include "material_selector_cohesive.hh"
#include "random_internal_field.hh" // included to have the specialization of
// ParameterTyped::operator Real()
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH_
#define AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class FacetSynchronizer;
class FacetStressSynchronizer;
class ElementSynchronizer;
} // namespace akantu
namespace akantu {
/* -------------------------------------------------------------------------- */
struct FacetsCohesiveIntegrationOrderFunctor {
template <ElementType type, ElementType cohesive_type =
CohesiveFacetProperty<type>::cohesive_type>
struct _helper {
static constexpr int get() {
return ElementClassProperty<cohesive_type>::polynomial_degree;
}
};
template <ElementType type> struct _helper<type, _not_defined> {
static constexpr int get() {
return ElementClassProperty<type>::polynomial_degree;
}
};
template <ElementType type> static inline constexpr int getOrder() {
return _helper<type>::get();
}
};
/* -------------------------------------------------------------------------- */
/* Solid Mechanics Model for Cohesive elements */
/* -------------------------------------------------------------------------- */
class SolidMechanicsModelCohesive : public SolidMechanicsModel,
public SolidMechanicsModelEventHandler {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
class NewCohesiveNodesEvent : public NewNodesEvent {
public:
AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &);
AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &);
protected:
Array<UInt> old_nodes;
};
using MyFEEngineCohesiveType =
FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive>;
using MyFEEngineFacetType =
FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular,
FacetsCohesiveIntegrationOrderFunctor>;
SolidMechanicsModelCohesive(
- Mesh & mesh, UInt dim = _all_dimensions,
+ Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "solid_mechanics_model_cohesive",
std::shared_ptr<DOFManager> dof_manager = nullptr);
~SolidMechanicsModelCohesive() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
/// initialize the cohesive model
void initFullImpl(const ModelOptions & options) override;
public:
/// set the value of the time step
void setTimeStep(Real time_step, const ID & solver_id = "") override;
/// assemble the residual for the explicit scheme
void assembleInternalForces() override;
/// function to perform a stress check on each facet and insert
/// cohesive elements if needed (returns the number of new cohesive
/// elements)
UInt checkCohesiveStress();
/// interpolate stress on facets
void interpolateStress();
/// update automatic insertion after a change in the element inserter
void updateAutomaticInsertion();
/// insert intrinsic cohesive elements
void insertIntrinsicElements();
// template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria
// criteria> bool solveStepCohesive(Real tolerance, Real & error, UInt
// max_iteration = 100,
// bool load_reduction = false,
// Real tol_increase_factor = 1.0,
// bool do_not_factorize = false);
protected:
/// initialize stress interpolation
void initStressInterpolation();
/// initialize the model
void initModel() override;
/// initialize cohesive material
void initMaterials() override;
/// init facet filters for cohesive materials
void initFacetFilter();
/// function to print the contain of the class
void printself(std::ostream & stream, int indent = 0) const override;
private:
/// insert cohesive elements along a given physical surface of the mesh
void insertElementsFromMeshData(const std::string & physical_name);
/// initialize completely the model for extrinsic elements
void initAutomaticInsertion();
/// compute facets' normals
void computeNormals();
/// resize facet stress
void resizeFacetStress();
/// init facets_check array
void initFacetsCheck();
/* ------------------------------------------------------------------------ */
/* Mesh Event Handler inherited members */
/* ------------------------------------------------------------------------ */
protected:
- void onNodesAdded(const Array<UInt> & new_nodes,
+ void onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) override;
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
/* ------------------------------------------------------------------------ */
/* SolidMechanicsModelEventHandler inherited members */
/* ------------------------------------------------------------------------ */
public:
void afterSolveStep(bool converged = true) override;
/* ------------------------------------------------------------------------ */
/* Dumpable interface */
/* ------------------------------------------------------------------------ */
public:
void onDump() override;
void addDumpGroupFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name,
ElementKind element_kind,
bool padding_flag) override;
public:
/// register the tags associated with the parallel synchronizer for
/// cohesive elements
// void initParallel(MeshPartition * partition,
// DataAccessor * data_accessor = NULL,
// bool extrinsic = false);
protected:
// void synchronizeGhostFacetsConnectivity();
void updateCohesiveSynchronizers(NewElementsEvent & elements_event);
void updateFacetStressSynchronizer();
friend class CohesiveElementInserter;
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override;
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const override;
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) override;
protected:
- UInt getNbQuadsForFacetCheck(const Array<Element> & elements) const;
+ Int getNbQuadsForFacetCheck(const Array<Element> & elements) const;
template <typename T>
void packFacetStressDataHelper(const ElementTypeMapArray<T> & data_to_pack,
CommunicationBuffer & buffer,
const Array<Element> & elements) const;
template <typename T>
void unpackFacetStressDataHelper(ElementTypeMapArray<T> & data_to_unpack,
CommunicationBuffer & buffer,
const Array<Element> & elements) const;
template <typename T, bool pack_helper>
void packUnpackFacetStressDataHelper(ElementTypeMapArray<T> & data_to_pack,
CommunicationBuffer & buffer,
const Array<Element> & element) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get facet mesh
- AKANTU_GET_MACRO(MeshFacets, mesh.getMeshFacets(), const Mesh &);
+ AKANTU_GET_MACRO_AUTO(MeshFacets, mesh.getMeshFacets());
/// get stress on facets vector
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressOnFacets, facet_stress, Real);
/// get facet material
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetMaterial, facet_material, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetMaterial, facet_material, Idx);
/// get facet material
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, Idx);
/// get facet material
- AKANTU_GET_MACRO(FacetMaterial, facet_material,
- const ElementTypeMapArray<UInt> &);
+ AKANTU_GET_MACRO_AUTO(FacetMaterial, facet_material);
/// @todo THIS HAS TO BE CHANGED
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Tangents, tangents, Real);
/// get element inserter
AKANTU_GET_MACRO_NOT_CONST(ElementInserter, *inserter,
CohesiveElementInserter &);
/// get is_extrinsic boolean
AKANTU_GET_MACRO(IsExtrinsic, is_extrinsic, bool);
/// get cohesive elements synchronizer
AKANTU_GET_MACRO_NOT_CONST(CohesiveSynchronizer, *cohesive_synchronizer,
ElementSynchronizer &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
friend class CohesiveMeshGlobalDataUpdater;
/// @todo store tangents when normals are computed:
ElementTypeMapArray<Real> tangents;
/// stress on facets on the two sides by quadrature point
ElementTypeMapArray<Real> facet_stress;
/// material to use if a cohesive element is created on a facet
- ElementTypeMapArray<UInt> facet_material;
+ ElementTypeMapArray<Idx> facet_material;
bool is_extrinsic{false};
/// cohesive element inserter
std::unique_ptr<CohesiveElementInserter> inserter;
/// facet stress synchronizer
std::unique_ptr<ElementSynchronizer> facet_stress_synchronizer;
/// cohesive elements synchronizer
std::unique_ptr<ElementSynchronizer> cohesive_synchronizer;
};
} // namespace akantu
#include "solid_mechanics_model_cohesive_inline_impl.hh"
#endif /* AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh
index cea382f2c..58e50832d 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh
@@ -1,307 +1,307 @@
/**
* @file solid_mechanics_model_cohesive_inline_impl.hh
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jan 18 2013
* @date last modification: Sun Dec 30 2018
*
* @brief Implementation of inline functions for the Cohesive element model
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_HH_
#define AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
// template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
// bool SolidMechanicsModelCohesive::solveStepCohesive(
// Real tolerance, Real & error, UInt max_iteration, bool load_reduction,
// Real tol_increase_factor, bool do_not_factorize) {
// // EventManager::sendEvent(
// // SolidMechanicsModelEvent::BeforeSolveStepEvent(method));
// // this->implicitPred();
// // bool insertion_new_element = true;
// // bool converged = false;
// // Array<Real> * displacement_tmp = NULL;
// // Array<Real> * velocity_tmp = NULL;
// // Array<Real> * acceleration_tmp = NULL;
// // StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
// // Int prank = comm.whoAmI();
// // /// Loop for the insertion of new cohesive elements
// // while (insertion_new_element) {
// // if (is_extrinsic) {
// // /**
// // * If in extrinsic the solution of the previous incremental step
// // * is saved in temporary arrays created for displacements,
// // * velocities and accelerations. Such arrays are used to find
// // * the solution with the Newton-Raphson scheme (this is done by
// // * pointing the pointer "displacement" to displacement_tmp). In
// // * this way, inside the array "displacement" is kept the
// // * solution of the previous incremental step, and in
// // * "displacement_tmp" is saved the current solution.
// // */
// // if (!displacement_tmp)
// // displacement_tmp = new Array<Real>(0, spatial_dimension);
// // displacement_tmp->copy(*(this->displacement));
// // if (!velocity_tmp)
// // velocity_tmp = new Array<Real>(0, spatial_dimension);
// // velocity_tmp->copy(*(this->velocity));
// // if (!acceleration_tmp) {
// // acceleration_tmp = new Array<Real>(0, spatial_dimension);
// // }
// // acceleration_tmp->copy(*(this->acceleration));
// // std::swap(displacement, displacement_tmp);
// // std::swap(velocity, velocity_tmp);
// // std::swap(acceleration, acceleration_tmp);
// // }
// // this->updateResidual();
// // AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL,
// // "You should first initialize the implicit solver and
// "
// // "assemble the stiffness matrix");
// // bool need_factorize = !do_not_factorize;
// // if (method == _implicit_dynamic) {
// // AKANTU_DEBUG_ASSERT(mass_matrix != NULL, "You should first initialize
// "
// // "the implicit solver and "
// // "assemble the mass matrix");
// // }
// // switch (cmethod) {
// // case _scm_newton_raphson_tangent:
// // case _scm_newton_raphson_tangent_not_computed:
// // break;
// // case _scm_newton_raphson_tangent_modified:
// // this->assembleStiffnessMatrix();
// // break;
// // default:
// // AKANTU_ERROR("The resolution method "
// // << cmethod << " has not been implemented!");
// // }
// // UInt iter = 0;
// // converged = false;
// // error = 0.;
// // if (criteria == SolveConvergenceCriteria::_residual) {
// // converged = this->testConvergence<criteria>(tolerance, error);
// // if (converged)
// // return converged;
// // }
// // /// Loop to solve the nonlinear system
// // do {
// // if (cmethod == _scm_newton_raphson_tangent)
// // this->assembleStiffnessMatrix();
// // solve<NewmarkBeta::_displacement_corrector>(*increment, 1.,
// // need_factorize);
// // this->implicitCorr();
// // this->updateResidual();
// // converged = this->testConvergence<criteria>(tolerance, error);
// // iter++;
// // AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration "
// // << std::setw(std::log10(max_iteration)) << iter
// // << ": error " << error
// // << (converged ? " < " : " > ") << tolerance);
// // switch (cmethod) {
// // case _scm_newton_raphson_tangent:
// // need_factorize = true;
// // break;
// // case _scm_newton_raphson_tangent_not_computed:
// // case _scm_newton_raphson_tangent_modified:
// // need_factorize = false;
// // break;
// // default:
// // AKANTU_ERROR("The resolution method "
// // << cmethod << " has not been implemented!");
// // }
// // } while (!converged && iter < max_iteration);
// // /**
// // * This is to save the obtained result and proceed with the
// // * simulation even if the error is higher than the pre-fixed
// // * tolerance. This is done only after loading reduction
// // * (load_reduction = true).
// // */
// // // if (load_reduction && (error < tolerance * tol_increase_factor))
// // // converged = true;
// // if ((error < tolerance * tol_increase_factor))
// // converged = true;
// // if (converged) {
// // } else if (iter == max_iteration) {
// // if (prank == 0) {
// // AKANTU_DEBUG_WARNING(
// // "[" << criteria << "] Convergence not reached after "
// // << std::setw(std::log10(max_iteration)) << iter << "
// iteration"
// // << (iter == 1 ? "" : "s") << "!" << std::endl);
// // }
// // }
// // if (is_extrinsic) {
// // /**
// // * If is extrinsic the pointer "displacement" is moved back to
// // * the array displacement. In this way, the array displacement is
// // * correctly resized during the checkCohesiveStress function (in
// // * case new cohesive elements are added). This is possible
// // * because the procedure called by checkCohesiveStress does not
// // * use the displacement field (the correct one is now stored in
// // * displacement_tmp), but directly the stress field that is
// // * already computed.
// // */
// // Array<Real> * tmp_swap;
// // tmp_swap = displacement_tmp;
// // displacement_tmp = this->displacement;
// // this->displacement = tmp_swap;
// // tmp_swap = velocity_tmp;
// // velocity_tmp = this->velocity;
// // this->velocity = tmp_swap;
// // tmp_swap = acceleration_tmp;
// // acceleration_tmp = this->acceleration;
// // this->acceleration = tmp_swap;
// // /// If convergence is reached, call checkCohesiveStress in order
// // /// to check if cohesive elements have to be introduced
// // if (converged) {
// // UInt new_cohesive_elements = checkCohesiveStress();
// // if (new_cohesive_elements == 0) {
// // insertion_new_element = false;
// // } else {
// // insertion_new_element = true;
// // }
// // }
// // }
// // if (!converged && load_reduction)
// // insertion_new_element = false;
// // /**
// // * If convergence is not reached, there is the possibility to
// // * return back to the main file and reduce the load. Before doing
// // * this, a pre-fixed value as to be defined for the parameter
// // * delta_max of the cohesive elements introduced in the current
// // * incremental step. This is done by calling the function
// // * checkDeltaMax.
// // */
// // if (!converged) {
// // insertion_new_element = false;
-// // for (UInt m = 0; m < materials.size(); ++m) {
+// // for (Int m = 0; m < materials.size(); ++m) {
// // try {
// // MaterialCohesive & mat =
// // aka::as_type<MaterialCohesive>(*materials[m]);
// // mat.checkDeltaMax(_not_ghost);
// // } catch (std::bad_cast &) {
// // }
// // }
// // }
// // } // end loop for the insertion of new cohesive elements
// // /**
// // * When the solution to the current incremental step is computed (no
// // * more cohesive elements have to be introduced), call the function
// // * to compute the energies.
// // */
// // if ((is_extrinsic && converged)) {
-// // for (UInt m = 0; m < materials.size(); ++m) {
+// // for (Int m = 0; m < materials.size(); ++m) {
// // try {
// // MaterialCohesive & mat =
// // aka::as_type<MaterialCohesive>(*materials[m]);
// // mat.computeEnergies();
// // } catch (std::bad_cast & bce) {
// // }
// // }
// // EventManager::sendEvent(
// // SolidMechanicsModelEvent::AfterSolveStepEvent(method));
// // /**
// // * The function resetVariables is necessary to correctly set a
// // * variable that permit to decrease locally the penalty parameter
// // * for compression.
// // */
-// // for (UInt m = 0; m < materials.size(); ++m) {
+// // for (Int m = 0; m < materials.size(); ++m) {
// // try {
// // MaterialCohesive & mat =
// // aka::as_type<MaterialCohesive>(*materials[m]);
// // mat.resetVariables(_not_ghost);
// // } catch (std::bad_cast &) {
// // }
// // }
// // /// The correct solution is saved
// // this->displacement->copy(*displacement_tmp);
// // this->velocity->copy(*velocity_tmp);
// // this->acceleration->copy(*acceleration_tmp);
// // }
// // delete displacement_tmp;
// // delete velocity_tmp;
// // delete acceleration_tmp;
// // return insertion_new_element;
//}
} // namespace akantu
#endif /* AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc
index 99bf41940..1b8430ab4 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc
@@ -1,527 +1,493 @@
/**
* @file solid_mechanics_model_cohesive_parallel.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Fri Apr 09 2021
*
* @brief Functions for parallel cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "element_synchronizer.hh"
#include "material_cohesive.hh"
#include "solid_mechanics_model_cohesive.hh"
#include "solid_mechanics_model_tmpl.hh"
/* -------------------------------------------------------------------------- */
#include <type_traits>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
// void SolidMechanicsModelCohesive::synchronizeGhostFacetsConnectivity() {
// AKANTU_DEBUG_IN();
// const Communicator & comm = mesh.getCommunicator();
// Int psize = comm.getNbProc();
// if (psize == 1) {
// AKANTU_DEBUG_OUT();
// return;
// }
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::updateCohesiveSynchronizers(
NewElementsEvent & elements_event) {
/// update synchronizers if needed
if (not mesh.isDistributed()) {
return;
}
ElementTypeMap<Int> nb_new_cohesive_elements;
for (auto ghost_type : ghost_types) {
for (auto cohesive_type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_cohesive)) {
nb_new_cohesive_elements(cohesive_type, ghost_type) = 0;
}
}
for (auto & el : elements_event.getList()) {
if (el.kind() != _ek_cohesive) {
continue;
}
++nb_new_cohesive_elements(el.type, el.ghost_type);
}
auto & mesh_facets = inserter->getMeshFacets();
auto & facet_synchronizer = mesh_facets.getElementSynchronizer();
const auto & cfacet_synchronizer = facet_synchronizer;
// update the cohesive element synchronizer
cohesive_synchronizer->updateSchemes(
[&](auto && scheme, auto && proc, auto && direction) {
auto & facet_scheme =
cfacet_synchronizer.getCommunications().getScheme(proc, direction);
for (auto && facet : facet_scheme) {
const auto & cohesive_element = const_cast<const Mesh &>(mesh_facets)
.getElementToSubelement(facet)[1];
if (cohesive_element == ElementNull or
cohesive_element.kind() != _ek_cohesive) {
continue;
}
auto && cohesive_type = FEEngine::getCohesiveElementType(facet.type);
auto old_nb_cohesive_elements =
mesh.getNbElement(cohesive_type, facet.ghost_type);
old_nb_cohesive_elements -=
nb_new_cohesive_elements(cohesive_type, facet.ghost_type);
if (cohesive_element.element >= old_nb_cohesive_elements) {
scheme.push_back(cohesive_element);
}
}
});
if (not facet_stress_synchronizer) {
return;
}
const auto & element_synchronizer = mesh.getElementSynchronizer();
const auto & comm = mesh.getCommunicator();
auto && my_rank = comm.whoAmI();
// update the facet stress synchronizer
facet_stress_synchronizer->updateSchemes([&](auto && scheme, auto && proc,
auto && /*direction*/) {
auto it_element = scheme.begin();
for (auto && element : scheme) {
auto && facet_check = inserter->getCheckFacets(
element.type, element.ghost_type)(element.element); // slow access
// here
if (facet_check) {
auto && connected_elements = mesh_facets.getElementToSubelement(
element.type, element.ghost_type)(element.element); // slow access
// here
auto && rank_left = element_synchronizer.getRank(connected_elements[0]);
auto && rank_right =
element_synchronizer.getRank(connected_elements[1]);
// keep element if the element is still a boundary element between two
// processors
if ((rank_left == Int(proc) and rank_right == my_rank) or
(rank_left == my_rank and rank_right == Int(proc))) {
*it_element = element;
++it_element;
}
}
}
scheme.resize(it_element - scheme.begin());
});
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::updateFacetStressSynchronizer() {
- if (facet_stress_synchronizer != nullptr) {
- const auto & rank_to_element =
- mesh.getElementSynchronizer().getElementToRank();
- const auto & facet_checks = inserter->getCheckFacets();
- const auto & mesh_facets = inserter->getMeshFacets();
- const auto & element_to_facet = mesh_facets.getElementToSubelement();
- UInt rank = mesh.getCommunicator().whoAmI();
-
- facet_stress_synchronizer->updateSchemes(
- [&](auto & scheme, auto & proc, auto & /*direction*/) {
- UInt el = 0;
- for (auto && element : scheme) {
- if (not facet_checks(element)) {
- continue;
- }
-
- const auto & next_el = element_to_facet(element);
- UInt rank_left = rank_to_element(next_el[0]);
- UInt rank_right = rank_to_element(next_el[1]);
-
- if ((rank_left == rank and rank_right == proc) or
- (rank_left == proc and rank_right == rank)) {
- scheme[el] = element;
- ++el;
- }
- }
- scheme.resize(el);
- });
+ if (facet_stress_synchronizer == nullptr) {
+ return;
}
+
+ const auto & rank_to_element =
+ mesh.getElementSynchronizer().getElementToRank();
+ const auto & facet_checks = inserter->getCheckFacets();
+ const auto & mesh_facets = inserter->getMeshFacets();
+ const auto & element_to_facet = mesh_facets.getElementToSubelement();
+ auto rank = mesh.getCommunicator().whoAmI();
+
+ facet_stress_synchronizer->updateSchemes(
+ [&](auto & scheme, auto & proc, auto & /*direction*/) {
+ Idx el = 0;
+ for (auto && element : scheme) {
+ if (not facet_checks(element)) {
+ continue;
+ }
+
+ const auto & next_el = element_to_facet(element);
+ auto rank_left = rank_to_element(next_el[0]);
+ auto rank_right = rank_to_element(next_el[1]);
+
+ if ((rank_left == rank and rank_right == proc) or
+ (rank_left == proc and rank_right == rank)) {
+ scheme[el] = element;
+ ++el;
+ }
+ }
+ scheme.resize(el);
+ });
}
/* -------------------------------------------------------------------------- */
template <typename T>
void SolidMechanicsModelCohesive::packFacetStressDataHelper(
const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
const Array<Element> & elements) const {
packUnpackFacetStressDataHelper<T, true>(
const_cast<ElementTypeMapArray<T> &>(data_to_pack), buffer, elements);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void SolidMechanicsModelCohesive::unpackFacetStressDataHelper(
ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer,
const Array<Element> & elements) const {
packUnpackFacetStressDataHelper<T, false>(data_to_unpack, buffer, elements);
}
/* -------------------------------------------------------------------------- */
template <typename T, bool pack_helper>
void SolidMechanicsModelCohesive::packUnpackFacetStressDataHelper(
ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
const Array<Element> & elements) const {
- ElementType current_element_type = _not_defined;
- GhostType current_ghost_type = _casper;
- UInt nb_quad_per_elem = 0;
- UInt sp2 = spatial_dimension * spatial_dimension;
- UInt nb_component = sp2 * 2;
bool element_rank = false;
- Mesh & mesh_facets = inserter->getMeshFacets();
-
- Array<T> * vect = nullptr;
- const Array<std::vector<Element>> * element_to_facet = nullptr;
+ auto & mesh_facets = inserter->getMeshFacets();
auto & fe_engine = this->getFEEngine("FacetsFEEngine");
for (auto && el : elements) {
if (el.type == _not_defined) {
AKANTU_EXCEPTION(
"packUnpackFacetStressDataHelper called with wrong inputs");
}
- if (el.type != current_element_type ||
- el.ghost_type != current_ghost_type) {
- current_element_type = el.type;
- current_ghost_type = el.ghost_type;
- vect = &data_to_pack(el.type, el.ghost_type);
-
- element_to_facet =
- &(mesh_facets.getElementToSubelement(el.type, el.ghost_type));
-
- nb_quad_per_elem =
- fe_engine.getNbIntegrationPoints(el.type, el.ghost_type);
- }
-
+ auto ghost_type = mesh_facets.getElementToSubelement()(el)[0].ghost_type;
if (pack_helper) {
- element_rank =
- (*element_to_facet)(el.element)[0].ghost_type != _not_ghost;
+ element_rank = ghost_type != _not_ghost;
} else {
- element_rank =
- (*element_to_facet)(el.element)[0].ghost_type == _not_ghost;
+ element_rank = ghost_type == _not_ghost;
}
- for (UInt q = 0; q < nb_quad_per_elem; ++q) {
- Vector<T> data(vect->storage() +
- (el.element * nb_quad_per_elem + q) * nb_component +
- element_rank * sp2,
- sp2);
+ auto nb_quad_per_elem =
+ fe_engine.getNbIntegrationPoints(el.type, el.ghost_type);
+
+ auto && data_per_element = data_to_pack.get(
+ el, spatial_dimension * spatial_dimension, 2, nb_quad_per_elem);
+ for (auto && data_per_quad : data_per_element) {
+ auto && data = data_per_quad(element_rank);
if (pack_helper) {
buffer << data;
} else {
buffer >> data;
}
}
}
}
/* -------------------------------------------------------------------------- */
-UInt SolidMechanicsModelCohesive::getNbQuadsForFacetCheck(
+Int SolidMechanicsModelCohesive::getNbQuadsForFacetCheck(
const Array<Element> & elements) const {
- UInt nb_quads = 0;
- UInt nb_quad_per_facet = 0;
-
- ElementType current_element_type = _not_defined;
- GhostType current_ghost_type = _casper;
- auto & fe_engine = this->getFEEngine("FacetsFEEngine");
+ Int nb_quads = 0;
+ const auto & fe_engine = this->getFEEngine("FacetsFEEngine");
for (const auto & el : elements) {
- if (el.type != current_element_type ||
- el.ghost_type != current_ghost_type) {
- current_element_type = el.type;
- current_ghost_type = el.ghost_type;
-
- nb_quad_per_facet =
- fe_engine.getNbIntegrationPoints(el.type, el.ghost_type);
- }
+ auto nb_quad_per_facet =
+ fe_engine.getNbIntegrationPoints(el.type, el.ghost_type);
nb_quads += nb_quad_per_facet;
}
return nb_quads;
}
/* -------------------------------------------------------------------------- */
-UInt SolidMechanicsModelCohesive::getNbData(
+Int SolidMechanicsModelCohesive::getNbData(
const Array<Element> & elements, const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
- UInt size = 0;
+ Int size = 0;
if (elements.empty()) {
return 0;
}
/// regular element case
if (elements(0).kind() == _ek_regular) {
switch (tag) {
// case SynchronizationTag::_smmc_facets: {
// size += elements.size() * sizeof(bool);
// break;
// }
case SynchronizationTag::_smmc_facets_stress: {
- UInt nb_quads = getNbQuadsForFacetCheck(elements);
+ auto nb_quads = getNbQuadsForFacetCheck(elements);
size += nb_quads * spatial_dimension * spatial_dimension * sizeof(Real);
break;
}
case SynchronizationTag::_material_id: {
for (auto && element : elements) {
if (Mesh::getSpatialDimension(element.type) ==
(spatial_dimension - 1)) {
- size += sizeof(UInt);
+ size += sizeof(Idx);
}
}
size += SolidMechanicsModel::getNbData(elements, tag);
break;
}
default: {
size += SolidMechanicsModel::getNbData(elements, tag);
}
}
}
/// cohesive element case
else if (elements(0).kind() == _ek_cohesive) {
switch (tag) {
case SynchronizationTag::_material_id: {
size += elements.size() * sizeof(UInt);
break;
}
case SynchronizationTag::_smm_boundary: {
UInt nb_nodes_per_element = 0;
for (auto && el : elements) {
nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
}
// force, displacement, boundary
size += nb_nodes_per_element * spatial_dimension *
(2 * sizeof(Real) + sizeof(bool));
break;
}
default:
break;
}
if (tag != SynchronizationTag::_material_id &&
tag != SynchronizationTag::_smmc_facets) {
splitByMaterial(elements, [&](auto && mat, auto && elements) {
size += mat.getNbData(elements, tag);
});
}
}
AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::packData(
CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
if (elements.empty()) {
return;
}
if (elements(0).kind() == _ek_regular) {
switch (tag) {
// case SynchronizationTag::_smmc_facets: {
// packElementalDataHelper(inserter->getInsertionFacetsByElement(),
// buffer,
// elements, false, getFEEngine());
// break;
// }
case SynchronizationTag::_smmc_facets_stress: {
packFacetStressDataHelper(facet_stress, buffer, elements);
break;
}
case SynchronizationTag::_material_id: {
for (auto && element : elements) {
if (Mesh::getSpatialDimension(element.type) !=
(spatial_dimension - 1)) {
continue;
}
buffer << material_index(element);
}
SolidMechanicsModel::packData(buffer, elements, tag);
break;
}
default: {
SolidMechanicsModel::packData(buffer, elements, tag);
}
}
AKANTU_DEBUG_OUT();
return;
}
if (elements(0).kind() == _ek_cohesive) {
switch (tag) {
case SynchronizationTag::_material_id: {
packElementalDataHelper(material_index, buffer, elements, false,
getFEEngine("CohesiveFEEngine"));
break;
}
case SynchronizationTag::_smm_boundary: {
packNodalDataHelper(*internal_force, buffer, elements, mesh);
packNodalDataHelper(*velocity, buffer, elements, mesh);
packNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
break;
}
default: {
}
}
if (tag != SynchronizationTag::_material_id &&
tag != SynchronizationTag::_smmc_facets) {
splitByMaterial(elements, [&](auto && mat, auto && elements) {
mat.packData(buffer, elements, tag);
});
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
if (elements.empty()) {
return;
}
if (elements(0).kind() == _ek_regular) {
switch (tag) {
- // case SynchronizationTag::_smmc_facets: {
- // unpackElementalDataHelper(inserter->getInsertionFacetsByElement(),
- // buffer,
- // elements, false, getFEEngine());
- // break;
- // }
case SynchronizationTag::_smmc_facets_stress: {
unpackFacetStressDataHelper(facet_stress, buffer, elements);
break;
}
case SynchronizationTag::_material_id: {
for (auto && element : elements) {
if (Mesh::getSpatialDimension(element.type) !=
(spatial_dimension - 1)) {
continue;
}
- UInt recv_mat_index;
+ Int recv_mat_index;
buffer >> recv_mat_index;
- UInt & mat_index = material_index(element);
- if (mat_index != UInt(-1)) {
+ auto & mat_index = material_index(element);
+ if (mat_index != Int(-1)) {
continue;
}
// add ghosts element to the correct material
mat_index = recv_mat_index;
auto & mat = aka::as_type<MaterialCohesive>(*materials[mat_index]);
if (is_extrinsic) {
mat.addFacet(element);
}
facet_material(element) = recv_mat_index;
}
SolidMechanicsModel::unpackData(buffer, elements, tag);
break;
}
default: {
SolidMechanicsModel::unpackData(buffer, elements, tag);
}
}
AKANTU_DEBUG_OUT();
return;
}
if (elements(0).kind() == _ek_cohesive) {
switch (tag) {
case SynchronizationTag::_material_id: {
for (auto && element : elements) {
- UInt recv_mat_index;
+ Int recv_mat_index;
buffer >> recv_mat_index;
- UInt & mat_index = material_index(element);
- if (mat_index != UInt(-1)) {
+ auto & mat_index = material_index(element);
+ if (mat_index != Int(-1)) {
continue;
}
// add ghosts element to the correct material
mat_index = recv_mat_index;
- UInt index = materials[mat_index]->addElement(element);
+ auto index = materials[mat_index]->addElement(element);
material_local_numbering(element) = index;
}
break;
}
case SynchronizationTag::_smm_boundary: {
unpackNodalDataHelper(*internal_force, buffer, elements, mesh);
unpackNodalDataHelper(*velocity, buffer, elements, mesh);
unpackNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
break;
}
default: {
}
}
if (tag != SynchronizationTag::_material_id &&
tag != SynchronizationTag::_smmc_facets) {
splitByMaterial(elements, [&](auto && mat, auto && elements) {
mat.unpackData(buffer, elements, tag);
});
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc
index b6aa612e3..6489009f1 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc
@@ -1,172 +1,161 @@
/**
* @file embedded_interface_intersector.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri May 01 2015
* @date last modification: Tue May 21 2019
*
* @brief Class that loads the interface from mesh and computes intersections
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "embedded_interface_intersector.hh"
#include "mesh_segment_intersector.hh"
/// Helper macro for types in the mesh. Creates an intersector and computes
/// intersection queries
#define INTERFACE_INTERSECTOR_CASE(dim, type) \
do { \
MeshSegmentIntersector<dim, type> intersector(this->mesh, interface_mesh); \
- name_to_primitives_it = name_to_primitives_map.begin(); \
- for (; name_to_primitives_it != name_to_primitives_end; \
- ++name_to_primitives_it) { \
- intersector.setPhysicalName(name_to_primitives_it->first); \
- intersector.buildResultFromQueryList(name_to_primitives_it->second); \
+ for (auto && [name, segment_list] : name_to_primitives) { \
+ intersector.setPhysicalName(name); \
+ intersector.buildResultFromQueryList(segment_list); \
} \
} while (0)
#define INTERFACE_INTERSECTOR_CASE_2D(type) INTERFACE_INTERSECTOR_CASE(2, type)
#define INTERFACE_INTERSECTOR_CASE_3D(type) INTERFACE_INTERSECTOR_CASE(3, type)
namespace akantu {
EmbeddedInterfaceIntersector::EmbeddedInterfaceIntersector(
Mesh & mesh, const Mesh & primitive_mesh)
: MeshGeomAbstract(mesh),
interface_mesh(mesh.getSpatialDimension(), "interface_mesh"),
primitive_mesh(primitive_mesh) {
// Initiating mesh connectivity and data
interface_mesh.addConnectivityType(_segment_2, _not_ghost);
interface_mesh.addConnectivityType(_segment_2, _ghost);
interface_mesh.getElementalData<Element>("associated_element")
.alloc(0, 1, _segment_2);
interface_mesh.getElementalData<std::string>("physical_names")
.alloc(0, 1, _segment_2);
}
void EmbeddedInterfaceIntersector::constructData(GhostType /*ghost_type*/) {
AKANTU_DEBUG_IN();
- const UInt dim = this->mesh.getSpatialDimension();
+ const Int dim = this->mesh.getSpatialDimension();
if (dim == 1) {
AKANTU_ERROR(
"No embedded model in 1D. Deactivate intersection initialization");
}
Array<std::string> * physical_names = nullptr;
try {
physical_names = &const_cast<Array<std::string> &>(
this->primitive_mesh.getData<std::string>("physical_names",
_segment_2));
} catch (debug::Exception & e) {
AKANTU_ERROR("You must define physical names to reinforcements in "
"order to use the embedded model");
throw e;
}
- const UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_segment_2);
+ constexpr Int nb_nodes_per_element = Mesh::getNbNodesPerElement(_segment_2);
auto connectivity =
primitive_mesh.getConnectivity(_segment_2).begin(nb_nodes_per_element);
- auto names_it = physical_names->begin();
- auto names_end = physical_names->end();
-
- std::map<std::string, std::list<K::Segment_3>> name_to_primitives_map;
+ std::map<std::string, std::list<K::Segment_3>> name_to_primitives;
// Loop over the physical names and register segment lists in
// name_to_primitives_map
- for (; names_it != names_end; ++names_it) {
- UInt element_id = names_it - physical_names->begin();
- const Vector<UInt> el_connectivity = connectivity[element_id];
+ for (auto && [element_id, name] : enumerate(*physical_names)) {
+ auto && el_connectivity = connectivity[element_id];
- K::Segment_3 segment = this->createSegment(el_connectivity);
- name_to_primitives_map[*names_it].push_back(segment);
+ auto segment = this->createSegment(el_connectivity);
+ name_to_primitives[name].push_back(segment);
}
// Loop over the background types of the mesh
- auto name_to_primitives_end = name_to_primitives_map.end();
- decltype(name_to_primitives_end) name_to_primitives_it;
-
for (auto type : this->mesh.elementTypes(dim, _not_ghost)) {
// Used in AKANTU_BOOST_ELEMENT_SWITCH
AKANTU_DEBUG_INFO("Computing intersections with background element type "
<< type);
- switch (dim) {
- case 1:
- break;
-
- case 2:
- // Compute intersections for supported 2D elements
- AKANTU_BOOST_ELEMENT_SWITCH(INTERFACE_INTERSECTOR_CASE_2D,
- (_triangle_3)(_triangle_6));
- break;
-
- case 3:
- // Compute intersections for supported 3D elements
- AKANTU_BOOST_ELEMENT_SWITCH(INTERFACE_INTERSECTOR_CASE_3D,
- (_tetrahedron_4));
- break;
- }
+ tuple_dispatch<
+ std::tuple<_element_type_triangle_3, _element_type_triangle_6,
+ _element_type_tetrahedron_4>>(
+ [&](auto && enum_type) {
+ constexpr auto type = aka::decay_v<decltype(enum_type)>;
+ constexpr auto dim = Mesh::getSpatialDimension(type);
+ MeshSegmentIntersector<dim, type> intersector(this->mesh,
+ interface_mesh);
+ for (auto && [name, segment_list] : name_to_primitives) {
+ intersector.setPhysicalName(name);
+ intersector.buildResultFromQueryList(segment_list);
+ }
+ },
+ type);
}
AKANTU_DEBUG_OUT();
}
K::Segment_3
-EmbeddedInterfaceIntersector::createSegment(const Vector<UInt> & connectivity) {
+EmbeddedInterfaceIntersector::createSegment(const Vector<Idx> & connectivity) {
AKANTU_DEBUG_IN();
std::unique_ptr<K::Point_3> source;
std::unique_ptr<K::Point_3> target;
- const Array<Real> & nodes = this->primitive_mesh.getNodes();
+ const auto & nodes = this->primitive_mesh.getNodes();
if (this->mesh.getSpatialDimension() == 2) {
source = std::make_unique<K::Point_3>(nodes(connectivity(0), 0),
nodes(connectivity(0), 1), 0.);
target = std::make_unique<K::Point_3>(nodes(connectivity(1), 0),
nodes(connectivity(1), 1), 0.);
} else if (this->mesh.getSpatialDimension() == 3) {
source = std::make_unique<K::Point_3>(nodes(connectivity(0), 0),
nodes(connectivity(0), 1),
nodes(connectivity(0), 2));
target = std::make_unique<K::Point_3>(nodes(connectivity(1), 0),
nodes(connectivity(1), 1),
nodes(connectivity(1), 2));
}
K::Segment_3 segment(*source, *target);
AKANTU_DEBUG_OUT();
return segment;
}
} // namespace akantu
#undef INTERFACE_INTERSECTOR_CASE
#undef INTERFACE_INTERSECTOR_CASE_2D
#undef INTERFACE_INTERSECTOR_CASE_3D
diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh
index aab5c0789..817350c49 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh
@@ -1,99 +1,99 @@
/**
* @file embedded_interface_intersector.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri May 01 2015
* @date last modification: Wed Jan 31 2018
*
* @brief Class that loads the interface from mesh and computes intersections
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_EMBEDDED_INTERFACE_INTERSECTOR_HH_
#define AKANTU_EMBEDDED_INTERFACE_INTERSECTOR_HH_
#include "aka_common.hh"
#include "mesh_geom_abstract.hh"
#include "mesh_geom_common.hh"
#include "mesh_segment_intersector.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace {
using K = cgal::Cartesian;
}
/**
* @brief Computes the intersections of the reinforcements defined in the
* primitive mesh
*
* The purpose of this class is to look for reinforcements in the primitive
* mesh, which
* should be defined by physical groups with the same names as the reinforcement
* materials
* in the model.
*
* It then constructs the CGAL primitives from the elements of those
* reinforcements
* and computes the intersections with the background mesh, to create an
* `interface_mesh`,
* which is in turn used by the EmbeddedInterfaceModel.
*
* @see MeshSegmentIntersector, MeshGeomAbstract
* @see EmbeddedInterfaceModel
*/
class EmbeddedInterfaceIntersector : public MeshGeomAbstract {
public:
/// Construct from mesh and a reinforcement mesh
explicit EmbeddedInterfaceIntersector(Mesh & mesh,
const Mesh & primitive_mesh);
/// Destructor
~EmbeddedInterfaceIntersector() override = default;
public:
/// Generate the interface mesh
void constructData(GhostType ghost_type = _not_ghost) override;
/// Create a segment with an element connectivity
- K::Segment_3 createSegment(const Vector<UInt> & connectivity);
+ K::Segment_3 createSegment(const Vector<Idx> & connectivity);
/// Getter for interface mesh
AKANTU_GET_MACRO_NOT_CONST(InterfaceMesh, interface_mesh, Mesh &);
protected:
/// Resulting mesh of intersection
Mesh interface_mesh;
/// Mesh used for primitive construction
const Mesh & primitive_mesh;
};
} // namespace akantu
#endif // AKANTU_EMBEDDED_INTERFACE_INTERSECTOR_HH_
diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc
index 096cf4d17..0f6deb08f 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc
@@ -1,166 +1,166 @@
/**
* @file embedded_interface_model.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri Mar 13 2015
* @date last modification: Wed Feb 14 2018
*
* @brief Model of Solid Mechanics with embedded interfaces
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "embedded_interface_model.hh"
#include "integrator_gauss.hh"
#include "material_elastic.hh"
#include "material_reinforcement.hh"
#include "mesh_iterators.hh"
#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
EmbeddedInterfaceModel::EmbeddedInterfaceModel(Mesh & mesh,
Mesh & primitive_mesh,
- UInt spatial_dimension,
+ Int spatial_dimension,
const ID & id)
: SolidMechanicsModel(mesh, spatial_dimension, id),
intersector(mesh, primitive_mesh), interface_mesh(nullptr),
primitive_mesh(primitive_mesh), interface_material_selector(nullptr) {
this->model_type = ModelType::_embedded_model;
// This pointer should be deleted by ~SolidMechanicsModel()
auto mat_sel_pointer =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
*this);
this->setMaterialSelector(mat_sel_pointer);
interface_mesh = &(intersector.getInterfaceMesh());
// Create 1D FEEngine on the interface mesh
registerFEEngineObject<MyFEEngineType>("EmbeddedInterfaceFEEngine",
*interface_mesh, 1);
// Registering allocator for material reinforcement
MaterialFactory::getInstance().registerAllocator(
"reinforcement",
- [&](UInt dim, const ID & constitutive, SolidMechanicsModel & /*unused*/,
+ [&](Int dim, const ID & constitutive, SolidMechanicsModel & /*unused*/,
const ID & id) -> std::unique_ptr<Material> {
if (constitutive == "elastic") {
using mat = MaterialElastic<1>;
switch (dim) {
case 2:
return std::make_unique<MaterialReinforcement<mat, 2>>(*this, id);
case 3:
return std::make_unique<MaterialReinforcement<mat, 3>>(*this, id);
default:
AKANTU_EXCEPTION("Dimension 1 is invalid for reinforcements");
}
} else {
AKANTU_EXCEPTION("Reinforcement type" << constitutive
<< " is not recognized");
}
});
}
/* -------------------------------------------------------------------------- */
EmbeddedInterfaceModel::~EmbeddedInterfaceModel() {
delete interface_material_selector;
}
/* -------------------------------------------------------------------------- */
void EmbeddedInterfaceModel::initFullImpl(const ModelOptions & options) {
const auto & eim_options =
aka::as_type<EmbeddedInterfaceModelOptions>(options);
// Do no initialize interface_mesh if told so
if (eim_options.has_intersections) {
intersector.constructData();
}
SolidMechanicsModel::initFullImpl(options);
this->mesh.registerDumper<DumperParaview>("reinforcement", id);
this->mesh.addDumpMeshToDumper("reinforcement", *interface_mesh, 1,
_not_ghost, _ek_regular);
}
void EmbeddedInterfaceModel::initModel() {
// Initialize interface FEEngine
SolidMechanicsModel::initModel();
FEEngine & engine = getFEEngine("EmbeddedInterfaceFEEngine");
engine.initShapeFunctions(_not_ghost);
engine.initShapeFunctions(_ghost);
}
/* -------------------------------------------------------------------------- */
void EmbeddedInterfaceModel::assignMaterialToElements(
- const ElementTypeMapArray<UInt> * filter) {
+ const ElementTypeMapArray<Idx> * filter) {
delete interface_material_selector;
interface_material_selector =
new InterfaceMeshDataMaterialSelector<std::string>("physical_names",
*this);
for_each_element(
getInterfaceMesh(),
[&](auto && element) {
auto mat_index = (*interface_material_selector)(element);
// material_index(element) = mat_index;
materials[mat_index]->addElement(element);
// this->material_local_numbering(element) = index;
},
_element_filter = filter, _spatial_dimension = 1);
SolidMechanicsModel::assignMaterialToElements(filter);
}
/* -------------------------------------------------------------------------- */
void EmbeddedInterfaceModel::addDumpGroupFieldToDumper(
const std::string & dumper_name, const std::string & field_id,
const std::string & group_name, ElementKind element_kind,
bool padding_flag) {
std::shared_ptr<dumpers::Field> field;
// If dumper is reinforcement, create a 1D elemental field
if (dumper_name == "reinforcement") {
field = this->createElementalField(field_id, group_name, padding_flag, 1,
element_kind);
} else {
try {
SolidMechanicsModel::addDumpGroupFieldToDumper(
dumper_name, field_id, group_name, element_kind, padding_flag);
} catch (...) {
}
}
if (field) {
DumperIOHelper & dumper = mesh.getGroupDumper(dumper_name, group_name);
Model::addDumpGroupFieldToDumper(field_id, field, dumper);
}
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh
index 0bd97618a..cfe41cb94 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh
@@ -1,156 +1,156 @@
/**
* @file embedded_interface_model.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Jan 31 2018
*
* @brief Model of Solid Mechanics with embedded interfaces
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_EMBEDDED_INTERFACE_MODEL_HH_
#define AKANTU_EMBEDDED_INTERFACE_MODEL_HH_
#include "aka_common.hh"
#include "mesh.hh"
#include "solid_mechanics_model.hh"
#include "embedded_interface_intersector.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/**
* @brief Solid mechanics model using the embedded model.
*
* This SolidMechanicsModel subclass implements the embedded model,
* a method used to represent 1D elements in a finite elements model
* (eg. reinforcements in concrete).
*
* In addition to the SolidMechanicsModel properties, this model has
* a mesh of the 1D elements embedded in the model, and an instance of the
* EmbeddedInterfaceIntersector class for the computation of the intersections
* of the
* 1D elements with the background (bulk) mesh.
*
* @see MaterialReinforcement
*/
class EmbeddedInterfaceModel : public SolidMechanicsModel {
using MyFEEngineType = SolidMechanicsModel::MyFEEngineType;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
/**
* @brief Constructor
*
* @param mesh main mesh (concrete)
* @param primitive_mesh mesh of the embedded reinforcement
* @param spatial_dimension the spatial dimension to be considered by this
* model
* @param id the id of the model
*/
EmbeddedInterfaceModel(Mesh & mesh, Mesh & primitive_mesh,
- UInt spatial_dimension = _all_dimensions,
+ Int spatial_dimension = _all_dimensions,
const ID & id = "embedded_interface_model");
/// Destructor
~EmbeddedInterfaceModel() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// Initialise the model
void initFullImpl(
const ModelOptions & options = EmbeddedInterfaceModelOptions()) override;
/// Initialise the materials
void
- assignMaterialToElements(const ElementTypeMapArray<UInt> * filter) override;
+ assignMaterialToElements(const ElementTypeMapArray<Idx> * filter) override;
/// Initialize the embedded shape functions
void initModel() override;
/// Allows filtering of dump fields which need to be dumpes on interface mesh
void addDumpGroupFieldToDumper(const std::string & dumper_name,
const std::string & field_id,
const std::string & group_name,
ElementKind element_kind,
bool padding_flag) override;
// virtual ElementTypeMap<UInt> getInternalDataPerElem(const std::string &
// field_name,
// ElementKind
// kind);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Get interface mesh
AKANTU_GET_MACRO(InterfaceMesh, *interface_mesh, Mesh &);
/// Get associated elements
AKANTU_GET_MACRO_BY_ELEMENT_TYPE(
InterfaceAssociatedElements,
interface_mesh->getData<Element>("associated_element"), Element);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// Intersector object to build the interface mesh
EmbeddedInterfaceIntersector intersector;
/// Interface mesh (weak reference)
Mesh * interface_mesh;
/// Mesh used to create the CGAL primitives for intersections
Mesh & primitive_mesh;
/// Material selector for interface
MaterialSelector * interface_material_selector;
};
/// Material selector based on mesh data for interface elements
template <typename T>
class InterfaceMeshDataMaterialSelector
: public ElementDataMaterialSelector<T> {
public:
InterfaceMeshDataMaterialSelector(const std::string & name,
const EmbeddedInterfaceModel & model,
- UInt first_index = 1)
+ Int first_index = 1)
: ElementDataMaterialSelector<T>(
model.getInterfaceMesh().getData<T>(name), model, first_index) {}
};
} // namespace akantu
#endif // AKANTU_EMBEDDED_INTERFACE_MODEL_HH_
diff --git a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.hh b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.hh
index d3dfed74f..81704dd27 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.hh
@@ -1,118 +1,117 @@
/**
* @file solid_mechanics_model_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Fri Mar 26 2021
*
* @brief Implementation of the inline functions of the SolidMechanicsModel
* class
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_named_argument.hh"
#include "material_selector.hh"
#include "material_selector_tmpl.hh"
-#include "solid_mechanics_model.hh"
+//#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_HH_
#define AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline decltype(auto) SolidMechanicsModel::getMaterials() {
return make_dereference_adaptor(materials);
}
/* -------------------------------------------------------------------------- */
inline decltype(auto) SolidMechanicsModel::getMaterials() const {
return make_dereference_adaptor(materials);
}
/* -------------------------------------------------------------------------- */
inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) {
AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
"The model " << id << " has no material no "
<< mat_index);
return *materials.at(mat_index);
}
/* -------------------------------------------------------------------------- */
inline const Material & SolidMechanicsModel::getMaterial(UInt mat_index) const {
AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
"The model " << id << " has no material no "
<< mat_index);
return *materials.at(mat_index);
}
/* -------------------------------------------------------------------------- */
inline Material & SolidMechanicsModel::getMaterial(const std::string & name) {
- std::map<std::string, UInt>::const_iterator it =
- materials_names_to_id.find(name);
+ auto it = materials_names_to_id.find(name);
if (it == materials_names_to_id.end()) {
AKANTU_SILENT_EXCEPTION("The model " << id << " has no material named "
<< name);
}
return *materials[it->second];
}
/* -------------------------------------------------------------------------- */
inline const Material &
SolidMechanicsModel::getMaterial(const Element & element) const {
auto mat_id = material_index(element);
return *materials[mat_id];
}
/* -------------------------------------------------------------------------- */
-inline UInt
+inline Int
SolidMechanicsModel::getMaterialIndex(const std::string & name) const {
auto it = materials_names_to_id.find(name);
if (it == materials_names_to_id.end()) {
AKANTU_SILENT_EXCEPTION("The model " << id << " has no material named "
<< name);
}
return it->second;
}
/* -------------------------------------------------------------------------- */
inline const Material &
SolidMechanicsModel::getMaterial(const std::string & name) const {
auto it = materials_names_to_id.find(name);
if (it == materials_names_to_id.end()) {
AKANTU_SILENT_EXCEPTION("The model " << id << " has no material named "
<< name);
}
return *materials[it->second];
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_io.cc b/src/model/solid_mechanics/solid_mechanics_model_io.cc
index b67dff6e4..46292d552 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_io.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_io.cc
@@ -1,323 +1,324 @@
/**
* @file solid_mechanics_model_io.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Jul 09 2017
* @date last modification: Fri Apr 09 2021
*
* @brief Dumpable part of the SolidMechnicsModel
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
#include "group_manager_inline_impl.hh"
#include "dumpable_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_element_partition.hh"
#include "dumper_elemental_field.hh"
#include "dumper_field.hh"
#include "dumper_homogenizing_field.hh"
#include "dumper_internal_material_field.hh"
#include "dumper_iohelper.hh"
#include "dumper_material_padders.hh"
#include "dumper_paraview.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
bool SolidMechanicsModel::isInternal(const std::string & field_name,
ElementKind element_kind) {
/// check if at least one material contains field_id as an internal
for (auto & material : materials) {
bool is_internal = material->isInternal<Real>(field_name, element_kind);
if (is_internal) {
return true;
}
}
return false;
}
/* -------------------------------------------------------------------------- */
-ElementTypeMap<UInt>
+ElementTypeMap<Int>
SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name,
ElementKind element_kind) {
if (!(this->isInternal(field_name, element_kind))) {
AKANTU_EXCEPTION("unknown internal " << field_name);
}
for (auto & material : materials) {
if (material->isInternal<Real>(field_name, element_kind)) {
return material->getInternalDataPerElem<Real>(field_name, element_kind);
}
}
- return ElementTypeMap<UInt>();
+ return ElementTypeMap<Int>();
}
/* -------------------------------------------------------------------------- */
ElementTypeMapArray<Real> &
SolidMechanicsModel::flattenInternal(const std::string & field_name,
ElementKind kind,
const GhostType ghost_type) {
auto key = std::make_pair(field_name, kind);
ElementTypeMapArray<Real> * internal_flat;
auto it = this->registered_internals.find(key);
if (it == this->registered_internals.end()) {
auto internal =
std::make_unique<ElementTypeMapArray<Real>>(field_name, this->id);
internal_flat = internal.get();
this->registered_internals[key] = std::move(internal);
} else {
internal_flat = it->second.get();
}
for (auto type :
mesh.elementTypes(Model::spatial_dimension, ghost_type, kind)) {
if (internal_flat->exists(type, ghost_type)) {
auto & internal = (*internal_flat)(type, ghost_type);
internal.resize(0);
}
}
for (auto & material : materials) {
if (material->isInternal<Real>(field_name, kind)) {
material->flattenInternal(field_name, *internal_flat, ghost_type, kind);
}
}
return *internal_flat;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::flattenAllRegisteredInternals(ElementKind kind) {
ElementKind _kind;
ID _id;
for (auto & internal : this->registered_internals) {
std::tie(_id, _kind) = internal.first;
if (kind == _kind) {
this->flattenInternal(_id, kind);
}
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::inflateInternal(
const std::string & field_name, const ElementTypeMapArray<Real> & field,
ElementKind kind, GhostType ghost_type) {
for (auto & material : materials) {
if (material->isInternal<Real>(field_name, kind)) {
material->inflateInternal(field_name, field, ghost_type, kind);
}
}
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::onDump() {
this->flattenAllRegisteredInternals(_ek_regular);
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> SolidMechanicsModel::createElementalField(
const std::string & field_name, const std::string & group_name,
- bool padding_flag, UInt spatial_dimension, ElementKind kind) {
+ bool padding_flag, Int spatial_dimension, ElementKind kind) {
std::shared_ptr<dumpers::Field> field;
if (field_name == "partitions") {
- field = mesh.createElementalField<UInt, dumpers::ElementPartitionField>(
+ field = mesh.createElementalField<Int, dumpers::ElementPartitionField>(
mesh.getConnectivities(), group_name, spatial_dimension, kind);
} else if (field_name == "material_index") {
- field = mesh.createElementalField<UInt, Vector, dumpers::ElementalField>(
- material_index, group_name, spatial_dimension, kind);
+ field =
+ mesh.createElementalField<Idx, Vector<Idx>, dumpers::ElementalField>(
+ material_index, group_name, spatial_dimension, kind);
} else {
// this copy of field_name is used to compute derivated data such as
// strain and von mises stress that are based on grad_u and stress
std::string field_name_copy(field_name);
if (field_name == "strain" || field_name == "Green strain" ||
field_name == "principal strain" ||
field_name == "principal Green strain") {
field_name_copy = "grad_u";
} else if (field_name == "Von Mises stress") {
field_name_copy = "stress";
}
bool is_internal = this->isInternal(field_name_copy, kind);
if (is_internal) {
auto nb_data_per_elem =
this->getInternalDataPerElem(field_name_copy, kind);
auto & internal_flat = this->flattenInternal(field_name_copy, kind);
field = mesh.createElementalField<Real, dumpers::InternalMaterialField>(
internal_flat, group_name, spatial_dimension, kind, nb_data_per_elem);
std::unique_ptr<dumpers::ComputeFunctorInterface> func;
if (field_name == "strain") {
func = std::make_unique<dumpers::ComputeStrain<false>>(*this);
} else if (field_name == "Von Mises stress") {
func = std::make_unique<dumpers::ComputeVonMisesStress>(*this);
} else if (field_name == "Green strain") {
func = std::make_unique<dumpers::ComputeStrain<true>>(*this);
} else if (field_name == "principal strain") {
func = std::make_unique<dumpers::ComputePrincipalStrain<false>>(*this);
} else if (field_name == "principal Green strain") {
func = std::make_unique<dumpers::ComputePrincipalStrain<true>>(*this);
}
if (func) {
field = dumpers::FieldComputeProxy::createFieldCompute(field,
std::move(func));
}
// treat the paddings
if (padding_flag) {
if (field_name == "stress") {
if (spatial_dimension == 2) {
auto foo = std::make_unique<dumpers::StressPadder<2>>(*this);
field = dumpers::FieldComputeProxy::createFieldCompute(
field, std::move(foo));
}
} else if (field_name == "strain" || field_name == "Green strain") {
if (spatial_dimension == 2) {
auto foo = std::make_unique<dumpers::StrainPadder<2>>(*this);
field = dumpers::FieldComputeProxy::createFieldCompute(
field, std::move(foo));
}
}
}
// homogenize the field
auto foo = dumpers::HomogenizerProxy::createHomogenizer(*field);
field =
dumpers::FieldComputeProxy::createFieldCompute(field, std::move(foo));
}
}
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
SolidMechanicsModel::createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) {
std::map<std::string, Array<Real> *> real_nodal_fields;
real_nodal_fields["displacement"] = this->displacement.get();
real_nodal_fields["mass"] = this->mass.get();
real_nodal_fields["velocity"] = this->velocity.get();
real_nodal_fields["acceleration"] = this->acceleration.get();
real_nodal_fields["external_force"] = this->external_force.get();
real_nodal_fields["internal_force"] = this->internal_force.get();
real_nodal_fields["increment"] = this->displacement_increment.get();
if (field_name == "force") {
AKANTU_EXCEPTION("The 'force' field has been renamed in 'external_force'");
} else if (field_name == "residual") {
AKANTU_EXCEPTION(
"The 'residual' field has been replaced by 'internal_force'");
}
std::shared_ptr<dumpers::Field> field;
if (padding_flag) {
field = this->mesh.createNodalField(real_nodal_fields[field_name],
group_name, 3);
} else {
field =
this->mesh.createNodalField(real_nodal_fields[field_name], group_name);
}
return field;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> SolidMechanicsModel::createNodalFieldBool(
const std::string & field_name, const std::string & group_name,
__attribute__((unused)) bool padding_flag) {
std::map<std::string, Array<bool> *> uint_nodal_fields;
uint_nodal_fields["blocked_dofs"] = blocked_dofs.get();
std::shared_ptr<dumpers::Field> field;
field = mesh.createNodalField(uint_nodal_fields[field_name], group_name);
return field;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::dump(const std::string & dumper_name) {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump(dumper_name);
}
/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) {
+void SolidMechanicsModel::dump(const std::string & dumper_name, Int step) {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump(dumper_name, step);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::dump(const std::string & dumper_name, Real time,
- UInt step) {
+ Int step) {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump(dumper_name, time, step);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::dump() {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump();
}
/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::dump(UInt step) {
+void SolidMechanicsModel::dump(Int step) {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump(step);
}
/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::dump(Real time, UInt step) {
+void SolidMechanicsModel::dump(Real time, Int step) {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump(time, step);
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_mass.cc b/src/model/solid_mechanics/solid_mechanics_model_mass.cc
index c8b2a0e2d..547c6d41b 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_mass.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_mass.cc
@@ -1,160 +1,158 @@
/**
* @file solid_mechanics_model_mass.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Oct 05 2010
* @date last modification: Fri Jul 24 2020
*
* @brief function handling mass computation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "integrator_gauss.hh"
#include "material.hh"
#include "model_solver.hh"
#include "shape_lagrange.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class ComputeRhoFunctor {
public:
explicit ComputeRhoFunctor(const SolidMechanicsModel & model)
: model(model){};
void operator()(Matrix<Real> & rho, const Element & element) {
- const Array<UInt> & mat_indexes =
+ const auto & mat_indexes =
model.getMaterialByElement(element.type, element.ghost_type);
Real mat_rho =
model.getMaterial(mat_indexes(element.element)).getParam("rho");
rho.set(mat_rho);
}
private:
const SolidMechanicsModel & model;
};
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleMassLumped() {
AKANTU_DEBUG_IN();
if (not need_to_reassemble_lumped_mass) {
return;
}
this->allocNodalField(this->mass, spatial_dimension, "mass");
mass->zero();
if (!this->getDOFManager().hasLumpedMatrix("M")) {
this->getDOFManager().getNewLumpedMatrix("M");
}
this->getDOFManager().zeroLumpedMatrix("M");
assembleMassLumped(_not_ghost);
assembleMassLumped(_ghost);
this->getDOFManager().getLumpedMatrixPerDOFs("displacement", "M",
*(this->mass));
/// for not connected nodes put mass to one in order to avoid
#if !defined(AKANTU_NDEBUG)
- bool has_unconnected_nodes = false;
- auto mass_it = mass->begin_reinterpret(mass->size() * mass->getNbComponent());
- auto mass_end = mass->end_reinterpret(mass->size() * mass->getNbComponent());
- for (; mass_it != mass_end; ++mass_it) {
- if (std::abs(*mass_it) < std::numeric_limits<Real>::epsilon() ||
- Math::isnan(*mass_it)) {
- has_unconnected_nodes = true;
- break;
+ std::set<Idx> unconnected_nodes;
+ for (auto && data : enumerate(make_view(*mass))) {
+ auto & m = std::get<1>(data);
+ if (std::abs(m) < std::numeric_limits<Real>::epsilon() || Math::isnan(m)) {
+ m = 0.;
+ unconnected_nodes.insert(std::get<0>(data));
}
}
- if (has_unconnected_nodes) {
+ if (unconnected_nodes.begin() != unconnected_nodes.end()) {
AKANTU_DEBUG_WARNING("There are nodes that seem to not be connected to any "
"elements, beware that they have lumped mass of 0.");
}
#endif
this->synchronize(SynchronizationTag::_smm_mass);
need_to_reassemble_lumped_mass = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleMass() {
AKANTU_DEBUG_IN();
if (not this->getDOFManager().hasMatrix("M")) {
this->getDOFManager().getNewMatrix("M", this->getMatrixType("M"));
}
if (not need_to_reassemble_mass) {
return;
}
this->getDOFManager().zeroMatrix("M");
assembleMass(_not_ghost);
need_to_reassemble_mass = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleMassLumped(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & fem = getFEEngineClass<MyFEEngineType>();
ComputeRhoFunctor compute_rho(*this);
for (auto type :
mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_regular)) {
fem.assembleFieldLumped(compute_rho, "M", "displacement",
this->getDOFManager(), type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assembleMass(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & fem = getFEEngineClass<MyFEEngineType>();
ComputeRhoFunctor compute_rho(*this);
for (auto type :
mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_regular)) {
fem.assembleFieldMatrix(compute_rho, "M", "displacement",
this->getDOFManager(), type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc
index 1c44afdd4..a18deb3ce 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_material.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc
@@ -1,252 +1,252 @@
/**
* @file solid_mechanics_model_material.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Nov 26 2010
* @date last modification: Fri Mar 26 2021
*
* @brief instatiation of materials
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_factory.hh"
#include "aka_math.hh"
#include "material_non_local.hh"
#include "mesh_iterators.hh"
#include "non_local_manager.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
Material &
SolidMechanicsModel::registerNewMaterial(const ParserSection & section) {
std::string mat_name;
std::string mat_type = section.getName();
std::string opt_param = section.getOption();
try {
std::string tmp = section.getParameter("name");
mat_name = tmp; /** this can seam weird, but there is an ambiguous operator
* overload that i couldn't solve. @todo remove the
* weirdness of this code
*/
} catch (debug::Exception &) {
AKANTU_ERROR("A material of type \'"
<< mat_type
<< "\' in the input file has been defined without a name!");
}
Material & mat = this->registerNewMaterial(mat_name, mat_type, opt_param);
mat.parseSection(section);
return mat;
}
/* -------------------------------------------------------------------------- */
Material & SolidMechanicsModel::registerNewMaterial(const ID & mat_name,
const ID & mat_type,
const ID & opt_param) {
AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) ==
materials_names_to_id.end(),
"A material with this name '"
<< mat_name << "' has already been registered. "
<< "Please use unique names for materials");
- UInt mat_count = materials.size();
+ auto mat_count = materials.size();
materials_names_to_id[mat_name] = mat_count;
ID mat_id = this->id + ":" + std::to_string(mat_count) + ":" + mat_type;
std::unique_ptr<Material> material = MaterialFactory::getInstance().allocate(
mat_type, spatial_dimension, opt_param, *this, mat_id);
material->setName(mat_name);
materials.push_back(std::move(material));
return *(materials.back());
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::instantiateMaterials() {
ParserSection model_section;
bool is_empty;
std::tie(model_section, is_empty) = this->getParserSection();
if (not is_empty) {
auto model_materials = model_section.getSubSections(ParserType::_material);
for (const auto & section : model_materials) {
this->registerNewMaterial(section);
}
}
auto sub_sections = this->parser.getSubSections(ParserType::_material);
for (const auto & section : sub_sections) {
this->registerNewMaterial(section);
}
#ifdef AKANTU_DAMAGE_NON_LOCAL
for (auto & material : materials) {
if (dynamic_cast<MaterialNonLocalInterface *>(material.get()) == nullptr) {
continue;
}
this->non_local_manager = std::make_unique<NonLocalManager>(
*this, *this, id + ":non_local_manager");
break;
}
#endif
if (materials.empty()) {
AKANTU_EXCEPTION("No materials where instantiated for the model"
<< getID());
}
are_materials_instantiated = true;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::assignMaterialToElements(
- const ElementTypeMapArray<UInt> * filter) {
+ const ElementTypeMapArray<Idx> * filter) {
for_each_element(
mesh,
[&](auto && element) {
- UInt mat_index = (*material_selector)(element);
+ auto mat_index = (*material_selector)(element);
AKANTU_DEBUG_ASSERT(
- mat_index < materials.size(),
+ mat_index < Int(materials.size()),
"The material selector returned an index that does not exists");
material_index(element) = mat_index;
},
_element_filter = filter, _ghost_type = _not_ghost);
if (non_local_manager) {
non_local_manager->synchronize(*this, SynchronizationTag::_material_id);
}
for_each_element(
mesh,
[&](auto && element) {
auto mat_index = material_index(element);
auto index = materials[mat_index]->addElement(element);
material_local_numbering(element) = index;
},
_element_filter = filter, _ghost_type = _not_ghost);
// synchronize the element material arrays
this->synchronize(SynchronizationTag::_material_id);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::initMaterials() {
AKANTU_DEBUG_ASSERT(not materials.empty(), "No material to initialize !");
// if (!are_materials_instantiated)
// instantiateMaterials();
this->assignMaterialToElements();
for (auto & material : materials) {
/// init internals properties
material->initMaterial();
}
this->synchronize(SynchronizationTag::_smm_init_mat);
if (this->non_local_manager) {
this->non_local_manager->initialize();
}
}
/* -------------------------------------------------------------------------- */
Int SolidMechanicsModel::getInternalIndexFromID(const ID & id) const {
AKANTU_DEBUG_IN();
auto it = materials.begin();
auto end = materials.end();
for (; it != end; ++it) {
if ((*it)->getID() == id) {
AKANTU_DEBUG_OUT();
return (it - materials.begin());
}
}
AKANTU_DEBUG_OUT();
return -1;
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::reassignMaterial() {
AKANTU_DEBUG_IN();
std::vector<Array<Element>> element_to_add(materials.size());
std::vector<Array<Element>> element_to_remove(materials.size());
for_each_element(
mesh,
[&](auto && element) {
auto old_material = material_index(element);
auto new_material = (*material_selector)(element);
if (old_material != new_material) {
element_to_add[new_material].push_back(element);
element_to_remove[old_material].push_back(element);
}
},
_spatial_dimension = spatial_dimension);
for (auto && data : enumerate(materials)) {
auto mat_index = std::get<0>(data);
auto & mat = *std::get<1>(data);
/* Only update if there are changes. */
if (element_to_remove[mat_index].empty() == false) {
mat.removeElements(element_to_remove[mat_index]);
}
if (element_to_add[mat_index].empty() == false) {
mat.addElements(element_to_add[mat_index]);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::applyEigenGradU(
const Matrix<Real> & prescribed_eigen_grad_u, const ID & material_name,
const GhostType ghost_type) {
AKANTU_DEBUG_ASSERT(prescribed_eigen_grad_u.size() ==
spatial_dimension * spatial_dimension,
"The prescribed grad_u is not of the good size");
for (auto & material : materials) {
if (material->getName() == material_name) {
material->applyEigenGradU(prescribed_eigen_grad_u, ghost_type);
}
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh
index d468a43f0..f2c092ee1 100644
--- a/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh
+++ b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh
@@ -1,72 +1,72 @@
/**
* @file structural_element_bernoulli_beam_2.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Oct 11 2017
* @date last modification: Fri Feb 05 2021
*
* @brief Specific functions for bernoulli beam 2d
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "structural_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_2_HH_
#define AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_2_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <>
void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_2>(
Array<Real> & tangent_moduli) {
// auto nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_2);
auto nb_quadrature_points =
getFEEngine().getNbIntegrationPoints(_bernoulli_beam_2);
auto tangent_size = 2;
tangent_moduli.zero();
auto D_it = tangent_moduli.begin(tangent_size, tangent_size);
auto el_mat = element_material(_bernoulli_beam_2, _not_ghost).begin();
for (auto & mat : element_material(_bernoulli_beam_2, _not_ghost)) {
auto E = materials[mat].E;
auto A = materials[mat].A;
auto I = materials[mat].I;
- for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
+ for (Int q = 0; q < nb_quadrature_points; ++q, ++D_it) {
auto & D = *D_it;
D(0, 0) = E * A;
D(1, 1) = E * I;
}
}
}
} // namespace akantu
#endif /* AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_2_HH_ */
diff --git a/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh
index 913a81752..ff2250f70 100644
--- a/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh
+++ b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh
@@ -1,76 +1,76 @@
/**
* @file structural_element_bernoulli_beam_3.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Spielmann <damien.spielmann@epfl.ch>
*
* @date creation: Wed Oct 11 2017
* @date last modification: Fri Feb 05 2021
*
* @brief Specific functions for bernoulli beam 3d
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_3_HH_
#define AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_3_HH_
#include "structural_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <>
void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_3>(
- Array<Real> & tangent_moduli) {
- UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3);
- UInt nb_quadrature_points =
+ Array<Real> &tangent_moduli) {
+ Int nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3);
+ Int nb_quadrature_points =
getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3);
- UInt tangent_size = 4;
+ Int tangent_size = 4;
tangent_moduli.zero();
Array<Real>::matrix_iterator D_it =
tangent_moduli.begin(tangent_size, tangent_size);
- for (UInt e = 0; e < nb_element; ++e) {
+ for (Int e = 0; e < nb_element; ++e) {
UInt mat = element_material(_bernoulli_beam_3, _not_ghost)(e);
Real E = materials[mat].E;
Real A = materials[mat].A;
Real Iz = materials[mat].Iz;
Real Iy = materials[mat].Iy;
Real GJ = materials[mat].GJ;
- for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
- Matrix<Real> & D = *D_it;
+ for (Int q = 0; q < nb_quadrature_points; ++q, ++D_it) {
+ auto &D = *D_it;
D(0, 0) = E * A;
D(1, 1) = E * Iz;
D(2, 2) = E * Iy;
D(3, 3) = GJ;
}
}
}
} // namespace akantu
#endif /* AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_3_HH_ */
diff --git a/src/model/structural_mechanics/structural_elements/structural_element_kirchhoff_shell.hh b/src/model/structural_mechanics/structural_elements/structural_element_kirchhoff_shell.hh
index aa9cfb8a4..a4d42b955 100644
--- a/src/model/structural_mechanics/structural_elements/structural_element_kirchhoff_shell.hh
+++ b/src/model/structural_mechanics/structural_elements/structural_element_kirchhoff_shell.hh
@@ -1,74 +1,75 @@
/**
* @file structural_element_kirchhoff_shell.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Spielmann <damien.spielmann@epfl.ch>
*
* @date creation: Wed Oct 11 2017
* @date last modification: Fri Feb 05 2021
*
* @brief Specific functions for bernoulli kirchhoff shell
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_KIRCHHOFF_SHELL_HH_
#define AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_KIRCHHOFF_SHELL_HH_
#include "structural_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <>
void StructuralMechanicsModel::computeTangentModuli<
_discrete_kirchhoff_triangle_18>(Array<Real> & tangent_moduli) {
auto tangent_size =
ElementClass<_discrete_kirchhoff_triangle_18>::getNbStressComponents();
auto nb_quad =
getFEEngine().getNbIntegrationPoints(_discrete_kirchhoff_triangle_18);
auto H_it = tangent_moduli.begin(tangent_size, tangent_size);
- for (UInt mat :
+ for (Int mat :
element_material(_discrete_kirchhoff_triangle_18, _not_ghost)) {
auto & m = materials[mat];
+ Matrix<Real, 3, 3> D{
+ {1., m.nu, 0.}, {m.nu, 1., 0.}, {0., 0., (1. - m.nu) / 2.}};
+ D *= m.E * m.t / (1. - m.nu * m.nu);
- for (UInt q = 0; q < nb_quad; ++q, ++H_it) {
+ for (Int q = 0; q < nb_quad; ++q, ++H_it) {
auto & H = *H_it;
H.zero();
- Matrix<Real> D = {{1, m.nu, 0}, {m.nu, 1, 0}, {0, 0, (1 - m.nu) / 2}};
- D *= m.E * m.t / (1 - m.nu * m.nu);
- H.block(D, 0, 0); // in plane membrane behavior
- H.block(D * Math::pow<3>(m.t) / 12., 3, 3); // bending behavior
+ H.block<3, 3>(0, 0) = D; // in plane membrane behavior
+ H.block<3, 3>(3, 3) = D * Math::pow<3>(m.t) / 12.; // bending behavior
}
}
}
} // namespace akantu
#endif /* AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_DISCRETE_KIRCHHOFF_TRIANGLE_18_HH_ \
*/
diff --git a/src/model/structural_mechanics/structural_mechanics_model.cc b/src/model/structural_mechanics/structural_mechanics_model.cc
index 04e05dc5e..5bd097325 100644
--- a/src/model/structural_mechanics/structural_mechanics_model.cc
+++ b/src/model/structural_mechanics/structural_mechanics_model.cc
@@ -1,775 +1,749 @@
/**
* @file structural_mechanics_model.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Spielmann <damien.spielmann@epfl.ch>
*
* @date creation: Fri Jul 15 2011
* @date last modification: Mon Mar 15 2021
*
* @brief Model implementation for Structural Mechanics elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "structural_mechanics_model.hh"
#include "dof_manager.hh"
#include "integrator_gauss.hh"
#include "mesh.hh"
#include "shape_structural.hh"
#include "sparse_matrix.hh"
#include "time_step_solver.hh"
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "dumper_elemental_field.hh"
#include "dumper_internal_material_field.hh"
#include "dumper_iohelper_paraview.hh"
#include "group_manager_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#include "structural_element_bernoulli_beam_2.hh"
#include "structural_element_bernoulli_beam_3.hh"
#include "structural_element_kirchhoff_shell.hh"
/* -------------------------------------------------------------------------- */
-//#include "structural_mechanics_model_inline_impl.hh"
+// #include "structural_mechanics_model_inline_impl.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
inline UInt StructuralMechanicsModel::getNbDegreeOfFreedom(ElementType type) {
- UInt ndof = 0;
-#define GET_(type) ndof = ElementClass<type>::getNbDegreeOfFreedom()
- AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_, _ek_structural);
-#undef GET_
-
- return ndof;
+ return tuple_dispatch<ElementTypes_t<_ek_structural>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getNbDegreeOfFreedom();
+ },
+ type);
}
/* -------------------------------------------------------------------------- */
-StructuralMechanicsModel::StructuralMechanicsModel(Mesh & mesh, UInt dim,
+StructuralMechanicsModel::StructuralMechanicsModel(Mesh & mesh, Int dim,
const ID & id)
: Model(mesh, ModelType::_structural_mechanics_model, dim, id), f_m2a(1.0),
stress("stress", id), element_material("element_material", id),
set_ID("beam sets", id) {
AKANTU_DEBUG_IN();
registerFEEngineObject<MyFEEngineType>("StructuralMechanicsFEEngine", mesh,
spatial_dimension);
if (spatial_dimension == 2) {
nb_degree_of_freedom = 3;
} else if (spatial_dimension == 3) {
nb_degree_of_freedom = 6;
} else {
AKANTU_TO_IMPLEMENT();
}
this->mesh.registerDumper<DumperParaview>("structural_mechanics_model", id,
true);
this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_structural);
this->initDOFManager();
this->dumper_default_element_kind = _ek_structural;
mesh.getElementalData<Real>("extra_normal")
.initialize(mesh, _element_kind = _ek_structural,
_nb_component = spatial_dimension, _with_nb_element = true,
_default_value = 0.);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
StructuralMechanicsModel::~StructuralMechanicsModel() = default;
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::initFullImpl(const ModelOptions & options) {
Model::initFullImpl(options);
// Initializing stresses
ElementTypeMap<UInt> stress_components;
- /// TODO this is ugly af, maybe add a function to FEEngine
for (auto && type : mesh.elementTypes(_spatial_dimension = _all_dimensions,
_element_kind = _ek_structural)) {
- UInt nb_components = 0;
-
-// Getting number of components for each element type
-#define GET_(type) nb_components = ElementClass<type>::getNbStressComponents()
- AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(GET_);
-#undef GET_
+ // Getting number of components for each element type
+ auto nb_components = tuple_dispatch<ElementTypes_t<_ek_structural>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ return ElementClass<type>::getNbStressComponents();
+ },
+ type);
stress_components(nb_components, type);
}
stress.initialize(
getFEEngine(), _spatial_dimension = _all_dimensions,
_element_kind = _ek_structural,
_nb_component = [&stress_components](ElementType type,
GhostType /*unused*/) -> UInt {
return stress_components(type);
});
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::initFEEngineBoundary() {
- /// TODO: this function should not be reimplemented
+ /// this function should not be reimplemented
/// we're just avoiding a call to Model::initFEEngineBoundary()
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::setTimeStep(Real time_step,
const ID & solver_id) {
Model::setTimeStep(time_step, solver_id);
this->mesh.getDumper().setTimeStep(time_step);
}
/* -------------------------------------------------------------------------- */
/* Initialisation */
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::initSolver(
TimeStepSolverType time_step_solver_type, NonLinearSolverType /*unused*/) {
AKANTU_DEBUG_IN();
this->allocNodalField(displacement_rotation, nb_degree_of_freedom,
"displacement");
this->allocNodalField(external_force, nb_degree_of_freedom, "external_force");
this->allocNodalField(internal_force, nb_degree_of_freedom, "internal_force");
this->allocNodalField(blocked_dofs, nb_degree_of_freedom, "blocked_dofs");
auto & dof_manager = this->getDOFManager();
if (not dof_manager.hasDOFs("displacement")) {
dof_manager.registerDOFs("displacement", *displacement_rotation,
_dst_nodal);
dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs);
}
if (time_step_solver_type == TimeStepSolverType::_dynamic ||
time_step_solver_type == TimeStepSolverType::_dynamic_lumped) {
this->allocNodalField(velocity, nb_degree_of_freedom, "velocity");
this->allocNodalField(acceleration, nb_degree_of_freedom, "acceleration");
if (!dof_manager.hasDOFsDerivatives("displacement", 1)) {
dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity);
dof_manager.registerDOFsDerivative("displacement", 2,
*this->acceleration);
}
/* Only allocate the mass if the "lumped" mode is ennabled.
* Also it is not a 1D array, but has an element for every
* DOF, which are most of the time equal, but makes handling
* some operations a bit simpler. */
if (time_step_solver_type == TimeStepSolverType::_dynamic_lumped) {
this->allocateLumpedMassArray();
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::initModel() {
element_material.initialize(mesh, _element_kind = _ek_structural,
_default_value = 0, _with_nb_element = true);
getFEEngine().initShapeFunctions(_not_ghost);
getFEEngine().initShapeFunctions(_ghost);
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::assembleStiffnessMatrix() {
AKANTU_DEBUG_IN();
if (not need_to_reassemble_stiffness) {
return;
}
if (not getDOFManager().hasMatrix("K")) {
getDOFManager().getNewMatrix("K", getMatrixType("K"));
}
this->getDOFManager().zeroMatrix("K");
for (const auto & type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_structural)) {
-#define ASSEMBLE_STIFFNESS_MATRIX(type) assembleStiffnessMatrix<type>();
- AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(ASSEMBLE_STIFFNESS_MATRIX);
-#undef ASSEMBLE_STIFFNESS_MATRIX
+ tuple_dispatch<ElementTypes_t<_ek_structural>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->assembleStiffnessMatrix<type>();
+ },
+ type);
}
need_to_reassemble_stiffness = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::computeStresses() {
AKANTU_DEBUG_IN();
for (const auto & type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_structural)) {
-#define COMPUTE_STRESS_ON_QUAD(type) computeStressOnQuad<type>();
-
- AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(COMPUTE_STRESS_ON_QUAD);
-#undef COMPUTE_STRESS_ON_QUAD
+ tuple_dispatch<ElementTypes_t<_ek_structural>>(
+ [&](auto && enum_type) {
+ constexpr ElementType type = aka::decay_v<decltype(enum_type)>;
+ this->computeStressOnQuad<type>();
+ },
+ type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
bool StructuralMechanicsModel::allocateLumpedMassArray() {
- if (this->mass != nullptr) // Already allocated, so nothing to do.
- {
- return true;
- };
-
- // now allocate it
this->allocNodalField(this->mass, this->nb_degree_of_freedom, "lumped_mass");
return true;
-};
+}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> StructuralMechanicsModel::createNodalFieldBool(
const std::string & field_name, const std::string & group_name,
__attribute__((unused)) bool padding_flag) {
std::map<std::string, Array<bool> *> uint_nodal_fields;
uint_nodal_fields["blocked_dofs"] = blocked_dofs.get();
return mesh.createNodalField(uint_nodal_fields[field_name], group_name);
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field>
StructuralMechanicsModel::createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) {
UInt n;
if (spatial_dimension == 2) {
n = 2;
} else {
n = 3;
}
UInt padding_size = 0;
if (padding_flag) {
padding_size = 3;
}
if (field_name == "displacement") {
return mesh.createStridedNodalField(displacement_rotation.get(), group_name,
n, 0, padding_size);
}
if (field_name == "velocity") {
return mesh.createStridedNodalField(velocity.get(), group_name, n, 0,
padding_size);
}
if (field_name == "acceleration") {
return mesh.createStridedNodalField(acceleration.get(), group_name, n, 0,
padding_size);
}
if (field_name == "rotation") {
return mesh.createStridedNodalField(displacement_rotation.get(), group_name,
nb_degree_of_freedom - n, n,
padding_size);
}
if (field_name == "force") {
return mesh.createStridedNodalField(external_force.get(), group_name, n, 0,
padding_size);
}
if (field_name == "external_force") {
return mesh.createStridedNodalField(external_force.get(), group_name, n, 0,
padding_size);
}
if (field_name == "momentum") {
return mesh.createStridedNodalField(external_force.get(), group_name,
nb_degree_of_freedom - n, n,
padding_size);
}
if (field_name == "internal_force") {
return mesh.createStridedNodalField(internal_force.get(), group_name, n, 0,
padding_size);
}
if (field_name == "internal_momentum") {
return mesh.createStridedNodalField(internal_force.get(), group_name,
nb_degree_of_freedom - n, n,
padding_size);
}
if (field_name == "mass") {
AKANTU_DEBUG_ASSERT(this->mass.get() != nullptr,
"The lumped mass matrix was not allocated.");
return mesh.createStridedNodalField(this->mass.get(), group_name, n, 0,
padding_size);
}
return nullptr;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<dumpers::Field> StructuralMechanicsModel::createElementalField(
const std::string & field_name, const std::string & group_name,
- bool /*unused*/, UInt spatial_dimension, ElementKind kind) {
+ bool /*unused*/, Int spatial_dimension, ElementKind kind) {
std::shared_ptr<dumpers::Field> field;
if (field_name == "element_index_by_material") {
- field = mesh.createElementalField<UInt, Vector, dumpers::ElementalField>(
- field_name, group_name, spatial_dimension, kind);
+ field =
+ mesh.createElementalField<Idx, Vector<Idx>, dumpers::ElementalField>(
+ field_name, group_name, spatial_dimension, kind);
}
if (field_name == "stress") {
- ElementTypeMap<UInt> nb_data_per_elem = this->mesh.getNbDataPerElem(stress);
+ ElementTypeMap<Int> nb_data_per_elem = this->mesh.getNbDataPerElem(stress);
field = mesh.createElementalField<Real, dumpers::InternalMaterialField>(
stress, group_name, this->spatial_dimension, kind, nb_data_per_elem);
}
return field;
}
/* -------------------------------------------------------------------------- */
/* Virtual methods from SolverCallback */
/* -------------------------------------------------------------------------- */
/// get the type of matrix needed
MatrixType StructuralMechanicsModel::getMatrixType(const ID & /*id*/) const {
return _symmetric;
}
/// callback to assemble a Matrix
void StructuralMechanicsModel::assembleMatrix(const ID & id) {
if (id == "K") {
assembleStiffnessMatrix();
} else if (id == "M") {
assembleMassMatrix();
}
}
/// callback to assemble a lumped Matrix
void StructuralMechanicsModel::assembleLumpedMatrix(const ID & id) {
if ("M" == id) {
this->assembleLumpedMassMatrix();
}
return;
}
/// callback to assemble the residual StructuralMechanicsModel::(rhs)
void StructuralMechanicsModel::assembleResidual() {
AKANTU_DEBUG_IN();
auto & dof_manager = getDOFManager();
assembleInternalForce();
- // Ensures that the matrix are assembled.
- if (dof_manager.hasMatrix("K")) {
- this->assembleMatrix("K");
- }
- if (dof_manager.hasMatrix("M")) {
- this->assembleMatrix("M");
- }
- if (dof_manager.hasLumpedMatrix("M")) {
- this->assembleLumpedMassMatrix();
- }
-
/* This is essentially a summing up of forces
* first the external forces are counted for and then stored inside the
* residual.
*/
dof_manager.assembleToResidual("displacement", *external_force, 1);
dof_manager.assembleToResidual("displacement", *internal_force, 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::assembleResidual(const ID & residual_part) {
AKANTU_DEBUG_IN();
auto & dof_manager = this->getDOFManager();
if ("external" == residual_part) {
dof_manager.assembleToResidual("displacement", *this->external_force, 1);
AKANTU_DEBUG_OUT();
return;
}
if ("internal" == residual_part) {
this->assembleInternalForce();
dof_manager.assembleToResidual("displacement", *this->internal_force, 1);
AKANTU_DEBUG_OUT();
return;
}
AKANTU_CUSTOM_EXCEPTION(
debug::SolverCallbackResidualPartUnknown(residual_part));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/* Virtual methods from Model */
/* -------------------------------------------------------------------------- */
/// get some default values for derived classes
std::tuple<ID, TimeStepSolverType>
StructuralMechanicsModel::getDefaultSolverID(const AnalysisMethod & method) {
switch (method) {
case _static: {
return std::make_tuple("static", TimeStepSolverType::_static);
}
case _implicit_dynamic: {
return std::make_tuple("implicit", TimeStepSolverType::_dynamic);
}
case _explicit_lumped_mass: { // Taken from the solid mechanics part
return std::make_tuple("explicit_lumped",
TimeStepSolverType::_dynamic_lumped);
}
case _explicit_consistent_mass: { // Taken from the solid mechanics part
return std::make_tuple("explicit", TimeStepSolverType::_dynamic);
}
default:
std::cout << "UNKOWN." << std::endl;
return std::make_tuple("unknown", TimeStepSolverType::_not_defined);
}
}
/* ------------------------------------------------------------------------ */
ModelSolverOptions StructuralMechanicsModel::getDefaultSolverOptions(
const TimeStepSolverType & type) const {
ModelSolverOptions options;
switch (type) {
case TimeStepSolverType::_dynamic_lumped: { // Taken from the solid mechanic
// part
options.non_linear_solver_type = NonLinearSolverType::_lumped;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
break;
}
case TimeStepSolverType::_static: {
options.non_linear_solver_type =
NonLinearSolverType::_newton_raphson; // _linear;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_pseudo_time;
options.solution_type["displacement"] = IntegrationScheme::_not_defined;
break;
}
#if 1
case TimeStepSolverType::_dynamic: { // Copied from solid
if (this->method == _explicit_consistent_mass) {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_central_difference;
options.solution_type["displacement"] = IntegrationScheme::_acceleration;
} else {
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_trapezoidal_rule_2;
options.solution_type["displacement"] = IntegrationScheme::_displacement;
}
break;
}
#else
case TimeStepSolverType::_dynamic: { // Original
options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
options.integration_scheme_type["displacement"] =
IntegrationSchemeType::_trapezoidal_rule_2;
options.solution_type["displacement"] = IntegrationScheme::_displacement;
break;
}
#endif
default:
AKANTU_EXCEPTION(type << " is not a valid time step solver type");
}
return options;
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::assembleInternalForce() {
internal_force->zero();
computeStresses();
for (auto type : mesh.elementTypes(_spatial_dimension = _all_dimensions,
_element_kind = _ek_structural)) {
assembleInternalForce(type, _not_ghost);
// assembleInternalForce(type, _ghost);
}
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::assembleInternalForce(ElementType type,
GhostType gt) {
auto & fem = getFEEngine();
auto & sigma = stress(type, gt);
auto ndof = getNbDegreeOfFreedom(type);
auto nb_nodes = mesh.getNbNodesPerElement(type);
auto ndof_per_elem = ndof * nb_nodes;
Array<Real> BtSigma(fem.getNbIntegrationPoints(type) *
mesh.getNbElement(type),
ndof_per_elem, "BtSigma");
fem.computeBtD(sigma, BtSigma, type, gt);
Array<Real> intBtSigma(0, ndof_per_elem, "intBtSigma");
fem.integrate(BtSigma, intBtSigma, ndof_per_elem, type, gt);
getDOFManager().assembleElementalArrayLocalArray(intBtSigma, *internal_force,
type, gt, -1.);
}
/* -------------------------------------------------------------------------- */
Real StructuralMechanicsModel::getKineticEnergy() {
const UInt nb_nodes = mesh.getNbNodes();
const UInt nb_degree_of_freedom = this->nb_degree_of_freedom;
Real ekin = 0.; // used to sum up energy (is divided by two at the very end)
- // if mass matrix was not assembled, assemble it now
- this->assembleMassMatrix();
-
if (this->getDOFManager().hasLumpedMatrix("M")) {
/* This code computes the kinetic energy for the case when the mass is
* lumped. It is based on the solid mechanic equivalent.
*/
AKANTU_DEBUG_ASSERT(this->mass != nullptr,
"The lumped mass is not allocated.");
- if (this->need_to_reassemble_lumpedMass) {
- this->assembleLumpedMatrix("M");
- }
+ this->assembleLumpedMatrix("M");
/* Iterating over all nodes.
* Important the velocity and mass also contains the rotational parts.
* However, they can be handled in an uniform way. */
for (auto && data :
zip(arange(nb_nodes), make_view(*this->velocity, nb_degree_of_freedom),
make_view(*this->mass, nb_degree_of_freedom))) {
const UInt n = std::get<0>(data); // This is the ID of the current node
- if (not mesh.isLocalOrMasterNode(
- n)) // Only handle the node if it belongs to us.
- {
+ // Only handle the node if it belongs to us.
+ if (not mesh.isLocalOrMasterNode(n)) {
continue;
}
- const auto & v =
- std::get<1>(data); // Get the velocity and mass of that node.
- const auto & m = std::get<2>(data);
- Real mv2 = 0.; // Contribution of this node.
-
- for (UInt i = 0; i < nb_degree_of_freedom; ++i) {
- /* In the solid mechanics part, only masses that are above a certain
- * value are considered.
- * However, the structural part, does not do this. */
- const Real v_ = v(i);
- const Real m_ = m(i);
- mv2 += v_ * v_ * m_;
- } // end for(i): going through the components
-
- ekin += mv2; // add continution
- } // end for(n): iterating through all nodes
+ const auto & velocity = std::get<1>(data);
+ const auto & mass = std::get<2>(data);
+ Real mv2 = 0.;
+
+ for (auto && node_data : zip(velocity, mass)) {
+ mv2 += Math::pow<2>(std::get<0>(node_data)) * std::get<1>(node_data);
+ }
+
+ ekin += mv2;
+ }
} else if (this->getDOFManager().hasMatrix("M")) {
/* Handle the case where no lumped mass is there.
* This is basically the original code.
*/
- if (this->need_to_reassemble_mass) {
- this->assembleMassMatrix();
- }
+ this->assembleMassMatrix();
Array<Real> Mv(nb_nodes, nb_degree_of_freedom);
this->getDOFManager().assembleMatMulVectToArray("displacement", "M",
*this->velocity, Mv);
for (auto && data :
zip(arange(nb_nodes), make_view(Mv, nb_degree_of_freedom),
make_view(*this->velocity, nb_degree_of_freedom))) {
- if (mesh.isLocalOrMasterNode(std::get<0>(
- data))) // only consider the node if we are blonging to it
- {
+ // only consider the node if we are belonging to it
+ if (mesh.isLocalOrMasterNode(std::get<0>(data))) {
ekin += std::get<2>(data).dot(std::get<1>(data));
}
}
} else {
/* This is the case where no mass is present, for whatever reason, such as
* the static case. We handle it specially be returning directly zero.
- * However, by doing that there will not be a syncronizing event as in the
+ * However, by doing that there will not be a synchronizing event as in the
* other cases. Which is faster, but could be a problem in case the user
* expects this.
*
* Another not is, that the solid mechanics part, would generate an error in
* this clause. But, since the original implementation of the structural
* part, did not do that, I, Philip, decided to refrain from that. However,
* it is an option that should be considered.
*/
return 0.;
}
// Sum up across the comunicator
mesh.getCommunicator().allReduce(ekin, SynchronizerOperation::_sum);
return ekin / 2.; // finally divide the energy by two
}
/* -------------------------------------------------------------------------- */
Real StructuralMechanicsModel::getPotentialEnergy() {
Real epot = 0.;
UInt nb_nodes = mesh.getNbNodes();
// if stiffness matrix is not assembled, do it
this->assembleStiffnessMatrix();
Array<Real> Ku(nb_nodes, nb_degree_of_freedom);
this->getDOFManager().assembleMatMulVectToArray(
"displacement", "K", *this->displacement_rotation, Ku);
for (auto && data :
zip(arange(nb_nodes), make_view(Ku, nb_degree_of_freedom),
make_view(*this->displacement_rotation, nb_degree_of_freedom))) {
epot += std::get<2>(data).dot(std::get<1>(data)) *
static_cast<Real>(mesh.isLocalOrMasterNode(std::get<0>(data)));
}
mesh.getCommunicator().allReduce(epot, SynchronizerOperation::_sum);
return epot / 2.;
}
/* -------------------------------------------------------------------------- */
Real StructuralMechanicsModel::getEnergy(const ID & energy) {
if (energy == "kinetic") {
return getKineticEnergy();
}
if (energy == "potential") {
return getPotentialEnergy();
}
return 0;
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::computeForcesByLocalTractionArray(
const Array<Real> & tractions, ElementType type) {
AKANTU_DEBUG_IN();
auto nb_element = getFEEngine().getMesh().getNbElement(type);
auto nb_nodes_per_element =
getFEEngine().getMesh().getNbNodesPerElement(type);
auto nb_quad = getFEEngine().getNbIntegrationPoints(type);
// check dimension match
AKANTU_DEBUG_ASSERT(
Mesh::getSpatialDimension(type) == getFEEngine().getElementDimension(),
"element type dimension does not match the dimension of boundaries : "
<< getFEEngine().getElementDimension()
<< " != " << Mesh::getSpatialDimension(type));
// check size of the vector
AKANTU_DEBUG_ASSERT(
tractions.size() == nb_quad * nb_element,
"the size of the vector should be the total number of quadrature points");
// check number of components
AKANTU_DEBUG_ASSERT(tractions.getNbComponent() == nb_degree_of_freedom,
"the number of components should be the spatial "
"dimension of the problem");
Array<Real> Ntbs(nb_element * nb_quad,
nb_degree_of_freedom * nb_nodes_per_element);
auto & fem = getFEEngine();
fem.computeNtb(tractions, Ntbs, type);
// allocate the vector that will contain the integrated values
auto name = id + std::to_string(type) + ":integral_boundary";
Array<Real> int_funct(nb_element, nb_degree_of_freedom * nb_nodes_per_element,
name);
// do the integration
getFEEngine().integrate(Ntbs, int_funct,
nb_degree_of_freedom * nb_nodes_per_element, type);
// assemble the result into force vector
getDOFManager().assembleElementalArrayLocalArray(int_funct, *external_force,
type, _not_ghost, 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::computeForcesByGlobalTractionArray(
const Array<Real> & traction_global, ElementType type) {
AKANTU_DEBUG_IN();
- UInt nb_element = mesh.getNbElement(type);
- UInt nb_quad = getFEEngine().getNbIntegrationPoints(type);
+ auto nb_element = mesh.getNbElement(type);
+ auto nb_quad = getFEEngine().getNbIntegrationPoints(type);
Array<Real> traction_local(nb_element * nb_quad, nb_degree_of_freedom,
id + ":structuralmechanics:imposed_linear_load");
auto R_it = getFEEngineClass<MyFEEngineType>()
.getShapeFunctions()
.getRotations(type)
.begin(nb_degree_of_freedom, nb_degree_of_freedom);
auto Te_it = traction_global.begin(nb_degree_of_freedom);
auto te_it = traction_local.begin(nb_degree_of_freedom);
- for (UInt e = 0; e < nb_element; ++e, ++R_it) {
- for (UInt q = 0; q < nb_quad; ++q, ++Te_it, ++te_it) {
+ for (Int e = 0; e < nb_element; ++e, ++R_it) {
+ for (Int q = 0; q < nb_quad; ++q, ++Te_it, ++te_it) {
// turn the traction in the local referential
- te_it->template mul<false>(*R_it, *Te_it);
+ *te_it = *R_it * *Te_it;
}
}
computeForcesByLocalTractionArray(traction_local, type);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::afterSolveStep(bool converged) {
if (converged) {
assembleInternalForce();
}
}
} // namespace akantu
diff --git a/src/model/structural_mechanics/structural_mechanics_model.hh b/src/model/structural_mechanics/structural_mechanics_model.hh
index 3c80f2bd2..98d00a01e 100644
--- a/src/model/structural_mechanics/structural_mechanics_model.hh
+++ b/src/model/structural_mechanics/structural_mechanics_model.hh
@@ -1,398 +1,397 @@
/**
* @file structural_mechanics_model.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Philip Mueller <philip.paul.mueller@bluemail.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Spielmann <damien.spielmann@epfl.ch>
*
* @date creation: Fri Jul 15 2011
* @date last modification: Thu Apr 01 2021
*
* @brief Particular implementation of the structural elements in the
* StructuralMechanicsModel
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_named_argument.hh"
-#include "boundary_condition.hh"
#include "model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_STRUCTURAL_MECHANICS_MODEL_HH_
#define AKANTU_STRUCTURAL_MECHANICS_MODEL_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class Material;
class MaterialSelector;
class DumperIOHelper;
class NonLocalManager;
template <ElementKind kind, class IntegrationOrderFunctor>
class IntegratorGauss;
template <ElementKind kind> class ShapeStructural;
} // namespace akantu
namespace akantu {
struct StructuralMaterial {
Real E{0};
Real A{1};
Real I{0};
Real Iz{0};
Real Iy{0};
Real GJ{0};
Real rho{0};
Real t{0};
Real nu{0};
};
class StructuralMechanicsModel : public Model {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using MyFEEngineType =
FEEngineTemplate<IntegratorGauss, ShapeStructural, _ek_structural>;
- StructuralMechanicsModel(Mesh & mesh, UInt dim = _all_dimensions,
+ StructuralMechanicsModel(Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "structural_mechanics_model");
~StructuralMechanicsModel() override;
/// Init full model
void initFullImpl(const ModelOptions & options) override;
/// Init boundary FEEngine
void initFEEngineBoundary() override;
/* ------------------------------------------------------------------------ */
/* Virtual methods from SolverCallback */
/* ------------------------------------------------------------------------ */
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override;
/// callback to assemble a Matrix
void assembleMatrix(const ID & matrix_id) override;
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & matrix_id) override;
/// callback to assemble the residual (rhs)
void assembleResidual() override;
void assembleResidual(const ID & residual_part) override;
bool canSplitResidual() const override { return true; }
void afterSolveStep(bool converged) override;
/// compute kinetic energy
Real getKineticEnergy();
/// compute potential energy
Real getPotentialEnergy();
/// compute the specified energy
Real getEnergy(const ID & energy);
/**
* \brief This function computes the an approximation of the lumped mass.
*
* The mass is computed by looping over all beams and computing their mass.
* The mass of a single beam is computed by the (initial) length of the beam,
* its cross sectional area and its density.
* The beam mass is then equaly distributed among the two nodes.
*
* For computing the rotational inertia, the function assumes that the mass of
* a node is uniformaly distributed inside a disc (2D) or a sphere (3D). The
* size of that disc, depends on the volume of the beam.
*
* Note that the computation of the mass is not unambigius.
* The reason for this is, that the units of `StructralMaterial::rho` are not
* clear. By default the function assumes that its unit are 'Mass per Volume'.
* However, this makes the computed mass different than the consistent mass,
* which seams to assume that its units are 'mass per unit length'.
* The main difference between thge two are not the values, but that the
* first version depends on `StructuralMaterial::A` while the later does not.
* By defining the macro `AKANTU_STRUCTURAL_MECHANICS_CONSISTENT_LUMPED_MASS`
* the function will compute the mass in a way that is consistent with the
* consistent mass matrix.
*
* \note The lumped mass is not stored inside the DOFManager.
*
* \param ghost_type Should ghost types be computed.
*/
void assembleLumpedMassMatrix();
/* ------------------------------------------------------------------------ */
/* Virtual methods from Model */
/* ------------------------------------------------------------------------ */
protected:
/// get some default values for derived classes
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
static UInt getNbDegreeOfFreedom(ElementType type);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
void initSolver(TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type) override;
/// initialize the model
void initModel() override;
/// compute the stresses per elements
void computeStresses();
/// compute the nodal forces
void assembleInternalForce();
/// compute the nodal forces for an element type
void assembleInternalForce(ElementType type, GhostType gt);
/// assemble the stiffness matrix
void assembleStiffnessMatrix();
/// assemble the mass matrix for consistent mass resolutions
void assembleMassMatrix();
protected:
/// assemble the mass matrix for either _ghost or _not_ghost elements
void assembleMassMatrix(GhostType ghost_type);
/// computes rho
void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type);
/// finish the computation of residual to solve in increment
void updateResidualInternal();
/* ------------------------------------------------------------------------ */
private:
template <ElementType type> void assembleStiffnessMatrix();
template <ElementType type> void computeStressOnQuad();
template <ElementType type>
void computeTangentModuli(Array<Real> & tangent_moduli);
/* ------------------------------------------------------------------------ */
/* Dumpable interface */
/* ------------------------------------------------------------------------ */
public:
std::shared_ptr<dumpers::Field>
createNodalFieldReal(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createNodalFieldBool(const std::string & field_name,
const std::string & group_name,
bool padding_flag) override;
std::shared_ptr<dumpers::Field>
createElementalField(const std::string & field_name,
const std::string & group_name, bool padding_flag,
- UInt spatial_dimension, ElementKind kind) override;
+ Int spatial_dimension, ElementKind kind) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// set the value of the time step
void setTimeStep(Real time_step, const ID & solver_id = "") override;
/// get the StructuralMechanicsModel::displacement vector
AKANTU_GET_MACRO(Displacement, *displacement_rotation, Array<Real> &);
/// get the StructuralMechanicsModel::velocity vector
AKANTU_GET_MACRO(Velocity, *velocity, Array<Real> &);
/// get the StructuralMechanicsModel::acceleration vector, updated
/// by
/// StructuralMechanicsModel::updateAcceleration
AKANTU_GET_MACRO(Acceleration, *acceleration, Array<Real> &);
/// get the StructuralMechanicsModel::external_force vector
AKANTU_GET_MACRO(ExternalForce, *external_force, Array<Real> &);
/// get the StructuralMechanicsModel::internal_force vector (boundary forces)
AKANTU_GET_MACRO(InternalForce, *internal_force, Array<Real> &);
/// get the StructuralMechanicsModel::boundary vector
AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool> &);
/**
* Returns a const reference to the array that stores the lumped mass.
*
* The returned array has dimension `N x d` where `N` is the number of nodes
* and `d`, is the number of degrees of freedom per node.
*/
inline const Array<Real> & getLumpedMass() const {
if (this->mass == nullptr) {
AKANTU_EXCEPTION("The pointer to the mass was not allocated.");
};
return *(this->mass);
};
// These function is an alias, for compability with the solid mechanics
inline const Array<Real> & getMass() const { return this->getLumpedMass(); }
// Creates the array for storing the mass
bool allocateLumpedMassArray();
/**
* Tests if *this has a lumped mass pointer.
*/
inline bool hasLumpedMass() const { return (this->mass != nullptr); };
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(RotationMatrix, rotation_matrix, Real);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, UInt);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Set_ID, set_ID, UInt);
/**
* \brief This function adds the `StructuralMaterial` material to the list of
* materials managed by *this.
*
* It is important that this function might invalidate all references to
* structural materials, that were previously optained by `getMaterial()`.
*
* \param material The new material.
*
* \return The ID of the material that was added.
*
* \note The return type is is new.
*/
UInt addMaterial(StructuralMaterial & material, const ID & name = "");
const StructuralMaterial &
getMaterialByElement(const Element & element) const;
/**
* \brief Returns the ith material of *this.
* \param i The ith material
*/
const StructuralMaterial & getMaterial(UInt material_index) const;
const StructuralMaterial & getMaterial(const ID & name) const;
/**
* \brief Returns the number of the different materials inside *this.
*/
UInt getNbMaterials() const { return materials.size(); }
/* ------------------------------------------------------------------------ */
/* Boundaries (structural_mechanics_model_boundary.cc) */
/* ------------------------------------------------------------------------ */
public:
/// Compute Linear load function set in global axis
void computeForcesByGlobalTractionArray(const Array<Real> & traction_global,
ElementType type);
/// Compute Linear load function set in local axis
void computeForcesByLocalTractionArray(const Array<Real> & tractions,
ElementType type);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// time step
Real time_step;
/// conversion coefficient form force/mass to acceleration
Real f_m2a;
/// displacements array
std::unique_ptr<Array<Real>> displacement_rotation;
/// velocities array
std::unique_ptr<Array<Real>> velocity;
/// accelerations array
std::unique_ptr<Array<Real>> acceleration;
/// forces array
std::unique_ptr<Array<Real>> internal_force;
/// forces array
std::unique_ptr<Array<Real>> external_force;
/**
* \brief This is the "lumped" mass array.
*
* It is a bit special, since it is not a one dimensional array, bit it is
* actually a matrix. The number of rows equals the number of nodes. The
* number of colums equals the number of degrees of freedoms per node. This
* layout makes the thing a bit more simple.
*
* Note that it is only allocated in case, the "Lumped" mode is enabled.
*/
std::unique_ptr<Array<Real>> mass;
/// boundaries array
std::unique_ptr<Array<bool>> blocked_dofs;
/// stress array
ElementTypeMapArray<Real> stress;
ElementTypeMapArray<UInt> element_material;
// Define sets of beams
ElementTypeMapArray<UInt> set_ID;
/// number of degre of freedom
- UInt nb_degree_of_freedom;
+ Int nb_degree_of_freedom;
// Rotation matrix
ElementTypeMapArray<Real> rotation_matrix;
// /// analysis method check the list in akantu::AnalysisMethod
// AnalysisMethod method;
/// flag defining if the increment must be computed or not
bool increment_flag;
bool need_to_reassemble_mass{true};
bool need_to_reassemble_stiffness{true};
- bool need_to_reassemble_lumpedMass{true};
+ bool need_to_reassemble_lumped_mass{true};
/* ------------------------------------------------------------------------ */
std::vector<StructuralMaterial> materials;
std::map<std::string, UInt> materials_names_to_id;
};
} // namespace akantu
#include "structural_mechanics_model_inline_impl.hh"
#endif /* AKANTU_STRUCTURAL_MECHANICS_MODEL_HH_ */
diff --git a/src/model/structural_mechanics/structural_mechanics_model_inline_impl.hh b/src/model/structural_mechanics/structural_mechanics_model_inline_impl.hh
index 77ae249b7..32611723a 100644
--- a/src/model/structural_mechanics/structural_mechanics_model_inline_impl.hh
+++ b/src/model/structural_mechanics/structural_mechanics_model_inline_impl.hh
@@ -1,282 +1,266 @@
/**
* @file structural_mechanics_model_inline_impl.hh
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Damien Spielmann <damien.spielmann@epfl.ch>
*
* @date creation: Fri Jul 15 2011
* @date last modification: Mon Mar 15 2021
*
* @brief Implementation of inline functions of StructuralMechanicsModel
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "structural_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_STRUCTURAL_MECHANICS_MODEL_INLINE_IMPL_HH_
#define AKANTU_STRUCTURAL_MECHANICS_MODEL_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline UInt StructuralMechanicsModel::addMaterial(StructuralMaterial & material,
const ID & name) {
const auto material_index = materials.size();
auto material_name = name;
if (name.empty()) {
material_name = "material_" + std::to_string(material_index);
}
if (materials_names_to_id.find(material_name) !=
materials_names_to_id.end()) {
AKANTU_EXCEPTION("The material " << material_name
<< " already exists in the model " << id);
}
AKANTU_DEBUG_ASSERT(material_index <=
(::std::size_t)::std::numeric_limits<UInt>::max(),
"Can not represent the material ID");
materials_names_to_id[material_name] = material_index;
materials.push_back(material); // add the material, might cause
// reallocation.
return UInt(material_index);
}
/* -------------------------------------------------------------------------- */
inline const StructuralMaterial &
StructuralMechanicsModel::getMaterialByElement(const Element & element) const {
return materials[element_material(element)];
}
/* -------------------------------------------------------------------------- */
inline const StructuralMaterial &
StructuralMechanicsModel::getMaterial(UInt material_index) const {
return materials.at(material_index);
}
/* -------------------------------------------------------------------------- */
inline const StructuralMaterial &
StructuralMechanicsModel::getMaterial(const ID & name) const {
auto it = materials_names_to_id.find(name);
if (it == materials_names_to_id.end()) {
AKANTU_EXCEPTION("The material " << name << " was not found in the model "
<< id);
}
return materials.at(it->second);
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void StructuralMechanicsModel::computeTangentModuli(
Array<Real> & /*tangent_moduli*/) {
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void StructuralMechanicsModel::assembleStiffnessMatrix() {
AKANTU_DEBUG_IN();
auto nb_element = getFEEngine().getMesh().getNbElement(type);
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
auto tangent_size = ElementClass<type>::getNbStressComponents();
auto tangent_moduli = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points, tangent_size * tangent_size,
"tangent_stiffness_matrix");
computeTangentModuli<type>(*tangent_moduli);
/// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
UInt bt_d_b_size = nb_degree_of_freedom * nb_nodes_per_element;
auto bt_d_b = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B");
const auto & b = getFEEngine().getShapesDerivatives(type);
- Matrix<Real> BtD(bt_d_b_size, tangent_size);
-
for (auto && tuple :
zip(make_view(b, tangent_size, bt_d_b_size),
make_view(*tangent_moduli, tangent_size, tangent_size),
make_view(*bt_d_b, bt_d_b_size, bt_d_b_size))) {
auto & B = std::get<0>(tuple);
auto & D = std::get<1>(tuple);
auto & BtDB = std::get<2>(tuple);
- BtD.mul<true, false>(B, D);
- BtDB.template mul<false, false>(BtD, B);
+
+ BtDB = B.transpose() * D * B;
}
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
auto int_bt_d_b = std::make_unique<Array<Real>>(
nb_element, bt_d_b_size * bt_d_b_size, "int_B^t*D*B");
getFEEngine().integrate(*bt_d_b, *int_bt_d_b, bt_d_b_size * bt_d_b_size,
type);
getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *int_bt_d_b, type, _not_ghost, _symmetric);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <ElementType type>
void StructuralMechanicsModel::computeStressOnQuad() {
AKANTU_DEBUG_IN();
auto & sigma = stress(type, _not_ghost);
auto nb_element = mesh.getNbElement(type);
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
auto nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
auto tangent_size = ElementClass<type>::getNbStressComponents();
+ auto d_b_size = nb_degree_of_freedom * nb_nodes_per_element;
auto tangent_moduli = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points, tangent_size * tangent_size,
"tangent_stiffness_matrix");
computeTangentModuli<type>(*tangent_moduli);
- /// compute DB
- auto d_b_size = nb_degree_of_freedom * nb_nodes_per_element;
-
- auto d_b = std::make_unique<Array<Real>>(nb_element * nb_quadrature_points,
- d_b_size * tangent_size, "D*B");
-
- const auto & b = getFEEngine().getShapesDerivatives(type);
-
- auto B = b.begin(tangent_size, d_b_size);
- auto D = tangent_moduli->begin(tangent_size, tangent_size);
- auto D_B = d_b->begin(tangent_size, d_b_size);
-
- for (UInt e = 0; e < nb_element; ++e) {
- for (UInt q = 0; q < nb_quadrature_points; ++q, ++B, ++D, ++D_B) {
- D_B->template mul<false, false>(*D, *B);
- }
- }
-
- /// compute DBu
- D_B = d_b->begin(tangent_size, d_b_size);
- auto DBu = sigma.begin(tangent_size);
-
Array<Real> u_el(0, d_b_size);
FEEngine::extractNodalToElementField(mesh, *displacement_rotation, u_el,
type);
- auto ug = u_el.begin(d_b_size);
+ const auto & b = getFEEngine().getShapesDerivatives(type);
- // No need to rotate because B is post-multiplied
- for (UInt e = 0; e < nb_element; ++e, ++ug) {
- for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_B, ++DBu) {
- DBu->template mul<false>(*D_B, *ug);
- }
+ for (auto && data :
+ zip(make_view(*tangent_moduli, tangent_size, tangent_size),
+ make_view(b, tangent_size, d_b_size),
+ repeat_n(make_view(u_el, d_b_size), nb_quadrature_points),
+ make_view(sigma, tangent_size))) {
+ auto && D = std::get<0>(data);
+ auto && B = std::get<1>(data);
+ auto && u = std::get<2>(data);
+
+ auto && DBu = std::get<3>(data);
+
+ DBu = D * B * u;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* @param myf pointer to a function that fills a vector/tensor with respect to
* passed coordinates
*/
#if 0
template <ElementType type>
inline void StructuralMechanicsModel::computeForcesFromFunction(
BoundaryFunction myf, BoundaryFunctionType function_type) {
/** function type is
** _bft_forces : linear load is given
** _bft_stress : stress function is given -> Not already done for this kind
*of model
*/
std::stringstream name;
name << id << ":structuralmechanics:imposed_linear_load";
Array<Real> lin_load(0, nb_degree_of_freedom, name.str());
name.zero();
UInt offset = nb_degree_of_freedom;
// prepare the loop over element types
UInt nb_quad = getFEEngine().getNbIntegrationPoints(type);
UInt nb_element = getFEEngine().getMesh().getNbElement(type);
name.zero();
name << id << ":structuralmechanics:quad_coords";
Array<Real> quad_coords(nb_element * nb_quad, spatial_dimension,
"quad_coords");
getFEEngineClass<MyFEEngineType>()
.getShapeFunctions()
.interpolateOnIntegrationPoints<type>(getFEEngine().getMesh().getNodes(),
quad_coords, spatial_dimension);
getFEEngineClass<MyFEEngineType>()
.getShapeFunctions()
.interpolateOnIntegrationPoints<type>(
getFEEngine().getMesh().getNodes(), quad_coords, spatial_dimension,
_not_ghost, empty_filter, true, 0, 1, 1);
if (spatial_dimension == 3)
getFEEngineClass<MyFEEngineType>()
.getShapeFunctions()
.interpolateOnIntegrationPoints<type>(
getFEEngine().getMesh().getNodes(), quad_coords, spatial_dimension,
_not_ghost, empty_filter, true, 0, 2, 2);
lin_load.resize(nb_element * nb_quad);
- Real * imposed_val = lin_load.storage();
+ Real * imposed_val = lin_load.data();
/// sigma/load on each quadrature points
- Real * qcoord = quad_coords.storage();
- for (UInt el = 0; el < nb_element; ++el) {
- for (UInt q = 0; q < nb_quad; ++q) {
+ Real * qcoord = quad_coords.data();
+ for (Int el = 0; el < nb_element; ++el) {
+ for (Int q = 0; q < nb_quad; ++q) {
myf(qcoord, imposed_val, NULL, 0);
imposed_val += offset;
qcoord += spatial_dimension;
}
}
switch (function_type) {
case _bft_traction_local:
computeForcesByLocalTractionArray<type>(lin_load);
break;
case _bft_traction:
computeForcesByGlobalTractionArray<type>(lin_load);
break;
default:
break;
}
}
#endif
} // namespace akantu
#endif /* AKANTU_STRUCTURAL_MECHANICS_MODEL_INLINE_IMPL_HH_ */
diff --git a/src/model/structural_mechanics/structural_mechanics_model_mass.cc b/src/model/structural_mechanics/structural_mechanics_model_mass.cc
index 9aad97666..306f97947 100644
--- a/src/model/structural_mechanics/structural_mechanics_model_mass.cc
+++ b/src/model/structural_mechanics/structural_mechanics_model_mass.cc
@@ -1,219 +1,220 @@
/**
* @file structural_mechanics_model_mass.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jul 07 2014
* @date last modification: Thu Mar 04 2021
*
* @brief function handling mass computation
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_math.hh"
#include "integrator_gauss.hh"
#include "material.hh"
#include "shape_structural.hh"
#include "structural_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class ComputeRhoFunctorStruct {
public:
explicit ComputeRhoFunctorStruct(const StructuralMechanicsModel & model)
: model(model){};
void operator()(Matrix<Real> & rho, const Element & element) const {
const auto & mat = model.getMaterialByElement(element);
const Real mat_rho = mat.rho; // This is the density
const Real mat_A = mat.A; // This is the cross section
const Real mat_mass_per_length =
mat_rho * mat_A; // Mass of the beam per unit length
rho.set(
mat_mass_per_length); // The integrator _recquiers_ mass per unit length
}
private:
const StructuralMechanicsModel & model;
};
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::assembleMassMatrix() {
AKANTU_DEBUG_IN();
if (not need_to_reassemble_mass) {
return;
}
if (not getDOFManager().hasMatrix("M")) {
getDOFManager().getNewMatrix("M", getMatrixType("M"));
}
this->getDOFManager().zeroMatrix("M");
assembleMassMatrix(_not_ghost);
need_to_reassemble_mass = false;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::assembleMassMatrix(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & fem = getFEEngineClass<MyFEEngineType>();
ComputeRhoFunctorStruct compute_rho(*this);
for (auto type :
mesh.elementTypes(spatial_dimension, ghost_type, _ek_structural)) {
fem.assembleFieldMatrix(compute_rho, "M", "displacement",
this->getDOFManager(), type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void StructuralMechanicsModel::assembleLumpedMassMatrix() {
- if (not this->need_to_reassemble_lumpedMass)
+ if (not this->need_to_reassemble_lumped_mass) {
return;
+ }
allocNodalField(this->mass, nb_degree_of_freedom, "lumped_mass");
if (!this->getDOFManager().hasLumpedMatrix("M")) {
this->getDOFManager().getNewLumpedMatrix("M");
}
this->getDOFManager().zeroLumpedMatrix("M");
// Preparing
const UInt nb_nodes = mesh.getNbNodes();
const auto & nodes = mesh.getNodes();
const auto & node_it = make_view(nodes, spatial_dimension).begin();
auto & lumped_mass = *(this->mass);
lumped_mass.zero(); // Set the lumped mass to zero
Array<Real> volumes(nb_nodes, 1, 0., "volumes");
/// We now compute the mass and the volume, but not the inertia
for (auto type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_structural)) {
const auto & element_material_id = this->element_material(type);
const auto & connectivity = mesh.getConnectivity(type);
- const UInt nb_element = connectivity.size();
+ // const auto nb_element = connectivity.size();
- if (type != _bernoulli_beam_3 or type != _bernoulli_beam_2) {
+ if (type != _bernoulli_beam_3 and type != _bernoulli_beam_2) {
AKANTU_EXCEPTION(
"The lumped mass was not implemented for non Bernoulli Beams");
}
// Now iterate through all the connectivity
for (auto && data : zip(make_view(connectivity, 2), element_material_id)) {
const auto & conn = std::get<0>(data);
auto node1 = conn(0);
auto node2 = conn(0);
const auto & material = this->materials.at(std::get<1>(data));
- const Real rho = material.rho;
- const Real cross_section = material.A;
+ const auto rho = material.rho;
+ const auto cross_section = material.A;
- const Vector<Real> coord_node_1 = node_it[node1];
- const Vector<Real> coord_node_2 = node_it[node2];
+ auto && coord_node_1 = node_it[node1];
+ auto && coord_node_2 = node_it[node2];
- const Real length = coord_node_1.distance(coord_node_2);
- const Real volume = length * cross_section;
- const Real mass = volume * rho;
+ const auto length = coord_node_1.distance(coord_node_2);
+ const auto volume = length * cross_section;
+ const auto mass = volume * rho;
// Now distribute the mass at the right places
- for (UInt d = 0; d != spatial_dimension; ++d) {
+ for (auto d : arange(spatial_dimension)) {
lumped_mass(node1, d) += mass / 2.;
lumped_mass(node2, d) += mass / 2.;
}; // end for(d):
volumes(node1) += volume / 2.; // this entry never point to mass
volumes(node2) += volume / 2.;
}
}
- const Real pi = std::atan(1.) * 4;
+ const auto pi = std::atan(1.) * 4;
// We now compute the inertia.
if (spatial_dimension == 2) {
/* This is the 2D case, so we are assuming that the mass is inside a disc.
* Which is given as
* \begin{align}
* I := m \cdot r^2
* \end{align}
*
* The radius is obtained by assuming that the volume, that is associated to
* a beam, forms a uniformly disc. From this volume we can compute the
* radius.
*/
for (auto && data :
zip(make_view(lumped_mass, nb_degree_of_freedom), volumes)) {
const Real volume = std::get<1>(data);
auto & masses = std::get<0>(data);
const Real r2 = volume / pi; // The square of the volume
const Real inertia = masses(0) * r2;
masses(spatial_dimension) = inertia;
}
} else if (spatial_dimension == 3) {
/* This is essentially the same as for 2D only that we assume here,
* that the mass is uniformly distributed inside a sphere.
* And thus we have
* \begin{align}
* I := \frac{2}{5} m \cdot r^2
* \end{align}
*
* We also have to set three values, for the three axis.
* But since we assume a sphere, they are all the same.
*/
for (auto && data :
zip(make_view(lumped_mass, nb_degree_of_freedom), volumes)) {
const Real volume = std::get<1>(data);
auto & masses = std::get<0>(data);
const Real r2 = std::pow((volume * 3.) / (4 * pi), 2. / 3.);
const Real inertia = (2. / 5.) * masses(0) * r2;
- for (UInt d = spatial_dimension; d < masses.size(); ++d) {
- masses(d) = inertia;
+ for (auto && m : masses) {
+ m = inertia;
}
}
} else {
AKANTU_EXCEPTION("The dimension " << spatial_dimension << " is not known.");
}
this->getDOFManager().assembleToLumpedMatrix("displacement", lumped_mass,
"M");
- this->need_to_reassemble_lumpedMass = false;
- return;
+
+ this->need_to_reassemble_lumped_mass = false;
}
} // namespace akantu
diff --git a/src/solver/solver_petsc.cc b/src/solver/solver_petsc.cc
index baa032bde..52c89578a 100644
--- a/src/solver/solver_petsc.cc
+++ b/src/solver/solver_petsc.cc
@@ -1,100 +1,95 @@
/**
* @file solver_petsc.cc
*
* @author Alejandro M. Aragón <alejandro.aragon@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue May 13 2014
* @date last modification: Tue May 26 2020
*
* @brief Solver class implementation for the petsc solver
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solver_petsc.hh"
#include "dof_manager_petsc.hh"
#include "mpi_communicator_data.hh"
#include "solver_vector_petsc.hh"
#include "sparse_matrix_petsc.hh"
/* -------------------------------------------------------------------------- */
#include <petscksp.h>
//#include <petscsys.h>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
SolverPETSc::SolverPETSc(DOFManagerPETSc & dof_manager, const ID & matrix_id,
const ID & id)
: SparseSolver(dof_manager, matrix_id, id), dof_manager(dof_manager),
matrix(dof_manager.getMatrix(matrix_id)) {
auto && mpi_comm = dof_manager.getMPIComm();
/// create a solver context
PETSc_call(KSPCreate, mpi_comm, &this->ksp);
}
/* -------------------------------------------------------------------------- */
SolverPETSc::~SolverPETSc() {
if (ksp != nullptr) {
PETSc_call(KSPDestroy, &ksp);
}
}
/* -------------------------------------------------------------------------- */
void SolverPETSc::setOperators() {
// set the matrix that defines the linear system and the matrix for
// preconditioning (here they are the same)
#if PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 5
PETSc_call(KSPSetOperators, ksp, this->matrix.getMat(),
this->matrix.getMat());
#else
PETSc_call(KSPSetOperators, ksp, this->matrix.getMat(), this->matrix.getMat(),
SAME_NONZERO_PATTERN);
#endif
// If this is not called the solution vector is zeroed in the call to
// KSPSolve().
PETSc_call(KSPSetInitialGuessNonzero, ksp, PETSC_TRUE);
PETSc_call(KSPSetFromOptions, ksp);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolverPETSc::solve() {
Vec & rhs(this->dof_manager.getResidual());
Vec & solution(this->dof_manager.getSolution());
PETSc_call(KSPSolve, ksp, rhs, solution);
}
/* -------------------------------------------------------------------------- */
-bool SolverPETSc::isFinite() const {
- PetscReal norm;
- PETSc_call(VecNorm, NORM_INFINITY, &norm);
- return std::isfinite(norm);
-}
} // namespace akantu
diff --git a/src/solver/solver_petsc.hh b/src/solver/solver_petsc.hh
index d14feca41..e0b573f35 100644
--- a/src/solver/solver_petsc.hh
+++ b/src/solver/solver_petsc.hh
@@ -1,84 +1,82 @@
/**
* @file solver_petsc.hh
*
* @author Alejandro M. Aragón <alejandro.aragon@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue May 13 2014
* @date last modification: Tue May 26 2020
*
* @brief Solver class interface for the petsc solver
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "sparse_solver.hh"
/* -------------------------------------------------------------------------- */
#include <petscksp.h>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLVER_PETSC_HH_
#define AKANTU_SOLVER_PETSC_HH_
namespace akantu {
class SparseMatrixPETSc;
class DOFManagerPETSc;
} // namespace akantu
namespace akantu {
class SolverPETSc : public SparseSolver {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SolverPETSc(DOFManagerPETSc & dof_manager, const ID & matrix_id,
const ID & id = "solver_petsc");
~SolverPETSc() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// create the solver context and set the matrices
virtual void setOperators();
void solve() override;
- bool isFinite() const override;
-
private:
/// DOFManager correctly typed
DOFManagerPETSc & dof_manager;
/// PETSc linear solver
KSP ksp;
/// Matrix defining the system of equations
SparseMatrixPETSc & matrix;
};
} // namespace akantu
#endif /* AKANTU_SOLVER_PETSC_HH_ */
diff --git a/src/solver/solver_vector.hh b/src/solver/solver_vector.hh
index d05727fa3..d41946875 100644
--- a/src/solver/solver_vector.hh
+++ b/src/solver/solver_vector.hh
@@ -1,96 +1,96 @@
/**
* @file solver_vector.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Tue May 26 2020
*
* @brief Solver vector interface base class
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLVER_VECTOR_HH_
#define AKANTU_SOLVER_VECTOR_HH_
namespace akantu {
class DOFManager;
}
namespace akantu {
class SolverVector {
public:
SolverVector(DOFManager & dof_manager, const ID & id = "solver_vector")
: id(id), _dof_manager(dof_manager) {}
SolverVector(const SolverVector & vector, const ID & id = "solver_vector")
: id(id), _dof_manager(vector._dof_manager) {}
virtual ~SolverVector() = default;
// resize the vector to the size of the problem
virtual void resize() = 0;
// clear the vector
virtual void set(Real val) = 0;
void zero() { this->set({}); }
virtual operator const Array<Real> &() const = 0;
virtual Int size() const = 0;
virtual Int localSize() const = 0;
virtual SolverVector & operator+(const SolverVector & y) = 0;
virtual SolverVector & operator=(const SolverVector & y) = 0;
- UInt & release() { return release_; }
- UInt release() const { return release_; }
+ Int & release() { return release_; }
+ Int release() const { return release_; }
virtual void printself(std::ostream & stream, int indent = 0) const = 0;
virtual bool isFinite() const = 0;
/// Returns `true` if `*this` is distributed or not.
virtual bool isDistributed() const { return false; }
protected:
ID id;
/// Underlying dof manager
DOFManager & _dof_manager;
- UInt release_{0};
+ Int release_{0};
};
inline std::ostream & operator<<(std::ostream & stream, SolverVector & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#endif /* AKANTU_SOLVER_VECTOR_HH_ */
diff --git a/src/solver/solver_vector_petsc.cc b/src/solver/solver_vector_petsc.cc
index e9019ed7b..66e39e2b9 100644
--- a/src/solver/solver_vector_petsc.cc
+++ b/src/solver/solver_vector_petsc.cc
@@ -1,293 +1,299 @@
/**
* @file solver_vector_petsc.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 01 2019
* @date last modification: Fri Jul 24 2020
*
* @brief Solver vector interface for PETSc
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solver_vector_petsc.hh"
#include "dof_manager_petsc.hh"
#include "mpi_communicator_data.hh"
/* -------------------------------------------------------------------------- */
#include <numeric>
#include <petscvec.h>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
SolverVectorPETSc::SolverVectorPETSc(DOFManagerPETSc & dof_manager,
const ID & id)
: SolverVector(dof_manager, id), dof_manager(dof_manager) {
auto && mpi_comm = dof_manager.getMPIComm();
PETSc_call(VecCreate, mpi_comm, &x);
detail::PETScSetName(x, id);
PETSc_call(VecSetFromOptions, x);
auto local_system_size = dof_manager.getLocalSystemSize();
auto nb_local_dofs = dof_manager.getPureLocalSystemSize();
PETSc_call(VecSetSizes, x, nb_local_dofs, PETSC_DECIDE);
VecType vec_type;
PETSc_call(VecGetType, x, &vec_type);
if (std::string(vec_type) == std::string(VECMPI)) {
PetscInt lowest_gidx;
PetscInt highest_gidx;
PETSc_call(VecGetOwnershipRange, x, &lowest_gidx, &highest_gidx);
std::vector<PetscInt> ghost_idx;
for (auto && d : arange(local_system_size)) {
int gidx = dof_manager.localToGlobalEquationNumber(d);
if (gidx != -1) {
if ((gidx < lowest_gidx) or (gidx >= highest_gidx)) {
ghost_idx.push_back(gidx);
}
}
}
PETSc_call(VecMPISetGhost, x, ghost_idx.size(), ghost_idx.data());
} else {
std::vector<int> idx(nb_local_dofs);
std::iota(idx.begin(), idx.end(), 0);
ISLocalToGlobalMapping is;
PETSc_call(ISLocalToGlobalMappingCreate, PETSC_COMM_SELF, 1, idx.size(),
idx.data(), PETSC_COPY_VALUES, &is);
PETSc_call(VecSetLocalToGlobalMapping, x, is);
PETSc_call(ISLocalToGlobalMappingDestroy, &is);
}
}
/* -------------------------------------------------------------------------- */
SolverVectorPETSc::SolverVectorPETSc( // NOLINT(bugprone-copy-constructor-init)
const SolverVectorPETSc & vector, const ID & id)
: SolverVector(vector, id), dof_manager(vector.dof_manager) {
if (vector.x != nullptr) {
PETSc_call(VecDuplicate, vector.x, &x);
PETSc_call(VecCopy, vector.x, x);
detail::PETScSetName(x, id);
}
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "SolverVectorPETSc [" << std::endl;
stream << space << " + id: " << id << std::endl;
PETSc_call(PetscViewerPushFormat, PETSC_VIEWER_STDOUT_WORLD,
PETSC_VIEWER_ASCII_INDEX);
PETSc_call(VecView, x, PETSC_VIEWER_STDOUT_WORLD);
PETSc_call(PetscViewerPopFormat, PETSC_VIEWER_STDOUT_WORLD);
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
SolverVectorPETSc::SolverVectorPETSc(Vec x, DOFManagerPETSc & dof_manager,
const ID & id)
: SolverVector(dof_manager, id), dof_manager(dof_manager) {
PETSc_call(VecDuplicate, x, &this->x);
PETSc_call(VecCopy, x, this->x);
detail::PETScSetName(x, id);
}
/* -------------------------------------------------------------------------- */
SolverVectorPETSc::~SolverVectorPETSc() {
if (x != nullptr) {
PETSc_call(VecDestroy, &x);
}
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::resize() {
// the arrays are destroyed and recreated in the dof manager
// resize is so not implemented
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::set(Real val) {
PETSc_call(VecSet, x, val);
applyModifications();
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::applyModifications() {
PETSc_call(VecAssemblyBegin, x);
PETSc_call(VecAssemblyEnd, x);
updateGhost();
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::updateGhost() {
Vec x_ghosted{nullptr};
PETSc_call(VecGhostGetLocalForm, x, &x_ghosted);
if (x_ghosted != nullptr) {
PETSc_call(VecGhostUpdateBegin, x, INSERT_VALUES, SCATTER_FORWARD);
PETSc_call(VecGhostUpdateEnd, x, INSERT_VALUES, SCATTER_FORWARD);
}
PETSc_call(VecGhostRestoreLocalForm, x, &x_ghosted);
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::getValues(const Array<Int> & idx,
Array<Real> & values) const {
if (idx.empty()) {
return;
}
ISLocalToGlobalMapping is_ltog_map;
PETSc_call(VecGetLocalToGlobalMapping, x, &is_ltog_map);
PetscInt n;
Array<PetscInt> lidx(idx.size());
PETSc_call(ISGlobalToLocalMappingApply, is_ltog_map, IS_GTOLM_MASK,
- idx.size(), idx.storage(), &n, lidx.storage());
+ idx.size(), idx.data(), &n, lidx.data());
getValuesLocal(lidx, values);
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::getValuesLocal(const Array<Int> & idx,
Array<Real> & values) const {
if (idx.empty()) {
return;
}
Vec x_ghosted{nullptr};
PETSc_call(VecGhostGetLocalForm, x, &x_ghosted);
// VecScatterBegin(scatter, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
// VecScatterEnd(scatter, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
if (x_ghosted == nullptr) {
const PetscScalar * array;
PETSc_call(VecGetArrayRead, x, &array);
for (auto && data : zip(idx, make_view(values))) {
auto i = std::get<0>(data);
if (i != -1) {
std::get<1>(data) = array[i];
}
}
PETSc_call(VecRestoreArrayRead, x, &array);
return;
}
PETSc_call(VecSetOption, x_ghosted, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
- PETSc_call(VecGetValues, x_ghosted, idx.size(), idx.storage(),
- values.storage());
+ PETSc_call(VecGetValues, x_ghosted, idx.size(), idx.data(), values.data());
PETSc_call(VecGhostRestoreLocalForm, x, &x_ghosted);
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::addValues(const Array<Int> & gidx,
const Array<Real> & values,
Real scale_factor) {
- Real * to_add = values.storage();
+ Real * to_add = values.data();
Array<Real> scaled_array;
if (scale_factor != 1.) {
scaled_array.copy(values, false);
scaled_array *= scale_factor;
- to_add = scaled_array.storage();
+ to_add = scaled_array.data();
}
PETSc_call(VecSetOption, x, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
- PETSc_call(VecSetValues, x, gidx.size(), gidx.storage(), to_add, ADD_VALUES);
+ PETSc_call(VecSetValues, x, gidx.size(), gidx.data(), to_add, ADD_VALUES);
applyModifications();
}
/* -------------------------------------------------------------------------- */
void SolverVectorPETSc::addValuesLocal(const Array<Int> & lidx,
const Array<Real> & values,
Real scale_factor) {
Vec x_ghosted{nullptr};
PETSc_call(VecGhostGetLocalForm, x, &x_ghosted);
if (x_ghosted == nullptr) {
- Real * to_add = values.storage();
+ Real * to_add = values.data();
Array<Real> scaled_array;
if (scale_factor != 1.) {
scaled_array.copy(values, false);
scaled_array *= scale_factor;
- to_add = scaled_array.storage();
+ to_add = scaled_array.data();
}
PETSc_call(VecSetOption, x, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
- PETSc_call(VecSetValuesLocal, x, lidx.size(), lidx.storage(), to_add,
+ PETSc_call(VecSetValuesLocal, x, lidx.size(), lidx.data(), to_add,
ADD_VALUES);
return;
}
PETSc_call(VecGhostRestoreLocalForm, x, &x_ghosted);
ISLocalToGlobalMapping is_ltog_map;
PETSc_call(VecGetLocalToGlobalMapping, x, &is_ltog_map);
Array<Int> gidx(lidx.size());
- PETSc_call(ISLocalToGlobalMappingApply, is_ltog_map, lidx.size(),
- lidx.storage(), gidx.storage());
+ PETSc_call(ISLocalToGlobalMappingApply, is_ltog_map, lidx.size(), lidx.data(),
+ gidx.data());
addValues(gidx, values, scale_factor);
}
/* -------------------------------------------------------------------------- */
SolverVectorPETSc::operator const Array<Real> &() const {
const_cast<Array<Real> &>(cache).resize(local_size());
auto xl = internal::make_petsc_local_vector(x);
auto cachep = internal::make_petsc_wraped_vector(this->cache);
PETSc_call(VecCopy, cachep, xl);
return cache;
}
/* -------------------------------------------------------------------------- */
SolverVectorPETSc & SolverVectorPETSc::operator=(const SolverVectorPETSc & y) {
if (size() != y.size()) {
PETSc_call(VecDuplicate, y, &x);
}
PETSc_call(VecCopy, y.x, x);
release_ = y.release_;
return *this;
}
/* -------------------------------------------------------------------------- */
SolverVector & SolverVectorPETSc::operator=(const SolverVector & y) {
const auto & y_ = aka::as_type<SolverVectorPETSc>(y);
return operator=(y_);
}
/* -------------------------------------------------------------------------- */
SolverVector & SolverVectorPETSc::operator+(const SolverVector & y) {
const auto & y_ = aka::as_type<SolverVectorPETSc>(y);
PETSc_call(VecAXPY, x, 1., y_.x);
release_ = y_.release_;
return *this;
}
+bool SolverVectorPETSc::isFinite() const {
+ Real max, min;
+ PETSc_call(VecMax, x, PETSC_NULL, &max);
+ PETSc_call(VecMin, x, PETSC_NULL, &min);
+ return std::isfinite(min) and std::isfinite(max);
+}
+
} // namespace akantu
diff --git a/src/solver/solver_vector_petsc.hh b/src/solver/solver_vector_petsc.hh
index 570220445..872114648 100644
--- a/src/solver/solver_vector_petsc.hh
+++ b/src/solver/solver_vector_petsc.hh
@@ -1,215 +1,211 @@
/**
* @file solver_vector_petsc.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 01 2019
* @date last modification: Fri Jul 24 2020
*
* @brief Solver vector interface for PETSc
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager_petsc.hh"
#include "solver_vector.hh"
/* -------------------------------------------------------------------------- */
#include <petscvec.h>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLVER_VECTOR_PETSC_HH_
#define AKANTU_SOLVER_VECTOR_PETSC_HH_
namespace akantu {
class DOFManagerPETSc;
} // namespace akantu
namespace akantu {
/* -------------------------------------------------------------------------- */
namespace internal {
/* ------------------------------------------------------------------------ */
class PETScVector {
public:
virtual ~PETScVector() = default;
operator Vec &() { return x; }
operator const Vec &() const { return x; }
Int size() const {
PetscInt n;
PETSc_call(VecGetSize, x, &n);
return n;
}
Int local_size() const {
PetscInt n;
PETSc_call(VecGetLocalSize, x, &n);
return n;
}
AKANTU_GET_MACRO_NOT_CONST(Vec, x, auto &);
AKANTU_GET_MACRO(Vec, x, const auto &);
protected:
Vec x{nullptr};
};
} // namespace internal
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class SolverVectorPETSc : public SolverVector, public internal::PETScVector {
public:
SolverVectorPETSc(DOFManagerPETSc & dof_manager,
const ID & id = "solver_vector_petsc");
SolverVectorPETSc(const SolverVectorPETSc & vector,
const ID & id = "solver_vector_petsc");
SolverVectorPETSc(Vec x, DOFManagerPETSc & dof_manager,
const ID & id = "solver_vector_petsc");
~SolverVectorPETSc() override;
// resize the vector to the size of the problem
void resize() override;
void set(Real val) override;
operator const Array<Real> &() const override;
SolverVector & operator+(const SolverVector & y) override;
SolverVector & operator=(const SolverVector & y) override;
SolverVectorPETSc & operator=(const SolverVectorPETSc & y);
/// get values using processors global indexes
void getValues(const Array<Int> & idx, Array<Real> & values) const;
/// get values using processors local indexes
void getValuesLocal(const Array<Int> & idx, Array<Real> & values) const;
/// adding values to the vector using the global indices
void addValues(const Array<Int> & gidx, const Array<Real> & values,
Real scale_factor = 1.);
/// adding values to the vector using the local indices
void addValuesLocal(const Array<Int> & lidx, const Array<Real> & values,
Real scale_factor = 1.);
Int size() const override { return internal::PETScVector::size(); }
Int localSize() const override { return internal::PETScVector::local_size(); }
void printself(std::ostream & stream, int indent = 0) const override;
- virtual
- bool
- isDistributed()
- const
- override
- { return true; }
+ bool isDistributed() const override { return true; }
+ bool isFinite() const override;
protected:
void applyModifications();
void updateGhost();
protected:
DOFManagerPETSc & dof_manager;
// used for the conversion operator
Array<Real> cache;
};
/* -------------------------------------------------------------------------- */
namespace internal {
/* ------------------------------------------------------------------------ */
template <class Array> class PETScWrapedVector : public PETScVector {
public:
PETScWrapedVector(Array && array) : array(array) {
PETSc_call(VecCreateSeqWithArray, PETSC_COMM_SELF, 1, array.size(),
- array.storage(), &x);
+ array.data(), &x);
}
~PETScWrapedVector() override { PETSc_call(VecDestroy, &x); }
private:
Array array;
};
/* ------------------------------------------------------------------------ */
template <bool read_only> class PETScLocalVector : public PETScVector {
public:
PETScLocalVector(const Vec & g) : g(g) {
PETSc_call(VecGetLocalVectorRead, g, x);
}
PETScLocalVector(const SolverVectorPETSc & g)
: PETScLocalVector(g.getVec()) {}
~PETScLocalVector() override {
PETSc_call(VecRestoreLocalVectorRead, g, x);
PETSc_call(VecDestroy, &x);
}
private:
const Vec & g;
};
template <> class PETScLocalVector<false> : public PETScVector {
public:
PETScLocalVector(Vec & g) : g(g) {
PETSc_call(VecGetLocalVectorRead, g, x);
}
PETScLocalVector(SolverVectorPETSc & g) : PETScLocalVector(g.getVec()) {}
~PETScLocalVector() override {
PETSc_call(VecRestoreLocalVectorRead, g, x);
PETSc_call(VecDestroy, &x);
}
private:
Vec & g;
};
/* ------------------------------------------------------------------------ */
template <class Array>
decltype(auto) make_petsc_wraped_vector(Array && array) {
return PETScWrapedVector<Array>(std::forward<Array>(array));
}
template <
typename V,
std::enable_if_t<std::is_same<Vec, std::decay_t<V>>::value> * = nullptr>
decltype(auto) make_petsc_local_vector(V && vec) {
constexpr auto read_only = std::is_const<std::remove_reference_t<V>>::value;
return PETScLocalVector<read_only>(vec);
}
template <typename V, std::enable_if_t<std::is_base_of<
SolverVector, std::decay_t<V>>::value> * = nullptr>
decltype(auto) make_petsc_local_vector(V && vec) {
constexpr auto read_only = std::is_const<std::remove_reference_t<V>>::value;
return PETScLocalVector<read_only>(
dynamic_cast<std::conditional_t<read_only, const SolverVectorPETSc,
SolverVectorPETSc> &>(vec));
}
} // namespace internal
} // namespace akantu
#endif /* AKANTU_SOLVER_VECTOR_PETSC_HH_ */
diff --git a/src/solver/sparse_matrix.hh b/src/solver/sparse_matrix.hh
index 1be77de04..f9b304336 100644
--- a/src/solver/sparse_matrix.hh
+++ b/src/solver/sparse_matrix.hh
@@ -1,171 +1,170 @@
/**
* @file sparse_matrix.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Wed Sep 16 2020
*
* @brief sparse matrix storage class (distributed assembled matrix)
* This is a COO format (Coordinate List)
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SPARSE_MATRIX_HH_
#define AKANTU_SPARSE_MATRIX_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
class DOFManager;
class TermsToAssemble;
class SolverVector;
} // namespace akantu
namespace akantu {
class SparseMatrix {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SparseMatrix(DOFManager & dof_manager, const MatrixType & matrix_type,
const ID & id = "sparse_matrix");
SparseMatrix(const SparseMatrix & matrix, const ID & id = "sparse_matrix");
virtual ~SparseMatrix();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// remove the existing profile
virtual void clearProfile();
/// set the matrix to 0
virtual void set(Real val) = 0;
virtual void zero() { this->set(0); }
/// add a non-zero element to the profile
- virtual UInt add(UInt i, UInt j) = 0;
+ virtual Idx add(Idx i, Idx j) = 0;
/// assemble a local matrix in the sparse one
- virtual void add(UInt i, UInt j, Real value) = 0;
+ virtual void add(Idx i, Idx j, Real value) = 0;
/// save the profil in a file using the MatrixMarket file format
virtual void saveProfile(const std::string & /* filename */) const {
AKANTU_TO_IMPLEMENT();
}
/// save the matrix in a file using the MatrixMarket file format
virtual void saveMatrix(const std::string & /* filename */) const {
AKANTU_TO_IMPLEMENT();
};
/// multiply the matrix by a coefficient
virtual void mul(Real alpha) = 0;
/// add matrices
virtual void add(const SparseMatrix & B, Real alpha = 1.);
/// Equivalent of *gemv in blas
virtual void matVecMul(const SolverVector & x, SolverVector & y,
Real alpha = 1., Real beta = 0.) const = 0;
/// modify the matrix to "remove" the blocked dof
virtual void applyBoundary(Real block_val = 1.) = 0;
/// copy the profile of another matrix
virtual void copyProfile(const SparseMatrix & other) = 0;
/// operator *=
SparseMatrix & operator*=(Real alpha) {
this->mul(alpha);
return *this;
}
/// Check if all entries are finite. The default implementation throws.
virtual bool isFinite() const { AKANTU_TO_IMPLEMENT(); }
protected:
/// This is the revert of add \f[B += \alpha * *this\f];
virtual void addMeTo(SparseMatrix & B, Real alpha) const = 0;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// return the values at potition i, j
- virtual inline Real operator()(UInt /*i*/, UInt /*j*/) const {
+ virtual inline Real operator()(Idx /*i*/, Idx /*j*/) const {
AKANTU_TO_IMPLEMENT();
}
/// return the values at potition i, j
- virtual inline Real & operator()(UInt /*i*/, UInt /*j*/) {
+ virtual inline Real & operator()(Idx /*i*/, Idx /*j*/) {
AKANTU_TO_IMPLEMENT();
}
- /// return the minimum value
- virtual inline Real min() { AKANTU_TO_IMPLEMENT(); }
+ AKANTU_GET_MACRO_AUTO(NbNonZero, nb_non_zero);
+ Int size() const { return size_; }
+ AKANTU_GET_MACRO_AUTO(MatrixType, matrix_type);
- AKANTU_GET_MACRO(NbNonZero, nb_non_zero, UInt);
- UInt size() const { return size_; }
- AKANTU_GET_MACRO(MatrixType, matrix_type, const MatrixType &);
+ virtual Int getRelease() const = 0;
- virtual UInt getRelease() const = 0;
+ virtual Real min() = 0;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ID id;
/// Underlying dof manager
DOFManager & _dof_manager;
/// sparce matrix type
MatrixType matrix_type;
/// Size of the matrix
- UInt size_;
+ Int size_;
/// number of processors
- UInt nb_proc;
+ Int nb_proc;
/// number of non zero element
- UInt nb_non_zero;
+ Int nb_non_zero;
};
// Array<Real> & operator*=(Array<Real> & vect, const SparseMatrix & mat);
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "sparse_matrix_inline_impl.hh"
#endif /* AKANTU_SPARSE_MATRIX_HH_ */
diff --git a/src/solver/sparse_matrix_aij.cc b/src/solver/sparse_matrix_aij.cc
index 1ada8ec87..9e9036286 100644
--- a/src/solver/sparse_matrix_aij.cc
+++ b/src/solver/sparse_matrix_aij.cc
@@ -1,310 +1,307 @@
/**
* @file sparse_matrix_aij.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Aug 21 2015
* @date last modification: Fri Jul 24 2020
*
* @brief Implementation of the AIJ sparse matrix
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "sparse_matrix_aij.hh"
#include "aka_iterators.hh"
#include "aka_math.hh"
#include "dof_manager_default.hh"
#include "dof_synchronizer.hh"
#include "solver_vector_default.hh"
#include "terms_to_assemble.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
SparseMatrixAIJ::SparseMatrixAIJ(DOFManagerDefault & dof_manager,
const MatrixType & matrix_type, const ID & id)
: SparseMatrix(dof_manager, matrix_type, id), dof_manager(dof_manager),
irn(0, 1, id + ":irn"), jcn(0, 1, id + ":jcn"), a(0, 1, id + ":a") {}
/* -------------------------------------------------------------------------- */
SparseMatrixAIJ::SparseMatrixAIJ(const SparseMatrixAIJ & matrix, const ID & id)
: SparseMatrix(matrix, id), dof_manager(matrix.dof_manager),
irn(matrix.irn, id + ":irn"), jcn(matrix.jcn, id + ":jcn"),
a(matrix.a, id + ":a") {}
/* -------------------------------------------------------------------------- */
SparseMatrixAIJ::~SparseMatrixAIJ() = default;
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::applyBoundary(Real block_val) {
AKANTU_DEBUG_IN();
const auto & blocked_dofs = this->dof_manager.getGlobalBlockedDOFs();
auto begin = blocked_dofs.begin();
auto end = blocked_dofs.end();
auto is_blocked = [&](auto && i) -> bool {
auto il = this->dof_manager.globalToLocalEquationNumber(i);
return std::binary_search(begin, end, il);
};
for (auto && ij_a : zip(irn, jcn, a)) {
- UInt ni = std::get<0>(ij_a) - 1;
- UInt nj = std::get<1>(ij_a) - 1;
+ auto ni = std::get<0>(ij_a) - 1;
+ auto nj = std::get<1>(ij_a) - 1;
if (is_blocked(ni) or is_blocked(nj)) {
std::get<2>(ij_a) =
std::get<0>(ij_a) != std::get<1>(ij_a) ? 0.
: this->dof_manager.isLocalOrMasterDOF(
this->dof_manager.globalToLocalEquationNumber(ni))
? block_val
: 0.;
}
}
this->value_release++;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::saveProfile(const std::string & filename) const {
AKANTU_DEBUG_IN();
std::ofstream outfile;
outfile.open(filename.c_str());
- UInt m = this->size_;
+ auto m = this->size_;
auto & comm = dof_manager.getCommunicator();
// write header
if (comm.whoAmI() == 0) {
outfile << "%%MatrixMarket matrix coordinate pattern";
if (this->matrix_type == _symmetric) {
outfile << " symmetric";
} else {
outfile << " general";
}
outfile << std::endl;
outfile << m << " " << m << " " << this->nb_non_zero << std::endl;
}
for (auto p : arange(comm.getNbProc())) {
// write content
if (comm.whoAmI() == p) {
- for (UInt i = 0; i < this->nb_non_zero; ++i) {
- outfile << this->irn.storage()[i] << " " << this->jcn.storage()[i]
- << " 1" << std::endl;
+ for (auto && data : zip(this->irn, this->jcn)) {
+ outfile << std::get<0>(data) << " " << std::get<1>(data) << " 1"
+ << std::endl;
}
}
comm.barrier();
}
outfile.close();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::saveMatrix(const std::string & filename) const {
AKANTU_DEBUG_IN();
auto & comm = dof_manager.getCommunicator();
// open and set the properties of the stream
std::ofstream outfile;
if (0 == comm.whoAmI()) {
outfile.open(filename.c_str());
} else {
outfile.open(filename.c_str(), std::ios_base::app);
}
outfile.precision(std::numeric_limits<Real>::digits10);
// write header
decltype(nb_non_zero) nnz = this->nb_non_zero;
comm.allReduce(nnz);
if (comm.whoAmI() == 0) {
outfile << "%%MatrixMarket matrix coordinate real";
if (this->matrix_type == _symmetric) {
outfile << " symmetric";
} else {
outfile << " general";
}
outfile << std::endl;
outfile << this->size_ << " " << this->size_ << " " << nnz << std::endl;
}
for (auto p : arange(comm.getNbProc())) {
// write content
if (comm.whoAmI() == p) {
- for (UInt i = 0; i < this->nb_non_zero; ++i) {
- outfile << this->irn(i) << " " << this->jcn(i) << " " << this->a(i)
- << std::endl;
+ for (auto && data : zip(this->irn, this->jcn, this->a)) {
+ outfile << std::get<0>(data) << " " << std::get<1>(data) << " "
+ << std::get<2>(data) << std::endl;
}
}
comm.barrier();
}
// time to end
outfile.close();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::matVecMul(const Array<Real> & x, Array<Real> & y,
Real alpha, Real beta) const {
AKANTU_DEBUG_IN();
Array<Real> tmp(y);
tmp.zero();
y *= beta;
+ auto x_it = make_view(x).begin();
+ auto y_it = make_view(y).begin();
- auto i_it = this->irn.begin();
- auto j_it = this->jcn.begin();
- auto a_it = this->a.begin();
- auto a_end = this->a.end();
- auto x_it = x.begin_reinterpret(x.size() * x.getNbComponent());
- auto y_it = tmp.begin_reinterpret(x.size() * x.getNbComponent());
-
- for (; a_it != a_end; ++i_it, ++j_it, ++a_it) {
- Int i = this->dof_manager.globalToLocalEquationNumber(*i_it - 1);
- Int j = this->dof_manager.globalToLocalEquationNumber(*j_it - 1);
- const Real & A = *a_it;
+ for (auto && data : zip(this->irn, this->jcn, this->a)) {
+ auto i =
+ this->dof_manager.globalToLocalEquationNumber(std::get<0>(data) - 1);
+ auto j =
+ this->dof_manager.globalToLocalEquationNumber(std::get<1>(data) - 1);
+ const auto & A = std::get<2>(data);
y_it[i] += alpha * A * x_it[j];
if ((this->matrix_type == _symmetric) && (i != j)) {
y_it[j] += alpha * A * x_it[i];
}
}
if (this->dof_manager.hasSynchronizer()) {
this->dof_manager.getSynchronizer().reduceSynchronizeArray<AddOperation>(
tmp);
}
y += tmp;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::matVecMul(const SolverVector & _x, SolverVector & _y,
Real alpha, Real beta) const {
AKANTU_DEBUG_IN();
auto && x = aka::as_type<SolverVectorArray>(_x).getVector();
auto && y = aka::as_type<SolverVectorArray>(_y).getVector();
this->matVecMul(x, y, alpha, beta);
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::copyContent(const SparseMatrix & matrix) {
AKANTU_DEBUG_IN();
const auto & mat = aka::as_type<SparseMatrixAIJ>(matrix);
AKANTU_DEBUG_ASSERT(nb_non_zero == mat.getNbNonZero(),
"The to matrix don't have the same profiles");
- memcpy(a.storage(), mat.getA().storage(), nb_non_zero * sizeof(Real));
+ memcpy(a.data(), mat.getA().data(), nb_non_zero * sizeof(Real));
this->value_release++;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::copyProfile(const SparseMatrix & other) {
const auto & A = aka::as_type<SparseMatrixAIJ>(other);
SparseMatrix::clearProfile();
this->irn.copy(A.irn);
this->jcn.copy(A.jcn);
this->irn_jcn_k.clear();
- UInt i;
- UInt j;
- UInt k;
+ Idx i;
+ Idx j;
+ Idx k;
for (auto && data : enumerate(irn, jcn)) {
std::tie(k, i, j) = data;
this->irn_jcn_k[this->key(i - 1, j - 1)] = k;
}
this->nb_non_zero = this->irn.size();
this->a.resize(this->nb_non_zero);
this->a.set(0.);
this->size_ = A.size_;
this->profile_release = A.profile_release;
this->value_release++;
}
/* -------------------------------------------------------------------------- */
template <class MatrixType>
void SparseMatrixAIJ::addMeToTemplated(MatrixType & B, Real alpha) const {
- UInt i;
- UInt j;
+ Idx i;
+ Idx j;
Real A_ij;
for (auto && tuple : zip(irn, jcn, a)) {
std::tie(i, j, A_ij) = tuple;
B.add(i - 1, j - 1, alpha * A_ij);
}
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::addMeTo(SparseMatrix & B, Real alpha) const {
if (aka::is_of_type<SparseMatrixAIJ>(B)) {
this->addMeToTemplated<SparseMatrixAIJ>(aka::as_type<SparseMatrixAIJ>(B),
alpha);
} else {
// this->addMeToTemplated<SparseMatrix>(*this, alpha);
}
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::mul(Real alpha) {
this->a *= alpha;
this->value_release++;
}
/* -------------------------------------------------------------------------- */
void SparseMatrixAIJ::set(Real val) {
a.set(val);
this->value_release++;
}
/* -------------------------------------------------------------------------- */
-bool SparseMatrixAIJ::isFinite() const { return this->a.isFinite(); };
+bool SparseMatrixAIJ::isFinite() const { return this->a.isFinite(); }
} // namespace akantu
diff --git a/src/solver/sparse_matrix_aij.hh b/src/solver/sparse_matrix_aij.hh
index 771d48e8e..b0aa4e939 100644
--- a/src/solver/sparse_matrix_aij.hh
+++ b/src/solver/sparse_matrix_aij.hh
@@ -1,206 +1,204 @@
/**
* @file sparse_matrix_aij.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Wed Sep 16 2020
*
* @brief AIJ implementation of the SparseMatrix (this the format used by
* Mumps)
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
#include <unordered_map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SPARSE_MATRIX_AIJ_HH_
#define AKANTU_SPARSE_MATRIX_AIJ_HH_
namespace akantu {
class DOFManagerDefault;
class TermsToAssemble;
} // namespace akantu
namespace akantu {
class SparseMatrixAIJ : public SparseMatrix {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SparseMatrixAIJ(DOFManagerDefault & dof_manager,
const MatrixType & matrix_type,
const ID & id = "sparse_matrix_aij");
SparseMatrixAIJ(const SparseMatrixAIJ & matrix,
const ID & id = "sparse_matrix_aij");
~SparseMatrixAIJ() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// remove the existing profile
inline void clearProfile() override;
/// add a non-zero element
- inline UInt add(UInt i, UInt j) override;
+ inline Idx add(Idx i, Idx j) override;
/// set the matrix to 0
void set(Real val) override;
/// assemble a local matrix in the sparse one
- inline void add(UInt i, UInt j, Real value) override;
+ inline void add(Idx i, Idx j, Real value) override;
/// add a block of values
inline void addValues(const Vector<Int> & is, const Vector<Int> & js,
const Matrix<Real> & values, MatrixType values_type);
/// set the size of the matrix
- void resize(UInt size) { this->size_ = size; }
+ void resize(Int size) { this->size_ = size; }
/// modify the matrix to "remove" the blocked dof
void applyBoundary(Real block_val = 1.) override;
/// save the profil in a file using the MatrixMarket file format
void saveProfile(const std::string & filename) const override;
/// save the matrix in a file using the MatrixMarket file format
void saveMatrix(const std::string & filename) const override;
/// copy assuming the profile are the same
virtual void copyContent(const SparseMatrix & matrix);
/// multiply the matrix by a scalar
void mul(Real alpha) override;
/// Equivalent of *gemv in blas
void matVecMul(const SolverVector & x, SolverVector & y, Real alpha = 1.,
Real beta = 0.) const override;
void matVecMul(const Array<Real> & x, Array<Real> & y, Real alpha = 1.,
Real beta = 0.) const;
/// copy the profile of another matrix
void copyProfile(const SparseMatrix & other) override;
/// Check if all entries are finite
virtual bool isFinite() const override;
/* ------------------------------------------------------------------------ */
/// accessor to A_{ij} - if (i, j) not present it returns 0
- inline Real operator()(UInt i, UInt j) const override;
+ inline Real operator()(Idx i, Idx j) const override;
/// accessor to A_{ij} - if (i, j) not present it fails, (i, j) should be
/// first added to the profile
- inline Real & operator()(UInt i, UInt j) override;
+ inline Real & operator()(Idx i, Idx j) override;
/// accessor to get the minimum value of A_{ij}
inline Real min() override;
protected:
void addMeTo(SparseMatrix & B, Real alpha) const override;
- inline void addSymmetricValuesToSymmetric(const Vector<Int> & is,
- const Vector<Int> & js,
+ inline void addSymmetricValuesToSymmetric(const Vector<Idx> & is,
+ const Vector<Idx> & js,
const Matrix<Real> & values);
- inline void addUnsymmetricValuesToSymmetric(const Vector<Int> & is,
- const Vector<Int> & js,
+ inline void addUnsymmetricValuesToSymmetric(const Vector<Idx> & is,
+ const Vector<Idx> & js,
const Matrix<Real> & values);
- inline void addValuesToUnsymmetric(const Vector<Int> & is,
- const Vector<Int> & js,
+ inline void addValuesToUnsymmetric(const Vector<Idx> & is,
+ const Vector<Idx> & js,
const Matrix<Real> & values);
private:
/// This is just to inline the addToMatrix function
template <class MatrixType>
void addMeToTemplated(MatrixType & B, Real alpha) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(IRN, irn, const Array<Int> &);
-
- AKANTU_GET_MACRO(JCN, jcn, const Array<Int> &);
-
- AKANTU_GET_MACRO(A, a, const Array<Real> &);
+ AKANTU_GET_MACRO_AUTO(IRN, irn);
+ AKANTU_GET_MACRO_AUTO(JCN, jcn);
+ AKANTU_GET_MACRO_AUTO(A, a);
/// The release changes at each call of a function that changes the profile,
/// it in increasing but could overflow so it should be checked as
/// (my_release != release) and not as (my_release < release)
- AKANTU_GET_MACRO(ProfileRelease, profile_release, UInt);
- AKANTU_GET_MACRO(ValueRelease, value_release, UInt);
- UInt getRelease() const override { return value_release; }
+ AKANTU_GET_MACRO_AUTO(ProfileRelease, profile_release);
+ AKANTU_GET_MACRO_AUTO(ValueRelease, value_release);
+ Int getRelease() const override { return value_release; }
protected:
- using KeyCOO = std::pair<UInt, UInt>;
- using coordinate_list_map = std::unordered_map<KeyCOO, UInt>;
+ using KeyCOO = std::pair<Idx, Idx>;
+ using coordinate_list_map = std::unordered_map<KeyCOO, Idx>;
/// get the pair corresponding to (i, j)
- inline KeyCOO key(UInt i, UInt j) const {
+ inline KeyCOO key(Idx i, Idx j) const {
if (this->matrix_type == _symmetric && (i > j)) {
return std::make_pair(j, i);
}
return std::make_pair(i, j);
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
DOFManagerDefault & dof_manager;
/// row indexes
Array<Int> irn;
/// column indexes
Array<Int> jcn;
/// values : A[k] = Matrix[irn[k]][jcn[k]]
Array<Real> a;
/// Profile release
- UInt profile_release{1};
+ Int profile_release{1};
/// Value release
- UInt value_release{1};
+ Int value_release{1};
/// map for (i, j) -> k correspondence
coordinate_list_map irn_jcn_k;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "sparse_matrix_aij_inline_impl.hh"
#endif /* AKANTU_SPARSE_MATRIX_AIJ_HH_ */
diff --git a/src/solver/sparse_matrix_aij_inline_impl.hh b/src/solver/sparse_matrix_aij_inline_impl.hh
index 95a3e7a81..e031c4132 100644
--- a/src/solver/sparse_matrix_aij_inline_impl.hh
+++ b/src/solver/sparse_matrix_aij_inline_impl.hh
@@ -1,201 +1,201 @@
/**
* @file sparse_matrix_aij_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Aug 21 2015
* @date last modification: Tue Mar 31 2020
*
* @brief Implementation of inline functions of SparseMatrixAIJ
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "sparse_matrix_aij.hh"
+//#include "sparse_matrix_aij.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SPARSE_MATRIX_AIJ_INLINE_IMPL_HH_
#define AKANTU_SPARSE_MATRIX_AIJ_INLINE_IMPL_HH_
namespace akantu {
-inline UInt SparseMatrixAIJ::add(UInt i, UInt j) {
+inline Idx SparseMatrixAIJ::add(Idx i, Idx j) {
KeyCOO jcn_irn = this->key(i, j);
auto it = this->irn_jcn_k.find(jcn_irn);
if (!(it == this->irn_jcn_k.end())) {
return it->second;
}
if (i + 1 > this->size_) {
this->size_ = i + 1;
}
if (j + 1 > this->size_) {
this->size_ = j + 1;
}
this->irn.push_back(i + 1);
this->jcn.push_back(j + 1);
this->a.push_back(0.);
this->irn_jcn_k[jcn_irn] = this->nb_non_zero;
(this->nb_non_zero)++;
this->profile_release++;
this->value_release++;
return (this->nb_non_zero - 1);
}
/* -------------------------------------------------------------------------- */
inline void SparseMatrixAIJ::clearProfile() {
SparseMatrix::clearProfile();
this->irn_jcn_k.clear();
this->irn.clear();
this->jcn.clear();
this->a.clear();
this->size_ = 0;
this->nb_non_zero = 0;
this->profile_release++;
this->value_release++;
}
/* -------------------------------------------------------------------------- */
-inline void SparseMatrixAIJ::add(UInt i, UInt j, Real value) {
- UInt idx = this->add(i, j);
+inline void SparseMatrixAIJ::add(Idx i, Idx j, Real value) {
+ Idx idx = this->add(i, j);
this->a(idx) += value;
this->value_release++;
}
/* -------------------------------------------------------------------------- */
-inline Real SparseMatrixAIJ::operator()(UInt i, UInt j) const {
+inline Real SparseMatrixAIJ::operator()(Idx i, Idx j) const {
KeyCOO jcn_irn = this->key(i, j);
auto irn_jcn_k_it = this->irn_jcn_k.find(jcn_irn);
if (irn_jcn_k_it == this->irn_jcn_k.end()) {
return 0.;
}
return this->a(irn_jcn_k_it->second);
}
/* -------------------------------------------------------------------------- */
-inline Real & SparseMatrixAIJ::operator()(UInt i, UInt j) {
+inline Real & SparseMatrixAIJ::operator()(Idx i, Idx j) {
KeyCOO jcn_irn = this->key(i, j);
auto irn_jcn_k_it = this->irn_jcn_k.find(jcn_irn);
AKANTU_DEBUG_ASSERT(irn_jcn_k_it != this->irn_jcn_k.end(),
"Couple (i,j) = (" << i << "," << j
<< ") does not exist in the profile");
// it may change the profile so it is considered as a change
this->value_release++;
return this->a(irn_jcn_k_it->second);
}
/* -------------------------------------------------------------------------- */
inline void
-SparseMatrixAIJ::addSymmetricValuesToSymmetric(const Vector<Int> & is,
- const Vector<Int> & js,
+SparseMatrixAIJ::addSymmetricValuesToSymmetric(const Vector<Idx> & is,
+ const Vector<Idx> & js,
const Matrix<Real> & values) {
- for (UInt i = 0; i < values.rows(); ++i) {
- UInt c_irn = is(i);
+ for (decltype(values.rows()) i = 0; i < values.rows(); ++i) {
+ auto c_irn = is(i);
if (c_irn < size_) {
- for (UInt j = i; j < values.cols(); ++j) {
- UInt c_jcn = js(j);
+ for (decltype(values.cols()) j = i; j < values.cols(); ++j) {
+ auto c_jcn = js(j);
if (c_jcn < size_) {
operator()(c_irn, c_jcn) += values(i, j);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
inline void
-SparseMatrixAIJ::addUnsymmetricValuesToSymmetric(const Vector<Int> & is,
- const Vector<Int> & js,
+SparseMatrixAIJ::addUnsymmetricValuesToSymmetric(const Vector<Idx> & is,
+ const Vector<Idx> & js,
const Matrix<Real> & values) {
- for (UInt i = 0; i < values.rows(); ++i) {
- UInt c_irn = is(i);
+ for (decltype(values.rows()) i = 0; i < values.rows(); ++i) {
+ auto c_irn = is(i);
if (c_irn < size_) {
- for (UInt j = 0; j < values.cols(); ++j) {
- UInt c_jcn = js(j);
+ for (decltype(values.cols()) j = 0; j < values.cols(); ++j) {
+ auto c_jcn = js(j);
if (c_jcn < size_) {
if (c_jcn >= c_irn) {
operator()(c_irn, c_jcn) += values(i, j);
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
inline void
-SparseMatrixAIJ::addValuesToUnsymmetric(const Vector<Int> & is,
- const Vector<Int> & js,
+SparseMatrixAIJ::addValuesToUnsymmetric(const Vector<Idx> & is,
+ const Vector<Idx> & js,
const Matrix<Real> & values) {
- for (UInt i = 0; i < values.rows(); ++i) {
- UInt c_irn = is(i);
+ for (decltype(values.rows()) i = 0; i < values.rows(); ++i) {
+ auto c_irn = is(i);
if (c_irn < size_) {
- for (UInt j = 0; j < values.cols(); ++j) {
- UInt c_jcn = js(j);
+ for (decltype(values.cols()) j = 0; j < values.cols(); ++j) {
+ auto c_jcn = js(j);
if (c_jcn < size_) {
operator()(c_irn, c_jcn) += values(i, j);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
-inline void SparseMatrixAIJ::addValues(const Vector<Int> & is,
- const Vector<Int> & js,
+inline void SparseMatrixAIJ::addValues(const Vector<Idx> & is,
+ const Vector<Idx> & js,
const Matrix<Real> & values,
MatrixType values_type) {
if (getMatrixType() == _symmetric) {
if (values_type == _symmetric) {
this->addSymmetricValuesToSymmetric(is, js, values);
} else {
this->addUnsymmetricValuesToSymmetric(is, js, values);
}
} else {
this->addValuesToUnsymmetric(is, js, values);
}
}
/* -------------------------------------------------------------------------- */
inline Real SparseMatrixAIJ::min() {
- return *std::min(this->a.begin(), this->a.end());
+ return *std::min_element(this->a.cbegin(), this->a.cend());
}
} // namespace akantu
#endif /* AKANTU_SPARSE_MATRIX_AIJ_INLINE_IMPL_HH_ */
diff --git a/src/solver/sparse_matrix_petsc.cc b/src/solver/sparse_matrix_petsc.cc
index a6ccc79cc..489b5a315 100644
--- a/src/solver/sparse_matrix_petsc.cc
+++ b/src/solver/sparse_matrix_petsc.cc
@@ -1,290 +1,290 @@
/**
* @file sparse_matrix_petsc.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Implementation of PETSc matrix class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "sparse_matrix_petsc.hh"
#include "dof_manager_petsc.hh"
#include "mpi_communicator_data.hh"
#include "solver_vector_petsc.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
SparseMatrixPETSc::SparseMatrixPETSc(DOFManagerPETSc & dof_manager,
const MatrixType & matrix_type,
const ID & id)
: SparseMatrix(dof_manager, matrix_type, id), dof_manager(dof_manager) {
AKANTU_DEBUG_IN();
auto && mpi_comm = dof_manager.getMPIComm();
PETSc_call(MatCreate, mpi_comm, &mat);
detail::PETScSetName(mat, id);
resize();
PETSc_call(MatSetFromOptions, mat);
PETSc_call(MatSetUp, mat);
PETSc_call(MatSetOption, mat, MAT_ROW_ORIENTED, PETSC_TRUE);
PETSc_call(MatSetOption, mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_TRUE);
if (matrix_type == _symmetric) {
PETSc_call(MatSetOption, mat, MAT_SYMMETRIC, PETSC_TRUE);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
SparseMatrixPETSc::SparseMatrixPETSc(const SparseMatrixPETSc & matrix,
const ID & id)
: SparseMatrix(matrix, id), dof_manager(matrix.dof_manager) {
PETSc_call(MatDuplicate, matrix.mat, MAT_COPY_VALUES, &mat);
detail::PETScSetName(mat, id);
}
/* -------------------------------------------------------------------------- */
SparseMatrixPETSc::~SparseMatrixPETSc() {
AKANTU_DEBUG_IN();
if (mat != nullptr) {
PETSc_call(MatDestroy, &mat);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::resize() {
auto local_size = dof_manager.getPureLocalSystemSize();
PETSc_call(MatSetSizes, mat, local_size, local_size, size_, size_);
auto & is_ltog_mapping = dof_manager.getISLocalToGlobalMapping();
PETSc_call(MatSetLocalToGlobalMapping, mat, is_ltog_mapping, is_ltog_mapping);
}
/* -------------------------------------------------------------------------- */
/**
* Method to save the nonzero pattern and the values stored at each position
* @param filename name of the file in which the information will be stored
*/
void SparseMatrixPETSc::saveMatrix(const std::string & filename) const {
AKANTU_DEBUG_IN();
auto && mpi_comm = dof_manager.getMPIComm();
/// create Petsc viewer
PetscViewer viewer;
PETSc_call(PetscViewerASCIIOpen, mpi_comm, filename.c_str(), &viewer);
PETSc_call(PetscViewerPushFormat, viewer, PETSC_VIEWER_ASCII_MATRIXMARKET);
PETSc_call(MatView, mat, viewer);
PETSc_call(PetscViewerPopFormat, viewer);
PETSc_call(PetscViewerDestroy, &viewer);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/// Equivalent of *gemv in blas
void SparseMatrixPETSc::matVecMul(const SolverVector & _x, SolverVector & _y,
Real alpha, Real beta) const {
const auto & x = aka::as_type<SolverVectorPETSc>(_x);
auto & y = aka::as_type<SolverVectorPETSc>(_y);
// y = alpha A x + beta y
SolverVectorPETSc w(x, this->id + ":tmp");
// w = A x
if (release == 0) {
PETSc_call(VecZeroEntries, w);
} else {
PETSc_call(MatMult, mat, x, w);
}
if (alpha != 1.) {
// w = alpha w
PETSc_call(VecScale, w, alpha);
}
// y = w + beta y
PETSc_call(VecAYPX, y, beta, w);
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::addMeToImpl(SparseMatrixPETSc & B, Real alpha) const {
PETSc_call(MatAXPY, B.mat, alpha, mat, SAME_NONZERO_PATTERN);
B.release++;
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::addMeTo(SparseMatrix & B, Real alpha) const {
if (aka::is_of_type<SparseMatrixPETSc>(B)) {
auto & B_petsc = aka::as_type<SparseMatrixPETSc>(B);
this->addMeToImpl(B_petsc, alpha);
} else {
AKANTU_TO_IMPLEMENT();
// this->addMeToTemplated<SparseMatrix>(*this, alpha);
}
}
/* -------------------------------------------------------------------------- */
/**
* MatSetValues() generally caches the values. The matrix is ready to
* use only after MatAssemblyBegin() and MatAssemblyEnd() have been
* called. (http://www.mcs.anl.gov/petsc/)
*/
void SparseMatrixPETSc::applyModifications() {
this->beginAssembly();
this->endAssembly();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::beginAssembly() {
PETSc_call(MatAssemblyBegin, mat, MAT_FINAL_ASSEMBLY);
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::endAssembly() {
PETSc_call(MatAssemblyEnd, mat, MAT_FINAL_ASSEMBLY);
PETSc_call(MatSetOption, mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
this->release++;
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::copyProfile(const SparseMatrix & other) {
const auto & A = aka::as_type<SparseMatrixPETSc>(other);
MatDestroy(&mat);
MatDuplicate(A.mat, MAT_DO_NOT_COPY_VALUES, &mat);
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::applyBoundary(Real block_val) {
AKANTU_DEBUG_IN();
const auto & blocked_dofs = this->dof_manager.getGlobalBlockedDOFs();
// std::vector<PetscInt> rows;
// for (auto && data : enumerate(blocked)) {
// if (std::get<1>(data)) {
// rows.push_back(std::get<0>(data));
// }
// }
// applyModifications();
static int c = 0;
saveMatrix("before_blocked_" + std::to_string(c) + ".mtx");
PETSc_call(MatZeroRowsColumnsLocal, mat, blocked_dofs.size(),
- blocked_dofs.storage(), block_val, nullptr, nullptr);
+ blocked_dofs.data(), block_val, nullptr, nullptr);
saveMatrix("after_blocked_" + std::to_string(c) + ".mtx");
++c;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::mul(Real alpha) {
PETSc_call(MatScale, mat, alpha);
this->release++;
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::zero() {
PETSc_call(MatZeroEntries, mat);
this->release++;
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::clearProfile() {
SparseMatrix::clearProfile();
PETSc_call(MatResetPreallocation, mat);
PETSc_call(MatSetOption, mat, MAT_NEW_NONZERO_LOCATIONS, PETSC_TRUE);
// PETSc_call(MatSetOption, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE);
// PETSc_call(MatSetOption, MAT_NEW_NONZERO_ALLOCATIONS, PETSC_TRUE);
// PETSc_call(MatSetOption, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
this->zero();
}
/* -------------------------------------------------------------------------- */
-UInt SparseMatrixPETSc::add(UInt i, UInt j) {
+Idx SparseMatrixPETSc::add(Idx i, Idx j) {
PETSc_call(MatSetValue, mat, i, j, 0, ADD_VALUES);
return 0;
}
/* -------------------------------------------------------------------------- */
-void SparseMatrixPETSc::add(UInt i, UInt j, Real val) {
+void SparseMatrixPETSc::add(Idx i, Idx j, Real val) {
PETSc_call(MatSetValue, mat, i, j, val, ADD_VALUES);
}
/* -------------------------------------------------------------------------- */
-void SparseMatrixPETSc::addLocal(UInt i, UInt j) {
+void SparseMatrixPETSc::addLocal(Idx i, Idx j) {
PETSc_call(MatSetValueLocal, mat, i, j, 0, ADD_VALUES);
}
/* -------------------------------------------------------------------------- */
-void SparseMatrixPETSc::addLocal(UInt i, UInt j, Real val) {
+void SparseMatrixPETSc::addLocal(Idx i, Idx j, Real val) {
PETSc_call(MatSetValueLocal, mat, i, j, val, ADD_VALUES);
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::addLocal(const Vector<Int> & rows,
const Vector<Int> & cols,
const Matrix<Real> & values) {
- PETSc_call(MatSetValuesLocal, mat, rows.size(), rows.storage(), cols.size(),
- cols.storage(), values.storage(), ADD_VALUES);
+ PETSc_call(MatSetValuesLocal, mat, rows.size(), rows.data(), cols.size(),
+ cols.data(), values.data(), ADD_VALUES);
}
/* -------------------------------------------------------------------------- */
void SparseMatrixPETSc::addValues(const Vector<Int> & rows,
const Vector<Int> & cols,
const Matrix<Real> & values,
MatrixType values_type) {
if (values_type == _unsymmetric and matrix_type == _symmetric) {
PETSc_call(MatSetOption, mat, MAT_SYMMETRIC, PETSC_FALSE);
PETSc_call(MatSetOption, mat, MAT_STRUCTURALLY_SYMMETRIC, PETSC_FALSE);
}
- PETSc_call(MatSetValues, mat, rows.size(), rows.storage(), cols.size(),
- cols.storage(), values.storage(), ADD_VALUES);
+ PETSc_call(MatSetValues, mat, rows.size(), rows.data(), cols.size(),
+ cols.data(), values.data(), ADD_VALUES);
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/solver/sparse_matrix_petsc.hh b/src/solver/sparse_matrix_petsc.hh
index 2d20d85eb..cd20e69ed 100644
--- a/src/solver/sparse_matrix_petsc.hh
+++ b/src/solver/sparse_matrix_petsc.hh
@@ -1,160 +1,163 @@
/**
* @file sparse_matrix_petsc.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Jul 24 2020
*
* @brief Interface for PETSc matrices
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PETSC_MATRIX_HH_
#define AKANTU_PETSC_MATRIX_HH_
/* -------------------------------------------------------------------------- */
+#include "aka_types.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
#include <petscmat.h>
/* -------------------------------------------------------------------------- */
namespace akantu {
class DOFManagerPETSc;
}
namespace akantu {
class SparseMatrixPETSc : public SparseMatrix {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SparseMatrixPETSc(DOFManagerPETSc & dof_manager,
const MatrixType & matrix_type,
const ID & id = "sparse_matrix_petsc");
SparseMatrixPETSc(const SparseMatrixPETSc & matrix,
const ID & id = "sparse_matrix_petsc");
~SparseMatrixPETSc() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// set the matrix to 0
void zero() override;
void set(Real /*val*/) override { AKANTU_TO_IMPLEMENT(); }
void clearProfile() override;
/// add a non-zero element to the profile
- UInt add(UInt i, UInt j) override;
+ Idx add(Idx i, Idx j) override;
/// assemble a local matrix in the sparse one
- void add(UInt i, UInt j, Real value) override;
+ void add(Idx i, Idx j, Real value) override;
- void addLocal(UInt i, UInt j);
- void addLocal(UInt i, UInt j, Real val);
+ void addLocal(Idx i, Idx j);
+ void addLocal(Idx i, Idx j, Real val);
void addLocal(const Vector<Int> & rows, const Vector<Int> & cols,
const Matrix<Real> & values);
/// add a block of values
void addValues(const Vector<Int> & rows, const Vector<Int> & cols,
const Matrix<Real> & values, MatrixType values_type);
/// save the profil in a file using the MatrixMarket file format
// void saveProfile(__attribute__((unused)) const std::string &) const
// override {
// AKANTU_DEBUG_TO_IMPLEMENT();
// }
/// save the matrix in a file using the MatrixMarket file format
void saveMatrix(const std::string & filename) const override;
/// multiply the matrix by a coefficient
void mul(Real alpha) override;
/// Equivalent of *gemv in blas
void matVecMul(const SolverVector & x, SolverVector & y, Real alpha = 1.,
Real beta = 0.) const override;
/// modify the matrix to "remove" the blocked dof
void applyBoundary(Real block_val = 1.) override;
/// copy the profile of a matrix
void copyProfile(const SparseMatrix & other) override;
void applyModifications();
void resize();
+ Real min() override { AKANTU_TO_IMPLEMENT(); }
+
protected:
void addMeTo(SparseMatrix & B, Real alpha) const override;
/// This is the specific implementation
void addMeToImpl(SparseMatrixPETSc & B, Real alpha) const;
void beginAssembly();
void endAssembly();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// return the values at potition i, j
- inline Real operator()(UInt /*i*/, UInt /*j*/) const override {
+ inline Real operator()(Idx /*i*/, Idx /*j*/) const override {
AKANTU_TO_IMPLEMENT();
}
/// return the values at potition i, j
- inline Real & operator()(UInt /*i*/, UInt /*j*/) override {
+ inline Real & operator()(Idx /*i*/, Idx /*j*/) override {
AKANTU_TO_IMPLEMENT();
}
- UInt getRelease() const override { return release; };
+ Int getRelease() const override { return release; };
operator Mat &() { return mat; }
operator const Mat &() const { return mat; }
AKANTU_GET_MACRO(Mat, mat, const Mat &);
AKANTU_GET_MACRO_NOT_CONST(Mat, mat, Mat &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
// DOFManagerPETSc that contains the numbering for petsc
DOFManagerPETSc & dof_manager;
/// store the PETSc matrix
Mat mat;
/// matrix release
- UInt release{0};
+ Int release{0};
};
} // namespace akantu
#endif /* AKANTU_PETSC_MATRIX_HH_ */
diff --git a/src/solver/sparse_solver.hh b/src/solver/sparse_solver.hh
index 14547daf4..b554ee84d 100644
--- a/src/solver/sparse_solver.hh
+++ b/src/solver/sparse_solver.hh
@@ -1,128 +1,117 @@
/**
* @file sparse_solver.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Jan 24 2018
*
* @brief interface for solvers
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator_event_handler.hh"
#include "parsable.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLVER_HH_
#define AKANTU_SOLVER_HH_
namespace akantu {
enum SolverParallelMethod {
_not_parallel,
_fully_distributed,
_master_slave_distributed
};
class DOFManager;
} // namespace akantu
namespace akantu {
class SparseSolver : public Parsable, public CommunicatorEventHandler {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SparseSolver(DOFManager & dof_manager, const ID & matrix_id,
const ID & id = "solver");
~SparseSolver() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// initialize the solver
virtual void initialize() = 0;
virtual void analysis(){};
virtual void factorize(){};
virtual void solve(){};
protected:
virtual void destroyInternalData(){};
public:
virtual void beforeStaticSolverDestroy();
void createSynchronizerRegistry();
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
void onCommunicatorFinalize() override;
- // inline virtual UInt getNbDataForDOFs(const Array<UInt> & dofs,
- // SynchronizationTag tag) const;
-
- // inline virtual void packDOFData(CommunicationBuffer & buffer,
- // const Array<UInt> & dofs,
- // SynchronizationTag tag) const;
-
- // inline virtual void unpackDOFData(CommunicationBuffer & buffer,
- // const Array<UInt> & dofs,
- // SynchronizationTag tag);
-
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// manager handling the dofs for this SparseMatrix solver
DOFManager & _dof_manager;
/// The id of the associated matrix
ID matrix_id;
/// How to parallelize the solve
SolverParallelMethod parallel_method;
/// Communicator used by the solver
Communicator & communicator;
};
namespace debug {
class SingularMatrixException : public Exception {
public:
SingularMatrixException(const SparseMatrix & matrix)
: Exception("Solver encountered singular matrix"), matrix(matrix) {}
const SparseMatrix & matrix;
};
} // namespace debug
} // namespace akantu
#endif /* AKANTU_SOLVER_HH_ */
diff --git a/src/solver/sparse_solver_inline_impl.hh b/src/solver/sparse_solver_inline_impl.hh
index f71d17fa9..1007584a5 100644
--- a/src/solver/sparse_solver_inline_impl.hh
+++ b/src/solver/sparse_solver_inline_impl.hh
@@ -1,88 +1,31 @@
/**
* @file sparse_solver_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Sun Dec 30 2018
*
* @brief implementation of solver inline functions
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
-
-/* -------------------------------------------------------------------------- */
-// inline UInt Solver::getNbDataForDOFs(const Array<UInt> & dofs,
-// SynchronizationTag tag) const {
-// AKANTU_DEBUG_IN();
-
-// UInt size = 0;
-
-// switch(tag) {
-// case SynchronizationTag::_solver_solution: {
-// size += dofs.size() * sizeof(Real);
-// break;
-// }
-// default: { }
-// }
-
-// AKANTU_DEBUG_OUT();
-// return size;
-// }
-
-// /* --------------------------------------------------------------------------
-// */
-// inline void Solver::packDOFData(CommunicationBuffer & buffer,
-// const Array<UInt> & dofs,
-// SynchronizationTag tag) const {
-// AKANTU_DEBUG_IN();
-
-// switch(tag) {
-// case SynchronizationTag::_solver_solution: {
-// packDOFDataHelper(*solution, buffer, dofs);
-// break;
-// }
-// default: {
-// }
-// }
-
-// AKANTU_DEBUG_OUT();
-// }
-
-// /* --------------------------------------------------------------------------
-// */
-// inline void Solver::unpackDOFData(CommunicationBuffer & buffer,
-// const Array<UInt> & dofs,
-// SynchronizationTag tag) {
-// AKANTU_DEBUG_IN();
-
-// switch(tag) {
-// case SynchronizationTag::_solver_solution: {
-// unpackDOFDataHelper(*solution, buffer, dofs);
-// break;
-// }
-// default: {
-// }
-// }
-
-// AKANTU_DEBUG_OUT();
-// }
diff --git a/src/solver/sparse_solver_mumps.cc b/src/solver/sparse_solver_mumps.cc
index 45a4632e1..dda8ae8ea 100644
--- a/src/solver/sparse_solver_mumps.cc
+++ b/src/solver/sparse_solver_mumps.cc
@@ -1,398 +1,398 @@
/**
* @file sparse_solver_mumps.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Dec 13 2010
* @date last modification: Wed Sep 02 2020
*
* @brief implem of SparseSolverMumps class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dof_manager_default.hh"
#include "dof_synchronizer.hh"
#include "solver_vector_default.hh"
#include "sparse_matrix_aij.hh"
#if defined(AKANTU_USE_MPI)
#include "mpi_communicator_data.hh"
#endif
#include "sparse_solver_mumps.hh"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
// static std::ostream & operator <<(std::ostream & stream, const DMUMPS_STRUC_C
// & _this) {
// stream << "DMUMPS Data [" << std::endl;
// stream << " + job : " << _this.job << std::endl;
// stream << " + par : " << _this.par << std::endl;
// stream << " + sym : " << _this.sym << std::endl;
// stream << " + comm_fortran : " << _this.comm_fortran << std::endl;
// stream << " + nz : " << _this.nz << std::endl;
// stream << " + irn : " << _this.irn << std::endl;
// stream << " + jcn : " << _this.jcn << std::endl;
// stream << " + nz_loc : " << _this.nz_loc << std::endl;
// stream << " + irn_loc : " << _this.irn_loc << std::endl;
// stream << " + jcn_loc : " << _this.jcn_loc << std::endl;
// stream << "]";
// return stream;
// }
namespace akantu {
/* -------------------------------------------------------------------------- */
SparseSolverMumps::SparseSolverMumps(DOFManagerDefault & dof_manager,
const ID & matrix_id, const ID & id)
: SparseSolver(dof_manager, matrix_id, id), dof_manager(dof_manager),
master_rhs_solution(0, 1) {
AKANTU_DEBUG_IN();
this->prank = communicator.whoAmI();
#ifdef AKANTU_USE_MPI
this->parallel_method = _fully_distributed;
#else // AKANTU_USE_MPI
this->parallel_method = _not_parallel;
#endif // AKANTU_USE_MPI
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
SparseSolverMumps::~SparseSolverMumps() {
AKANTU_DEBUG_IN();
mumpsDataDestroy();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::mumpsDataDestroy() {
#ifdef AKANTU_USE_MPI
int finalized = 0;
MPI_Finalized(&finalized);
if (finalized != 0) { // Da fuck !?
return;
}
#endif
if (this->is_initialized) {
this->mumps_data.job = _smj_destroy; // destroy
dmumps_c(&this->mumps_data);
this->is_initialized = false;
}
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::destroyInternalData() { mumpsDataDestroy(); }
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::checkInitialized() {
if (this->is_initialized) {
return;
}
this->initialize();
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::setOutputLevel() {
// Output setup
icntl(1) = 0; // error output
icntl(2) = 0; // diagnostics output
icntl(3) = 0; // information
icntl(4) = 0;
#if !defined(AKANTU_NDEBUG)
DebugLevel dbg_lvl = debug::debugger.getDebugLevel();
if (AKANTU_DEBUG_TEST(dblDump)) {
strcpy(this->mumps_data.write_problem, "mumps_matrix.mtx");
}
// clang-format off
icntl(1) = (dbg_lvl >= dblWarning) ? 6 : 0;
icntl(3) = (dbg_lvl >= dblInfo) ? 6 : 0;
icntl(2) = (dbg_lvl >= dblTrace) ? 6 : 0;
icntl(4) =
dbg_lvl >= dblDump ? 4 :
dbg_lvl >= dblTrace ? 3 :
dbg_lvl >= dblInfo ? 2 :
dbg_lvl >= dblWarning ? 1 :
0;
// clang-format on
#endif
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::initMumpsData() {
auto & A = dof_manager.getMatrix(matrix_id);
// Default Scaling
icntl(8) = 77;
// Assembled matrix
icntl(5) = 0;
/// Default centralized dense second member
icntl(20) = 0;
icntl(21) = 0;
// automatic choice for analysis
icntl(28) = 0;
- UInt size = A.size();
+ auto size = A.size();
if (prank == 0) {
this->master_rhs_solution.resize(size);
}
this->mumps_data.nz_alloc = 0;
this->mumps_data.n = size;
switch (this->parallel_method) {
case _fully_distributed:
icntl(18) = 3; // fully distributed
this->mumps_data.nz_loc = A.getNbNonZero();
- this->mumps_data.irn_loc = A.getIRN().storage();
- this->mumps_data.jcn_loc = A.getJCN().storage();
+ this->mumps_data.irn_loc = A.getIRN().data();
+ this->mumps_data.jcn_loc = A.getJCN().data();
break;
case _not_parallel:
case _master_slave_distributed:
icntl(18) = 0; // centralized
if (prank == 0) {
this->mumps_data.nz = A.getNbNonZero();
- this->mumps_data.irn = A.getIRN().storage();
- this->mumps_data.jcn = A.getJCN().storage();
+ this->mumps_data.irn = A.getIRN().data();
+ this->mumps_data.jcn = A.getJCN().data();
} else {
this->mumps_data.nz = 0;
this->mumps_data.irn = nullptr;
this->mumps_data.jcn = nullptr;
}
break;
default:
AKANTU_ERROR("This case should not happen!!");
}
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::initialize() {
AKANTU_DEBUG_IN();
this->mumps_data.par = 1; // The host is part of computations
switch (this->parallel_method) {
case _not_parallel:
break;
case _master_slave_distributed:
this->mumps_data.par = 0; // The host is not part of the computations
/* FALLTHRU */
/* [[fallthrough]]; un-comment when compiler will get it */
case _fully_distributed:
#ifdef AKANTU_USE_MPI
const auto & mpi_data =
aka::as_type<MPICommunicatorData>(communicator.getCommunicatorData());
MPI_Comm mpi_comm = mpi_data.getMPICommunicator();
this->mumps_data.comm_fortran = MPI_Comm_c2f(mpi_comm);
#else
AKANTU_ERROR(
"You cannot use parallel method to solve without activating MPI");
#endif
break;
}
const auto & A = dof_manager.getMatrix(matrix_id);
this->mumps_data.sym = 2 * static_cast<int>(A.getMatrixType() == _symmetric);
this->prank = communicator.whoAmI();
this->setOutputLevel();
this->mumps_data.job = _smj_initialize; // initialize
dmumps_c(&this->mumps_data);
this->setOutputLevel();
this->is_initialized = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::analysis() {
AKANTU_DEBUG_IN();
initMumpsData();
this->mumps_data.job = _smj_analyze; // analyze
dmumps_c(&this->mumps_data);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::factorize() {
AKANTU_DEBUG_IN();
auto & A = dof_manager.getMatrix(matrix_id);
if (parallel_method == _fully_distributed) {
- this->mumps_data.a_loc = A.getA().storage();
+ this->mumps_data.a_loc = A.getA().data();
} else {
if (prank == 0) {
- this->mumps_data.a = A.getA().storage();
+ this->mumps_data.a = A.getA().data();
}
}
this->mumps_data.job = _smj_factorize; // factorize
dmumps_c(&this->mumps_data);
this->printError();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::solve(Array<Real> & x, const Array<Real> & b) {
auto & synch = this->dof_manager.getSynchronizer();
if (this->prank == 0) {
this->master_rhs_solution.resize(this->dof_manager.getSystemSize());
synch.gather(b, this->master_rhs_solution);
} else {
synch.gather(b);
}
this->solveInternal();
if (this->prank == 0) {
synch.scatter(x, this->master_rhs_solution);
} else {
synch.scatter(x);
}
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::solve() {
this->master_rhs_solution.copy(
aka::as_type<SolverVectorDefault>(this->dof_manager.getResidual())
.getGlobalVector());
this->solveInternal();
aka::as_type<SolverVectorDefault>(this->dof_manager.getSolution())
.setGlobalVector(this->master_rhs_solution);
this->dof_manager.splitSolutionPerDOFs();
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::solveInternal() {
AKANTU_DEBUG_IN();
this->checkInitialized();
const auto & A = dof_manager.getMatrix(matrix_id);
this->setOutputLevel();
if (this->last_profile_release != A.getProfileRelease()) {
this->analysis();
this->last_profile_release = A.getProfileRelease();
}
if (AKANTU_DEBUG_TEST(dblDump)) {
A.saveMatrix("solver_mumps" + std::to_string(prank) + ".mtx");
}
if (this->last_value_release != A.getValueRelease()) {
this->factorize();
this->last_value_release = A.getValueRelease();
}
if (prank == 0) {
- this->mumps_data.rhs = this->master_rhs_solution.storage();
+ this->mumps_data.rhs = this->master_rhs_solution.data();
}
this->mumps_data.job = _smj_solve; // solve
dmumps_c(&this->mumps_data);
this->printError();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SparseSolverMumps::printError() {
Vector<Int> _info_v(2);
_info_v[0] = info(1); // to get errors
_info_v[1] = -info(1); // to get warnings
dof_manager.getCommunicator().allReduce(_info_v, SynchronizerOperation::_min);
_info_v[1] = -_info_v[1];
if (_info_v[0] < 0) { // < 0 is an error
switch (_info_v[0]) {
case -10: {
AKANTU_CUSTOM_EXCEPTION(
debug::SingularMatrixException(dof_manager.getMatrix(matrix_id)));
break;
}
case -9: {
icntl(14) += 10;
if (icntl(14) != 90) {
// std::cout << "Dynamic memory increase of 10%" << std::endl;
AKANTU_DEBUG_WARNING("MUMPS dynamic memory is insufficient it will be "
"increased allowed to use 10% more");
// change releases to force a recompute
this->last_value_release--;
this->last_profile_release--;
this->solve();
} else {
AKANTU_ERROR("The MUMPS workarray is too small INFO(2)="
<< info(2) << "No further increase possible");
}
break;
}
default:
AKANTU_ERROR("Error in mumps during solve process, check mumps "
"user guide INFO(1) = "
<< _info_v[1]);
}
} else if (_info_v[1] > 0) {
AKANTU_DEBUG_WARNING("Warning in mumps during solve process, check mumps "
"user guide INFO(1) = "
<< _info_v[1]);
}
}
} // namespace akantu
diff --git a/src/solver/sparse_solver_mumps.hh b/src/solver/sparse_solver_mumps.hh
index 3517b3934..1028c6122 100644
--- a/src/solver/sparse_solver_mumps.hh
+++ b/src/solver/sparse_solver_mumps.hh
@@ -1,158 +1,158 @@
/**
* @file sparse_solver_mumps.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri May 19 2017
*
* @brief Solver class implementation for the mumps solver
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "sparse_solver.hh"
/* -------------------------------------------------------------------------- */
#include <dmumps_c.h>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLVER_MUMPS_HH_
#define AKANTU_SOLVER_MUMPS_HH_
namespace akantu {
class DOFManagerDefault;
class SparseMatrixAIJ;
} // namespace akantu
namespace akantu {
class SparseSolverMumps : public SparseSolver {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SparseSolverMumps(DOFManagerDefault & dof_manager, const ID & matrix_id,
const ID & id = "sparse_solver_mumps");
~SparseSolverMumps() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// build the profile and do the analysis part
void initialize() override;
/// analysis (symbolic facto + permutations)
void analysis() override;
/// factorize the matrix
void factorize() override;
/// solve the system
virtual void solve(Array<Real> & x, const Array<Real> & b);
/// solve using residual and solution from the dof_manager
void solve() override;
private:
/// print the error if any happened in mumps
void printError();
/// solve the system with master_rhs_solution as b and x
void solveInternal();
/// set internal values;
void initMumpsData();
/// set the level of verbosity of mumps based on the debug level of akantu
void setOutputLevel();
protected:
/// de-initialize the internal data
void destroyInternalData() override;
/// check if initialized and except if it is not the case
void checkInitialized();
private:
void mumpsDataDestroy();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
private:
/// access the control variable
- inline Int & icntl(UInt i) { return mumps_data.icntl[i - 1]; }
+ inline Int & icntl(Int i) { return mumps_data.icntl[i - 1]; }
/// access the results info
- inline Int & info(UInt i) { return mumps_data.info[i - 1]; }
+ inline Int & info(Int i) { return mumps_data.info[i - 1]; }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// DOFManager used by the Mumps implementation of the SparseSolver
DOFManagerDefault & dof_manager;
/// Full right hand side on the master processors and solution after solve
Array<Real> master_rhs_solution;
/// mumps data
DMUMPS_STRUC_C mumps_data;
/// Rank of the current process
- UInt prank;
+ Int prank;
/// matrix release at last solve
- UInt last_profile_release{UInt(-1)};
+ Int last_profile_release{-1};
/// matrix release at last solve
- UInt last_value_release{UInt(-1)};
+ Int last_value_release{-1};
/// check if the solver data are initialized
bool is_initialized{false};
/* ------------------------------------------------------------------------ */
/* Local types */
/* ------------------------------------------------------------------------ */
private:
SolverParallelMethod parallel_method;
// bool rhs_is_local;
enum SolverMumpsJob {
_smj_initialize = -1,
_smj_analyze = 1,
_smj_factorize = 2,
_smj_solve = 3,
_smj_analyze_factorize = 4,
_smj_factorize_solve = 5,
_smj_complete = 6, // analyze, factorize, solve
_smj_destroy = -2
};
};
} // namespace akantu
#endif /* AKANTU_SOLVER_MUMPS_HH_ */
diff --git a/src/solver/terms_to_assemble.hh b/src/solver/terms_to_assemble.hh
index 1db26403b..127729344 100644
--- a/src/solver/terms_to_assemble.hh
+++ b/src/solver/terms_to_assemble.hh
@@ -1,106 +1,106 @@
/**
* @file terms_to_assemble.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Oct 11 2017
*
* @brief List of terms to assemble to a matrix
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TERMS_TO_ASSEMBLE_HH_
#define AKANTU_TERMS_TO_ASSEMBLE_HH_
namespace akantu {
class TermsToAssemble {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
TermsToAssemble(const ID & dof_id_m, const ID & dof_id_n)
: dof_id_m(dof_id_m), dof_id_n(dof_id_n) {}
virtual ~TermsToAssemble() = default;
class TermToAssemble {
public:
- TermToAssemble(UInt i, UInt j) : _i(i), _j(j) {}
+ TermToAssemble(Idx i, Idx j) : _i(i), _j(j) {}
inline TermToAssemble & operator=(Real val) {
this->val = val;
return *this;
}
inline TermToAssemble operator+=(Real val) {
this->val += val;
return *this;
}
inline operator Real() const { return val; }
- inline UInt i() const { return _i; }
- inline UInt j() const { return _j; }
+ inline Idx i() const { return _i; }
+ inline Idx j() const { return _j; }
private:
- UInt _i, _j;
+ Idx _i, _j;
Real val{0.};
};
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- inline TermToAssemble & operator()(UInt i, UInt j) {
+ inline TermToAssemble & operator()(Idx i, Idx j) {
terms.emplace_back(i, j);
return terms.back();
}
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
private:
using TermsContainer = std::vector<TermToAssemble>;
public:
using const_terms_iterator = TermsContainer::const_iterator;
auto begin() const { return terms.begin(); }
auto end() const { return terms.end(); }
AKANTU_GET_MACRO(DOFIdM, dof_id_m, const ID &);
AKANTU_GET_MACRO(DOFIdN, dof_id_n, const ID &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
TermsContainer terms;
ID dof_id_m, dof_id_n;
};
} // namespace akantu
#endif /* AKANTU_TERMS_TO_ASSEMBLE_HH_ */
diff --git a/src/synchronizer/communication_buffer.hh b/src/synchronizer/communication_buffer.hh
index 9181fa943..de49ddc7d 100644
--- a/src/synchronizer/communication_buffer.hh
+++ b/src/synchronizer/communication_buffer.hh
@@ -1,183 +1,197 @@
/**
* @file communication_buffer.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Dec 11 2019
*
* @brief Buffer for packing and unpacking data
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "element.hh"
/* -------------------------------------------------------------------------- */
#include <array>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COMMUNICATION_BUFFER_HH_
#define AKANTU_COMMUNICATION_BUFFER_HH_
namespace akantu {
template <bool is_static = true> class CommunicationBufferTemplated {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- explicit CommunicationBufferTemplated(UInt size) : buffer(size, 1, char()) {
- ptr_pack = buffer.storage();
- ptr_unpack = buffer.storage();
+ explicit CommunicationBufferTemplated(std::size_t size)
+ : buffer(size, 1, char()) {
+ ptr_pack = buffer.data();
+ ptr_unpack = buffer.data();
};
CommunicationBufferTemplated() : CommunicationBufferTemplated(0) {}
CommunicationBufferTemplated(const CommunicationBufferTemplated & other) =
delete;
CommunicationBufferTemplated &
operator=(const CommunicationBufferTemplated & other) = delete;
CommunicationBufferTemplated(CommunicationBufferTemplated && other) noexcept =
default;
virtual ~CommunicationBufferTemplated() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// reset to "empty"
inline void reset();
/// resize the internal buffer do not allocate on dynamic buffers
- inline void resize(UInt size);
+ inline void resize(std::size_t size);
/// resize the internal buffer allocate always
- inline void reserve(UInt size);
+ inline void reserve(std::size_t size);
/// clear buffer context
inline void zero();
private:
- inline void packResize(UInt size);
+ inline void packResize(std::size_t size);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- inline char * storage() { return buffer.storage(); };
- inline const char * storage() const { return buffer.storage(); };
+ [[deprecated("use data instead to be stl compatible")]] inline char *
+ storage() {
+ return buffer.data();
+ };
+ [[deprecated("use data instead to be stl compatible")]] inline const char *
+ storage() const {
+ return buffer.data();
+ };
+
+ inline char * data() { return buffer.data(); };
+ inline const char * data() const { return buffer.data(); };
+
/* ------------------------------------------------------------------------ */
/* Operators */
/* ------------------------------------------------------------------------ */
public:
/// printing tool
- template <typename T> inline std::string extractStream(UInt block_size);
+ template <typename T>
+ inline std::string extractStream(std::size_t block_size);
/// packing data
- template <typename T>
+ template <typename T, std::enable_if_t<std::is_standard_layout_v<T> and
+ not aka::is_tensor_v<T>> * = nullptr>
inline CommunicationBufferTemplated & operator<<(const T & to_pack);
- template <typename T>
- inline CommunicationBufferTemplated & operator<<(const Vector<T> & to_pack);
-
- template <typename T>
- inline CommunicationBufferTemplated & operator<<(const Matrix<T> & to_pack);
+ template <typename T, std::enable_if_t<aka::is_tensor_v<T>> * = nullptr>
+ inline CommunicationBufferTemplated & operator<<(const T & to_pack);
template <typename T>
inline CommunicationBufferTemplated &
operator<<(const std::vector<T> & to_pack);
+ inline CommunicationBufferTemplated & operator<<(const std::string & to_pack);
+
/// unpacking data
- template <typename T>
+ template <typename T, std::enable_if_t<std::is_standard_layout_v<T> and
+ not aka::is_tensor_v<T>> * = nullptr>
inline CommunicationBufferTemplated & operator>>(T & to_unpack);
- template <typename T>
- inline CommunicationBufferTemplated & operator>>(Vector<T> & to_unpack);
-
- template <typename T>
- inline CommunicationBufferTemplated & operator>>(Matrix<T> & to_unpack);
+ template <typename T, std::enable_if_t<aka::is_tensor_v<T>> * = nullptr>
+ inline CommunicationBufferTemplated & operator>>(T & to_pack);
template <typename T>
inline CommunicationBufferTemplated & operator>>(std::vector<T> & to_unpack);
- inline CommunicationBufferTemplated & operator<<(const std::string & to_pack);
inline CommunicationBufferTemplated & operator>>(std::string & to_unpack);
private:
template <typename T> inline void packIterable(T & to_pack);
template <typename T> inline void unpackIterable(T & to_unpack);
/* ------------------------------------------------------------------------ */
/* Accessor */
/* ------------------------------------------------------------------------ */
public:
- template <typename T> static inline UInt sizeInBuffer(const T & data);
- template <typename T> static inline UInt sizeInBuffer(const Vector<T> & data);
- template <typename T> static inline UInt sizeInBuffer(const Matrix<T> & data);
+ template <typename T, std::enable_if_t<std::is_standard_layout_v<T> and
+ not aka::is_tensor_v<T>> * = nullptr>
+ static inline std::size_t sizeInBuffer(const T & data);
+
+ template <typename T, std::enable_if_t<aka::is_tensor_v<T>> * = nullptr>
+ static inline std::size_t sizeInBuffer(const T & data);
+
template <typename T>
- static inline UInt sizeInBuffer(const std::vector<T> & data);
- static inline UInt sizeInBuffer(const std::string & data);
+ static inline std::size_t sizeInBuffer(const std::vector<T> & data);
+
+ static inline std::size_t sizeInBuffer(const std::string & data);
/// return the size in bytes of the stored values
- inline UInt getPackedSize() const { return ptr_pack - buffer.storage(); };
+ inline std::size_t getPackedSize() const { return ptr_pack - buffer.data(); };
/// return the size in bytes of data left to be unpacked
- inline UInt getLeftToUnpack() const {
- return buffer.size() - (ptr_unpack - buffer.storage());
+ inline std::size_t getLeftToUnpack() const {
+ return buffer.size() - (ptr_unpack - buffer.data());
};
/// return the global size allocated
- inline UInt size() const { return buffer.size(); };
+ inline std::size_t size() const { return buffer.size(); };
/// is the buffer empty
inline bool empty() const {
return (getPackedSize() == 0) and (getLeftToUnpack() == 0);
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// current position for packing
char * ptr_pack;
/// current position for unpacking
char * ptr_unpack;
/// storing buffer
Array<char> buffer;
};
using CommunicationBuffer = CommunicationBufferTemplated<true>;
using DynamicCommunicationBuffer = CommunicationBufferTemplated<false>;
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "communication_buffer_inline_impl.hh"
#endif /* AKANTU_COMMUNICATION_BUFFER_HH_ */
diff --git a/src/synchronizer/communication_buffer_inline_impl.hh b/src/synchronizer/communication_buffer_inline_impl.hh
index e2d3764ea..31319927f 100644
--- a/src/synchronizer/communication_buffer_inline_impl.hh
+++ b/src/synchronizer/communication_buffer_inline_impl.hh
@@ -1,331 +1,300 @@
/**
* @file communication_buffer_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Apr 14 2011
* @date last modification: Tue Dec 04 2018
*
* @brief CommunicationBuffer inline implementation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communication_buffer.hh"
#include <cstring>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <bool is_static>
-template <typename T>
-inline UInt
+template <typename T, std::enable_if_t<std::is_standard_layout_v<T> and
+ not aka::is_tensor_v<T>> *>
+inline std::size_t
CommunicationBufferTemplated<is_static>::sizeInBuffer(const T & /*unused*/) {
return sizeof(T);
}
template <bool is_static>
-template <typename T>
-inline UInt
-CommunicationBufferTemplated<is_static>::sizeInBuffer(const Vector<T> & data) {
- UInt size = data.size() * sizeof(T);
+template <typename Tensor, std::enable_if_t<aka::is_tensor_v<Tensor>> *>
+inline std::size_t
+CommunicationBufferTemplated<is_static>::sizeInBuffer(const Tensor & data) {
+ std::size_t size = data.size() * sizeof(typename Tensor::Scalar);
return size;
}
template <bool is_static>
template <typename T>
-inline UInt
-CommunicationBufferTemplated<is_static>::sizeInBuffer(const Matrix<T> & data) {
- UInt size = data.size() * sizeof(T);
- return size;
-}
-
-template <bool is_static>
-template <typename T>
-inline UInt CommunicationBufferTemplated<is_static>::sizeInBuffer(
+inline std::size_t CommunicationBufferTemplated<is_static>::sizeInBuffer(
const std::vector<T> & data) {
- UInt size = data.size() * sizeof(T) + sizeof(size_t);
+ std::size_t size = data.size() * sizeof(T) + sizeof(size_t);
return size;
}
template <bool is_static>
-inline UInt CommunicationBufferTemplated<is_static>::sizeInBuffer(
+inline std::size_t CommunicationBufferTemplated<is_static>::sizeInBuffer(
const std::string & data) {
- UInt size = data.size() * sizeof(std::string::value_type) + sizeof(size_t);
+ std::size_t size =
+ data.size() * sizeof(std::string::value_type) + sizeof(size_t);
return size;
}
/* -------------------------------------------------------------------------- */
template <bool is_static>
-inline void CommunicationBufferTemplated<is_static>::packResize(UInt size) {
+inline void
+CommunicationBufferTemplated<is_static>::packResize(std::size_t size) {
if (not is_static) {
- char * values = buffer.storage();
+ char * values = buffer.data();
auto nb_packed = ptr_pack - values;
- if (buffer.size() > nb_packed + size) {
+ if (std::size_t(buffer.size()) > nb_packed + size) {
return;
}
buffer.resize(nb_packed + size);
- ptr_pack = buffer.storage() + nb_packed;
- ptr_unpack = buffer.storage() + (ptr_unpack - values);
+ ptr_pack = buffer.data() + nb_packed;
+ ptr_unpack = buffer.data() + (ptr_unpack - values);
}
}
/* -------------------------------------------------------------------------- */
template <bool is_static>
-template <typename T>
+template <typename T, std::enable_if_t<std::is_standard_layout_v<T> and
+ not aka::is_tensor_v<T>> *>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator<<(const T & to_pack) {
- UInt size = sizeInBuffer(to_pack);
+ std::size_t size = sizeInBuffer(to_pack);
packResize(size);
AKANTU_DEBUG_ASSERT(
- (buffer.storage() + buffer.size()) >= (ptr_pack + size),
+ (buffer.data() + buffer.size()) >= (ptr_pack + size),
"Packing too much data in the CommunicationBufferTemplated");
std::memcpy(ptr_pack, reinterpret_cast<const char *>(&to_pack), size);
ptr_pack += size;
return *this;
}
/* -------------------------------------------------------------------------- */
template <bool is_static>
-template <typename T>
+template <typename T, std::enable_if_t<std::is_standard_layout_v<T> and
+ not aka::is_tensor_v<T>> *>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator>>(T & to_unpack) {
- UInt size = sizeInBuffer(to_unpack);
+ std::size_t size = sizeInBuffer(to_unpack);
alignas(alignof(T)) std::array<char, sizeof(T)> aligned_ptr;
memcpy(aligned_ptr.data(), ptr_unpack, size);
auto * tmp = reinterpret_cast<T *>(aligned_ptr.data());
AKANTU_DEBUG_ASSERT(
- (buffer.storage() + buffer.size()) >= (ptr_unpack + size),
+ (buffer.data() + buffer.size()) >= (ptr_unpack + size),
"Unpacking too much data in the CommunicationBufferTemplated");
to_unpack = *tmp;
// memcpy(reinterpret_cast<char *>(&to_unpack), ptr_unpack, size);
ptr_unpack += size;
return *this;
}
-/* -------------------------------------------------------------------------- */
-/* Specialization */
-/* -------------------------------------------------------------------------- */
-
-/**
- * Vector
- */
-
/* -------------------------------------------------------------------------- */
template <bool is_static>
-template <typename T>
+template <typename Tensor, std::enable_if_t<aka::is_tensor_v<Tensor>> *>
inline CommunicationBufferTemplated<is_static> &
-CommunicationBufferTemplated<is_static>::operator<<(const Vector<T> & to_pack) {
- UInt size = sizeInBuffer(to_pack);
+CommunicationBufferTemplated<is_static>::operator<<(const Tensor & to_pack) {
+ std::size_t size = sizeInBuffer(to_pack);
packResize(size);
AKANTU_DEBUG_ASSERT(
- (buffer.storage() + buffer.size()) >= (ptr_pack + size),
+ (buffer.data() + buffer.size()) >= (ptr_pack + size),
"Packing too much data in the CommunicationBufferTemplated");
- memcpy(ptr_pack, to_pack.storage(), size);
+ memcpy(ptr_pack, to_pack.data(), size);
ptr_pack += size;
return *this;
}
-/* -------------------------------------------------------------------------- */
-template <bool is_static>
-template <typename T>
-inline CommunicationBufferTemplated<is_static> &
-CommunicationBufferTemplated<is_static>::operator>>(Vector<T> & to_unpack) {
- UInt size = sizeInBuffer(to_unpack);
- AKANTU_DEBUG_ASSERT(
- (buffer.storage() + buffer.size()) >= (ptr_unpack + size),
- "Unpacking too much data in the CommunicationBufferTemplated");
- memcpy(to_unpack.storage(), ptr_unpack, size);
- ptr_unpack += size;
- return *this;
-}
-
-/**
- * Matrix
+/* --------------------------------------------------------------------------
*/
-
-/* -------------------------------------------------------------------------- */
template <bool is_static>
-template <typename T>
+template <typename Tensor, std::enable_if_t<aka::is_tensor_v<Tensor>> *>
inline CommunicationBufferTemplated<is_static> &
-CommunicationBufferTemplated<is_static>::operator<<(const Matrix<T> & to_pack) {
- UInt size = sizeInBuffer(to_pack);
- packResize(size);
+CommunicationBufferTemplated<is_static>::operator>>(Tensor & to_unpack) {
+ std::size_t size = sizeInBuffer(to_unpack);
AKANTU_DEBUG_ASSERT(
- (buffer.storage() + buffer.size()) >= (ptr_pack + size),
- "Packing too much data in the CommunicationBufferTemplated");
- memcpy(ptr_pack, to_pack.storage(), size);
- ptr_pack += size;
- return *this;
-}
-
-/* -------------------------------------------------------------------------- */
-template <bool is_static>
-template <typename T>
-inline CommunicationBufferTemplated<is_static> &
-CommunicationBufferTemplated<is_static>::operator>>(Matrix<T> & to_unpack) {
- UInt size = sizeInBuffer(to_unpack);
- AKANTU_DEBUG_ASSERT(
- (buffer.storage() + buffer.size()) >= (ptr_unpack + size),
+ (buffer.data() + buffer.size()) >= (ptr_unpack + size),
"Unpacking too much data in the CommunicationBufferTemplated");
- memcpy(to_unpack.storage(), ptr_unpack, size);
+ memcpy(to_unpack.data(), ptr_unpack, size);
ptr_unpack += size;
return *this;
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
template <typename T>
inline void CommunicationBufferTemplated<is_static>::packIterable(T & to_pack) {
- operator<<(size_t(to_pack.size()));
+ operator<<(std::size_t(to_pack.size()));
auto it = to_pack.begin();
auto end = to_pack.end();
for (; it != end; ++it) {
operator<<(*it);
}
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
template <typename T>
inline void
CommunicationBufferTemplated<is_static>::unpackIterable(T & to_unpack) {
- size_t size;
+ std::size_t size;
operator>>(size);
+
to_unpack.resize(size);
auto it = to_unpack.begin();
auto end = to_unpack.end();
for (; it != end; ++it) {
operator>>(*it);
}
}
/**
* std::vector<T>
*/
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
template <typename T>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator<<(
const std::vector<T> & to_pack) {
packIterable(to_pack);
return *this;
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
template <typename T>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator>>(
std::vector<T> & to_unpack) {
unpackIterable(to_unpack);
return *this;
}
/**
* std::string
*/
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator<<(
const std::string & to_pack) {
packIterable(to_pack);
return *this;
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator>>(std::string & to_unpack) {
unpackIterable(to_unpack);
return *this;
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
template <typename T>
inline std::string
-CommunicationBufferTemplated<is_static>::extractStream(UInt block_size) {
+CommunicationBufferTemplated<is_static>::extractStream(std::size_t block_size) {
std::stringstream str;
- auto * ptr = reinterpret_cast<T *>(buffer.storage());
- UInt sz = buffer.size() / sizeof(T);
- UInt sz_block = block_size / sizeof(T);
+ auto * ptr = reinterpret_cast<T *>(buffer.data());
+ auto sz = buffer.size() / sizeof(T);
+ auto sz_block = block_size / sizeof(T);
- UInt n_block = 0;
- for (UInt i = 0; i < sz; ++i) {
+ std::size_t n_block = 0;
+ for (std::size_t i = 0; i < sz; ++i) {
if (i % sz_block == 0) {
str << std::endl << n_block << " ";
++n_block;
}
str << *ptr << " ";
++ptr;
}
return str.str();
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
-inline void CommunicationBufferTemplated<is_static>::resize(UInt size) {
+inline void CommunicationBufferTemplated<is_static>::resize(std::size_t size) {
if (!is_static) {
buffer.resize(0, 0);
} else {
buffer.resize(size, 0);
}
reset();
#ifndef AKANTU_NDEBUG
zero();
#endif
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
-inline void CommunicationBufferTemplated<is_static>::reserve(UInt size) {
- char * values = buffer.storage();
- auto nb_packed = ptr_pack - values;
+inline void CommunicationBufferTemplated<is_static>::reserve(std::size_t size) {
+ char * values = buffer.data();
+ std::size_t nb_packed = ptr_pack - values;
buffer.resize(size);
- ptr_pack = buffer.storage() + nb_packed;
- ptr_unpack = buffer.storage() + (ptr_unpack - values);
+ ptr_pack = buffer.data() + nb_packed;
+ ptr_unpack = buffer.data() + (ptr_unpack - values);
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
inline void CommunicationBufferTemplated<is_static>::zero() {
buffer.zero();
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
template <bool is_static>
inline void CommunicationBufferTemplated<is_static>::reset() {
- ptr_pack = buffer.storage();
- ptr_unpack = buffer.storage();
+ ptr_pack = buffer.data();
+ ptr_unpack = buffer.data();
}
} // namespace akantu
diff --git a/src/synchronizer/communication_descriptor.hh b/src/synchronizer/communication_descriptor.hh
index 71a2af303..bc22e4d5d 100644
--- a/src/synchronizer/communication_descriptor.hh
+++ b/src/synchronizer/communication_descriptor.hh
@@ -1,155 +1,155 @@
/**
* @file communication_descriptor.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Thu Jan 25 2018
*
* @brief Implementation of the helper classes for the synchronizer
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "communication_request.hh"
#include "communication_tag.hh"
#include "data_accessor.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COMMUNICATION_DESCRIPTOR_HH_
#define AKANTU_COMMUNICATION_DESCRIPTOR_HH_
namespace akantu {
/* ------------------------------------------------------------------------ */
enum CommunicationSendRecv { _send, _recv, _csr_not_defined };
/* -------------------------------------------------------------------------- */
struct CommunicationSRType {
using type = CommunicationSendRecv;
static const type _begin_ = _send;
static const type _end_ = _csr_not_defined;
};
using send_recv_t = safe_enum<CommunicationSRType>;
namespace {
send_recv_t iterate_send_recv{};
}
/* ------------------------------------------------------------------------ */
class Communication {
public:
explicit Communication(const CommunicationSendRecv & type = _csr_not_defined)
: _type(type) {}
Communication(const Communication &) = delete;
Communication & operator=(const Communication &) = delete;
- void resize(UInt size) {
+ void resize(Int size) {
this->_size = size;
this->_buffer.resize(size);
}
inline const CommunicationSendRecv & type() const { return this->_type; }
- inline const UInt & size() const { return this->_size; }
+ inline Int size() const { return this->_size; }
inline const CommunicationRequest & request() const { return this->_request; }
inline CommunicationRequest & request() { return this->_request; }
inline const CommunicationBuffer & buffer() const { return this->_buffer; }
inline CommunicationBuffer & buffer() { return this->_buffer; }
private:
- UInt _size{0};
+ Int _size{0};
CommunicationBuffer _buffer;
CommunicationRequest _request;
CommunicationSendRecv _type;
};
template <class Entity> class Communications;
/* ------------------------------------------------------------------------ */
template <class Entity> class CommunicationDescriptor {
public:
CommunicationDescriptor(Communication & communication, Array<Entity> & scheme,
Communications<Entity> & communications,
- const SynchronizationTag & tag, UInt proc);
+ const SynchronizationTag & tag, Idx proc);
CommunicationDescriptor(const CommunicationDescriptor &) = default;
CommunicationDescriptor &
operator=(const CommunicationDescriptor &) = default;
/// get the quantity of data in the buffer
- UInt getNbData() { return communication.size(); }
+ Int getNbData() { return communication.size(); }
/// set the quantity of data in the buffer
- void setNbData(UInt size) { communication.resize(size); }
+ void setNbData(Int size) { communication.resize(size); }
/// get the corresponding tag
const SynchronizationTag & getTag() const { return tag; }
/// get the data buffer
CommunicationBuffer & getBuffer();
/// get the corresponding request
CommunicationRequest & getRequest();
/// get the communication scheme
const Array<Entity> & getScheme();
/// reset the buffer before pack or after unpack
void resetBuffer();
/// pack data for entities in the buffer
void packData(const DataAccessor<Entity> & accessor);
/// unpack data for entities from the buffer
void unpackData(DataAccessor<Entity> & accessor);
/// posts asynchronous send requests
void postSend(int hash_id);
/// posts asynchronous receive requests
void postRecv(int hash_id);
/// free the request
void freeRequest();
- UInt getProc() { return proc; }
+ Idx getProc() { return proc; }
protected:
Communication & communication;
const Array<Entity> & scheme;
Communications<Entity> & communications;
const SynchronizationTag & tag;
- UInt proc;
- UInt rank;
- UInt counter;
+ Idx proc;
+ Idx rank;
+ Int counter;
};
/* -------------------------------------------------------------------------- */
} // namespace akantu
#include "communication_descriptor_tmpl.hh"
#endif /* AKANTU_COMMUNICATION_DESCRIPTOR_HH_ */
diff --git a/src/synchronizer/communication_descriptor_tmpl.hh b/src/synchronizer/communication_descriptor_tmpl.hh
index f4c85e242..e9469a4fc 100644
--- a/src/synchronizer/communication_descriptor_tmpl.hh
+++ b/src/synchronizer/communication_descriptor_tmpl.hh
@@ -1,153 +1,153 @@
/**
* @file communication_descriptor_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Thu Jan 25 2018
*
* @brief implementation of CommunicationDescriptor
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communication_descriptor.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COMMUNICATION_DESCRIPTOR_TMPL_HH_
#define AKANTU_COMMUNICATION_DESCRIPTOR_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Implementations */
/* -------------------------------------------------------------------------- */
template <class Entity>
CommunicationDescriptor<Entity>::CommunicationDescriptor(
- Communication & communication, Array<Entity> & scheme,
- Communications<Entity> & communications, const SynchronizationTag & tag,
- UInt proc)
+ Communication &communication, Array<Entity> &scheme,
+ Communications<Entity> &communications, const SynchronizationTag &tag,
+ Int proc)
: communication(communication), scheme(scheme),
communications(communications), tag(tag), proc(proc),
rank(communications.getCommunicator().whoAmI()) {
counter = communications.getCounter(tag);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
-CommunicationBuffer & CommunicationDescriptor<Entity>::getBuffer() {
+CommunicationBuffer &CommunicationDescriptor<Entity>::getBuffer() {
return communication.buffer();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
-CommunicationRequest & CommunicationDescriptor<Entity>::getRequest() {
+CommunicationRequest &CommunicationDescriptor<Entity>::getRequest() {
return communication.request();
}
/* -------------------------------------------------------------------------- */
template <class Entity> void CommunicationDescriptor<Entity>::freeRequest() {
- const auto & comm = communications.getCommunicator();
+ const auto &comm = communications.getCommunicator();
// comm.test(communication.request());
comm.freeCommunicationRequest(communication.request());
communications.decrementPending(tag, communication.type());
}
/* -------------------------------------------------------------------------- */
template <class Entity>
-const Array<Entity> & CommunicationDescriptor<Entity>::getScheme() {
+const Array<Entity> &CommunicationDescriptor<Entity>::getScheme() {
return scheme;
}
template <class Entity> void CommunicationDescriptor<Entity>::resetBuffer() {
this->communication.buffer().reset();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void CommunicationDescriptor<Entity>::packData(
- const DataAccessor<Entity> & accessor) {
+ const DataAccessor<Entity> &accessor) {
AKANTU_DEBUG_ASSERT(
communication.type() == _send,
"Cannot pack data on communication that is not of type _send");
accessor.packData(communication.buffer(), scheme, tag);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void CommunicationDescriptor<Entity>::unpackData(
- DataAccessor<Entity> & accessor) {
+ DataAccessor<Entity> &accessor) {
AKANTU_DEBUG_ASSERT(
communication.type() == _recv,
"Cannot unpack data from communication that is not of type _recv");
accessor.unpackData(communication.buffer(), scheme, tag);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void CommunicationDescriptor<Entity>::postSend(int hash_id) {
AKANTU_DEBUG_ASSERT(communication.type() == _send,
"Cannot send a communication that is not of type _send");
Tag comm_tag = Tag::genTag(rank, counter, tag, hash_id);
AKANTU_DEBUG_ASSERT(communication.buffer().getPackedSize() ==
- communication.size(),
+ std::size_t(communication.size()),
"a problem have been introduced with "
<< "false sent sizes declaration "
<< communication.buffer().getPackedSize()
<< " != " << communication.size());
AKANTU_DEBUG_INFO("Posting send to proc " << proc << " (tag: " << tag << " - "
<< communication.size()
<< " data to send) "
<< " [ " << comm_tag << " ]");
- CommunicationRequest & request = communication.request();
+ CommunicationRequest &request = communication.request();
request = communications.getCommunicator().asyncSend(communication.buffer(),
proc, comm_tag);
communications.incrementPending(tag, communication.type());
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void CommunicationDescriptor<Entity>::postRecv(int hash_id) {
AKANTU_DEBUG_ASSERT(communication.type() == _recv,
"Cannot receive data for communication ("
<< communication.type()
<< ")that is not of type _recv");
Tag comm_tag = Tag::genTag(proc, counter, tag, hash_id);
AKANTU_DEBUG_INFO("Posting receive from proc "
<< proc << " (tag: " << tag << " - " << communication.size()
<< " data to receive) "
<< " [ " << comm_tag << " ]");
- CommunicationRequest & request = communication.request();
+ CommunicationRequest &request = communication.request();
request = communications.getCommunicator().asyncReceive(
communication.buffer(), proc, comm_tag);
communications.incrementPending(tag, communication.type());
}
} // namespace akantu
#endif /* AKANTU_COMMUNICATION_DESCRIPTOR_TMPL_HH_ */
diff --git a/src/synchronizer/communication_request.hh b/src/synchronizer/communication_request.hh
index f593c5e11..73d42bd3a 100644
--- a/src/synchronizer/communication_request.hh
+++ b/src/synchronizer/communication_request.hh
@@ -1,113 +1,113 @@
/**
* @file communication_request.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Jun 14 2010
* @date last modification: Tue Nov 07 2017
*
* @brief empty class just for inheritance
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#include <memory>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_REAL_STATIC_COMMUNICATOR_HH_
#define AKANTU_REAL_STATIC_COMMUNICATOR_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
class InternalCommunicationRequest {
public:
- InternalCommunicationRequest(UInt source, UInt dest);
+ InternalCommunicationRequest(Idx source, Idx dest);
virtual ~InternalCommunicationRequest();
virtual void printself(std::ostream & stream, int indent = 0) const;
- AKANTU_GET_MACRO(Source, source, UInt);
- AKANTU_GET_MACRO(Destination, destination, UInt);
+ AKANTU_GET_MACRO(Source, source, Idx);
+ AKANTU_GET_MACRO(Destination, destination, Idx);
private:
- UInt source;
- UInt destination;
- UInt id;
- static UInt counter;
+ Idx source;
+ Idx destination;
+ Idx id;
+ static Int counter;
};
/* -------------------------------------------------------------------------- */
class CommunicationRequest {
public:
CommunicationRequest(
std::shared_ptr<InternalCommunicationRequest> request = nullptr)
: request(std::move(request)) {}
virtual ~CommunicationRequest() = default;
virtual void free() { request.reset(); }
void printself(std::ostream & stream, int indent = 0) const {
request->printself(stream, indent);
};
- UInt getSource() const { return request->getSource(); }
- UInt getDestination() const { return request->getDestination(); }
+ Idx getSource() const { return request->getSource(); }
+ Idx getDestination() const { return request->getDestination(); }
bool isFreed() const { return request == nullptr; }
InternalCommunicationRequest & getInternal() { return *request; }
private:
std::shared_ptr<InternalCommunicationRequest> request;
};
/* -------------------------------------------------------------------------- */
class CommunicationStatus {
public:
AKANTU_GET_MACRO(Source, source, Int);
- UInt size() const { return size_; }
+ Int size() const { return size_; }
AKANTU_GET_MACRO(Tag, tag, Int);
AKANTU_SET_MACRO(Source, source, Int);
- AKANTU_SET_MACRO(Size, size_, UInt);
+ AKANTU_SET_MACRO(Size, size_, Int);
AKANTU_SET_MACRO(Tag, tag, Int);
private:
- Int source{0};
- UInt size_{0};
+ Idx source{0};
+ Int size_{0};
Int tag{0};
};
/* -------------------------------------------------------------------------- */
/// Datatype to pack pairs for MPI_{MIN,MAX}LOC
template <typename T1, typename T2> struct SCMinMaxLoc {
T1 min_max;
T2 loc;
};
} // namespace akantu
#endif /* AKANTU_REAL_STATIC_COMMUNICATOR_HH_ */
diff --git a/src/synchronizer/communication_tag.hh b/src/synchronizer/communication_tag.hh
index cb7974912..1464180e9 100644
--- a/src/synchronizer/communication_tag.hh
+++ b/src/synchronizer/communication_tag.hh
@@ -1,129 +1,129 @@
/**
* @file communication_tag.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Mon Feb 10 2020
*
* @brief Description of the communication tags
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COMMUNICATION_TAG_HH_
#define AKANTU_COMMUNICATION_TAG_HH_
namespace akantu {
/**
* tag = |__________20_________|___8____|_4_|
* | proc | num mes| ct|
*/
class Tag {
public:
Tag() = default;
Tag(int val) : tag(val) {}
Tag(int val, int hash) : tag(val), hash(hash) {}
operator int() const {
return int(max_tag == 0 ? tag : (uint32_t(tag) % max_tag));
}
/// generates a tag
template <typename CommTag>
- static inline Tag genTag(int proc, UInt msg_count, CommTag tag) {
+ static inline Tag genTag(int proc, Idx msg_count, CommTag tag) {
int _tag = ((((proc & 0xFFFFF) << 12) + ((msg_count & 0xFF) << 4) +
((int)tag & 0xF)));
Tag t(_tag);
return t;
}
/// generates a tag and hashes it
template <typename CommTag>
- static inline Tag genTag(int proc, UInt msg_count, CommTag tag, int hash) {
+ static inline Tag genTag(int proc, Idx msg_count, CommTag tag, int hash) {
Tag t = genTag(proc, msg_count, tag);
t.tag = t.tag ^ hash;
t.hash = hash;
return t;
}
virtual void printself(std::ostream & stream, int /*unused*/) const {
int t = tag;
stream << "TAG(";
if (hash != 0) {
t = t ^ hash;
}
stream << (t >> 12) << ":" << (t >> 4 & 0xFF) << ":" << (t & 0xF) << " -> "
<< std::hex << "0x" << int(*this);
if (hash != 0) {
stream << " {hash: 0x" << hash << "}";
}
stream << " [0x" << max_tag << "]";
stream << ")" << std::dec;
}
enum CommTags : int {
_sizes = 1,
_connectivity = 2,
_data = 3,
_partitions = 4,
_nb_nodes = 5,
_nodes = 6,
_coordinates = 7,
_nodes_type = 8,
_mesh_data = 9,
_element_group = 10,
_node_group = 11,
_modify_scheme = 12,
_gather_initialization = 1,
_gather = 2,
_scatter = 3,
_synchronize = 15,
_reduce,
_periodic_slaves,
_periodic_nodes,
};
private:
static void setMaxTag(int _max_tag) { max_tag = _max_tag; }
friend void initialize(const std::string & /*input_file*/, int & /*argc*/,
char **& /*argv*/);
private:
int tag{0};
int hash{0};
static int max_tag;
};
/* -------------------------------------------------------------------------- */
inline std::ostream & operator<<(std::ostream & stream, const Tag & _this) {
_this.printself(stream, 0);
return stream;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_COMMUNICATION_TAG_HH_ */
diff --git a/src/synchronizer/communications.hh b/src/synchronizer/communications.hh
index 915d18935..1dfa0538f 100644
--- a/src/synchronizer/communications.hh
+++ b/src/synchronizer/communications.hh
@@ -1,277 +1,269 @@
/**
* @file communications.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Fri Jul 24 2020
*
* @brief Class handling the pending communications and the communications
* schemes
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communication_descriptor.hh"
#include "communicator.hh"
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COMMUNICATIONS_HH_
#define AKANTU_COMMUNICATIONS_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Entity> class Communications {
public:
using Scheme = Array<Entity>;
protected:
- using CommunicationPerProcs = std::map<UInt, Communication>;
+ using CommunicationPerProcs = std::map<Int, Communication>;
using CommunicationsPerTags =
std::map<SynchronizationTag, CommunicationPerProcs>;
- using CommunicationSchemes = std::map<UInt, Scheme>;
- using Request = std::map<UInt, std::vector<CommunicationRequest>>;
+ using CommunicationSchemes = std::map<Int, Scheme>;
+ using Request = std::map<Int, std::vector<CommunicationRequest>>;
friend class CommunicationDescriptor<Entity>;
public:
using scheme_iterator = typename CommunicationSchemes::iterator;
using const_scheme_iterator = typename CommunicationSchemes::const_iterator;
/* ------------------------------------------------------------------------ */
class iterator;
class tag_iterator;
/* ------------------------------------------------------------------------ */
public:
CommunicationPerProcs & getCommunications(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
/* ------------------------------------------------------------------------ */
bool hasPending(const SynchronizationTag & tag,
const CommunicationSendRecv & sr) const;
- UInt getPending(const SynchronizationTag & tag,
- const CommunicationSendRecv & sr) const;
+ Int getPending(const SynchronizationTag & tag,
+ const CommunicationSendRecv & sr) const;
/* ------------------------------------------------------------------------ */
iterator begin(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
iterator end(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
/* ------------------------------------------------------------------------ */
iterator waitAny(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
/* ------------------------------------------------------------------------ */
void waitAll(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
void incrementPending(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
void decrementPending(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
void freeRequests(const SynchronizationTag & tag,
const CommunicationSendRecv & sr);
/* ------------------------------------------------------------------------ */
- Scheme & createScheme(UInt proc, const CommunicationSendRecv & sr);
+ Scheme & createScheme(Idx proc, const CommunicationSendRecv & sr);
void resetSchemes(const CommunicationSendRecv & sr);
/* ------------------------------------------------------------------------ */
- void setCommunicationSize(const SynchronizationTag & tag, UInt proc,
- UInt size, const CommunicationSendRecv & sr);
+ void setCommunicationSize(const SynchronizationTag & tag, Idx proc, Int size,
+ const CommunicationSendRecv & sr);
public:
explicit Communications(const Communicator & communicator);
explicit Communications(const Communications & other);
/* ------------------------------------------------------------------------ */
void swapSendRecv();
/* ------------------------------------------------------------------------ */
class IterableCommunicationDesc {
public:
IterableCommunicationDesc(Communications & communications,
SynchronizationTag tag, CommunicationSendRecv sr)
: communications(communications), tag(tag), sr(sr) {}
auto begin() { return communications.begin(tag, sr); }
auto end() { return communications.end(tag, sr); }
private:
Communications & communications;
SynchronizationTag tag;
CommunicationSendRecv sr;
};
auto iterateRecv(const SynchronizationTag & tag) {
return IterableCommunicationDesc(*this, tag, _recv);
}
auto iterateSend(const SynchronizationTag & tag) {
return IterableCommunicationDesc(*this, tag, _send);
}
- /* ------------------------------------------------------------------------ */
- // iterator begin_send(const SynchronizationTag & tag);
- // iterator end_send(const SynchronizationTag & tag);
-
- /* ------------------------------------------------------------------------ */
- // iterator begin_recv(const SynchronizationTag & tag);
- // iterator end_recv(const SynchronizationTag & tag);
-
/* ------------------------------------------------------------------------ */
class IterableTags {
public:
explicit IterableTags(Communications & communications)
: communications(communications) {}
decltype(auto) begin() { return communications.begin_tag(); }
decltype(auto) end() { return communications.end_tag(); }
private:
Communications & communications;
};
decltype(auto) iterateTags() { return IterableTags(*this); }
tag_iterator begin_tag();
tag_iterator end_tag();
/* ------------------------------------------------------------------------ */
bool hasCommunication(const SynchronizationTag & tag) const;
void incrementCounter(const SynchronizationTag & tag);
- UInt getCounter(const SynchronizationTag & tag) const;
+ Int getCounter(const SynchronizationTag & tag) const;
bool hasCommunicationSize(const SynchronizationTag & tag) const;
void invalidateSizes();
/* ------------------------------------------------------------------------ */
bool hasPendingRecv(const SynchronizationTag & tag) const;
bool hasPendingSend(const SynchronizationTag & tag) const;
const auto & getCommunicator() const;
/* ------------------------------------------------------------------------ */
iterator waitAnyRecv(const SynchronizationTag & tag);
iterator waitAnySend(const SynchronizationTag & tag);
void waitAllRecv(const SynchronizationTag & tag);
void waitAllSend(const SynchronizationTag & tag);
void freeSendRequests(const SynchronizationTag & tag);
void freeRecvRequests(const SynchronizationTag & tag);
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
class IterableSchemes {
public:
IterableSchemes(Communications & communications, CommunicationSendRecv sr)
: communications(communications), sr(sr) {}
decltype(auto) begin() { return communications.begin_scheme(sr); }
decltype(auto) end() { return communications.end_scheme(sr); }
private:
Communications & communications;
CommunicationSendRecv sr;
};
class ConstIterableSchemes {
public:
ConstIterableSchemes(const Communications & communications,
CommunicationSendRecv sr)
: communications(communications), sr(sr) {}
decltype(auto) begin() const { return communications.begin_scheme(sr); }
decltype(auto) end() const { return communications.end_scheme(sr); }
private:
const Communications & communications;
CommunicationSendRecv sr;
};
decltype(auto) iterateSchemes(const CommunicationSendRecv & sr) {
return IterableSchemes(*this, sr);
}
decltype(auto) iterateSchemes(const CommunicationSendRecv & sr) const {
return ConstIterableSchemes(*this, sr);
}
decltype(auto) iterateSendSchemes() { return IterableSchemes(*this, _send); }
decltype(auto) iterateSendSchemes() const {
return ConstIterableSchemes(*this, _send);
}
decltype(auto) iterateRecvSchemes() { return IterableSchemes(*this, _recv); }
decltype(auto) iterateRecvSchemes() const {
return ConstIterableSchemes(*this, _recv);
}
scheme_iterator begin_scheme(const CommunicationSendRecv & sr);
scheme_iterator end_scheme(const CommunicationSendRecv & sr);
const_scheme_iterator begin_scheme(const CommunicationSendRecv & sr) const;
const_scheme_iterator end_scheme(const CommunicationSendRecv & sr) const;
/* ------------------------------------------------------------------------ */
scheme_iterator begin_send_scheme();
scheme_iterator end_send_scheme();
const_scheme_iterator begin_send_scheme() const;
const_scheme_iterator end_send_scheme() const;
/* ------------------------------------------------------------------------ */
scheme_iterator begin_recv_scheme();
scheme_iterator end_recv_scheme();
const_scheme_iterator begin_recv_scheme() const;
const_scheme_iterator end_recv_scheme() const;
/* ------------------------------------------------------------------------ */
- Scheme & createSendScheme(UInt proc);
- Scheme & createRecvScheme(UInt proc);
+ Scheme & createSendScheme(Idx proc);
+ Scheme & createRecvScheme(Idx proc);
/* ------------------------------------------------------------------------ */
- Scheme & getScheme(UInt proc, const CommunicationSendRecv & sr);
- const Scheme & getScheme(UInt proc, const CommunicationSendRecv & sr) const;
+ Scheme & getScheme(Idx proc, const CommunicationSendRecv & sr);
+ const Scheme & getScheme(Idx proc, const CommunicationSendRecv & sr) const;
/* ------------------------------------------------------------------------ */
void resetSchemes();
/* ------------------------------------------------------------------------ */
- void setSendCommunicationSize(const SynchronizationTag & tag, UInt proc,
- UInt size);
- void setRecvCommunicationSize(const SynchronizationTag & tag, UInt proc,
- UInt size);
+ void setSendCommunicationSize(const SynchronizationTag & tag, Idx proc,
+ Int size);
+ void setRecvCommunicationSize(const SynchronizationTag & tag, Idx proc,
+ Int size);
void initializeCommunications(const SynchronizationTag & tag);
protected:
CommunicationSchemes schemes[2];
CommunicationsPerTags communications[2];
- std::map<SynchronizationTag, UInt> comm_counter;
- std::map<SynchronizationTag, UInt> pending_communications[2];
+ std::map<SynchronizationTag, Int> comm_counter;
+ std::map<SynchronizationTag, Int> pending_communications[2];
std::map<SynchronizationTag, bool> comm_size_computed;
const Communicator & communicator;
};
} // namespace akantu
#include "communications_tmpl.hh"
#endif /* AKANTU_COMMUNICATIONS_HH_ */
diff --git a/src/synchronizer/communications_tmpl.hh b/src/synchronizer/communications_tmpl.hh
index b80769b93..a78d6cd95 100644
--- a/src/synchronizer/communications_tmpl.hh
+++ b/src/synchronizer/communications_tmpl.hh
@@ -1,554 +1,553 @@
/**
* @file communications_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Fri Jul 24 2020
*
* @brief Implementation of Communications
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "communications.hh"
+//#include "communications.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_COMMUNICATIONS_TMPL_HH_
#define AKANTU_COMMUNICATIONS_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Entity>
Communications<Entity>::Communications(const Communicator & communicator)
: communicator(communicator) {}
/* -------------------------------------------------------------------------- */
template <class Entity>
Communications<Entity>::Communications(const Communications & other)
: communicator(other.communicator) {
for (auto sr : iterate_send_recv) {
for (const auto & scheme_pair : other.iterateSchemes(sr)) {
auto proc = scheme_pair.first;
auto & other_scheme = scheme_pair.second;
auto & scheme = this->createScheme(proc, sr);
scheme.copy(other_scheme);
}
}
this->invalidateSizes();
}
/* -------------------------------------------------------------------------- */
template <class Entity> void Communications<Entity>::swapSendRecv() {
std::swap(schemes[_send], schemes[_recv]);
}
/* -------------------------------------------------------------------------- */
template <class Entity> class Communications<Entity>::iterator {
using communication_iterator =
- typename std::map<UInt, Communication>::iterator;
+ typename std::map<Int, Communication>::iterator;
public:
iterator() : communications(nullptr) {}
iterator(scheme_iterator scheme_it, communication_iterator comm_it,
Communications<Entity> & communications,
const SynchronizationTag & tag)
: scheme_it(scheme_it), comm_it(comm_it), communications(&communications),
tag(tag) {}
iterator(const iterator & other) = default;
iterator(iterator && other) noexcept = default;
iterator & operator=(const iterator & other) = default;
iterator & operator=(iterator && other) noexcept = default;
iterator & operator++() {
++scheme_it;
++comm_it;
return *this;
}
CommunicationDescriptor<Entity> operator*() {
AKANTU_DEBUG_ASSERT(
scheme_it->first == comm_it->first,
"The two iterators are not in phase, something wrong"
<< " happened, time to take out your favorite debugger ("
<< scheme_it->first << " != " << comm_it->first << ")");
return CommunicationDescriptor<Entity>(comm_it->second, scheme_it->second,
*communications, tag,
scheme_it->first);
}
bool operator==(const iterator & other) const {
return scheme_it == other.scheme_it && comm_it == other.comm_it;
}
bool operator!=(const iterator & other) const {
return scheme_it != other.scheme_it || comm_it != other.comm_it;
}
private:
scheme_iterator scheme_it;
communication_iterator comm_it;
Communications<Entity> * communications;
SynchronizationTag tag;
};
/* -------------------------------------------------------------------------- */
template <class Entity> class Communications<Entity>::tag_iterator {
- using internal_iterator = std::map<SynchronizationTag, UInt>::const_iterator;
+ using internal_iterator = std::map<SynchronizationTag, Int>::const_iterator;
public:
tag_iterator(const internal_iterator & it) : it(it) {}
tag_iterator & operator++() {
++it;
return *this;
}
SynchronizationTag operator*() { return it->first; }
bool operator==(const tag_iterator & other) const { return it == other.it; }
bool operator!=(const tag_iterator & other) const { return it != other.it; }
private:
internal_iterator it;
};
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::CommunicationPerProcs &
Communications<Entity>::getCommunications(const SynchronizationTag & tag,
const CommunicationSendRecv & sr) {
auto comm_it = this->communications[sr].find(tag);
if (comm_it == this->communications[sr].end()) {
AKANTU_CUSTOM_EXCEPTION_INFO(
debug::CommunicationException(),
"No known communications for the tag: " << tag);
}
return comm_it->second;
}
/* ---------------------------------------------------------------------- */
template <class Entity>
-UInt Communications<Entity>::getPending(
- const SynchronizationTag & tag, const CommunicationSendRecv & sr) const {
- const std::map<SynchronizationTag, UInt> & pending =
- pending_communications[sr];
+Int Communications<Entity>::getPending(const SynchronizationTag & tag,
+ const CommunicationSendRecv & sr) const {
+ const auto & pending = pending_communications[sr];
auto it = pending.find(tag);
if (it == pending.end()) {
return 0;
}
return it->second;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
bool Communications<Entity>::hasPending(
const SynchronizationTag & tag, const CommunicationSendRecv & sr) const {
return this->hasCommunication(tag) && (this->getPending(tag, sr) != 0);
}
/* ---------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::iterator
Communications<Entity>::begin(const SynchronizationTag & tag,
const CommunicationSendRecv & sr) {
auto & comms = this->getCommunications(tag, sr);
return iterator(this->schemes[sr].begin(), comms.begin(), *this, tag);
}
template <class Entity>
typename Communications<Entity>::iterator
Communications<Entity>::end(const SynchronizationTag & tag,
const CommunicationSendRecv & sr) {
auto & comms = this->getCommunications(tag, sr);
return iterator(this->schemes[sr].end(), comms.end(), *this, tag);
}
/* ---------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::iterator
Communications<Entity>::waitAny(const SynchronizationTag & tag,
const CommunicationSendRecv & sr) {
auto & comms = this->getCommunications(tag, sr);
auto it = comms.begin();
auto end = comms.end();
std::vector<CommunicationRequest> requests;
for (; it != end; ++it) {
auto & request = it->second.request();
if (!request.isFreed()) {
requests.push_back(request);
}
}
- UInt req_id = Communicator::waitAny(requests);
- if (req_id != UInt(-1)) {
+ auto req_id = Communicator::waitAny(requests);
+ if (req_id != -1) {
auto & request = requests[req_id];
- UInt proc = sr == _recv ? request.getSource() : request.getDestination();
+ auto proc = sr == _recv ? request.getSource() : request.getDestination();
return iterator(this->schemes[sr].find(proc), comms.find(proc), *this, tag);
}
return this->end(tag, sr);
}
/* ---------------------------------------------------------------------- */
template <class Entity>
void Communications<Entity>::waitAll(const SynchronizationTag & tag,
const CommunicationSendRecv & sr) {
auto & comms = this->getCommunications(tag, sr);
auto it = comms.begin();
auto end = comms.end();
std::vector<CommunicationRequest> requests;
for (; it != end; ++it) {
requests.push_back(it->second.request());
}
Communicator::waitAll(requests);
}
template <class Entity>
void Communications<Entity>::incrementPending(
const SynchronizationTag & tag, const CommunicationSendRecv & sr) {
++(pending_communications[sr][tag]);
}
template <class Entity>
void Communications<Entity>::decrementPending(
const SynchronizationTag & tag, const CommunicationSendRecv & sr) {
--(pending_communications[sr][tag]);
}
template <class Entity>
void Communications<Entity>::freeRequests(const SynchronizationTag & tag,
const CommunicationSendRecv & sr) {
- iterator it = this->begin(tag, sr);
- iterator end = this->end(tag, sr);
+ auto it = this->begin(tag, sr);
+ auto end = this->end(tag, sr);
for (; it != end; ++it) {
(*it).freeRequest();
}
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::Scheme &
-Communications<Entity>::createScheme(UInt proc,
+Communications<Entity>::createScheme(Idx proc,
const CommunicationSendRecv & sr) {
// scheme_iterator it = schemes[sr].find(proc);
// if (it != schemes[sr].end()) {
// AKANTU_CUSTOM_EXCEPTION_INFO(debug::CommunicationException(),
// "Communication scheme("
// << sr
// << ") already created for proc: " <<
// proc);
// }
return schemes[sr][proc];
}
template <class Entity>
void Communications<Entity>::resetSchemes(const CommunicationSendRecv & sr) {
auto it = this->schemes[sr].begin();
auto end = this->schemes[sr].end();
for (; it != end; ++it) {
it->second.resize(0);
}
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void Communications<Entity>::setCommunicationSize(
- const SynchronizationTag & tag, UInt proc, UInt size,
+ const SynchronizationTag & tag, Idx proc, Idx size,
const CommunicationSendRecv & sr) {
// accessor that fails if it does not exists
comm_size_computed[tag] = true; // TODO: need perhaps to be split based on sr
auto & comms = this->communications[sr];
auto & comms_per_tag = comms.at(tag);
comms_per_tag.at(proc).resize(size);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void Communications<Entity>::initializeCommunications(
const SynchronizationTag & tag) {
for (auto t : send_recv_t{}) {
pending_communications[t].insert(std::make_pair(tag, 0));
auto & comms = this->communications[t];
auto & comms_per_tag =
comms.insert(std::make_pair(tag, CommunicationPerProcs()))
.first->second;
for (const auto & pair : this->schemes[t]) {
comms_per_tag.emplace(std::piecewise_construct,
std::forward_as_tuple(pair.first),
std::forward_as_tuple(t));
}
}
comm_counter.insert(std::make_pair(tag, 0));
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::tag_iterator
Communications<Entity>::begin_tag() {
return tag_iterator(comm_counter.begin());
}
template <class Entity>
typename Communications<Entity>::tag_iterator
Communications<Entity>::end_tag() {
return tag_iterator(comm_counter.end());
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::scheme_iterator
Communications<Entity>::begin_scheme(const CommunicationSendRecv & sr) {
return this->schemes[sr].begin();
}
template <class Entity>
typename Communications<Entity>::scheme_iterator
Communications<Entity>::end_scheme(const CommunicationSendRecv & sr) {
return this->schemes[sr].end();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::const_scheme_iterator
Communications<Entity>::begin_scheme(const CommunicationSendRecv & sr) const {
return this->schemes[sr].begin();
}
template <class Entity>
typename Communications<Entity>::const_scheme_iterator
Communications<Entity>::end_scheme(const CommunicationSendRecv & sr) const {
return this->schemes[sr].end();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::scheme_iterator
Communications<Entity>::begin_send_scheme() {
return this->begin_scheme(_send);
}
template <class Entity>
typename Communications<Entity>::scheme_iterator
Communications<Entity>::end_send_scheme() {
return this->end_scheme(_send);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::const_scheme_iterator
Communications<Entity>::begin_send_scheme() const {
return this->begin_scheme(_send);
}
template <class Entity>
typename Communications<Entity>::const_scheme_iterator
Communications<Entity>::end_send_scheme() const {
return this->end_scheme(_send);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::scheme_iterator
Communications<Entity>::begin_recv_scheme() {
return this->begin_scheme(_recv);
}
template <class Entity>
typename Communications<Entity>::scheme_iterator
Communications<Entity>::end_recv_scheme() {
return this->end_scheme(_recv);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::const_scheme_iterator
Communications<Entity>::begin_recv_scheme() const {
return this->begin_scheme(_recv);
}
template <class Entity>
typename Communications<Entity>::const_scheme_iterator
Communications<Entity>::end_recv_scheme() const {
return this->end_scheme(_recv);
}
/* ------------------------------------------------------------------------ */
template <class Entity>
bool Communications<Entity>::hasCommunication(
const SynchronizationTag & tag) const {
return (communications[_send].find(tag) != communications[_send].end());
}
template <class Entity>
void Communications<Entity>::incrementCounter(const SynchronizationTag & tag) {
auto it = comm_counter.find(tag);
if (it == comm_counter.end()) {
AKANTU_CUSTOM_EXCEPTION_INFO(
debug::CommunicationException(),
"No counter initialized in communications for the tags: " << tag);
}
++(it->second);
}
template <class Entity>
-UInt Communications<Entity>::getCounter(const SynchronizationTag & tag) const {
+Int Communications<Entity>::getCounter(const SynchronizationTag & tag) const {
auto it = comm_counter.find(tag);
if (it == comm_counter.end()) {
AKANTU_CUSTOM_EXCEPTION_INFO(
debug::CommunicationException(),
"No counter initialized in communications for the tags: " << tag);
}
return it->second;
}
template <class Entity>
bool Communications<Entity>::hasCommunicationSize(
const SynchronizationTag & tag) const {
auto it = comm_size_computed.find(tag);
if (it == comm_size_computed.end()) {
return false;
}
return it->second;
}
template <class Entity> void Communications<Entity>::invalidateSizes() {
for (auto && pair : comm_size_computed) {
pair.second = false;
}
}
template <class Entity>
bool Communications<Entity>::hasPendingRecv(
const SynchronizationTag & tag) const {
return this->hasPending(tag, _recv);
}
template <class Entity>
bool Communications<Entity>::hasPendingSend(
const SynchronizationTag & tag) const {
return this->hasPending(tag, _send);
}
template <class Entity>
const auto & Communications<Entity>::getCommunicator() const {
return communicator;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::iterator
Communications<Entity>::waitAnyRecv(const SynchronizationTag & tag) {
return this->waitAny(tag, _recv);
}
template <class Entity>
typename Communications<Entity>::iterator
Communications<Entity>::waitAnySend(const SynchronizationTag & tag) {
return this->waitAny(tag, _send);
}
template <class Entity>
void Communications<Entity>::waitAllRecv(const SynchronizationTag & tag) {
this->waitAll(tag, _recv);
}
template <class Entity>
void Communications<Entity>::waitAllSend(const SynchronizationTag & tag) {
this->waitAll(tag, _send);
}
template <class Entity>
void Communications<Entity>::freeSendRequests(const SynchronizationTag & tag) {
this->freeRequests(tag, _send);
}
template <class Entity>
void Communications<Entity>::freeRecvRequests(const SynchronizationTag & tag) {
this->freeRequests(tag, _recv);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::Scheme &
-Communications<Entity>::createSendScheme(UInt proc) {
+Communications<Entity>::createSendScheme(Idx proc) {
return createScheme(proc, _send);
}
template <class Entity>
typename Communications<Entity>::Scheme &
-Communications<Entity>::createRecvScheme(UInt proc) {
+Communications<Entity>::createRecvScheme(Idx proc) {
return createScheme(proc, _recv);
}
/* -------------------------------------------------------------------------- */
template <class Entity> void Communications<Entity>::resetSchemes() {
resetSchemes(_send);
resetSchemes(_recv);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
typename Communications<Entity>::Scheme &
-Communications<Entity>::getScheme(UInt proc, const CommunicationSendRecv & sr) {
+Communications<Entity>::getScheme(Idx proc, const CommunicationSendRecv & sr) {
return this->schemes[sr].find(proc)->second;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
const typename Communications<Entity>::Scheme &
-Communications<Entity>::getScheme(UInt proc,
+Communications<Entity>::getScheme(Idx proc,
const CommunicationSendRecv & sr) const {
return this->schemes[sr].find(proc)->second;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void Communications<Entity>::setSendCommunicationSize(
- const SynchronizationTag & tag, UInt proc, UInt size) {
+ const SynchronizationTag & tag, Idx proc, Int size) {
this->setCommunicationSize(tag, proc, size, _send);
}
template <class Entity>
void Communications<Entity>::setRecvCommunicationSize(
- const SynchronizationTag & tag, UInt proc, UInt size) {
+ const SynchronizationTag & tag, Idx proc, Int size) {
this->setCommunicationSize(tag, proc, size, _recv);
}
} // namespace akantu
#endif /* AKANTU_COMMUNICATIONS_TMPL_HH_ */
diff --git a/src/synchronizer/communicator.cc b/src/synchronizer/communicator.cc
index 35465e618..ca3d0ceb7 100644
--- a/src/synchronizer/communicator.cc
+++ b/src/synchronizer/communicator.cc
@@ -1,192 +1,192 @@
/**
* @file communicator.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Jun 05 2019
*
* @brief implementation of the common part of the static communicator
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#if defined(AKANTU_USE_MPI)
#include "mpi_communicator_data.hh"
#endif
/* -------------------------------------------------------------------------- */
namespace akantu {
#if defined(AKANTU_USE_MPI)
int MPICommunicatorData::is_externaly_initialized = 0;
#endif
-UInt InternalCommunicationRequest::counter = 0;
+Int InternalCommunicationRequest::counter = 0;
/* -------------------------------------------------------------------------- */
-InternalCommunicationRequest::InternalCommunicationRequest(UInt source,
- UInt dest)
+InternalCommunicationRequest::InternalCommunicationRequest(Idx source, Idx dest)
: source(source), destination(dest) {
this->id = counter++;
}
/* -------------------------------------------------------------------------- */
InternalCommunicationRequest::~InternalCommunicationRequest() = default;
/* -------------------------------------------------------------------------- */
void InternalCommunicationRequest::printself(std::ostream & stream,
int indent) const {
std::string space(indent, AKANTU_INDENT);
stream << space << "CommunicationRequest [" << std::endl;
stream << space << " + id : " << id << std::endl;
stream << space << " + source : " << source << std::endl;
stream << space << " + destination : " << destination << std::endl;
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
Communicator::~Communicator() {
auto * event = new FinalizeCommunicatorEvent(*this);
this->sendEvent(*event);
delete event;
}
/* -------------------------------------------------------------------------- */
Communicator & Communicator::getStaticCommunicator() {
AKANTU_DEBUG_IN();
if (!static_communicator) {
int nb_args = 0;
char ** null = nullptr;
static_communicator =
std::make_unique<Communicator>(nb_args, null, private_member{});
}
AKANTU_DEBUG_OUT();
return *static_communicator;
}
/* -------------------------------------------------------------------------- */
Communicator & Communicator::getStaticCommunicator(int & argc, char **& argv) {
if (!static_communicator) {
static_communicator =
std::make_unique<Communicator>(argc, argv, private_member{});
}
return getStaticCommunicator();
}
} // namespace akantu
#ifdef AKANTU_USE_MPI
#include "communicator_mpi_inline_impl.hh"
#else
#include "communicator_dummy_inline_impl.hh"
#endif
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Template instantiation */
/* -------------------------------------------------------------------------- */
#define AKANTU_COMM_INSTANTIATE(T) \
template void Communicator::probe<T>(Int sender, Int tag, \
CommunicationStatus & status) const; \
template bool Communicator::asyncProbe<T>( \
Int sender, Int tag, CommunicationStatus & status) const; \
template void Communicator::sendImpl<T>( \
const T * buffer /*NOLINT*/, Int size, Int receiver, Int tag, \
const CommunicationMode & mode) const; \
template void Communicator::receiveImpl<T>(T * buffer /*NOLINT*/, Int size, \
Int sender, Int tag) const; \
template CommunicationRequest Communicator::asyncSendImpl<T>( \
const T * buffer /*NOLINT*/, Int size, Int receiver, Int tag, \
const CommunicationMode & mode) const; \
template CommunicationRequest Communicator::asyncReceiveImpl<T>( \
T * buffer /* NOLINT */, Int size, Int sender, Int tag) const; \
template void Communicator::allGatherImpl<T>(T * values /*NOLINT*/, \
int nb_values) const; \
template void Communicator::allGatherVImpl<T>(T * values /*NOLINT*/, \
int * nb_values) const; \
template void Communicator::gatherImpl<T>(T * values /*NOLINT*/, \
int nb_values, int root) const; \
template void Communicator::gatherImpl<T>( \
T * values /*NOLINT*/, int nb_values, T * gathered /*NOLINT*/, \
int nb_gathered) const; \
template void Communicator::gatherVImpl<T>(T * values /*NOLINT*/, \
int * nb_values, int root) const; \
template void Communicator::broadcastImpl<T>(T * values /*NOLINT*/, \
int nb_values, int root) const; \
template void Communicator::allReduceImpl<T>( \
T * values /*NOLINT*/, int nb_values, SynchronizerOperation op) const; \
template void Communicator::scanImpl<T>(T * values /*NOLINT*/, \
T * /*NOLINT*/, int nb_values, \
SynchronizerOperation op) const; \
template void Communicator::exclusiveScanImpl<T>( \
T * values /*NOLINT*/, T * /*NOLINT*/, int nb_values, \
SynchronizerOperation op) const
#define MIN_MAX_REAL SCMinMaxLoc<Real, int>
#if !defined(DOXYGEN)
AKANTU_COMM_INSTANTIATE(bool);
AKANTU_COMM_INSTANTIATE(Real);
AKANTU_COMM_INSTANTIATE(UInt);
AKANTU_COMM_INSTANTIATE(Int);
AKANTU_COMM_INSTANTIATE(char);
AKANTU_COMM_INSTANTIATE(NodeFlag);
AKANTU_COMM_INSTANTIATE(MIN_MAX_REAL);
+AKANTU_COMM_INSTANTIATE(std::size_t);
#if AKANTU_INTEGER_SIZE > 4
AKANTU_COMM_INSTANTIATE(int);
#endif
#endif
// template void Communicator::send<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * buffer, Int size, Int receiver, Int tag);
// template void Communicator::receive<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * buffer, Int size, Int sender, Int tag);
// template CommunicationRequest
// Communicator::asyncSend<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * buffer, Int size, Int receiver, Int tag);
// template CommunicationRequest
// Communicator::asyncReceive<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * buffer, Int size, Int sender, Int tag);
// template void Communicator::probe<SCMinMaxLoc<Real, int>>(
// Int sender, Int tag, CommunicationStatus & status);
// template void Communicator::allGather<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * values, int nb_values);
// template void Communicator::allGatherV<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * values, int * nb_values);
// template void Communicator::gather<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * values, int nb_values, int root);
// template void Communicator::gatherV<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * values, int * nb_values, int root);
// template void Communicator::broadcast<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * values, int nb_values, int root);
// template void Communicator::allReduce<SCMinMaxLoc<Real, int>>(
// SCMinMaxLoc<Real, int> * values, int nb_values,
// const SynchronizerOperation & op);
} // namespace akantu
diff --git a/src/synchronizer/communicator.hh b/src/synchronizer/communicator.hh
index be9e40c47..f4ec3ccd2 100644
--- a/src/synchronizer/communicator.hh
+++ b/src/synchronizer/communicator.hh
@@ -1,560 +1,550 @@
/**
* @file communicator.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Dec 09 2020
*
* @brief Class handling the parallel communications
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "aka_event_handler_manager.hh"
#include "communication_buffer.hh"
#include "communication_request.hh"
#include "communicator_event_handler.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_STATIC_COMMUNICATOR_HH_
#define AKANTU_STATIC_COMMUNICATOR_HH_
namespace akantu {
namespace debug {
class CommunicationException : public Exception {
public:
CommunicationException()
: Exception("An exception happen during a communication process.") {}
};
} // namespace debug
/// @enum SynchronizerOperation reduce operation that the synchronizer can
/// perform
enum class SynchronizerOperation {
_sum,
_min,
_max,
_prod,
_land,
_band,
_lor,
_bor,
_lxor,
_bxor,
_min_loc,
_max_loc,
_null
};
enum class CommunicationMode { _auto, _synchronous, _ready };
namespace {
int _any_source = -1;
}
} // namespace akantu
namespace akantu {
struct CommunicatorInternalData {
virtual ~CommunicatorInternalData() = default;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class Communicator : public EventHandlerManager<CommunicatorEventHandler> {
struct private_member {};
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
Communicator(int & argc, char **& argv, const private_member & /*m*/);
Communicator(const private_member & /*unused*/ = private_member{});
~Communicator() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Point to Point */
/* ------------------------------------------------------------------------ */
template <typename T>
void probe(Int sender, Int tag, CommunicationStatus & status) const;
template <typename T>
bool asyncProbe(Int sender, Int tag, CommunicationStatus & status) const;
/* ------------------------------------------------------------------------ */
template <typename T>
inline void receive(Array<T> & values, Int sender, Int tag) const {
return this->receiveImpl(
- values.storage(), values.size() * values.getNbComponent(), sender, tag);
+ values.data(), values.size() * values.getNbComponent(), sender, tag);
}
template <typename T>
inline void receive(std::vector<T> & values, Int sender, Int tag) const {
return this->receiveImpl(values.data(), values.size(), sender, tag);
}
template <typename Tensor>
inline void
receive(Tensor & values, Int sender, Int tag,
std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
nullptr) const {
- return this->receiveImpl(values.storage(), values.size(), sender, tag);
+ return this->receiveImpl(values.data(), values.size(), sender, tag);
}
inline void receive(CommunicationBufferTemplated<true> & values, Int sender,
Int tag) const {
- return this->receiveImpl(values.storage(), values.size(), sender, tag);
+ return this->receiveImpl(values.data(), values.size(), sender, tag);
}
inline void receive(CommunicationBufferTemplated<false> & values, Int sender,
Int tag) const {
CommunicationStatus status;
this->probe<char>(sender, tag, status);
values.reserve(status.size());
- return this->receiveImpl(values.storage(), values.size(), sender, tag);
+ return this->receiveImpl(values.data(), values.size(), sender, tag);
}
template <typename T>
inline void
receive(T & values, Int sender, Int tag,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
return this->receiveImpl(&values, 1, sender, tag);
}
/* ------------------------------------------------------------------------ */
template <typename T>
inline void
send(const Array<T> & values, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const {
- return this->sendImpl(values.storage(),
+ return this->sendImpl(values.data(),
values.size() * values.getNbComponent(), receiver,
tag, mode);
}
template <typename T>
inline void
send(const std::vector<T> & values, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const {
return this->sendImpl(values.data(), values.size(), receiver, tag, mode);
}
- template <typename Tensor>
+ template <typename Tensor,
+ std::enable_if_t<aka::is_tensor_v<Tensor>> * = nullptr>
inline void
send(const Tensor & values, Int receiver, Int tag,
- const CommunicationMode & mode = CommunicationMode::_auto,
- std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
- nullptr) const {
- return this->sendImpl(values.storage(), values.size(), receiver, tag, mode);
+ const CommunicationMode & mode = CommunicationMode::_auto) const {
+ return this->sendImpl(values.data(), values.size(), receiver, tag, mode);
}
template <bool is_static>
inline void
send(const CommunicationBufferTemplated<is_static> & values, Int receiver,
Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const {
- return this->sendImpl(values.storage(), values.size(), receiver, tag, mode);
+ return this->sendImpl(values.data(), values.size(), receiver, tag, mode);
}
template <typename T>
inline void send(const T & values, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
return this->sendImpl(&values, 1, receiver, tag, mode);
}
/* ------------------------------------------------------------------------ */
template <typename T>
inline CommunicationRequest
asyncSend(const Array<T> & values, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const {
- return this->asyncSendImpl(values.storage(),
+ return this->asyncSendImpl(values.data(),
values.size() * values.getNbComponent(),
receiver, tag, mode);
}
template <typename T>
inline CommunicationRequest
asyncSend(const std::vector<T> & values, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const {
return this->asyncSendImpl(values.data(), values.size(), receiver, tag,
mode);
}
template <typename Tensor>
- inline CommunicationRequest
- asyncSend(const Tensor & values, Int receiver, Int tag,
- const CommunicationMode & mode = CommunicationMode::_auto,
- std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
- nullptr) const {
- return this->asyncSendImpl(values.storage(), values.size(), receiver, tag,
+ inline CommunicationRequest asyncSend(
+ const Tensor & values, Int receiver, Int tag,
+ const CommunicationMode & mode = CommunicationMode::_auto,
+ std::enable_if_t<aka::is_tensor_v<Tensor>> * /*unused*/ = nullptr) const {
+ return this->asyncSendImpl(values.data(), values.size(), receiver, tag,
mode);
}
template <bool is_static>
inline CommunicationRequest
asyncSend(const CommunicationBufferTemplated<is_static> & values,
Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const {
- return this->asyncSendImpl(values.storage(), values.size(), receiver, tag,
+ return this->asyncSendImpl(values.data(), values.size(), receiver, tag,
mode);
}
template <typename T>
inline CommunicationRequest
asyncSend(const T & values, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
return this->asyncSendImpl(&values, 1, receiver, tag, mode);
}
/* ------------------------------------------------------------------------ */
template <typename T>
inline CommunicationRequest asyncReceive(Array<T> & values, Int sender,
Int tag) const {
return this->asyncReceiveImpl(
- values.storage(), values.size() * values.getNbComponent(), sender, tag);
+ values.data(), values.size() * values.getNbComponent(), sender, tag);
}
template <typename T>
inline CommunicationRequest asyncReceive(std::vector<T> & values, Int sender,
Int tag) const {
return this->asyncReceiveImpl(values.data(), values.size(), sender, tag);
}
template <typename Tensor,
- typename = std::enable_if_t<aka::is_tensor<Tensor>::value>>
+ typename = std::enable_if_t<aka::is_tensor_v<Tensor>>>
inline CommunicationRequest asyncReceive(Tensor & values, Int sender,
Int tag) const {
- return this->asyncReceiveImpl(values.storage(), values.size(), sender, tag);
+ return this->asyncReceiveImpl(values.data(), values.size(), sender, tag);
}
template <bool is_static>
inline CommunicationRequest
asyncReceive(CommunicationBufferTemplated<is_static> & values, Int sender,
Int tag) const {
- return this->asyncReceiveImpl(values.storage(), values.size(), sender, tag);
+ return this->asyncReceiveImpl(values.data(), values.size(), sender, tag);
}
/* ------------------------------------------------------------------------ */
/* Collectives */
/* ------------------------------------------------------------------------ */
template <typename T>
inline void
allReduce(Array<T> & values,
SynchronizerOperation op = SynchronizerOperation::_sum) const {
- this->allReduceImpl(values.storage(),
- values.size() * values.getNbComponent(), op);
+ this->allReduceImpl(values.data(), values.size() * values.getNbComponent(),
+ op);
}
- template <typename Tensor>
+ template <typename Derived>
inline void
- allReduce(Tensor & values,
- SynchronizerOperation op = SynchronizerOperation::_sum,
- std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
- nullptr) const {
- this->allReduceImpl(values.storage(), values.size(), op);
+ allReduce(Eigen::MatrixBase<Derived> & values,
+ SynchronizerOperation op = SynchronizerOperation::_sum) const {
+ this->allReduceImpl(values.derived().data(), values.size(), op);
}
template <typename T>
inline void
allReduce(T & values, SynchronizerOperation op = SynchronizerOperation::_sum,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
this->allReduceImpl(&values, 1, op);
}
template <typename T>
inline void
scan(Array<T> & values,
SynchronizerOperation op = SynchronizerOperation::_sum) const {
- this->scanImpl(values.storage(), values.storage(),
- values.size() * values.getNbComponent(), op);
+ this->scanImpl(values.data(), values.size() * values.getNbComponent(), op);
}
template <typename Tensor>
- inline void
- scan(Tensor & values, SynchronizerOperation op,
- std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
- nullptr) const {
- this->scanImpl(values.storage(), values.storage(), values.size(), op);
+ inline void scan(
+ Tensor & values, SynchronizerOperation op,
+ std::enable_if_t<aka::is_tensor_v<Tensor>> * /*unused*/ = nullptr) const {
+ this->scanImpl(values.data(), values.data(), values.size(), op);
}
template <typename T>
inline void scan(T & values,
SynchronizerOperation op = SynchronizerOperation::_sum,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
this->scanImpl(&values, &values, 1, op);
}
template <typename T>
inline void
exclusiveScan(Array<T> & values,
SynchronizerOperation op = SynchronizerOperation::_sum) const {
- this->exclusiveScanImpl(values.storage(), values.storage(),
+ this->exclusiveScanImpl(values.data(), values.data(),
values.size() * values.getNbComponent(), op);
}
template <typename Tensor>
inline void
exclusiveScan(Tensor & values,
SynchronizerOperation op = SynchronizerOperation::_sum,
- std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
- nullptr) const {
- this->exclusiveScanImpl(values.storage(), values.storage(), values.size(),
- op);
+ std::enable_if_t<aka::is_tensor_v<Tensor>> * = nullptr) const {
+ this->exclusiveScanImpl(values.data(), values.size(), op);
}
template <typename T>
inline void
exclusiveScan(T & values,
SynchronizerOperation op = SynchronizerOperation::_sum,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
this->exclusiveScanImpl(&values, &values, 1, op);
}
template <typename T>
inline void
exclusiveScan(T & values, T & result,
SynchronizerOperation op = SynchronizerOperation::_sum,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
this->exclusiveScanImpl(&values, &result, 1, op);
}
/* ------------------------------------------------------------------------ */
template <typename T> inline void allGather(Array<T> & values) const {
- AKANTU_DEBUG_ASSERT(UInt(getNbProc()) == values.size(),
+ AKANTU_DEBUG_ASSERT(getNbProc() == values.size(),
"The array size is not correct");
- this->allGatherImpl(values.storage(), values.getNbComponent());
+ this->allGatherImpl(values.data(), values.getNbComponent());
}
template <typename Tensor,
- typename = std::enable_if_t<aka::is_tensor<Tensor>::value>>
+ typename = std::enable_if_t<aka::is_tensor_v<Tensor>>>
inline void allGather(Tensor & values) const {
AKANTU_DEBUG_ASSERT(values.size() / getNbProc() > 0,
"The vector size is not correct");
- this->allGatherImpl(values.storage(), values.size() / getNbProc());
+ this->allGatherImpl(values.data(), values.size() / getNbProc());
}
/* ------------------------------------------------------------------------ */
template <typename T>
inline void allGatherV(Array<T> & values, const Array<Int> & sizes) const {
- this->allGatherVImpl(values.storage(), sizes.storage());
+ this->allGatherVImpl(values.data(), sizes.data());
}
/* ------------------------------------------------------------------------ */
template <typename T>
inline void reduce(Array<T> & values, SynchronizerOperation op,
int root = 0) const {
- this->reduceImpl(values.storage(), values.size() * values.getNbComponent(),
- op, root);
+ this->reduceImpl(values.data(), values.size() * values.getNbComponent(), op,
+ root);
}
/* ------------------------------------------------------------------------ */
template <typename Tensor>
- inline void
- gather(Tensor & values, int root = 0,
- std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
- nullptr) const {
- this->gatherImpl(values.storage(), values.getNbComponent(), root);
+ inline void gather(
+ Tensor & values, int root = 0,
+ std::enable_if_t<aka::is_tensor_v<Tensor>> * /*unused*/ = nullptr) const {
+ this->gatherImpl(values.data(), values.getNbComponent(), root);
}
template <typename T>
inline void
gather(T values, int root = 0,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
this->gatherImpl(&values, 1, root);
}
/* ------------------------------------------------------------------------ */
template <typename Tensor, typename T>
- inline void
- gather(Tensor & values, Array<T> & gathered,
- std::enable_if_t<aka::is_tensor<Tensor>::value> * /*unused*/ =
- nullptr) const {
+ inline void gather(
+ Tensor & values, Array<T> & gathered,
+ std::enable_if_t<aka::is_tensor_v<Tensor>> * /*unused*/ = nullptr) const {
AKANTU_DEBUG_ASSERT(values.size() == gathered.getNbComponent(),
"The array size is not correct");
gathered.resize(getNbProc());
- this->gatherImpl(values.data(), values.size(), gathered.storage(),
+ this->gatherImpl(values.data(), values.size(), gathered.data(),
gathered.getNbComponent());
}
template <typename T>
inline void
gather(T values, Array<T> & gathered,
std::enable_if_t<std::is_arithmetic<T>::value> * /*unused*/ =
nullptr) const {
- this->gatherImpl(&values, 1, gathered.storage(), 1);
+ this->gatherImpl(&values, 1, gathered.data(), 1);
}
/* ------------------------------------------------------------------------ */
template <typename T>
inline void gatherV(Array<T> & values, const Array<Int> & sizes,
int root = 0) const {
- this->gatherVImpl(values.storage(), sizes.storage(), root);
+ this->gatherVImpl(values.data(), sizes.data(), root);
}
/* ------------------------------------------------------------------------ */
template <typename T>
inline void broadcast(Array<T> & values, int root = 0) const {
- this->broadcastImpl(values.storage(),
- values.size() * values.getNbComponent(), root);
+ this->broadcastImpl(values.data(), values.size() * values.getNbComponent(),
+ root);
}
template <typename T>
inline void broadcast(std::vector<T> & values, int root = 0) const {
this->broadcastImpl(values.data(), values.size(), root);
}
inline void broadcast(CommunicationBufferTemplated<true> & buffer,
int root = 0) const {
- this->broadcastImpl(buffer.storage(), buffer.size(), root);
+ this->broadcastImpl(buffer.data(), buffer.size(), root);
}
inline void broadcast(CommunicationBufferTemplated<false> & buffer,
int root = 0) const {
- UInt buffer_size = buffer.size();
+ auto buffer_size = buffer.size();
this->broadcastImpl(&buffer_size, 1, root);
if (whoAmI() != root) {
buffer.reserve(buffer_size);
}
if (buffer_size == 0) {
return;
}
- this->broadcastImpl(buffer.storage(), buffer.size(), root);
+ this->broadcastImpl(buffer.data(), buffer.size(), root);
}
template <typename T> inline void broadcast(T & values, int root = 0) const {
this->broadcastImpl(&values, 1, root);
}
/* ------------------------------------------------------------------------ */
void barrier() const;
CommunicationRequest asyncBarrier() const;
/* ------------------------------------------------------------------------ */
/* Request handling */
/* ------------------------------------------------------------------------ */
static bool test(CommunicationRequest & request);
static bool testAll(std::vector<CommunicationRequest> & request);
static void wait(CommunicationRequest & request);
static void waitAll(std::vector<CommunicationRequest> & requests);
- static UInt waitAny(std::vector<CommunicationRequest> & requests);
+ static Int waitAny(std::vector<CommunicationRequest> & requests);
static inline void freeCommunicationRequest(CommunicationRequest & request);
static inline void
freeCommunicationRequest(std::vector<CommunicationRequest> & requests);
template <typename T, typename MsgProcessor>
inline void
receiveAnyNumber(std::vector<CommunicationRequest> & send_requests,
MsgProcessor && processor, Int tag) const;
protected:
template <typename T>
void
sendImpl(const T * buffer, Int size, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const;
template <typename T>
void receiveImpl(T * buffer, Int size, Int sender, Int tag) const;
template <typename T>
CommunicationRequest asyncSendImpl(
const T * buffer, Int size, Int receiver, Int tag,
const CommunicationMode & mode = CommunicationMode::_auto) const;
template <typename T>
CommunicationRequest asyncReceiveImpl(T * buffer, Int size, Int sender,
Int tag) const;
template <typename T>
void allReduceImpl(T * values, int nb_values, SynchronizerOperation op) const;
template <typename T>
void scanImpl(T * values, T * results, int nb_values,
SynchronizerOperation op) const;
template <typename T>
void exclusiveScanImpl(T * values, T * results, int nb_values,
SynchronizerOperation op) const;
template <typename T> void allGatherImpl(T * values, int nb_values) const;
template <typename T> void allGatherVImpl(T * values, int * nb_values) const;
template <typename T>
void reduceImpl(T * values, int nb_values, SynchronizerOperation op,
int root = 0) const;
template <typename T>
void gatherImpl(T * values, int nb_values, int root = 0) const;
template <typename T>
void gatherImpl(T * values, int nb_values, T * gathered,
int nb_gathered = 0) const;
template <typename T>
void gatherVImpl(T * values, int * nb_values, int root = 0) const;
template <typename T>
void broadcastImpl(T * values, int nb_values, int root = 0) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
Int getNbProc() const;
Int whoAmI() const;
static Communicator & getStaticCommunicator();
static Communicator & getStaticCommunicator(int & argc, char **& argv);
int getMaxTag() const;
int getMinTag() const;
AKANTU_GET_MACRO(CommunicatorData, (*communicator_data), decltype(auto));
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
static std::unique_ptr<Communicator> static_communicator;
protected:
std::unique_ptr<CommunicatorInternalData> communicator_data;
};
inline std::ostream & operator<<(std::ostream & stream,
const CommunicationRequest & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "communicator_inline_impl.hh"
#endif /* AKANTU_STATIC_COMMUNICATOR_HH_ */
diff --git a/src/synchronizer/communicator_dummy_inline_impl.hh b/src/synchronizer/communicator_dummy_inline_impl.hh
index 8eec30acc..7792fb532 100644
--- a/src/synchronizer/communicator_dummy_inline_impl.hh
+++ b/src/synchronizer/communicator_dummy_inline_impl.hh
@@ -1,152 +1,152 @@
/**
* @file communicator_dummy_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Nov 07 2017
* @date last modification: Wed Dec 09 2020
*
* @brief Dummy communicator to make everything work im sequential
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
/* -------------------------------------------------------------------------- */
#include <cstring>
#include <type_traits>
#include <vector>
/* -------------------------------------------------------------------------- */
namespace akantu {
Communicator::Communicator(int & /*argc*/, char **& /*argv*/,
const private_member & /*unused*/) {}
Communicator::Communicator(const private_member & /*unused*/) {}
template <typename T>
void Communicator::sendImpl(const T * /*unused*/, Int /*unused*/,
Int /*unused*/, Int /*unused*/,
const CommunicationMode & /*unused*/) const {}
template <typename T>
void Communicator::receiveImpl(T * /*unused*/, Int /*unused*/, Int /*unused*/,
Int /*unused*/) const {}
template <typename T>
CommunicationRequest
Communicator::asyncSendImpl(const T * /*unused*/, Int /*unused*/,
Int /*unused*/, Int /*unused*/,
const CommunicationMode & /*unused*/) const {
return std::shared_ptr<InternalCommunicationRequest>(
new InternalCommunicationRequest(0, 0));
}
template <typename T>
CommunicationRequest
Communicator::asyncReceiveImpl(T * /*unused*/, Int /*unused*/, Int /*unused*/,
Int /*unused*/) const {
return std::shared_ptr<InternalCommunicationRequest>(
new InternalCommunicationRequest(0, 0));
}
template <typename T>
void Communicator::probe(Int /*unused*/, Int /*unused*/,
CommunicationStatus & /*unused*/) const {}
template <typename T>
bool Communicator::asyncProbe(Int /*unused*/, Int /*unused*/,
CommunicationStatus & /*unused*/) const {
return true;
}
bool Communicator::test(CommunicationRequest & /*unused*/) { return true; }
bool Communicator::testAll(std::vector<CommunicationRequest> & /*unused*/) {
return true;
}
void Communicator::wait(CommunicationRequest & /*unused*/) {}
void Communicator::waitAll(std::vector<CommunicationRequest> & /*unused*/) {}
-UInt Communicator::waitAny(std::vector<CommunicationRequest> & /*unused*/) {
- return UInt(-1);
+Int Communicator::waitAny(std::vector<CommunicationRequest> & /*unused*/) {
+ return -1;
}
void Communicator::barrier() const {}
CommunicationRequest Communicator::asyncBarrier() const {
return std::shared_ptr<InternalCommunicationRequest>(
new InternalCommunicationRequest(0, 0));
}
template <typename T>
void Communicator::reduceImpl(T * /*unused*/, int /*unused*/,
SynchronizerOperation /*unused*/,
int /*unused*/) const {}
template <typename T>
void Communicator::allReduceImpl(T * /*unused*/, int /*unused*/,
SynchronizerOperation /*unused*/) const {}
template <typename T>
void Communicator::scanImpl(T * values, T * result, int n,
SynchronizerOperation /*unused*/) const {
if (values == result) {
return;
}
std::copy_n(values, n, result);
}
template <typename T>
void Communicator::exclusiveScanImpl(T * /*values*/, T * result, int n,
SynchronizerOperation /*unused*/) const {
std::fill_n(result, n, T());
}
template <typename T>
inline void Communicator::allGatherImpl(T * /*unused*/, int /*unused*/) const {}
template <typename T>
inline void Communicator::allGatherVImpl(T * /*unused*/,
int * /*unused*/) const {}
template <typename T>
inline void Communicator::gatherImpl(T * /*unused*/, int /*unused*/,
int /*unused*/) const {}
template <typename T>
void Communicator::gatherImpl(T * values, int nb_values, T * gathered,
int /*unused*/) const {
static_assert(std::is_trivially_copyable<T>{},
"Cannot send this type of data");
std::memcpy(gathered, values, nb_values);
}
template <typename T>
inline void Communicator::gatherVImpl(T * /*unused*/, int * /*unused*/,
int /*unused*/) const {}
template <typename T>
inline void Communicator::broadcastImpl(T * /*unused*/, int /*unused*/,
int /*unused*/) const {}
int Communicator::getMaxTag() const { return std::numeric_limits<int>::max(); }
int Communicator::getMinTag() const { return 0; }
Int Communicator::getNbProc() const { return 1; }
Int Communicator::whoAmI() const { return 0; }
} // namespace akantu
diff --git a/src/synchronizer/communicator_mpi_inline_impl.hh b/src/synchronizer/communicator_mpi_inline_impl.hh
index 15b6194ff..d56d1f0fb 100644
--- a/src/synchronizer/communicator_mpi_inline_impl.hh
+++ b/src/synchronizer/communicator_mpi_inline_impl.hh
@@ -1,510 +1,510 @@
/**
* @file communicator_mpi_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Nov 07 2017
* @date last modification: Wed Dec 09 2020
*
* @brief StaticCommunicatorMPI implementation
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "communicator.hh"
#include "mpi_communicator_data.hh"
/* -------------------------------------------------------------------------- */
#include <memory>
#include <type_traits>
#include <unordered_map>
#include <vector>
/* -------------------------------------------------------------------------- */
#include <mpi.h>
/* -------------------------------------------------------------------------- */
#if (defined(__GNUC__) || defined(__GNUG__))
#if AKA_GCC_VERSION < 60000
namespace std {
template <> struct hash<akantu::SynchronizerOperation> {
using argument_type = akantu::SynchronizerOperation;
size_t operator()(const argument_type & e) const noexcept {
auto ue = underlying_type_t<argument_type>(e);
return uh(ue);
}
private:
const hash<underlying_type_t<argument_type>> uh{};
};
} // namespace std
#endif
#endif
namespace akantu {
class CommunicationRequestMPI : public InternalCommunicationRequest {
public:
- CommunicationRequestMPI(UInt source, UInt dest)
+ CommunicationRequestMPI(Idx source, Idx dest)
: InternalCommunicationRequest(source, dest),
request(std::make_unique<MPI_Request>()) {}
MPI_Request & getMPIRequest() { return *request; };
private:
std::unique_ptr<MPI_Request> request;
};
namespace {
template <typename T> inline MPI_Datatype getMPIDatatype();
MPI_Op getMPISynchronizerOperation(SynchronizerOperation op) {
std::unordered_map<SynchronizerOperation, MPI_Op> _operations{
{SynchronizerOperation::_sum, MPI_SUM},
{SynchronizerOperation::_min, MPI_MIN},
{SynchronizerOperation::_max, MPI_MAX},
{SynchronizerOperation::_prod, MPI_PROD},
{SynchronizerOperation::_land, MPI_LAND},
{SynchronizerOperation::_band, MPI_BAND},
{SynchronizerOperation::_lor, MPI_LOR},
{SynchronizerOperation::_bor, MPI_BOR},
{SynchronizerOperation::_lxor, MPI_LXOR},
{SynchronizerOperation::_bxor, MPI_BXOR},
{SynchronizerOperation::_min_loc, MPI_MINLOC},
{SynchronizerOperation::_max_loc, MPI_MAXLOC},
{SynchronizerOperation::_null, MPI_OP_NULL}};
return _operations[op];
}
template <typename T> MPI_Datatype inline getMPIDatatype() {
return MPI_DATATYPE_NULL;
}
#define SPECIALIZE_MPI_DATATYPE(type, mpi_type) \
template <> MPI_Datatype inline getMPIDatatype<type>() { return mpi_type; }
#define COMMA ,
SPECIALIZE_MPI_DATATYPE(char, MPI_CHAR)
SPECIALIZE_MPI_DATATYPE(std::uint8_t, MPI_UINT8_T)
SPECIALIZE_MPI_DATATYPE(float, MPI_FLOAT)
SPECIALIZE_MPI_DATATYPE(double, MPI_DOUBLE)
SPECIALIZE_MPI_DATATYPE(long double, MPI_LONG_DOUBLE)
SPECIALIZE_MPI_DATATYPE(signed int, MPI_INT)
SPECIALIZE_MPI_DATATYPE(unsigned int, MPI_UNSIGNED)
SPECIALIZE_MPI_DATATYPE(signed long int, MPI_LONG)
SPECIALIZE_MPI_DATATYPE(unsigned long int, MPI_UNSIGNED_LONG)
SPECIALIZE_MPI_DATATYPE(signed long long int, MPI_LONG_LONG)
SPECIALIZE_MPI_DATATYPE(unsigned long long int, MPI_UNSIGNED_LONG_LONG)
SPECIALIZE_MPI_DATATYPE(SCMinMaxLoc<double COMMA int>, MPI_DOUBLE_INT)
SPECIALIZE_MPI_DATATYPE(SCMinMaxLoc<float COMMA int>, MPI_FLOAT_INT)
SPECIALIZE_MPI_DATATYPE(bool, MPI_CXX_BOOL)
template <> MPI_Datatype inline getMPIDatatype<NodeFlag>() {
return getMPIDatatype<std::underlying_type_t<NodeFlag>>();
}
inline int getMPISource(int src) {
if (src == _any_source) {
return MPI_ANY_SOURCE;
}
return src;
}
decltype(auto) convertRequests(std::vector<CommunicationRequest> & requests) {
std::vector<MPI_Request> mpi_requests(requests.size());
for (auto && request_pair : zip(requests, mpi_requests)) {
auto && req = std::get<0>(request_pair);
auto && mpi_req = std::get<1>(request_pair);
mpi_req = aka::as_type<CommunicationRequestMPI>(req.getInternal())
.getMPIRequest();
}
return mpi_requests;
}
} // namespace
// this is ugly but shorten the code a lot
#define MPIDATA \
(*reinterpret_cast<MPICommunicatorData *>(communicator_data.get()))
/* -------------------------------------------------------------------------- */
/* Implementation */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
Communicator::Communicator(int & /*argc*/, char **& /*argv*/,
const private_member & m)
: Communicator(m) {}
/* -------------------------------------------------------------------------- */
Communicator::Communicator(const private_member & /*unused*/)
: communicator_data(std::make_unique<MPICommunicatorData>()) {}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::sendImpl(const T * buffer, Int size, Int receiver, Int tag,
const CommunicationMode & mode) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Datatype type = getMPIDatatype<T>();
switch (mode) {
case CommunicationMode::_auto:
MPI_Send(buffer, size, type, receiver, tag, communicator);
break;
case CommunicationMode::_synchronous:
MPI_Ssend(buffer, size, type, receiver, tag, communicator);
break;
case CommunicationMode::_ready:
MPI_Rsend(buffer, size, type, receiver, tag, communicator);
break;
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::receiveImpl(T * buffer, Int size, Int sender,
Int tag) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Status status;
MPI_Datatype type = getMPIDatatype<T>();
MPI_Recv(buffer, size, type, getMPISource(sender), tag, communicator,
&status);
}
/* -------------------------------------------------------------------------- */
template <typename T>
CommunicationRequest
Communicator::asyncSendImpl(const T * buffer, Int size, Int receiver, Int tag,
const CommunicationMode & mode) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
auto * request = new CommunicationRequestMPI(whoAmI(), receiver);
MPI_Request & req = request->getMPIRequest();
MPI_Datatype type = getMPIDatatype<T>();
switch (mode) {
case CommunicationMode::_auto:
MPI_Isend(buffer, size, type, receiver, tag, communicator, &req);
break;
case CommunicationMode::_synchronous:
MPI_Issend(buffer, size, type, receiver, tag, communicator, &req);
break;
case CommunicationMode::_ready:
MPI_Irsend(buffer, size, type, receiver, tag, communicator, &req);
break;
}
return std::shared_ptr<InternalCommunicationRequest>(request);
}
/* -------------------------------------------------------------------------- */
template <typename T>
CommunicationRequest Communicator::asyncReceiveImpl(T * buffer, Int size,
Int sender, Int tag) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
auto * request = new CommunicationRequestMPI(sender, whoAmI());
MPI_Datatype type = getMPIDatatype<T>();
MPI_Request & req = request->getMPIRequest();
MPI_Irecv(buffer, size, type, getMPISource(sender), tag, communicator, &req);
return std::shared_ptr<InternalCommunicationRequest>(request);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::probe(Int sender, Int tag,
CommunicationStatus & status) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Status mpi_status;
MPI_Probe(getMPISource(sender), tag, communicator, &mpi_status);
MPI_Datatype type = getMPIDatatype<T>();
int count;
MPI_Get_count(&mpi_status, type, &count);
status.setSource(mpi_status.MPI_SOURCE);
status.setTag(mpi_status.MPI_TAG);
status.setSize(count);
}
/* -------------------------------------------------------------------------- */
template <typename T>
bool Communicator::asyncProbe(Int sender, Int tag,
CommunicationStatus & status) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Status mpi_status;
int test;
MPI_Iprobe(getMPISource(sender), tag, communicator, &test, &mpi_status);
if (not test) {
return false;
}
MPI_Datatype type = getMPIDatatype<T>();
int count;
MPI_Get_count(&mpi_status, type, &count);
status.setSource(mpi_status.MPI_SOURCE);
status.setTag(mpi_status.MPI_TAG);
status.setSize(count);
return true;
}
/* -------------------------------------------------------------------------- */
bool Communicator::test(CommunicationRequest & request) {
MPI_Status status;
int flag;
auto & req_mpi = aka::as_type<CommunicationRequestMPI>(request.getInternal());
MPI_Request & req = req_mpi.getMPIRequest();
MPI_Test(&req, &flag, &status);
return flag != 0;
}
/* -------------------------------------------------------------------------- */
bool Communicator::testAll(std::vector<CommunicationRequest> & requests) {
// int are_finished;
// auto && mpi_requests = convertRequests(requests);
// MPI_Testall(mpi_requests.size(), mpi_requests.data(), &are_finished,
// MPI_STATUSES_IGNORE);
// return are_finished;
for (auto & request : requests) {
if (not test(request)) {
return false;
}
}
return true;
}
/* -------------------------------------------------------------------------- */
void Communicator::wait(CommunicationRequest & request) {
MPI_Status status;
auto & req_mpi = aka::as_type<CommunicationRequestMPI>(request.getInternal());
MPI_Request & req = req_mpi.getMPIRequest();
MPI_Wait(&req, &status);
}
/* -------------------------------------------------------------------------- */
void Communicator::waitAll(std::vector<CommunicationRequest> & requests) {
auto && mpi_requests = convertRequests(requests);
MPI_Waitall(mpi_requests.size(), mpi_requests.data(), MPI_STATUSES_IGNORE);
}
/* -------------------------------------------------------------------------- */
-UInt Communicator::waitAny(std::vector<CommunicationRequest> & requests) {
+Int Communicator::waitAny(std::vector<CommunicationRequest> & requests) {
auto && mpi_requests = convertRequests(requests);
int pos;
MPI_Waitany(mpi_requests.size(), mpi_requests.data(), &pos,
MPI_STATUSES_IGNORE);
if (pos != MPI_UNDEFINED) {
return pos;
}
- return UInt(-1);
+ return -1;
}
/* -------------------------------------------------------------------------- */
void Communicator::barrier() const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Barrier(communicator);
}
/* -------------------------------------------------------------------------- */
CommunicationRequest Communicator::asyncBarrier() const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
auto * request = new CommunicationRequestMPI(0, 0);
MPI_Request & req = request->getMPIRequest();
MPI_Ibarrier(communicator, &req);
return std::shared_ptr<InternalCommunicationRequest>(request);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::reduceImpl(T * values, int nb_values,
SynchronizerOperation op, int root) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Datatype type = getMPIDatatype<T>();
MPI_Reduce(MPI_IN_PLACE, values, nb_values, type,
getMPISynchronizerOperation(op), root, communicator);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::allReduceImpl(T * values, int nb_values,
SynchronizerOperation op) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Datatype type = getMPIDatatype<T>();
MPI_Allreduce(MPI_IN_PLACE, values, nb_values, type,
getMPISynchronizerOperation(op), communicator);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::scanImpl(T * values, T * result, int nb_values,
SynchronizerOperation op) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Datatype type = getMPIDatatype<T>();
if (values == result) {
values = reinterpret_cast<T *>(MPI_IN_PLACE);
}
MPI_Scan(values, result, nb_values, type, getMPISynchronizerOperation(op),
communicator);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::exclusiveScanImpl(T * values, T * result, int nb_values,
SynchronizerOperation op) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Datatype type = getMPIDatatype<T>();
if (values == result) {
values = reinterpret_cast<T *>(MPI_IN_PLACE);
}
MPI_Exscan(values, result, nb_values, type, getMPISynchronizerOperation(op),
communicator);
if (whoAmI() == 0) {
result[0] = T();
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::allGatherImpl(T * values, int nb_values) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Datatype type = getMPIDatatype<T>();
MPI_Allgather(MPI_IN_PLACE, nb_values, type, values, nb_values, type,
communicator);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::allGatherVImpl(T * values, int * nb_values) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
std::vector<int> displs(getNbProc());
displs[0] = 0;
for (int i = 1; i < getNbProc(); ++i) {
displs[i] = displs[i - 1] + nb_values[i - 1];
}
MPI_Datatype type = getMPIDatatype<T>();
MPI_Allgatherv(MPI_IN_PLACE, *nb_values, type, values, nb_values,
displs.data(), type, communicator);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::gatherImpl(T * values, int nb_values, int root) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
T * send_buf = nullptr;
T * recv_buf = nullptr;
if (whoAmI() == root) {
send_buf = (T *)MPI_IN_PLACE;
recv_buf = values;
} else {
send_buf = values;
}
MPI_Datatype type = getMPIDatatype<T>();
MPI_Gather(send_buf, nb_values, type, recv_buf, nb_values, type, root,
communicator);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::gatherImpl(T * values, int nb_values, T * gathered,
int nb_gathered) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
T * send_buf = values;
T * recv_buf = gathered;
if (nb_gathered == 0) {
nb_gathered = nb_values;
}
MPI_Datatype type = getMPIDatatype<T>();
MPI_Gather(send_buf, nb_values, type, recv_buf, nb_gathered, type, whoAmI(),
communicator);
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::gatherVImpl(T * values, int * nb_values, int root) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
int * displs = nullptr;
auto psize = getNbProc();
auto prank = whoAmI();
if (prank == root) {
displs = new int[psize];
displs[0] = 0;
for (int i = 1; i < psize; ++i) {
displs[i] = displs[i - 1] + nb_values[i - 1];
}
}
T * send_buf = nullptr;
T * recv_buf = nullptr;
if (prank == root) {
send_buf = (T *)MPI_IN_PLACE;
recv_buf = values;
} else {
send_buf = values;
}
MPI_Datatype type = getMPIDatatype<T>();
MPI_Gatherv(send_buf, *nb_values, type, recv_buf, nb_values, displs, type,
root, communicator);
if (prank == root) {
delete[] displs;
}
}
/* -------------------------------------------------------------------------- */
template <typename T>
void Communicator::broadcastImpl(T * values, int nb_values, int root) const {
MPI_Comm communicator = MPIDATA.getMPICommunicator();
MPI_Datatype type = getMPIDatatype<T>();
MPI_Bcast(values, nb_values, type, root, communicator);
}
/* -------------------------------------------------------------------------- */
int Communicator::getMaxTag() const { return MPIDATA.getMaxTag(); }
int Communicator::
getMinTag() // NOLINT(readability-convert-member-functions-to-static)
const {
return 0;
}
/* -------------------------------------------------------------------------- */
Int Communicator::getNbProc() const { return MPIDATA.size(); }
Int Communicator::whoAmI() const { return MPIDATA.rank(); }
} // namespace akantu
diff --git a/src/synchronizer/data_accessor.cc b/src/synchronizer/data_accessor.cc
index 2d41ddc73..5a39fa543 100644
--- a/src/synchronizer/data_accessor.cc
+++ b/src/synchronizer/data_accessor.cc
@@ -1,158 +1,127 @@
/**
* @file data_accessor.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Fri Apr 09 2021
*
* @brief data accessors constructor functions
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "data_accessor.hh"
#include "fe_engine.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename T, bool pack_helper>
void DataAccessor<Element>::packUnpackNodalDataHelper(
Array<T> & data, CommunicationBuffer & buffer,
const Array<Element> & elements, const Mesh & mesh) {
- UInt nb_component = data.getNbComponent();
- UInt nb_nodes_per_element = 0;
-
- ElementType current_element_type = _not_defined;
- GhostType current_ghost_type = _casper;
- UInt * conn = nullptr;
+ Int nb_component = data.getNbComponent();
+ auto data_it = make_view(data, nb_component).begin();
for (const auto & el : elements) {
- if (el.type != current_element_type ||
- el.ghost_type != current_ghost_type) {
- current_element_type = el.type;
- current_ghost_type = el.ghost_type;
- conn = mesh.getConnectivity(el.type, el.ghost_type).storage();
- nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type);
- }
-
- UInt el_offset = el.element * nb_nodes_per_element;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- UInt offset_conn = conn[el_offset + n];
- Vector<T> data_vect(data.storage() + offset_conn * nb_component,
- nb_component);
+ auto && conn = mesh.getConnectivity(el);
+ for (auto node : conn) {
+ auto && data_vect = data_it[node];
if (pack_helper) {
buffer << data_vect;
} else {
buffer >> data_vect;
}
}
}
}
/* ------------------------------------------------------------------------ */
template <typename T, bool pack_helper>
void DataAccessor<Element>::packUnpackElementalDataHelper(
ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
const Array<Element> & element, bool per_quadrature_point_data,
const FEEngine & fem) {
- ElementType current_element_type = _not_defined;
- GhostType current_ghost_type = _casper;
- UInt nb_quad_per_elem = 0;
- UInt nb_component = 0;
-
- Array<T> * vect = nullptr;
-
for (const auto & el : element) {
- if (el.type != current_element_type ||
- el.ghost_type != current_ghost_type) {
- current_element_type = el.type;
- current_ghost_type = el.ghost_type;
- vect = &data_to_pack(el.type, el.ghost_type);
-
- nb_quad_per_elem =
- per_quadrature_point_data
- ? fem.getNbIntegrationPoints(el.type, el.ghost_type)
- : 1;
- nb_component = vect->getNbComponent();
- }
+ auto nb_quad_per_elem =
+ per_quadrature_point_data
+ ? fem.getNbIntegrationPoints(el.type, el.ghost_type)
+ : 1;
+ auto nb_component = data_to_pack(el.type, el.ghost_type).getNbComponent();
+ auto && data = data_to_pack.get(el, nb_component * nb_quad_per_elem);
- Vector<T> data(vect->storage() +
- el.element * nb_component * nb_quad_per_elem,
- nb_component * nb_quad_per_elem);
if (pack_helper) {
buffer << data;
} else {
buffer >> data;
}
}
}
/* -------------------------------------------------------------------------- */
template <typename T, bool pack_helper>
-void DataAccessor<UInt>::packUnpackDOFDataHelper(Array<T> & data,
- CommunicationBuffer & buffer,
- const Array<UInt> & dofs) {
- T * data_ptr = data.storage();
+void DataAccessor<Idx>::packUnpackDOFDataHelper(Array<T> & data,
+ CommunicationBuffer & buffer,
+ const Array<Idx> & dofs) {
+ T * data_ptr = data.data();
for (const auto & dof : dofs) {
if (pack_helper) {
buffer << data_ptr[dof];
} else {
buffer >> data_ptr[dof];
}
}
}
/* -------------------------------------------------------------------------- */
#define DECLARE_HELPERS(T) \
template void DataAccessor<Element>::packUnpackNodalDataHelper<T, false>( \
Array<T> & data, CommunicationBuffer & buffer, \
const Array<Element> & elements, const Mesh & mesh); \
template void DataAccessor<Element>::packUnpackNodalDataHelper<T, true>( \
Array<T> & data, CommunicationBuffer & buffer, \
const Array<Element> & elements, const Mesh & mesh); \
template void \
DataAccessor<Element>::packUnpackElementalDataHelper<T, false>( \
ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer, \
const Array<Element> & element, bool per_quadrature_point_data, \
const FEEngine & fem); \
template void DataAccessor<Element>::packUnpackElementalDataHelper<T, true>( \
ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer, \
const Array<Element> & element, bool per_quadrature_point_data, \
const FEEngine & fem); \
- template void DataAccessor<UInt>::packUnpackDOFDataHelper<T, true>( \
- Array<T> & data, CommunicationBuffer & buffer, \
- const Array<UInt> & dofs); \
- template void DataAccessor<UInt>::packUnpackDOFDataHelper<T, false>( \
- Array<T> & data, CommunicationBuffer & buffer, const Array<UInt> & dofs)
+ template void DataAccessor<Idx>::packUnpackDOFDataHelper<T, true>( \
+ Array<T> & data, CommunicationBuffer & buffer, const Array<Idx> & dofs); \
+ template void DataAccessor<Idx>::packUnpackDOFDataHelper<T, false>( \
+ Array<T> & data, CommunicationBuffer & buffer, const Array<Idx> & dofs)
/* -------------------------------------------------------------------------- */
DECLARE_HELPERS(Real);
-DECLARE_HELPERS(UInt);
+DECLARE_HELPERS(Idx);
DECLARE_HELPERS(bool);
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/synchronizer/data_accessor.hh b/src/synchronizer/data_accessor.hh
index e706856d6..d2b04c02b 100644
--- a/src/synchronizer/data_accessor.hh
+++ b/src/synchronizer/data_accessor.hh
@@ -1,355 +1,361 @@
/**
* @file data_accessor.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Sep 01 2010
* @date last modification: Fri Apr 09 2021
*
* @brief Interface of accessors for pack_unpack system
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "communication_buffer.hh"
#include "element.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DATA_ACCESSOR_HH_
#define AKANTU_DATA_ACCESSOR_HH_
namespace akantu {
class FEEngine;
} // namespace akantu
namespace akantu {
class DataAccessorBase {
public:
DataAccessorBase() = default;
virtual ~DataAccessorBase() = default;
};
template <class T> class DataAccessor : public virtual DataAccessorBase {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
DataAccessor() = default;
~DataAccessor() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/**
* @brief get the number of data to exchange for a given array of T
* (elements or dofs) and a given akantu::SynchronizationTag
*/
- virtual UInt getNbData(const Array<T> & elements,
- const SynchronizationTag & tag) const = 0;
+ virtual Int getNbData(const Array<T> & elements,
+ const SynchronizationTag & tag) const = 0;
/**
* @brief pack the data for a given array of T (elements or dofs) and a given
* akantu::SynchronizationTag
*/
virtual void packData(CommunicationBuffer & buffer, const Array<T> & element,
const SynchronizationTag & tag) const = 0;
/**
* @brief unpack the data for a given array of T (elements or dofs) and a
* given akantu::SynchronizationTag
*/
virtual void unpackData(CommunicationBuffer & buffer,
const Array<T> & element,
const SynchronizationTag & tag) = 0;
};
/* -------------------------------------------------------------------------- */
/* Specialization */
/* -------------------------------------------------------------------------- */
template <> class DataAccessor<Element> : public virtual DataAccessorBase {
public:
DataAccessor() = default;
~DataAccessor() override = default;
- virtual UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const = 0;
- virtual void packData(CommunicationBuffer & buffer,
- const Array<Element> & element,
- const SynchronizationTag & tag) const = 0;
- virtual void unpackData(CommunicationBuffer & buffer,
- const Array<Element> & element,
- const SynchronizationTag & tag) = 0;
+ [[nodiscard]] virtual Int
+ getNbData(const Array<Element> & /*elements*/,
+ const SynchronizationTag & /*tag*/) const {
+ return 0;
+ };
+ virtual void packData(CommunicationBuffer & /*buffer*/,
+ const Array<Element> & /*element*/,
+ const SynchronizationTag & /*tag*/) const {};
+ virtual void unpackData(CommunicationBuffer & /*buffer*/,
+ const Array<Element> & /*element*/,
+ const SynchronizationTag & /*tag*/){};
/* ------------------------------------------------------------------------ */
public:
template <typename T, bool pack_helper>
static void
packUnpackNodalDataHelper(Array<T> & data, CommunicationBuffer & buffer,
const Array<Element> & elements, const Mesh & mesh);
/* ------------------------------------------------------------------------ */
template <typename T, bool pack_helper>
static void packUnpackElementalDataHelper(
ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
const Array<Element> & element, bool per_quadrature_point_data,
const FEEngine & fem);
/* ------------------------------------------------------------------------ */
template <typename T>
static void
packNodalDataHelper(const Array<T> & data, CommunicationBuffer & buffer,
const Array<Element> & elements, const Mesh & mesh) {
packUnpackNodalDataHelper<T, true>(const_cast<Array<T> &>(data), buffer,
elements, mesh);
}
template <typename T>
static inline void
unpackNodalDataHelper(Array<T> & data, CommunicationBuffer & buffer,
const Array<Element> & elements, const Mesh & mesh) {
packUnpackNodalDataHelper<T, false>(data, buffer, elements, mesh);
}
/* ------------------------------------------------------------------------ */
template <typename T>
static inline void
packElementalDataHelper(const ElementTypeMapArray<T> & data_to_pack,
CommunicationBuffer & buffer,
const Array<Element> & elements,
bool per_quadrature_point, const FEEngine & fem) {
packUnpackElementalDataHelper<T, true>(
const_cast<ElementTypeMapArray<T> &>(data_to_pack), buffer, elements,
per_quadrature_point, fem);
}
template <typename T>
static inline void
unpackElementalDataHelper(ElementTypeMapArray<T> & data_to_unpack,
CommunicationBuffer & buffer,
const Array<Element> & elements,
bool per_quadrature_point, const FEEngine & fem) {
packUnpackElementalDataHelper<T, false>(data_to_unpack, buffer, elements,
per_quadrature_point, fem);
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <> class DataAccessor<UInt> : public virtual DataAccessorBase {
+template <> class DataAccessor<Idx> : public virtual DataAccessorBase {
public:
DataAccessor() = default;
~DataAccessor() override = default;
- virtual UInt getNbData(const Array<UInt> & elements,
- const SynchronizationTag & tag) const = 0;
- virtual void packData(CommunicationBuffer & buffer,
- const Array<UInt> & element,
- const SynchronizationTag & tag) const = 0;
- virtual void unpackData(CommunicationBuffer & buffer,
- const Array<UInt> & element,
- const SynchronizationTag & tag) = 0;
+ [[nodiscard]] virtual Int
+ getNbData(const Array<Idx> & /*elements*/,
+ const SynchronizationTag & /*tag*/) const {
+ return 0;
+ }
+ virtual void packData(CommunicationBuffer & /*buffer*/,
+ const Array<Idx> & /*element*/,
+ const SynchronizationTag & /*tag*/) const {}
+ virtual void unpackData(CommunicationBuffer & /*buffer*/,
+ const Array<Idx> & /*element*/,
+ const SynchronizationTag & /*tag*/) {}
/* ------------------------------------------------------------------------ */
public:
template <typename T, bool pack_helper>
static void packUnpackDOFDataHelper(Array<T> & data,
CommunicationBuffer & buffer,
- const Array<UInt> & dofs);
+ const Array<Idx> & dofs);
template <typename T>
static inline void packDOFDataHelper(const Array<T> & data_to_pack,
CommunicationBuffer & buffer,
- const Array<UInt> & dofs) {
+ const Array<Idx> & dofs) {
packUnpackDOFDataHelper<T, true>(const_cast<Array<T> &>(data_to_pack),
buffer, dofs);
}
template <typename T>
static inline void unpackDOFDataHelper(Array<T> & data_to_unpack,
CommunicationBuffer & buffer,
- const Array<UInt> & dofs) {
+ const Array<Idx> & dofs) {
packUnpackDOFDataHelper<T, false>(data_to_unpack, buffer, dofs);
}
};
/* -------------------------------------------------------------------------- */
template <typename T> class AddOperation {
public:
- inline T operator()(T & a, T & b) { return a + b; };
+ inline T operator()(const T & a, const T & b) { return a + b; };
};
template <typename T> class IdentityOperation {
public:
- inline T & operator()(T & /*unused*/, T & b) { return b; };
+ inline T operator()(const T & /*unused*/, const T & b) { return b; };
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <class Entity, template <class> class Op, class T>
class ReduceDataAccessor : public virtual DataAccessor<Entity> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
ReduceDataAccessor(Array<T> & data, const SynchronizationTag & tag)
: data(data), tag(tag) {}
~ReduceDataAccessor() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
- UInt getNbData(const Array<Entity> & entities,
- const SynchronizationTag & tag) const override {
+ Int getNbData(const Array<Entity> & entities,
+ const SynchronizationTag & tag) const override {
if (tag != this->tag) {
return 0;
}
Vector<T> tmp(data.getNbComponent());
return entities.size() * CommunicationBuffer::sizeInBuffer(tmp);
}
/* ------------------------------------------------------------------------ */
void packData(CommunicationBuffer & buffer, const Array<Entity> & entities,
const SynchronizationTag & tag) const override {
if (tag != this->tag) {
return;
}
auto data_it = data.begin(data.getNbComponent());
for (auto el : entities) {
- buffer << Vector<T>(data_it[el]);
+ buffer << data_it[el];
}
}
/* ------------------------------------------------------------------------ */
void unpackData(CommunicationBuffer & buffer, const Array<Entity> & entities,
const SynchronizationTag & tag) override {
if (tag != this->tag) {
return;
}
auto data_it = data.begin(data.getNbComponent());
for (auto el : entities) {
Vector<T> unpacked(data.getNbComponent());
- Vector<T> vect(data_it[el]);
+ auto && vect(data_it[el]);
buffer >> unpacked;
vect = oper(vect, unpacked);
}
}
protected:
/// data to (un)pack
Array<T> & data;
/// Tag to consider
SynchronizationTag tag;
/// reduction operator
Op<Vector<T>> oper;
};
/* -------------------------------------------------------------------------- */
template <class T>
-using SimpleUIntDataAccessor = ReduceDataAccessor<UInt, IdentityOperation, T>;
+using SimpleIdxDataAccessor = ReduceDataAccessor<Idx, IdentityOperation, T>;
/* -------------------------------------------------------------------------- */
template <class T>
class SimpleElementDataAccessor : public virtual DataAccessor<Element> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SimpleElementDataAccessor(ElementTypeMapArray<T> & data,
const SynchronizationTag & tag)
: data(data), tag(tag) {}
~SimpleElementDataAccessor() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
- UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override {
+ Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const override {
if (tag != this->tag) {
return 0;
}
Int size = 0;
for (const auto & el : elements) {
auto && data_type = data(el.type, el.ghost_type);
size += sizeof(T) * data_type.getNbComponent();
}
return size;
}
/* ------------------------------------------------------------------------ */
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const override {
if (tag != this->tag) {
return;
}
for (const auto & el : elements) {
auto && data_type = data(el.type, el.ghost_type);
for (auto c : arange(data_type.getNbComponent())) {
const auto & data_per_element = data_type(el.element, c);
buffer << data_per_element;
}
}
}
/* ------------------------------------------------------------------------ */
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) override {
if (tag != this->tag) {
return;
}
for (const auto & el : elements) {
auto && data_type = data(el.type, el.ghost_type);
for (auto c : arange(data_type.getNbComponent())) {
auto & data_per_element = data_type(el.element, c);
buffer >> data_per_element;
}
}
}
protected:
/// data to (un)pack
ElementTypeMapArray<T> & data;
/// Tag to consider
SynchronizationTag tag;
};
} // namespace akantu
#endif /* AKANTU_DATA_ACCESSOR_HH_ */
diff --git a/src/synchronizer/dof_synchronizer.cc b/src/synchronizer/dof_synchronizer.cc
index f414619c2..797f8d113 100644
--- a/src/synchronizer/dof_synchronizer.cc
+++ b/src/synchronizer/dof_synchronizer.cc
@@ -1,231 +1,230 @@
/**
* @file dof_synchronizer.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 17 2011
* @date last modification: Fri Jul 24 2020
*
* @brief DOF synchronizing object implementation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_synchronizer.hh"
#include "aka_iterators.hh"
#include "dof_manager_default.hh"
#include "mesh.hh"
#include "node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
/**
* A DOFSynchronizer needs a mesh and the number of degrees of freedom
* per node to be created. In the constructor computes the local and global dof
* number for each dof. The member
* proc_informations (std vector) is resized with the number of mpi
* processes. Each entry in the vector is a PerProcInformations object
* that contains the interactions of the current mpi process (prank) with the
* mpi process corresponding to the position of that entry. Every
* ProcInformations object contains one array with the dofs that have
* to be sent to prank and a second one with dofs that willl be received form
* prank.
* This information is needed for the asychronous communications. The
* constructor sets up this information.
*/
DOFSynchronizer::DOFSynchronizer(DOFManagerDefault & dof_manager, const ID & id)
- : SynchronizerImpl<UInt>(dof_manager.getCommunicator(), id),
+ : SynchronizerImpl<Idx>(dof_manager.getCommunicator(), id),
dof_manager(dof_manager) {
std::vector<ID> dof_ids = dof_manager.getDOFIDs();
// Transfers nodes to global equation numbers in new schemes
for (const ID & dof_id : dof_ids) {
registerDOFs(dof_id);
}
}
/* -------------------------------------------------------------------------- */
DOFSynchronizer::~DOFSynchronizer() = default;
/* -------------------------------------------------------------------------- */
void DOFSynchronizer::registerDOFs(const ID & dof_id) {
if (this->nb_proc == 1) {
return;
}
if (dof_manager.getSupportType(dof_id) != _dst_nodal) {
return;
}
const auto & equation_numbers = dof_manager.getLocalEquationsNumbers(dof_id);
-
const auto & associated_nodes = dof_manager.getDOFsAssociatedNodes(dof_id);
const auto & node_synchronizer = dof_manager.getMesh().getNodeSynchronizer();
const auto & node_communications = node_synchronizer.getCommunications();
auto transcode_node_to_global_dof_scheme =
[this, &associated_nodes, &equation_numbers](
auto && it, auto && end, const CommunicationSendRecv & sr) -> void {
for (; it != end; ++it) {
auto & scheme = communications.createScheme(it->first, sr);
const auto & node_scheme = it->second;
for (auto & node : node_scheme) {
auto an_begin = associated_nodes.begin();
auto an_it = an_begin;
auto an_end = associated_nodes.end();
- std::vector<UInt> global_dofs_per_node;
+ std::vector<Idx> global_dofs_per_node;
while ((an_it = std::find(an_it, an_end, node)) != an_end) {
- UInt pos = an_it - an_begin;
- UInt local_eq_num = equation_numbers(pos);
- UInt global_eq_num =
+ auto pos = an_it - an_begin;
+ auto local_eq_num = equation_numbers(pos);
+ auto global_eq_num =
dof_manager.localToGlobalEquationNumber(local_eq_num);
global_dofs_per_node.push_back(global_eq_num);
++an_it;
}
std::sort(global_dofs_per_node.begin(), global_dofs_per_node.end());
std::transform(global_dofs_per_node.begin(), global_dofs_per_node.end(),
- global_dofs_per_node.begin(), [this](UInt g) -> UInt {
- UInt l = dof_manager.globalToLocalEquationNumber(g);
+ global_dofs_per_node.begin(), [this](Idx g) -> Idx {
+ auto l = dof_manager.globalToLocalEquationNumber(g);
return l;
});
for (auto & leqnum : global_dofs_per_node) {
scheme.push_back(leqnum);
}
}
}
};
for (auto sr : send_recv_t{}) {
auto ncs_it = node_communications.begin_scheme(sr);
auto ncs_end = node_communications.end_scheme(sr);
transcode_node_to_global_dof_scheme(ncs_it, ncs_end, sr);
}
entities_changed = true;
}
/* -------------------------------------------------------------------------- */
-void DOFSynchronizer::fillEntityToSend(Array<UInt> & dofs_to_send) {
- UInt nb_dofs = dof_manager.getLocalSystemSize();
+void DOFSynchronizer::fillEntityToSend(Array<Idx> & dofs_to_send) {
+ auto nb_dofs = dof_manager.getLocalSystemSize();
this->entities_from_root.zero();
dofs_to_send.resize(0);
- for (UInt d : arange(nb_dofs)) {
+ for (Int d : arange(nb_dofs)) {
if (not dof_manager.isLocalOrMasterDOF(d)) {
continue;
}
entities_from_root.push_back(d);
}
for (auto d : entities_from_root) {
- UInt global_dof = dof_manager.localToGlobalEquationNumber(d);
+ auto global_dof = dof_manager.localToGlobalEquationNumber(d);
dofs_to_send.push_back(global_dof);
}
}
/* -------------------------------------------------------------------------- */
-void DOFSynchronizer::onNodesAdded(const Array<UInt> & /*nodes_list*/) {
+void DOFSynchronizer::onNodesAdded(const Array<Idx> & /*nodes_list*/) {
auto dof_ids = dof_manager.getDOFIDs();
for (auto sr : iterate_send_recv) {
for (auto && data : communications.iterateSchemes(sr)) {
auto & scheme = data.second;
scheme.resize(0);
}
}
for (auto & dof_id : dof_ids) {
registerDOFs(dof_id);
}
// const auto & node_synchronizer =
// dof_manager.getMesh().getNodeSynchronizer(); const auto &
// node_communications = node_synchronizer.getCommunications();
// std::map<UInt, std::vector<UInt>> nodes_per_proc[2];
// for (auto sr : iterate_send_recv) {
// for (auto && data : node_communications.iterateSchemes(sr)) {
// auto proc = data.first;
// const auto & scheme = data.second;
// for (auto node : scheme) {
// nodes_per_proc[sr][proc].push_back(node);
// }
// }
// }
// std::map<UInt, std::vector<UInt>> dofs_per_proc[2];
// for (auto & dof_id : dof_ids) {
// const auto & associated_nodes =
// dof_manager.getDOFsAssociatedNodes(dof_id); const auto &
// local_equation_numbers =
// dof_manager.getEquationsNumbers(dof_id);
// for (auto tuple : zip(associated_nodes, local_equation_numbers)) {
// UInt assoc_node;
// UInt local_eq_num;
// std::tie(assoc_node, local_eq_num) = tuple;
// for (auto sr_it = send_recv_t::begin(); sr_it != send_recv_t::end();
// ++sr_it) {
// for (auto & pair : nodes_per_proc[*sr_it]) {
// if (std::find(pair.second.end(), pair.second.end(), assoc_node) !=
// pair.second.end()) {
// dofs_per_proc[*sr_it][pair.first].push_back(local_eq_num);
// }
// }
// }
// }
// }
// for (auto sr_it = send_recv_t::begin(); sr_it != send_recv_t::end();
// ++sr_it) {
// for (auto & pair : dofs_per_proc[*sr_it]) {
// std::sort(pair.second.begin(), pair.second.end(),
// [this](UInt la, UInt lb) -> bool {
- // UInt ga = dof_manager.localToGlobalEquationNumber(la);
- // UInt gb = dof_manager.localToGlobalEquationNumber(lb);
+ // auto ga = dof_manager.localToGlobalEquationNumber(la);
+ // auto gb = dof_manager.localToGlobalEquationNumber(lb);
// return ga < gb;
// });
// auto & scheme = communications.getScheme(pair.first, *sr_it);
// scheme.resize(0);
// for (auto leq : pair.second) {
// scheme.push_back(leq);
// }
// }
// }
this->entities_changed = true;
}
} // namespace akantu
diff --git a/src/synchronizer/dof_synchronizer.hh b/src/synchronizer/dof_synchronizer.hh
index 606295588..94d9973b8 100644
--- a/src/synchronizer/dof_synchronizer.hh
+++ b/src/synchronizer/dof_synchronizer.hh
@@ -1,85 +1,85 @@
/**
* @file dof_synchronizer.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 17 2011
* @date last modification: Wed Mar 04 2020
*
* @brief Synchronize Array of DOFs
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
-#include "synchronizer_impl.hh"
+#include "synchronizer.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class Mesh;
class DOFManagerDefault;
} // namespace akantu
#ifndef AKANTU_DOF_SYNCHRONIZER_HH_
#define AKANTU_DOF_SYNCHRONIZER_HH_
namespace akantu {
-class DOFSynchronizer : public SynchronizerImpl<UInt> {
+class DOFSynchronizer : public SynchronizerImpl<Idx> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
DOFSynchronizer(DOFManagerDefault & dof_manager,
const ID & id = "dof_synchronizer");
~DOFSynchronizer() override;
virtual void registerDOFs(const ID & dof_id);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- void onNodesAdded(const Array<UInt> & nodes);
+ void onNodesAdded(const Array<Idx> & nodes);
protected:
- Int getRank(const UInt & /*node*/) const final { AKANTU_TO_IMPLEMENT(); }
+ Int getRank(const Idx & /*node*/) const final { AKANTU_TO_IMPLEMENT(); }
/// list the entities to send to root process
- void fillEntityToSend(Array<UInt> & dofs_to_send) override;
+ void fillEntityToSend(Array<Idx> & dofs_to_send) override;
- inline UInt canScatterSize() override;
- inline UInt gatheredSize() override;
+ inline Int canScatterSize() override;
+ inline Int gatheredSize() override;
- inline UInt localToGlobalEntity(const UInt & local) override;
+ inline Idx localToGlobalEntity(const Idx & local) override;
private:
/// information on the dofs
DOFManagerDefault & dof_manager;
};
} // namespace akantu
#include "dof_synchronizer_inline_impl.hh"
#endif /* AKANTU_DOF_SYNCHRONIZER_HH_ */
diff --git a/src/synchronizer/dof_synchronizer_inline_impl.hh b/src/synchronizer/dof_synchronizer_inline_impl.hh
index 1fddfa545..052b4b6ef 100644
--- a/src/synchronizer/dof_synchronizer_inline_impl.hh
+++ b/src/synchronizer/dof_synchronizer_inline_impl.hh
@@ -1,62 +1,62 @@
/**
* @file dof_synchronizer_inline_impl.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 17 2011
* @date last modification: Wed Mar 04 2020
*
* @brief DOFSynchronizer inline implementation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communication_buffer.hh"
#include "data_accessor.hh"
#include "dof_manager_default.hh"
#include "dof_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_DOF_SYNCHRONIZER_INLINE_IMPL_HH_
-#define AKANTU_DOF_SYNCHRONIZER_INLINE_IMPL_HH_
+// #ifndef __AKANTU_DOF_SYNCHRONIZER_INLINE_IMPL_CC__
+// #define __AKANTU_DOF_SYNCHRONIZER_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt DOFSynchronizer::canScatterSize() {
+inline Int DOFSynchronizer::canScatterSize() {
return dof_manager.getLocalSystemSize();
}
/* -------------------------------------------------------------------------- */
-inline UInt DOFSynchronizer::gatheredSize() {
+inline Int DOFSynchronizer::gatheredSize() {
return dof_manager.getSystemSize();
}
-inline UInt DOFSynchronizer::localToGlobalEntity(const UInt & local) {
+inline Idx DOFSynchronizer::localToGlobalEntity(const Idx & local) {
return dof_manager.localToGlobalEquationNumber(local);
}
} // namespace akantu
-#endif /* AKANTU_DOF_SYNCHRONIZER_INLINE_IMPL_HH_ */
+//#endif /* __AKANTU_DOF_SYNCHRONIZER_INLINE_IMPL_CC__ */
diff --git a/src/synchronizer/element_info_per_processor.cc b/src/synchronizer/element_info_per_processor.cc
index 1539dd643..0d6231dcd 100644
--- a/src/synchronizer/element_info_per_processor.cc
+++ b/src/synchronizer/element_info_per_processor.cc
@@ -1,127 +1,126 @@
/**
* @file element_info_per_processor.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Mar 16 2016
* @date last modification: Fri Jul 24 2020
*
* @brief Helper class to distribute a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_info_per_processor.hh"
#include "communicator.hh"
#include "element_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <iostream>
#include <map>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
ElementInfoPerProc::ElementInfoPerProc(ElementSynchronizer & synchronizer,
- UInt message_cnt, UInt root,
+ Int message_cnt, Int root,
ElementType type)
: MeshAccessor(synchronizer.getMesh()), synchronizer(synchronizer),
rank(synchronizer.getCommunicator().whoAmI()),
nb_proc(synchronizer.getCommunicator().getNbProc()), root(root),
type(type), message_count(message_cnt), mesh(synchronizer.getMesh()),
comm(synchronizer.getCommunicator()) {}
/* -------------------------------------------------------------------------- */
bool ElementInfoPerProc::synchronize() {
auto need_synchronize = needSynchronize();
if (need_synchronize) {
synchronizeConnectivities();
synchronizePartitions();
synchronizeTags();
synchronizeGroups();
}
return need_synchronize;
}
/* -------------------------------------------------------------------------- */
-void ElementInfoPerProc::fillCommunicationScheme(
- const Array<UInt> & partition) {
+void ElementInfoPerProc::fillCommunicationScheme(const Array<Int> & partition) {
AKANTU_DEBUG_IN();
Element element;
element.type = this->type;
auto & communications = this->synchronizer.getCommunications();
auto part = partition.begin();
- std::map<UInt, Array<Element>> send_array_per_proc;
- for (UInt lel = 0; lel < nb_local_element; ++lel) {
- UInt nb_send = *part;
+ std::map<Int, Array<Element>> send_array_per_proc;
+ for (Int lel = 0; lel < nb_local_element; ++lel) {
+ auto nb_send = *part;
++part;
element.element = lel;
element.ghost_type = _not_ghost;
- for (UInt p = 0; p < nb_send; ++p, ++part) {
- UInt proc = *part;
+ for (Int p = 0; p < nb_send; ++p, ++part) {
+ auto proc = *part;
AKANTU_DEBUG(dblAccessory,
"Must send : " << element << " to proc " << proc);
send_array_per_proc[proc].push_back(element);
}
}
for (auto & send_schemes : send_array_per_proc) {
if (send_schemes.second.empty()) {
continue;
}
auto & scheme = communications.createSendScheme(send_schemes.first);
scheme.append(send_schemes.second);
}
- std::map<UInt, Array<Element>> recv_array_per_proc;
+ std::map<Int, Array<Element>> recv_array_per_proc;
- for (UInt gel = 0; gel < nb_ghost_element; ++gel, ++part) {
- UInt proc = *part;
+ for (Int gel = 0; gel < nb_ghost_element; ++gel, ++part) {
+ auto proc = *part;
element.element = gel;
element.ghost_type = _ghost;
AKANTU_DEBUG(dblAccessory,
"Must recv : " << element << " from proc " << proc);
recv_array_per_proc[proc].push_back(element);
}
for (auto & recv_schemes : recv_array_per_proc) {
if (recv_schemes.second.empty()) {
continue;
}
auto & scheme = communications.createRecvScheme(recv_schemes.first);
scheme.append(recv_schemes.second);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/synchronizer/element_info_per_processor.hh b/src/synchronizer/element_info_per_processor.hh
index 46cd1e225..a7501630b 100644
--- a/src/synchronizer/element_info_per_processor.hh
+++ b/src/synchronizer/element_info_per_processor.hh
@@ -1,152 +1,152 @@
/**
* @file element_info_per_processor.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Mar 16 2016
* @date last modification: Fri Jul 24 2020
*
* @brief Helper classes to create the distributed synchronizer and distribute
* a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "communication_buffer.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_INFO_PER_PROCESSOR_HH_
#define AKANTU_ELEMENT_INFO_PER_PROCESSOR_HH_
namespace akantu {
class ElementSynchronizer;
class Communicator;
class MeshPartition;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
class ElementInfoPerProc : protected MeshAccessor {
public:
- ElementInfoPerProc(ElementSynchronizer & synchronizer, UInt message_cnt,
- UInt root, ElementType type);
+ ElementInfoPerProc(ElementSynchronizer & synchronizer, Int message_cnt,
+ Int root, ElementType type);
bool synchronize();
protected:
virtual void synchronizeConnectivities() = 0;
virtual void synchronizePartitions() = 0;
virtual void synchronizeTags() = 0;
virtual void synchronizeGroups() = 0;
virtual bool needSynchronize() = 0;
protected:
- void fillCommunicationScheme(const Array<UInt> & partition);
+ void fillCommunicationScheme(const Array<Int> & partition);
template <class CommunicationBuffer>
void fillElementGroupsFromBuffer(CommunicationBuffer & buffer);
template <typename T, typename BufferType>
void fillMeshDataTemplated(BufferType & buffer, const std::string & tag_name,
- UInt nb_component);
+ Int nb_component);
template <typename BufferType>
void fillMeshData(BufferType & buffer, const std::string & tag_name,
- const MeshDataTypeCode & type_code, UInt nb_component);
+ const MeshDataTypeCode & type_code, Int nb_component);
protected:
ElementSynchronizer & synchronizer;
- UInt rank{0};
- UInt nb_proc{1};
+ Int rank{0};
+ Int nb_proc{1};
- UInt root{0};
+ Int root{0};
ElementType type{_not_defined};
- UInt nb_tags{0};
- UInt nb_nodes_per_element{0};
- UInt nb_element{0};
+ Int nb_tags{0};
+ Int nb_nodes_per_element{0};
+ Int nb_element{0};
- UInt nb_local_element{0};
- UInt nb_ghost_element{0};
+ Int nb_local_element{0};
+ Int nb_ghost_element{0};
- UInt message_count{0};
+ Int message_count{0};
Mesh & mesh;
const Communicator & comm;
};
/* -------------------------------------------------------------------------- */
class MasterElementInfoPerProc : public ElementInfoPerProc {
public:
- MasterElementInfoPerProc(ElementSynchronizer & synchronizer, UInt message_cnt,
- UInt root, ElementType type,
+ MasterElementInfoPerProc(ElementSynchronizer & synchronizer, Int message_cnt,
+ Int root, ElementType type,
const MeshPartition & partition);
protected:
void synchronizeConnectivities() override;
void synchronizePartitions() override;
void synchronizeTags() override;
void synchronizeGroups() override;
bool needSynchronize() override { return type != _not_defined; }
protected:
template <typename T>
void fillTagBufferTemplated(std::vector<DynamicCommunicationBuffer> & buffers,
const std::string & tag_name);
void fillTagBuffer(std::vector<DynamicCommunicationBuffer> & buffers,
const std::string & tag_name);
private:
const MeshPartition & partition;
- Vector<UInt> all_nb_local_element;
- Vector<UInt> all_nb_ghost_element;
- Vector<UInt> all_nb_element_to_send;
+ Vector<Int> all_nb_local_element;
+ Vector<Int> all_nb_ghost_element;
+ Vector<Int> all_nb_element_to_send;
};
/* -------------------------------------------------------------------------- */
class SlaveElementInfoPerProc : public ElementInfoPerProc {
public:
- SlaveElementInfoPerProc(ElementSynchronizer & synchronizer, UInt message_cnt,
- UInt root);
+ SlaveElementInfoPerProc(ElementSynchronizer & synchronizer, Int message_cnt,
+ Int root);
protected:
void synchronizeConnectivities() override;
void synchronizePartitions() override;
void synchronizeTags() override;
void synchronizeGroups() override;
bool needSynchronize() override;
private:
- UInt nb_element_to_receive{0};
+ Int nb_element_to_receive{0};
};
} // namespace akantu
#include "element_info_per_processor_tmpl.hh"
#endif /* AKANTU_ELEMENT_INFO_PER_PROCESSOR_HH_ */
diff --git a/src/synchronizer/element_info_per_processor_tmpl.hh b/src/synchronizer/element_info_per_processor_tmpl.hh
index 135bf9b9b..6e9c8bb8d 100644
--- a/src/synchronizer/element_info_per_processor_tmpl.hh
+++ b/src/synchronizer/element_info_per_processor_tmpl.hh
@@ -1,148 +1,148 @@
/**
* @file element_info_per_processor_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Mar 16 2016
* @date last modification: Thu Nov 12 2020
*
* @brief Helper classes to create the distributed synchronizer and distribute
* a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
-#include "element_info_per_processor.hh"
+//#include "element_info_per_processor.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_INFO_PER_PROCESSOR_TMPL_HH_
#define AKANTU_ELEMENT_INFO_PER_PROCESSOR_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename T, typename BufferType>
void ElementInfoPerProc::fillMeshDataTemplated(BufferType & buffer,
const std::string & tag_name,
- UInt nb_component) {
+ Int nb_component) {
AKANTU_DEBUG_ASSERT(this->mesh.getNbElement(this->type) == nb_local_element,
"Did not got enought informations for the tag "
<< tag_name << " and the element type " << this->type
<< ":"
<< "_not_ghost."
<< " Got " << nb_local_element << " values, expected "
<< mesh.getNbElement(this->type));
mesh.getElementalData<T>(tag_name);
Array<T> & data = mesh.getElementalDataArrayAlloc<T>(
tag_name, this->type, _not_ghost, nb_component);
data.resize(nb_local_element);
/// unpacking the data, element by element
- for (UInt i(0); i < nb_local_element; ++i) {
- for (UInt j(0); j < nb_component; ++j) {
+ for (Int i(0); i < nb_local_element; ++i) {
+ for (Int j(0); j < nb_component; ++j) {
buffer >> data(i, j);
}
}
AKANTU_DEBUG_ASSERT(mesh.getNbElement(this->type, _ghost) == nb_ghost_element,
"Did not got enought informations for the tag "
<< tag_name << " and the element type " << this->type
<< ":"
<< "_ghost."
<< " Got " << nb_ghost_element << " values, expected "
<< mesh.getNbElement(this->type, _ghost));
Array<T> & data_ghost = mesh.getElementalDataArrayAlloc<T>(
tag_name, this->type, _ghost, nb_component);
data_ghost.resize(nb_ghost_element);
/// unpacking the ghost data, element by element
- for (UInt j(0); j < nb_ghost_element; ++j) {
- for (UInt k(0); k < nb_component; ++k) {
+ for (Int j(0); j < nb_ghost_element; ++j) {
+ for (Int k(0); k < nb_component; ++k) {
buffer >> data_ghost(j, k);
}
}
}
/* -------------------------------------------------------------------------- */
template <typename BufferType>
void ElementInfoPerProc::fillMeshData(BufferType & buffer,
const std::string & tag_name,
const MeshDataTypeCode & type_code,
- UInt nb_component) {
+ Int nb_component) {
#define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, extra_param, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
fillMeshDataTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(buffer, tag_name, \
nb_component); \
break; \
}
switch (type_code) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, ,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR("Could not determine the type of tag" << tag_name << "!");
break;
}
#undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA
}
/* -------------------------------------------------------------------------- */
template <class CommunicationBuffer>
void ElementInfoPerProc::fillElementGroupsFromBuffer(
CommunicationBuffer & buffer) {
AKANTU_DEBUG_IN();
Element el;
el.type = type;
for (auto ghost_type : ghost_types) {
- UInt nb_element = mesh.getNbElement(type, ghost_type);
+ auto nb_element = mesh.getNbElement(type, ghost_type);
el.ghost_type = ghost_type;
- for (UInt e = 0; e < nb_element; ++e) {
+ for (Int e = 0; e < nb_element; ++e) {
el.element = e;
std::vector<std::string> element_to_group;
buffer >> element_to_group;
AKANTU_DEBUG_ASSERT(e < mesh.getNbElement(type, ghost_type),
"The mesh does not have the element " << e);
for (auto && group : element_to_group) {
mesh.getElementGroup(group).add(el, false, false);
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_ELEMENT_INFO_PER_PROCESSOR_TMPL_HH_ */
diff --git a/src/synchronizer/element_synchronizer.cc b/src/synchronizer/element_synchronizer.cc
index 2fcf74b46..31b96a955 100644
--- a/src/synchronizer/element_synchronizer.cc
+++ b/src/synchronizer/element_synchronizer.cc
@@ -1,295 +1,294 @@
/**
* @file element_synchronizer.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Fri Jul 24 2020
*
* @brief implementation of a communicator using a static_communicator for
* real
* send/receive
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_synchronizer.hh"
#include "aka_common.hh"
#include "mesh.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <iostream>
#include <map>
/* -------------------------------------------------------------------------- */
namespace akantu {
#if defined(AKANTU_MODULE)
#define AKANTU_MODULE_SAVE_ AKANTU_MODULE
#undef AKANTU_MODULE
#endif
#define AKANTU_MODULE element_synchronizer
/* -------------------------------------------------------------------------- */
ElementSynchronizer::ElementSynchronizer(Mesh & mesh, const ID & id,
bool register_to_event_manager,
EventHandlerPriority event_priority)
: SynchronizerImpl<Element>(mesh.getCommunicator(), id), mesh(mesh),
element_to_prank("element_to_prank", id) {
AKANTU_DEBUG_IN();
if (register_to_event_manager) {
this->mesh.registerEventHandler(*this, event_priority);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
ElementSynchronizer::ElementSynchronizer(const ElementSynchronizer & other,
const ID & id,
bool register_to_event_manager,
EventHandlerPriority event_priority)
: SynchronizerImpl<Element>(other, id), mesh(other.mesh),
element_to_prank("element_to_prank", id) {
AKANTU_DEBUG_IN();
element_to_prank.copy(other.element_to_prank);
if (register_to_event_manager) {
this->mesh.registerEventHandler(*this, event_priority);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
ElementSynchronizer::~ElementSynchronizer() = default;
/* -------------------------------------------------------------------------- */
void ElementSynchronizer::substituteElements(
const std::map<Element, Element> & old_to_new_elements) {
auto found_element_end = old_to_new_elements.end();
// substitute old elements with new ones
for (auto && sr : iterate_send_recv) {
for (auto && scheme_pair : communications.iterateSchemes(sr)) {
auto & list = scheme_pair.second;
for (auto & el : list) {
auto found_element_it = old_to_new_elements.find(el);
if (found_element_it != found_element_end) {
el = found_element_it->second;
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void ElementSynchronizer::onElementsChanged(
const Array<Element> & old_elements_list,
- const Array<Element> & new_elements_list,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const ChangedElementsEvent & /*unused*/) {
+ const Array<Element> & new_elements_list, const ElementTypeMapArray<Idx> &,
+ const ChangedElementsEvent &) {
// create a map to link old elements to new ones
std::map<Element, Element> old_to_new_elements;
- for (UInt el = 0; el < old_elements_list.size(); ++el) {
+ for (Int el = 0; el < old_elements_list.size(); ++el) {
AKANTU_DEBUG_ASSERT(old_to_new_elements.find(old_elements_list(el)) ==
old_to_new_elements.end(),
"The same element cannot appear twice in the list");
old_to_new_elements[old_elements_list(el)] = new_elements_list(el);
}
substituteElements(old_to_new_elements);
communications.invalidateSizes();
}
/* -------------------------------------------------------------------------- */
void ElementSynchronizer::onElementsRemoved(
const Array<Element> & element_to_remove,
- const ElementTypeMapArray<UInt> & new_numbering,
- const RemovedElementsEvent & /*unused*/) {
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent &) {
AKANTU_DEBUG_IN();
this->filterScheme([&](auto && element) {
return std::find(element_to_remove.begin(), element_to_remove.end(),
element) == element_to_remove.end();
});
this->renumberElements(new_numbering);
communications.invalidateSizes();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ElementSynchronizer::buildElementToPrank() {
AKANTU_DEBUG_IN();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
element_to_prank.initialize(mesh, _spatial_dimension = spatial_dimension,
_element_kind = _ek_not_defined,
_with_nb_element = true, _default_value = rank);
/// assign prank to all ghost elements
for (auto && scheme : communications.iterateSchemes(_recv)) {
auto & recv = scheme.second;
auto proc = scheme.first;
for (auto & element : recv) {
element_to_prank(element) = proc;
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Int ElementSynchronizer::getRank(const Element & element) const {
if (not element_to_prank.exists(element.type, element.ghost_type)) {
// Nicolas: Ok This is nasty I know....
const_cast<ElementSynchronizer *>(this)->buildElementToPrank();
}
return element_to_prank(element);
}
/* -------------------------------------------------------------------------- */
void ElementSynchronizer::renumberElements(
- const ElementTypeMapArray<UInt> & new_numbering) {
+ const ElementTypeMapArray<Idx> & new_numbering) {
for (auto && sr : iterate_send_recv) {
for (auto && scheme_pair : communications.iterateSchemes(sr)) {
auto & list = scheme_pair.second;
for (auto && el : list) {
if (new_numbering.exists(el.type, el.ghost_type)) {
el.element = new_numbering(el);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
-UInt ElementSynchronizer::sanityCheckDataSize(const Array<Element> & elements,
- const SynchronizationTag & tag,
- bool from_comm_desc) const {
- UInt size = SynchronizerImpl<Element>::sanityCheckDataSize(elements, tag,
- from_comm_desc);
+Int ElementSynchronizer::sanityCheckDataSize(const Array<Element> & elements,
+ const SynchronizationTag & tag,
+ bool from_comm_desc) const {
+ Int size = SynchronizerImpl<Element>::sanityCheckDataSize(elements, tag,
+ from_comm_desc);
// global connectivities;
- size += mesh.getNbNodesPerElementList(elements) * sizeof(UInt);
+ size += mesh.getNbNodesPerElementList(elements) * sizeof(Idx);
// barycenters
size += (elements.size() * mesh.getSpatialDimension() * sizeof(Real));
return size;
}
/* -------------------------------------------------------------------------- */
void ElementSynchronizer::packSanityCheckData(
CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & /*tag*/) const {
for (auto && element : elements) {
Vector<Real> barycenter(mesh.getSpatialDimension());
mesh.getBarycenter(element, barycenter);
buffer << barycenter;
const auto & conns = mesh.getConnectivity(element.type, element.ghost_type);
for (auto n : arange(conns.getNbComponent())) {
buffer << mesh.getNodeGlobalId(conns(element.element, n));
}
}
}
/* -------------------------------------------------------------------------- */
void ElementSynchronizer::unpackSanityCheckData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag,
- UInt proc, UInt rank) const {
+ Int proc, Int rank) const {
auto spatial_dimension = mesh.getSpatialDimension();
std::set<SynchronizationTag> skip_conn_tags{
SynchronizationTag::_smmc_facets_conn,
SynchronizationTag::_giu_global_conn};
bool is_skip_tag_conn = skip_conn_tags.find(tag) != skip_conn_tags.end();
for (auto && element : elements) {
Vector<Real> barycenter_loc(spatial_dimension);
mesh.getBarycenter(element, barycenter_loc);
Vector<Real> barycenter(spatial_dimension);
buffer >> barycenter;
auto dist = barycenter_loc.distance(barycenter);
if (not Math::are_float_equal(dist, 0.)) {
AKANTU_EXCEPTION("Unpacking an unknown value for the element "
<< element << "(barycenter " << barycenter_loc
<< " != buffer " << barycenter << ") [" << dist
<< "] - tag: " << tag << " comm from " << proc << " to "
<< rank);
}
const auto & conns = mesh.getConnectivity(element.type, element.ghost_type);
- Vector<UInt> global_conn(conns.getNbComponent());
- Vector<UInt> local_global_conn(conns.getNbComponent());
+ Vector<Idx> global_conn(conns.getNbComponent());
+ Vector<Idx> local_global_conn(conns.getNbComponent());
auto is_same = true;
for (auto n : arange(global_conn.size())) {
buffer >> global_conn(n);
auto node = conns(element.element, n);
local_global_conn(n) = mesh.getNodeGlobalId(node);
is_same &= is_skip_tag_conn or mesh.isPureGhostNode(node) or
(local_global_conn(n) == global_conn(n));
}
if (not is_same) {
AKANTU_DEBUG_WARNING(
"The connectivity of the element "
<< element << " " << local_global_conn
<< " does not match the connectivity of the equivalent "
"element on proc "
<< proc << " " << global_conn << " in communication with tag "
<< tag);
}
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#if defined(AKANTU_MODULE_SAVE_)
#undef AKANTU_MODULE
#define AKANTU_MODULE AKANTU_MODULE_SAVE_
#undef AKANTU_MODULE_SAVE_
#endif
diff --git a/src/synchronizer/element_synchronizer.hh b/src/synchronizer/element_synchronizer.hh
index c1dd946c4..809da8586 100644
--- a/src/synchronizer/element_synchronizer.hh
+++ b/src/synchronizer/element_synchronizer.hh
@@ -1,198 +1,196 @@
/**
* @file element_synchronizer.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Dana Christen <dana.christen@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Mar 04 2020
*
* @brief Main element synchronizer
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ELEMENT_SYNCHRONIZER_HH_
#define AKANTU_ELEMENT_SYNCHRONIZER_HH_
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_common.hh"
#include "mesh_partition.hh"
-#include "synchronizer_impl.hh"
+#include "synchronizer.hh"
namespace akantu {
class Mesh;
}
/* -------------------------------------------------------------------------- */
namespace akantu {
class ElementSynchronizer : public SynchronizerImpl<Element>,
public MeshEventHandler {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
ElementSynchronizer(Mesh & mesh, const ID & id = "element_synchronizer",
bool register_to_event_manager = true,
EventHandlerPriority event_priority = _ehp_synchronizer);
ElementSynchronizer(const ElementSynchronizer & other,
const ID & id = "element_synchronizer_copy",
bool register_to_event_manager = true,
EventHandlerPriority event_priority = _ehp_synchronizer);
public:
~ElementSynchronizer() override;
friend class ElementInfoPerProc;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/// mesh event handler onElementsChanged
void onElementsChanged(const Array<Element> & old_elements_list,
const Array<Element> & new_elements_list,
- const ElementTypeMapArray<UInt> & new_numbering,
+ const ElementTypeMapArray<Idx> & new_numbering,
const ChangedElementsEvent & event) override;
/// mesh event handler onRemovedElement
- void onElementsRemoved(const Array<Element> & element_to_remove,
- const ElementTypeMapArray<UInt> & new_numbering,
+ void onElementsRemoved(const Array<Element> & element_list,
+ const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) override;
protected:
/// remove elements from the synchronizer without renumbering them
void removeElements(const Array<Element> & element_to_remove);
/// renumber the elements in the synchronizer
- void renumberElements(const ElementTypeMapArray<UInt> & new_numbering);
+ void renumberElements(const ElementTypeMapArray<Idx> & new_numbering);
/// build processor to element correspondence
void buildElementToPrank();
protected:
/// fill the nodes type vector
void fillNodesType(const MeshData & mesh_data,
DynamicCommunicationBuffer * buffers,
const std::string & tag_name, ElementType el_type,
- const Array<UInt> & partition_num);
+ const Array<Idx> & partition_num);
template <typename T>
void fillTagBufferTemplated(const MeshData & mesh_data,
DynamicCommunicationBuffer * buffers,
const std::string & tag_name, ElementType el_type,
- const Array<UInt> & partition_num,
- const CSR<UInt> & ghost_partition);
+ const Array<Idx> & partition_num,
+ const CSR<Idx> & ghost_partition);
void fillTagBuffer(const MeshData & mesh_data,
DynamicCommunicationBuffer * buffers,
const std::string & tag_name, ElementType el_type,
- const Array<UInt> & partition_num,
- const CSR<UInt> & ghost_partition);
+ const Array<Idx> & partition_num,
+ const CSR<Idx> & ghost_partition);
/// function that handels the MeshData to be split (root side)
- static void synchronizeTagsSend(ElementSynchronizer & communicator, UInt root,
- Mesh & mesh, UInt nb_tags, ElementType type,
- const Array<UInt> & partition_num,
- const CSR<UInt> & ghost_partition,
- UInt nb_local_element, UInt nb_ghost_element);
+ static void synchronizeTagsSend(ElementSynchronizer & communicator, Idx root,
+ Mesh & mesh, Int nb_tags, ElementType type,
+ const Array<Idx> & partition_num,
+ const CSR<Idx> & ghost_partition,
+ Int nb_local_element, Int nb_ghost_element);
/// function that handles the MeshData to be split (other nodes)
- static void synchronizeTagsRecv(ElementSynchronizer & communicator, UInt root,
- Mesh & mesh, UInt nb_tags, ElementType type,
- UInt nb_local_element, UInt nb_ghost_element);
+ static void synchronizeTagsRecv(ElementSynchronizer & communicator, Idx root,
+ Mesh & mesh, Int nb_tags, ElementType type,
+ Int nb_local_element, Int nb_ghost_element);
/// function that handles the preexisting groups in the mesh
static void synchronizeElementGroups(ElementSynchronizer & communicator,
- UInt root, Mesh & mesh, ElementType type,
- const Array<UInt> & partition_num,
- const CSR<UInt> & ghost_partition,
- UInt nb_element);
+ Idx root, Mesh & mesh, ElementType type,
+ const Array<Idx> & partition_num,
+ const CSR<Idx> & ghost_partition,
+ Int nb_element);
/// function that handles the preexisting groups in the mesh
static void synchronizeElementGroups(ElementSynchronizer & communicator,
- UInt root, Mesh & mesh,
- ElementType type);
+ Idx root, Mesh & mesh, ElementType type);
/// function that handles the preexisting groups in the mesh
static void synchronizeNodeGroupsMaster(ElementSynchronizer & communicator,
- UInt root, Mesh & mesh);
+ Idx root, Mesh & mesh);
/// function that handles the preexisting groups in the mesh
static void synchronizeNodeGroupsSlaves(ElementSynchronizer & communicator,
- UInt root, Mesh & mesh);
+ Idx root, Mesh & mesh);
template <class CommunicationBuffer>
static void fillNodeGroupsFromBuffer(ElementSynchronizer & communicator,
Mesh & mesh,
CommunicationBuffer & buffer);
/// substitute elements in the send and recv arrays
void
substituteElements(const std::map<Element, Element> & old_to_new_elements);
/* ------------------------------------------------------------------------ */
/* Sanity checks */
/* ------------------------------------------------------------------------ */
- UInt sanityCheckDataSize(const Array<Element> & elements,
- const SynchronizationTag & tag,
- bool from_comm_desc = true) const override;
+ Int sanityCheckDataSize(const Array<Element> & elements,
+ const SynchronizationTag & tag,
+ bool from_comm_desc = true) const override;
void packSanityCheckData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
const SynchronizationTag & /*tag*/) const override;
void unpackSanityCheckData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/, UInt /*proc*/,
- UInt /*rank*/) const override;
+ const SynchronizationTag & /*tag*/, Idx /*proc*/,
+ Idx /*rank*/) const override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- AKANTU_GET_MACRO(Mesh, mesh, Mesh &);
- AKANTU_GET_MACRO(ElementToRank, element_to_prank,
- const ElementTypeMapArray<Int> &);
+ AKANTU_GET_MACRO_AUTO(Mesh, mesh);
+ AKANTU_GET_MACRO_AUTO(ElementToRank, element_to_prank);
Int getRank(const Element & element) const final;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// reference to the underlying mesh
Mesh & mesh;
friend class FacetSynchronizer;
ElementTypeMapArray<Int> element_to_prank;
};
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_ELEMENT_SYNCHRONIZER_HH_ */
diff --git a/src/synchronizer/facet_synchronizer.cc b/src/synchronizer/facet_synchronizer.cc
index c0f5492c2..67411fbfd 100644
--- a/src/synchronizer/facet_synchronizer.cc
+++ b/src/synchronizer/facet_synchronizer.cc
@@ -1,227 +1,216 @@
/**
* @file facet_synchronizer.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Dec 09 2020
*
* @brief Facet synchronizer for parallel simulations with cohesive elments
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "facet_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_MODULE)
#define AKANTU_MODULE_SAVE_ AKANTU_MODULE
#undef AKANTU_MODULE
#endif
#define AKANTU_MODULE facet_synchronizer
namespace akantu {
/* -------------------------------------------------------------------------- */
FacetSynchronizer::FacetSynchronizer(
Mesh & mesh, const ElementSynchronizer & element_synchronizer,
const ID & id)
: ElementSynchronizer(mesh, id) {
auto spatial_dimension = mesh.getSpatialDimension();
element_to_prank.initialize(mesh, _spatial_dimension = spatial_dimension - 1,
_ghost_type = _ghost, _with_nb_element = true,
_default_value = rank);
// Build element to prank
for (auto && scheme_pair :
element_synchronizer.communications.iterateSchemes(_recv)) {
auto proc = std::get<0>(scheme_pair);
const auto & scheme = std::get<1>(scheme_pair);
for (auto && elem : scheme) {
- const auto & facet_to_element =
- mesh.getSubelementToElement(elem.type, elem.ghost_type);
- Vector<Element> facets = facet_to_element.begin(
- facet_to_element.getNbComponent())[elem.element];
+ const auto & facets = mesh.getSubelementToElement().get(elem);
- for (UInt f = 0; f < facets.size(); ++f) {
- const auto & facet = facets(f);
+ for (auto && facet : facets) {
if (facet == ElementNull) {
continue;
}
if (facet.ghost_type == _not_ghost) {
continue;
}
auto & facet_rank = element_to_prank(facet);
- if ((proc < UInt(facet_rank)) || (UInt(facet_rank) == rank)) {
+ if ((proc < facet_rank) || (facet_rank == rank)) {
facet_rank = proc;
}
}
}
}
- ElementTypeMapArray<UInt> facet_global_connectivities(
+ ElementTypeMapArray<Idx> facet_global_connectivities(
"facet_global_connectivities", id);
facet_global_connectivities.initialize(
mesh, _spatial_dimension = spatial_dimension - 1, _with_nb_element = true,
_with_nb_nodes_per_element = true);
mesh.getGlobalConnectivity(facet_global_connectivities);
// \TODO perhaps a global element numbering might be useful here...
for (auto type : facet_global_connectivities.elementTypes(_spatial_dimension =
_all_dimensions,
_element_kind = _ek_not_defined, _ghost_type = _not_ghost)) {
auto & conn = facet_global_connectivities(type, _not_ghost);
auto conn_view = make_view(conn, conn.getNbComponent());
std::for_each(conn_view.begin(), conn_view.end(), [&](auto & conn) {
- std::sort(conn.storage(), conn.storage() + conn.size());
+ std::sort(conn.data(), conn.data() + conn.size());
});
}
/// init facet check tracking
ElementTypeMapArray<bool> facet_checked("facet_checked", id);
- std::map<UInt, ElementTypeMapArray<UInt>> recv_connectivities;
+ std::map<Int, ElementTypeMapArray<Idx>> recv_connectivities;
/// Generate the recv scheme and connnectivities to send to the other
/// processors
for (auto && scheme_pair :
element_synchronizer.communications.iterateSchemes(_recv)) {
facet_checked.initialize(mesh, _spatial_dimension = spatial_dimension - 1,
_ghost_type = _ghost, _with_nb_element = true,
_default_value = false);
auto proc = scheme_pair.first;
const auto & elements = scheme_pair.second;
auto & facet_scheme = communications.createScheme(proc, _recv);
// this creates empty arrays...
auto & connectivities_for_proc = recv_connectivities[proc];
connectivities_for_proc.setID(
id + ":connectivities_for_proc:" + std::to_string(proc));
connectivities_for_proc.initialize(
mesh, _spatial_dimension = spatial_dimension - 1,
_with_nb_nodes_per_element = true, _ghost_type = _ghost);
// for every element in the element synchronizer communication scheme,
// check the facets to see if they should be communicated and create a
// connectivity array to match with the one other processors might send
for (auto && element : elements) {
- const auto & facet_to_element =
- mesh.getSubelementToElement(element.type, element.ghost_type);
- Vector<Element> facets = facet_to_element.begin(
- facet_to_element.getNbComponent())[element.element];
-
- for (UInt f = 0; f < facets.size(); ++f) {
- auto & facet = facets(f);
+ const auto & facet_to_element = mesh.getSubelementToElement();
+ auto && facets = facet_to_element.get(element);
+ for (auto && facet : facets) {
// exclude no valid facets
if (facet == ElementNull) {
continue;
}
// exclude _ghost facet from send scheme and _not_ghost from receive
if (facet.ghost_type != _ghost) {
continue;
}
// exclude facet from other processors then the one of current
// interest in case of receive scheme
- if (UInt(element_to_prank(facet)) != proc) {
+ if (element_to_prank(facet) != proc) {
continue;
}
auto & checked = facet_checked(facet);
// skip already checked facets
if (checked) {
continue;
}
checked = true;
facet_scheme.push_back(facet);
- auto & global_conn =
- facet_global_connectivities(facet.type, facet.ghost_type);
- Vector<UInt> conn =
- global_conn.begin(global_conn.getNbComponent())[facet.element];
- std::sort(conn.storage(), conn.storage() + conn.size());
+ auto && conn = facet_global_connectivities.get(facet);
+ std::sort(conn.data(), conn.data() + conn.size());
connectivities_for_proc(facet.type, facet.ghost_type).push_back(conn);
}
}
}
std::vector<CommunicationRequest> send_requests;
/// do every communication by element type
for (auto && type : mesh.elementTypes(spatial_dimension - 1)) {
for (auto && pair : recv_connectivities) {
auto proc = std::get<0>(pair);
const auto & connectivities_for_proc = std::get<1>(pair);
auto && tag = Tag::genTag(proc, type, 1337);
send_requests.push_back(
communicator.asyncSend(connectivities_for_proc(type, _ghost), proc,
tag, CommunicationMode::_synchronous));
}
auto nb_nodes_per_facet = Mesh::getNbNodesPerElement(type);
- communicator.receiveAnyNumber<UInt>(
+ communicator.receiveAnyNumber<Idx>(
send_requests,
[&](auto && proc, auto && message) {
auto & local_connectivities =
facet_global_connectivities(type, _not_ghost);
auto & send_scheme = communications.createScheme(proc, _send);
auto conn_view = make_view(local_connectivities, nb_nodes_per_facet);
auto conn_begin = conn_view.begin();
auto conn_end = conn_view.end();
for (const auto & c_to_match :
make_view(message, nb_nodes_per_facet)) {
auto it = std::find(conn_begin, conn_end, c_to_match);
if (it != conn_end) {
- auto facet = Element{type, UInt(it - conn_begin), _not_ghost};
+ auto facet = Element{type, it - conn_begin, _not_ghost};
send_scheme.push_back(facet);
} else {
AKANTU_EXCEPTION("No local facet found to send to proc "
<< proc << " corresponding to " << c_to_match);
}
}
},
Tag::genTag(rank, type, 1337));
}
}
} // namespace akantu
#if defined(AKANTU_MODULE_SAVE_)
#undef AKANTU_MODULE
#define AKANTU_MODULE AKANTU_MODULE_SAVE_
#undef AKANTU_MODULE_SAVE_
#endif
diff --git a/src/synchronizer/facet_synchronizer.hh b/src/synchronizer/facet_synchronizer.hh
index 98b6176b7..4be9f2f86 100644
--- a/src/synchronizer/facet_synchronizer.hh
+++ b/src/synchronizer/facet_synchronizer.hh
@@ -1,113 +1,113 @@
/**
* @file facet_synchronizer.hh
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Fri Jul 24 2020
*
* @brief Facet synchronizer for parallel simulations with cohesive elments
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_synchronizer.hh"
#include "fe_engine.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_FACET_SYNCHRONIZER_HH_
#define AKANTU_FACET_SYNCHRONIZER_HH_
namespace akantu {
class FacetSynchronizer : public ElementSynchronizer {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
FacetSynchronizer(Mesh & mesh,
const ElementSynchronizer & element_synchronizer,
const ID & id = "facet_synchronizer");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// update distributed synchronizer after elements' insertion
void
updateDistributedSynchronizer(ElementSynchronizer & distributed_synchronizer,
DataAccessor<Element> & data_accessor,
const Mesh & mesh_cohesive);
protected:
/// update elements list based on facets list
void updateElementList(Array<Element> * elements,
const Array<Element> * facets,
const Mesh & mesh_cohesive);
/// setup facet synchronization
void
setupFacetSynchronization(ElementSynchronizer & distributed_synchronizer);
/// build send facet arrays
void buildSendElementList(
- const Array<ElementTypeMapArray<UInt> *> & send_connectivity,
- const Array<ElementTypeMapArray<UInt> *> & recv_connectivity,
- const Array<ElementTypeMapArray<UInt> *> & temp_send_element);
+ const Array<ElementTypeMapArray<Idx> *> & send_connectivity,
+ const Array<ElementTypeMapArray<Idx> *> & recv_connectivity,
+ const Array<ElementTypeMapArray<Idx> *> & temp_send_element);
/// build recv facet arrays
void buildRecvElementList(
- const Array<ElementTypeMapArray<UInt> *> & temp_recv_element);
+ const Array<ElementTypeMapArray<Idx> *> & temp_recv_element);
/// get facets' global connectivity for a list of elements
template <GhostType ghost_facets>
inline void getFacetGlobalConnectivity(
const ElementSynchronizer & distributed_synchronizer,
- const ElementTypeMapArray<UInt> & rank_to_facet,
+ const ElementTypeMapArray<Idx> & rank_to_facet,
const Array<Element> * elements,
- Array<ElementTypeMapArray<UInt> *> & connectivity,
- Array<ElementTypeMapArray<UInt> *> & facets);
+ Array<ElementTypeMapArray<Idx> *> & connectivity,
+ Array<ElementTypeMapArray<Idx> *> & facets);
/// initialize ElementTypeMap containing correspondance between
/// facets and processors
- void initRankToFacet(ElementTypeMapArray<UInt> & rank_to_facet);
+ void initRankToFacet(ElementTypeMapArray<Idx> & rank_to_facet);
/// find which processor a facet is assigned to
- void buildRankToFacet(ElementTypeMapArray<UInt> & rank_to_facet,
+ void buildRankToFacet(ElementTypeMapArray<Idx> & rank_to_facet,
const Array<Element> * elements);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
- ElementTypeMapArray<UInt> facet_to_rank;
+ ElementTypeMapArray<Int> facet_to_rank;
};
} // namespace akantu
#include "facet_synchronizer_inline_impl.hh"
#endif /* AKANTU_FACET_SYNCHRONIZER_HH_ */
diff --git a/src/synchronizer/grid_synchronizer.cc b/src/synchronizer/grid_synchronizer.cc
index 5b45622b9..7720bb3d8 100644
--- a/src/synchronizer/grid_synchronizer.cc
+++ b/src/synchronizer/grid_synchronizer.cc
@@ -1,487 +1,478 @@
/**
* @file grid_synchronizer.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Oct 03 2011
* @date last modification: Fri Jul 24 2020
*
* @brief implementation of the grid synchronizer
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "grid_synchronizer.hh"
#include "aka_grid_dynamic.hh"
#include "communicator.hh"
#include "fe_engine.hh"
#include "integration_point.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include <iostream>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class E>
void GridSynchronizer::createGridSynchronizer(const SpatialGrid<E> & grid) {
AKANTU_DEBUG_IN();
- const Communicator & comm = this->mesh.getCommunicator();
- UInt nb_proc = comm.getNbProc();
- UInt my_rank = comm.whoAmI();
+ const auto & comm = this->mesh.getCommunicator();
+ auto nb_proc = comm.getNbProc();
+ auto my_rank = comm.whoAmI();
if (nb_proc == 1) {
return;
}
- UInt spatial_dimension = this->mesh.getSpatialDimension();
+ auto spatial_dimension = this->mesh.getSpatialDimension();
BBox my_bounding_box(spatial_dimension);
const auto & lower = grid.getLowerBounds();
const auto & upper = grid.getUpperBounds();
const auto & spacing = grid.getSpacing();
- my_bounding_box.getLowerBounds() = lower - spacing;
- my_bounding_box.getUpperBounds() = upper + spacing;
+ my_bounding_box.setLowerBounds(lower - spacing);
+ my_bounding_box.setUpperBounds(upper + spacing);
AKANTU_DEBUG_INFO(
"Exchange of bounding box to detect the overlapping regions.");
auto && bboxes = my_bounding_box.allGather(comm);
std::vector<bool> intersects_proc(nb_proc);
std::fill(intersects_proc.begin(), intersects_proc.end(), true);
Matrix<Int> first_cells(spatial_dimension, nb_proc);
Matrix<Int> last_cells(spatial_dimension, nb_proc);
- std::map<UInt, ElementTypeMapArray<UInt>> element_per_proc;
+ std::map<Int, ElementTypeMapArray<Idx>> element_per_proc;
// check the overlapping between my box and the one from other processors
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if (p == my_rank) {
continue;
}
const auto & proc_bounding_box = bboxes[p];
auto intersection = my_bounding_box.intersection(proc_bounding_box);
- Vector<Int> first_cell_p = first_cells(p);
- Vector<Int> last_cell_p = last_cells(p);
+ auto && first_cell_p = first_cells(p);
+ auto && last_cell_p = last_cells(p);
intersects_proc[p] = intersection;
if (intersects_proc[p]) {
- for (UInt s = 0; s < spatial_dimension; ++s) {
+ for (Int s = 0; s < spatial_dimension; ++s) {
first_cell_p(s) = grid.getCellID(intersection.getLowerBounds()(s), s);
last_cell_p(s) = grid.getCellID(intersection.getUpperBounds()(s), s);
}
}
// create the list of cells in the overlapping
using CellID = typename SpatialGrid<E>::CellID;
std::vector<CellID> cell_ids;
if (intersects_proc[p]) {
AKANTU_DEBUG_INFO("I intersects with processor " << p);
CellID cell_id(spatial_dimension);
- // for (UInt i = 0; i < spatial_dimension; ++i) {
- // if(first_cell_p[i] != 0) --first_cell_p[i];
- // if(last_cell_p[i] != 0) ++last_cell_p[i];
- // }
-
for (Int fd = first_cell_p(0); fd <= last_cell_p(0); ++fd) {
cell_id.setID(0, fd);
if (spatial_dimension == 1) {
cell_ids.push_back(cell_id);
} else {
for (Int sd = first_cell_p(1); sd <= last_cell_p(1); ++sd) {
cell_id.setID(1, sd);
if (spatial_dimension == 2) {
cell_ids.push_back(cell_id);
} else {
for (Int ld = first_cell_p(2); ld <= last_cell_p(2); ++ld) {
cell_id.setID(2, ld);
cell_ids.push_back(cell_id);
}
}
}
}
}
// get the list of elements in the cells of the overlapping
std::set<Element> to_send;
for (auto & cur_cell_id : cell_ids) {
auto & cell = grid.getCell(cur_cell_id);
for (auto & element : cell) {
to_send.insert(element);
}
}
AKANTU_DEBUG_INFO("I have prepared " << to_send.size()
<< " elements to send to processor "
<< p);
auto & scheme = this->getCommunications().createSendScheme(p);
- std::stringstream sstr;
- sstr << "element_per_proc_" << p;
- element_per_proc.emplace(std::piecewise_construct,
- std::forward_as_tuple(p),
- std::forward_as_tuple(sstr.str(), id));
- ElementTypeMapArray<UInt> & elempproc = element_per_proc[p];
+ element_per_proc.emplace(
+ std::piecewise_construct, std::forward_as_tuple(p),
+ std::forward_as_tuple(
+ std::string("element_per_proc_" + std::to_string(p)), id));
+
+ auto & elempproc = element_per_proc[p];
for (auto elem : to_send) {
- ElementType type = elem.type;
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ auto type = elem.type;
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
// /!\ this part must be slow due to the access in the
- // ElementTypeMapArray<UInt>
- if (!elempproc.exists(type, _not_ghost)) {
+ // ElementTypeMapArray<Idx>
+ if (not elempproc.exists(type, _not_ghost)) {
elempproc.alloc(0, nb_nodes_per_element, type, _not_ghost);
}
- Vector<UInt> global_connect(nb_nodes_per_element);
- Vector<UInt> local_connect = mesh.getConnectivity(type).begin(
+ Vector<Idx> global_connect(nb_nodes_per_element);
+ auto && local_connect = mesh.getConnectivity(type).begin(
nb_nodes_per_element)[elem.element];
- for (UInt i = 0; i < nb_nodes_per_element; ++i) {
+ for (Int i = 0; i < nb_nodes_per_element; ++i) {
global_connect(i) = mesh.getNodeGlobalId(local_connect(i));
AKANTU_DEBUG_ASSERT(
global_connect(i) < mesh.getNbGlobalNodes(),
"This global node send in the connectivity does not seem correct "
<< global_connect(i) << " corresponding to "
<< local_connect(i) << " from element " << elem.element);
}
elempproc(type).push_back(global_connect);
scheme.push_back(elem);
}
}
}
AKANTU_DEBUG_INFO("I have finished to compute intersection,"
<< " no it's time to communicate with my neighbors");
/**
* Sending loop, sends the connectivity asynchronously to all concerned proc
*/
std::vector<CommunicationRequest> isend_requests;
- Tensor3<UInt> space(2, _max_element_type, nb_proc);
+ Array<Int> space(0, 2);
+ space.reserve(nb_proc * Int(_max_element_type));
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if (p == my_rank) {
continue;
}
if (not intersects_proc[p]) {
continue;
}
- Matrix<UInt> info_proc = space(p);
auto & elempproc = element_per_proc[p];
- UInt count = 0;
+ Int count = 0;
for (auto type : elempproc.elementTypes(_all_dimensions, _not_ghost)) {
- Array<UInt> & conn = elempproc(type, _not_ghost);
-
- Vector<UInt> info = info_proc((UInt)type);
- info[0] = (UInt)type;
- info[1] = conn.size() * conn.getNbComponent();
+ const auto & conn = elempproc(type, _not_ghost);
+ space.push_back(
+ Vector<Int>{Int(type), conn.size() * conn.getNbComponent()});
+ VectorProxy<Int> info(space.data() + 2 * (space.size() - 1), 2);
AKANTU_DEBUG_INFO(
"I have " << conn.size() << " elements of type " << type
<< " to send to processor " << p << " (communication tag : "
<< Tag::genTag(my_rank, count, DATA_TAG) << ")");
isend_requests.push_back(
comm.asyncSend(info, p, Tag::genTag(my_rank, count, SIZE_TAG)));
if (info[1] != 0) {
- isend_requests.push_back(comm.asyncSend<UInt>(
- conn, p, Tag::genTag(my_rank, count, DATA_TAG)));
+ isend_requests.push_back(
+ comm.asyncSend(conn, p, Tag::genTag(my_rank, count, DATA_TAG)));
}
++count;
}
- Vector<UInt> info = info_proc((UInt)_not_defined);
- info[0] = (UInt)_not_defined;
- info[1] = 0;
+ space.push_back(Vector<Int>{Int(_not_defined), 0});
+ VectorProxy<Int> info(space.data() + 2 * (space.size() - 1), 2);
isend_requests.push_back(
comm.asyncSend(info, p, Tag::genTag(my_rank, count, SIZE_TAG)));
}
/**
* Receives the connectivity and store them in the ghosts elements
*/
MeshAccessor mesh_accessor(mesh);
auto & global_nodes_ids = mesh_accessor.getNodesGlobalIds();
auto & nodes_type = mesh_accessor.getNodesFlags();
std::vector<CommunicationRequest> isend_nodes_requests;
- Vector<UInt> nb_nodes_to_recv(nb_proc);
+ Vector<Int> nb_nodes_to_recv(nb_proc);
- UInt nb_total_nodes_to_recv = 0;
- UInt nb_current_nodes = global_nodes_ids.size();
+ Int nb_total_nodes_to_recv = 0;
+ Int nb_current_nodes = global_nodes_ids.size();
NewNodesEvent new_nodes;
NewElementsEvent new_elements;
- std::map<UInt, std::vector<UInt>> ask_nodes_per_proc;
+ std::map<Int, std::vector<Int>> ask_nodes_per_proc;
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
nb_nodes_to_recv(p) = 0;
if (p == my_rank) {
continue;
}
if (!intersects_proc[p]) {
continue;
}
auto & scheme = this->getCommunications().createRecvScheme(p);
ask_nodes_per_proc.emplace(std::piecewise_construct,
std::forward_as_tuple(p),
std::forward_as_tuple(0));
auto & ask_nodes = ask_nodes_per_proc[p];
- UInt count = 0;
+ Int count = 0;
- ElementType type = _not_defined;
+ auto type = _not_defined;
do {
- Vector<UInt> info(2);
+ Vector<Int> info(2);
comm.receive(info, p, Tag::genTag(p, count, SIZE_TAG));
type = (ElementType)info[0];
if (type == _not_defined) {
break;
}
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
- UInt nb_element = info[1] / nb_nodes_per_element;
+ auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ auto nb_element = info[1] / nb_nodes_per_element;
- Array<UInt> tmp_conn(nb_element, nb_nodes_per_element);
- tmp_conn.zero();
+ Array<Idx> tmp_conn(nb_element, nb_nodes_per_element);
if (info[1] != 0) {
- comm.receive<UInt>(tmp_conn, p, Tag::genTag(p, count, DATA_TAG));
+ comm.receive(tmp_conn, p, Tag::genTag(p, count, DATA_TAG));
}
-
AKANTU_DEBUG_INFO("I will receive "
<< nb_element << " elements of type "
<< ElementType(info[0]) << " from processor " << p
<< " (communication tag : "
<< Tag::genTag(p, count, DATA_TAG) << ")");
auto & ghost_connectivity = mesh_accessor.getConnectivity(type, _ghost);
auto & ghost_counter = mesh_accessor.getGhostsCounters(type, _ghost);
- UInt nb_ghost_element = ghost_connectivity.size();
+ auto nb_ghost_element = ghost_connectivity.size();
Element element{type, 0, _ghost};
- Vector<UInt> conn(nb_nodes_per_element);
- for (UInt el = 0; el < nb_element; ++el) {
- UInt nb_node_to_ask_for_elem = 0;
+ Vector<Idx> conn(nb_nodes_per_element);
+ for (Int el = 0; el < nb_element; ++el) {
+ Int nb_node_to_ask_for_elem = 0;
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
- UInt gn = tmp_conn(el, n);
- UInt ln = global_nodes_ids.find(gn);
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
+ auto gn = tmp_conn(el, n);
+ auto ln = global_nodes_ids.find(gn);
AKANTU_DEBUG_ASSERT(gn < mesh.getNbGlobalNodes(),
"This global node seems not correct "
<< gn << " from element " << el << " node "
<< n);
- if (ln == UInt(-1)) {
+ if (ln == -1) {
global_nodes_ids.push_back(gn);
nodes_type.push_back(NodeFlag::_pure_ghost); // pure ghost node
ln = nb_current_nodes;
new_nodes.getList().push_back(ln);
++nb_current_nodes;
ask_nodes.push_back(gn);
++nb_node_to_ask_for_elem;
}
conn[n] = ln;
}
// all the nodes are already known locally, the element should
// already exists
- auto c = UInt(-1);
+ Idx c = -1;
if (nb_node_to_ask_for_elem == 0) {
c = ghost_connectivity.find(conn);
element.element = c;
}
- if (c == UInt(-1)) {
+ if (c == -1) {
element.element = nb_ghost_element;
++nb_ghost_element;
ghost_connectivity.push_back(conn);
ghost_counter.push_back(1);
new_elements.getList().push_back(element);
} else {
++ghost_counter(c);
}
scheme.push_back(element);
}
count++;
} while (type != _not_defined);
AKANTU_DEBUG_INFO("I have "
<< ask_nodes.size()
<< " missing nodes for elements coming from processor "
<< p << " (communication tag : "
<< Tag::genTag(my_rank, 0, ASK_NODES_TAG) << ")");
- ask_nodes.push_back(UInt(-1));
+ ask_nodes.push_back(-1);
isend_nodes_requests.push_back(
comm.asyncSend(ask_nodes, p, Tag::genTag(my_rank, 0, ASK_NODES_TAG)));
nb_nodes_to_recv(p) = ask_nodes.size() - 1;
nb_total_nodes_to_recv += nb_nodes_to_recv(p);
}
Communicator::waitAll(isend_requests);
Communicator::freeCommunicationRequest(isend_requests);
/**
* Sends requested nodes to proc
*/
- auto & nodes = const_cast<Array<Real> &>(mesh.getNodes());
- UInt nb_nodes = nodes.size();
+ auto & nodes = mesh_accessor.getNodes();
+ auto nb_nodes = nodes.size();
std::vector<CommunicationRequest> isend_coordinates_requests;
- std::map<UInt, Array<Real>> nodes_to_send_per_proc;
- for (UInt p = 0; p < nb_proc; ++p) {
- if (p == my_rank || !intersects_proc[p]) {
+ std::map<Int, Array<Real>> nodes_to_send_per_proc;
+ for (Int p = 0; p < nb_proc; ++p) {
+ if (p == my_rank or not intersects_proc[p]) {
continue;
}
- Array<UInt> asked_nodes;
+ Array<Int> asked_nodes;
CommunicationStatus status;
AKANTU_DEBUG_INFO("Waiting list of nodes to send to processor "
<< p << "(communication tag : "
<< Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
- comm.probe<UInt>(p, Tag::genTag(p, 0, ASK_NODES_TAG), status);
- UInt nb_nodes_to_send = status.size();
+ comm.probe<Int>(p, Tag::genTag(p, 0, ASK_NODES_TAG), status);
+ Int nb_nodes_to_send = status.size();
asked_nodes.resize(nb_nodes_to_send);
AKANTU_DEBUG_INFO("I have " << nb_nodes_to_send - 1
<< " nodes to send to processor " << p
<< " (communication tag : "
<< Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
AKANTU_DEBUG_INFO("Getting list of nodes to send to processor "
<< p << " (communication tag : "
<< Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
comm.receive(asked_nodes, p, Tag::genTag(p, 0, ASK_NODES_TAG));
nb_nodes_to_send--;
asked_nodes.resize(nb_nodes_to_send);
nodes_to_send_per_proc.emplace(std::piecewise_construct,
std::forward_as_tuple(p),
std::forward_as_tuple(0, spatial_dimension));
auto & nodes_to_send = nodes_to_send_per_proc[p];
auto node_it = nodes.begin(spatial_dimension);
- for (UInt n = 0; n < nb_nodes_to_send; ++n) {
- UInt ln = global_nodes_ids.find(asked_nodes(n));
- AKANTU_DEBUG_ASSERT(ln != UInt(-1), "The node ["
- << asked_nodes(n)
- << "] requested by proc " << p
- << " was not found locally!");
- nodes_to_send.push_back(node_it + ln);
+ for (Int n = 0; n < nb_nodes_to_send; ++n) {
+ auto ln = global_nodes_ids.find(asked_nodes(n));
+ AKANTU_DEBUG_ASSERT(ln != -1, "The node [" << asked_nodes(n)
+ << "] requested by proc " << p
+ << " was not found locally!");
+ nodes_to_send.push_back(node_it[ln]);
}
if (nb_nodes_to_send != 0) {
AKANTU_DEBUG_INFO("Sending the "
<< nb_nodes_to_send << " nodes to processor " << p
<< " (communication tag : "
<< Tag::genTag(p, 0, SEND_NODES_TAG) << ")");
isend_coordinates_requests.push_back(comm.asyncSend(
nodes_to_send, p, Tag::genTag(my_rank, 0, SEND_NODES_TAG)));
}
#if not defined(AKANTU_NDEBUG)
else {
AKANTU_DEBUG_INFO("No nodes to send to processor " << p);
}
#endif
}
Communicator::waitAll(isend_nodes_requests);
Communicator::freeCommunicationRequest(isend_nodes_requests);
nodes.resize(nb_total_nodes_to_recv + nb_nodes);
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if ((p != my_rank) && (nb_nodes_to_recv(p) > 0)) {
AKANTU_DEBUG_INFO("Receiving the "
<< nb_nodes_to_recv(p) << " nodes from processor " << p
<< " (communication tag : "
<< Tag::genTag(p, 0, SEND_NODES_TAG) << ")");
- Vector<Real> nodes_to_recv(nodes.storage() + nb_nodes * spatial_dimension,
- nb_nodes_to_recv(p) * spatial_dimension);
+ VectorProxy<Real> nodes_to_recv(nodes.data() +
+ nb_nodes * spatial_dimension,
+ nb_nodes_to_recv(p) * spatial_dimension);
comm.receive(nodes_to_recv, p, Tag::genTag(p, 0, SEND_NODES_TAG));
nb_nodes += nb_nodes_to_recv(p);
}
#if not defined(AKANTU_NDEBUG)
else {
if (p != my_rank) {
AKANTU_DEBUG_INFO("No nodes to receive from processor " << p);
}
}
#endif
}
Communicator::waitAll(isend_coordinates_requests);
Communicator::freeCommunicationRequest(isend_coordinates_requests);
mesh.sendEvent(new_nodes);
mesh.sendEvent(new_elements);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template void GridSynchronizer::createGridSynchronizer<IntegrationPoint>(
const SpatialGrid<IntegrationPoint> & grid);
template void GridSynchronizer::createGridSynchronizer<Element>(
const SpatialGrid<Element> & grid);
} // namespace akantu
diff --git a/src/synchronizer/master_element_info_per_processor.cc b/src/synchronizer/master_element_info_per_processor.cc
index fa088465b..577e5540a 100644
--- a/src/synchronizer/master_element_info_per_processor.cc
+++ b/src/synchronizer/master_element_info_per_processor.cc
@@ -1,455 +1,460 @@
/**
* @file master_element_info_per_processor.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Mar 16 2016
* @date last modification: Thu Nov 12 2020
*
* @brief Helper class to distribute a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "communicator.hh"
#include "element_group.hh"
#include "element_info_per_processor.hh"
#include "element_synchronizer.hh"
#include "mesh_iterators.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <iostream>
#include <map>
#include <tuple>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
MasterElementInfoPerProc::MasterElementInfoPerProc(
- ElementSynchronizer & synchronizer, UInt message_cnt, UInt root,
+ ElementSynchronizer & synchronizer, Int message_cnt, Int root,
ElementType type, const MeshPartition & partition)
: ElementInfoPerProc(synchronizer, message_cnt, root, type),
- partition(partition), all_nb_local_element(nb_proc, 0),
- all_nb_ghost_element(nb_proc, 0), all_nb_element_to_send(nb_proc, 0) {
- Vector<UInt> size(5);
- size(0) = (UInt)type;
+ partition(partition), all_nb_local_element(Vector<Int>::Zero(nb_proc)),
+ all_nb_ghost_element(Vector<Int>::Zero(nb_proc)),
+ all_nb_element_to_send(Vector<Int>::Zero(nb_proc)) {
+ Vector<Int> size(5);
+ size(0) = (Int)type;
if (type != _not_defined) {
nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
nb_element = mesh.getNbElement(type);
const auto & partition_num =
this->partition.getPartition(this->type, _not_ghost);
const auto & ghost_partition =
this->partition.getGhostPartitionCSR()(this->type, _not_ghost);
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
this->all_nb_local_element[partition_num(el)]++;
for (auto part = ghost_partition.begin(el);
part != ghost_partition.end(el); ++part) {
this->all_nb_ghost_element[*part]++;
}
this->all_nb_element_to_send[partition_num(el)] +=
ghost_partition.getNbCols(el) + 1;
}
/// tag info
auto && tag_names = this->mesh.getTagNames(type);
this->nb_tags = tag_names.size();
size(4) = nb_tags;
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if (p != root) {
size(1) = this->all_nb_local_element[p];
size(2) = this->all_nb_ghost_element[p];
size(3) = this->all_nb_element_to_send[p];
AKANTU_DEBUG_INFO(
"Sending connectivities informations to proc "
<< p << " TAG("
<< Tag::genTag(this->rank, this->message_count, Tag::_sizes)
<< ")");
comm.send(size, p,
Tag::genTag(this->rank, this->message_count, Tag::_sizes));
} else {
this->nb_local_element = this->all_nb_local_element[p];
this->nb_ghost_element = this->all_nb_ghost_element[p];
}
}
} else {
- for (UInt p = 0; p < this->nb_proc; ++p) {
+ for (Int p = 0; p < this->nb_proc; ++p) {
if (p != this->root) {
AKANTU_DEBUG_INFO(
"Sending empty connectivities informations to proc "
<< p << " TAG("
<< Tag::genTag(this->rank, this->message_count, Tag::_sizes)
<< ")");
comm.send(size, p,
Tag::genTag(this->rank, this->message_count, Tag::_sizes));
}
}
}
}
/* ------------------------------------------------------------------------ */
void MasterElementInfoPerProc::synchronizeConnectivities() {
const auto & partition_num =
this->partition.getPartition(this->type, _not_ghost);
const auto & ghost_partition =
this->partition.getGhostPartitionCSR()(this->type, _not_ghost);
- std::vector<Array<UInt>> buffers(this->nb_proc);
+ std::vector<Array<Idx>> buffers(this->nb_proc);
const auto & connectivities =
this->mesh.getConnectivity(this->type, _not_ghost);
/// copying the local connectivity
for (auto && part_conn :
zip(partition_num,
make_view(connectivities, this->nb_nodes_per_element))) {
auto && part = std::get<0>(part_conn);
auto && conn = std::get<1>(part_conn);
- for (UInt i = 0; i < conn.size(); ++i) {
+ for (Int i = 0; i < conn.size(); ++i) {
buffers[part].push_back(conn[i]);
}
}
/// copying the connectivity of ghost element
for (auto && tuple :
enumerate(make_view(connectivities, this->nb_nodes_per_element))) {
auto && el = std::get<0>(tuple);
auto && conn = std::get<1>(tuple);
for (auto part = ghost_partition.begin(el); part != ghost_partition.end(el);
++part) {
- UInt proc = *part;
- for (UInt i = 0; i < conn.size(); ++i) {
+ auto proc = *part;
+ for (Int i = 0; i < conn.size(); ++i) {
buffers[proc].push_back(conn[i]);
}
}
}
#ifndef AKANTU_NDEBUG
for (auto p : arange(this->nb_proc)) {
- UInt size = this->nb_nodes_per_element *
+ auto size = this->nb_nodes_per_element *
(this->all_nb_local_element[p] + this->all_nb_ghost_element[p]);
AKANTU_DEBUG_ASSERT(
- buffers[p].size() == size,
+ Int(buffers[p].size()) == size,
"The connectivity data packed in the buffer are not correct");
}
#endif
/// send all connectivity and ghost information to all processors
std::vector<CommunicationRequest> requests;
for (auto p : arange(this->nb_proc)) {
if (p == this->root) {
continue;
}
auto && tag =
Tag::genTag(this->rank, this->message_count, Tag::_connectivity);
AKANTU_DEBUG_INFO("Sending connectivities to proc " << p << " TAG(" << tag
<< ")");
requests.push_back(comm.asyncSend(buffers[p], p, tag));
}
- Array<UInt> & old_nodes = this->getNodesGlobalIds();
+ auto & old_nodes = this->getNodesGlobalIds();
/// create the renumbered connectivity
AKANTU_DEBUG_INFO("Renumbering local connectivities");
MeshUtils::renumberMeshNodes(mesh, buffers[root], all_nb_local_element[root],
all_nb_ghost_element[root], type, old_nodes);
+ MeshAccessor mesh_accessor(mesh);
+ auto & ghost_counter = mesh_accessor.getGhostsCounters(type, _ghost);
+ ghost_counter.resize(nb_ghost_element, 1);
+
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
}
/* ------------------------------------------------------------------------ */
void MasterElementInfoPerProc::synchronizePartitions() {
const auto & partition_num =
this->partition.getPartition(this->type, _not_ghost);
const auto & ghost_partition =
this->partition.getGhostPartitionCSR()(this->type, _not_ghost);
- std::vector<Array<UInt>> buffers(this->partition.getNbPartition());
+ std::vector<Array<Int>> buffers(this->partition.getNbPartition());
/// splitting the partition information to send them to processors
- Vector<UInt> count_by_proc(nb_proc, 0);
- for (UInt el = 0; el < nb_element; ++el) {
- UInt proc = partition_num(el);
+ Vector<Int> count_by_proc(Vector<Int>::Zero(nb_proc));
+
+ for (Idx el = 0; el < nb_element; ++el) {
+ auto proc = partition_num(el);
buffers[proc].push_back(ghost_partition.getNbCols(el));
- UInt i(0);
+ Int i(0);
for (auto part = ghost_partition.begin(el); part != ghost_partition.end(el);
++part, ++i) {
buffers[proc].push_back(*part);
}
}
- for (UInt el = 0; el < nb_element; ++el) {
- UInt i(0);
+ for (Idx el = 0; el < nb_element; ++el) {
+ Int i(0);
for (auto part = ghost_partition.begin(el); part != ghost_partition.end(el);
++part, ++i) {
buffers[*part].push_back(partition_num(el));
}
}
#ifndef AKANTU_NDEBUG
- for (UInt p = 0; p < this->nb_proc; ++p) {
+ for (Int p = 0; p < this->nb_proc; ++p) {
AKANTU_DEBUG_ASSERT(buffers[p].size() == (this->all_nb_ghost_element[p] +
this->all_nb_element_to_send[p]),
"Data stored in the buffer are most probably wrong");
}
#endif
std::vector<CommunicationRequest> requests;
/// last data to compute the communication scheme
- for (UInt p = 0; p < this->nb_proc; ++p) {
+ for (Int p = 0; p < this->nb_proc; ++p) {
if (p == this->root) {
continue;
}
auto && tag =
Tag::genTag(this->rank, this->message_count, Tag::_partitions);
AKANTU_DEBUG_INFO("Sending partition informations to proc " << p << " TAG("
<< tag << ")");
requests.push_back(comm.asyncSend(buffers[p], p, tag));
}
if (Mesh::getSpatialDimension(this->type) ==
this->mesh.getSpatialDimension()) {
AKANTU_DEBUG_INFO("Creating communications scheme");
this->fillCommunicationScheme(buffers[this->rank]);
}
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
}
/* -------------------------------------------------------------------------- */
void MasterElementInfoPerProc::synchronizeTags() {
AKANTU_DEBUG_IN();
if (this->nb_tags == 0) {
AKANTU_DEBUG_OUT();
return;
}
/// tag info
auto tag_names = mesh.getTagNames(type);
// Make sure the tags are sorted (or at least not in random order),
// because they come from a map !!
std::sort(tag_names.begin(), tag_names.end());
// Sending information about the tags in mesh_data: name, data type and
// number of components of the underlying array associated to the current
// type
DynamicCommunicationBuffer mesh_data_sizes_buffer;
for (auto && tag_name : tag_names) {
mesh_data_sizes_buffer << tag_name;
mesh_data_sizes_buffer << mesh.getTypeCode(tag_name);
mesh_data_sizes_buffer << mesh.getNbComponent(tag_name, type);
}
AKANTU_DEBUG_INFO(
"Broadcasting the size of the information about the mesh data tags: ("
<< mesh_data_sizes_buffer.size() << ").");
AKANTU_DEBUG_INFO(
"Broadcasting the information about the mesh data tags, addr "
- << (void *)mesh_data_sizes_buffer.storage());
+ << (void *)mesh_data_sizes_buffer.data());
comm.broadcast(mesh_data_sizes_buffer, root);
if (mesh_data_sizes_buffer.empty()) {
return;
}
// Sending the actual data to each processor
std::vector<DynamicCommunicationBuffer> buffers(nb_proc);
// Loop over each tag for the current type
for (auto && tag_name : tag_names) {
// Type code of the current tag (i.e. the tag named *names_it)
this->fillTagBuffer(buffers, tag_name);
}
std::vector<CommunicationRequest> requests;
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if (p == root) {
continue;
}
auto && tag = Tag::genTag(this->rank, this->message_count, Tag::_mesh_data);
AKANTU_DEBUG_INFO("Sending " << buffers[p].size()
<< " bytes of mesh data to proc " << p
<< " TAG(" << tag << ")");
requests.push_back(comm.asyncSend(buffers[p], p, tag));
}
// Loop over each tag for the current type
for (auto && tag_name : tag_names) {
// Reinitializing the mesh data on the master
this->fillMeshData(buffers[root], tag_name, mesh.getTypeCode(tag_name),
mesh.getNbComponent(tag_name, type));
}
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
requests.clear();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename T>
void MasterElementInfoPerProc::fillTagBufferTemplated(
std::vector<DynamicCommunicationBuffer> & buffers,
const std::string & tag_name) {
const auto & data = mesh.getElementalDataArray<T>(tag_name, type);
const auto & partition_num =
this->partition.getPartition(this->type, _not_ghost);
const auto & ghost_partition =
this->partition.getGhostPartitionCSR()(this->type, _not_ghost);
// Not possible to use the iterator because it potentially triggers the
// creation of complex
// type templates (such as akantu::Vector< std::vector<Element> > which don't
// implement the right interface
// (e.g. operator<< in that case).
// typename Array<T>::template const_iterator< Vector<T> > data_it =
// data.begin(data.getNbComponent());
// typename Array<T>::template const_iterator< Vector<T> > data_end =
// data.end(data.getNbComponent());
- const T * data_it = data.storage();
- const T * data_end = data.storage() + data.size() * data.getNbComponent();
- const UInt * part = partition_num.storage();
+ const auto * data_it = data.data();
+ const auto * data_end = data.data() + data.size() * data.getNbComponent();
+ const auto * part = partition_num.data();
/// copying the data, element by element
for (; data_it != data_end; ++part) {
- for (UInt j(0); j < data.getNbComponent(); ++j, ++data_it) {
+ for (Int j(0); j < data.getNbComponent(); ++j, ++data_it) {
buffers[*part] << *data_it;
}
}
- data_it = data.storage();
+ data_it = data.data();
/// copying the data for the ghost element
- for (UInt el(0); data_it != data_end;
- data_it += data.getNbComponent(), ++el) {
+ for (Idx el(0); data_it != data_end; data_it += data.getNbComponent(), ++el) {
auto it = ghost_partition.begin(el);
auto end = ghost_partition.end(el);
for (; it != end; ++it) {
- UInt proc = *it;
- for (UInt j(0); j < data.getNbComponent(); ++j) {
+ auto proc = *it;
+ for (Int j(0); j < data.getNbComponent(); ++j) {
buffers[proc] << data_it[j];
}
}
}
}
/* -------------------------------------------------------------------------- */
void MasterElementInfoPerProc::fillTagBuffer(
std::vector<DynamicCommunicationBuffer> & buffers,
const std::string & tag_name) {
#define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, extra_param, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
this->fillTagBufferTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(buffers, \
tag_name); \
break; \
}
MeshDataTypeCode data_type_code = mesh.getTypeCode(tag_name);
switch (data_type_code) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, ,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR("Could not obtain the type of tag" << tag_name << "!");
break;
}
#undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA
}
/* -------------------------------------------------------------------------- */
void MasterElementInfoPerProc::synchronizeGroups() {
AKANTU_DEBUG_IN();
std::vector<DynamicCommunicationBuffer> buffers(nb_proc);
using ElementToGroup = std::vector<std::vector<std::string>>;
ElementToGroup element_to_group(nb_element);
for (auto & eg : mesh.iterateElementGroups()) {
const auto & name = eg.getName();
for (const auto & element : eg.getElements(type, _not_ghost)) {
element_to_group[element].push_back(name);
}
eg.clear(type, _not_ghost);
}
const auto & partition_num =
this->partition.getPartition(this->type, _not_ghost);
const auto & ghost_partition =
this->partition.getGhostPartitionCSR()(this->type, _not_ghost);
/// copying the data, element by element
for (auto && pair : zip(partition_num, element_to_group)) {
buffers[std::get<0>(pair)] << std::get<1>(pair);
}
/// copying the data for the ghost element
for (auto && pair : enumerate(element_to_group)) {
auto && el = std::get<0>(pair);
auto it = ghost_partition.begin(el);
auto end = ghost_partition.end(el);
for (; it != end; ++it) {
- UInt proc = *it;
+ auto proc = *it;
buffers[proc] << std::get<1>(pair);
}
}
std::vector<CommunicationRequest> requests;
- for (UInt p = 0; p < this->nb_proc; ++p) {
+ for (Int p = 0; p < this->nb_proc; ++p) {
if (p == this->rank) {
continue;
}
auto && tag = Tag::genTag(this->rank, p, Tag::_element_group);
AKANTU_DEBUG_INFO("Sending element groups to proc " << p << " TAG(" << tag
<< ")");
requests.push_back(comm.asyncSend(buffers[p], p, tag));
}
this->fillElementGroupsFromBuffer(buffers[this->rank]);
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
requests.clear();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/synchronizer/node_info_per_processor.cc b/src/synchronizer/node_info_per_processor.cc
index 05cfe1f3a..19869ead2 100644
--- a/src/synchronizer/node_info_per_processor.cc
+++ b/src/synchronizer/node_info_per_processor.cc
@@ -1,848 +1,844 @@
/**
* @file node_info_per_processor.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Mar 16 2016
* @date last modification: Fri Jul 24 2020
*
* @brief Please type the brief for file: Helper classes to create the
* distributed synchronizer and distribute a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "node_info_per_processor.hh"
#include "communicator.hh"
#include "node_group.hh"
#include "node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NodeInfoPerProc::NodeInfoPerProc(NodeSynchronizer & synchronizer,
- UInt message_cnt, UInt root)
+ Int message_cnt, Int root)
: MeshAccessor(synchronizer.getMesh()), synchronizer(synchronizer),
comm(synchronizer.getCommunicator()), rank(comm.whoAmI()),
nb_proc(comm.getNbProc()), root(root), mesh(synchronizer.getMesh()),
spatial_dimension(synchronizer.getMesh().getSpatialDimension()),
message_count(message_cnt) {}
/* -------------------------------------------------------------------------- */
void NodeInfoPerProc::synchronize() {
synchronizeNodes();
synchronizeTypes();
synchronizeGroups();
synchronizePeriodicity();
synchronizeTags();
}
/* -------------------------------------------------------------------------- */
template <class CommunicationBuffer>
void NodeInfoPerProc::fillNodeGroupsFromBuffer(CommunicationBuffer & buffer) {
AKANTU_DEBUG_IN();
std::vector<std::vector<std::string>> node_to_group;
buffer >> node_to_group;
- AKANTU_DEBUG_ASSERT(node_to_group.size() == mesh.getNbGlobalNodes(),
+ AKANTU_DEBUG_ASSERT(node_to_group.size() ==
+ std::size_t(mesh.getNbGlobalNodes()),
"Not the good amount of nodes where transmitted");
const auto & global_nodes = mesh.getGlobalNodesIds();
for (auto && data : enumerate(global_nodes)) {
for (const auto & node : node_to_group[std::get<1>(data)]) {
mesh.getNodeGroup(node).add(std::get<0>(data), false);
}
}
for (auto && ng_data : mesh.iterateNodeGroups()) {
ng_data.optimize();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void NodeInfoPerProc::fillNodesType() {
AKANTU_DEBUG_IN();
- UInt nb_nodes = mesh.getNbNodes();
+ auto nb_nodes = mesh.getNbNodes();
auto & nodes_flags = this->getNodesFlags();
- Array<UInt> nodes_set(nb_nodes);
+ Array<Idx> nodes_set(nb_nodes);
nodes_set.set(0);
- enum NodeSet {
+ enum NodeSet : Idx {
NORMAL_SET = 1,
GHOST_SET = 2,
};
Array<bool> already_seen(nb_nodes, 1, false);
for (auto gt : ghost_types) {
- UInt set = NORMAL_SET;
+ auto set = NORMAL_SET;
if (gt == _ghost) {
set = GHOST_SET;
}
already_seen.set(false);
for (auto && type :
mesh.elementTypes(_all_dimensions, gt, _ek_not_defined)) {
const auto & connectivity = mesh.getConnectivity(type, gt);
for (const auto & conn :
make_view(connectivity, connectivity.getNbComponent())) {
- for (UInt n = 0; n < conn.size(); ++n) {
+ for (Int n = 0; n < conn.size(); ++n) {
AKANTU_DEBUG_ASSERT(conn(n) < nb_nodes,
"Node " << conn(n)
<< " bigger than number of nodes "
<< nb_nodes);
if (!already_seen(conn(n))) {
nodes_set(conn(n)) += set;
already_seen(conn(n)) = true;
}
}
}
}
}
nodes_flags.resize(nb_nodes);
- for (UInt i = 0; i < nb_nodes; ++i) {
+ for (Int i = 0; i < nb_nodes; ++i) {
if (nodes_set(i) == NORMAL_SET) {
nodes_flags(i) = NodeFlag::_normal;
} else if (nodes_set(i) == GHOST_SET) {
nodes_flags(i) = NodeFlag::_pure_ghost;
} else if (nodes_set(i) == (GHOST_SET + NORMAL_SET)) {
nodes_flags(i) = NodeFlag::_master;
} else {
AKANTU_EXCEPTION("Gni ?");
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void NodeInfoPerProc::fillCommunicationScheme(const Array<UInt> & master_info) {
+void NodeInfoPerProc::fillCommunicationScheme(const Array<Idx> & master_info) {
AKANTU_DEBUG_IN();
- Communications<UInt> & communications =
- this->synchronizer.getCommunications();
+ auto & communications = this->synchronizer.getCommunications();
{ // send schemes
- std::map<UInt, Array<UInt>> send_array_per_proc;
+ std::map<Int, Array<Idx>> send_array_per_proc;
for (const auto & send_info : make_view(master_info, 2)) {
send_array_per_proc[send_info(0)].push_back(send_info(1));
}
for (auto & send_schemes : send_array_per_proc) {
auto & scheme = communications.createSendScheme(send_schemes.first);
auto & sends = send_schemes.second;
std::sort(sends.begin(), sends.end());
std::transform(sends.begin(), sends.end(), sends.begin(),
- [this](UInt g) -> UInt { return mesh.getNodeLocalId(g); });
+ [this](Idx g) -> Idx { return mesh.getNodeLocalId(g); });
scheme.copy(sends);
AKANTU_DEBUG_INFO("Proc " << rank << " has " << sends.size()
<< " nodes to send to to proc "
<< send_schemes.first);
}
}
{ // receive schemes
- std::map<UInt, Array<UInt>> recv_array_per_proc;
+ std::map<Int, Array<Idx>> recv_array_per_proc;
for (auto node : arange(mesh.getNbNodes())) {
if (mesh.isSlaveNode(node)) {
recv_array_per_proc[mesh.getNodePrank(node)].push_back(
mesh.getNodeGlobalId(node));
}
}
for (auto & recv_schemes : recv_array_per_proc) {
auto & scheme = communications.createRecvScheme(recv_schemes.first);
auto & recvs = recv_schemes.second;
std::sort(recvs.begin(), recvs.end());
std::transform(recvs.begin(), recvs.end(), recvs.begin(),
- [this](UInt g) -> UInt { return mesh.getNodeLocalId(g); });
+ [this](Idx g) -> Idx { return mesh.getNodeLocalId(g); });
scheme.copy(recvs);
AKANTU_DEBUG_INFO("Proc " << rank << " will receive " << recvs.size()
<< " nodes from proc " << recv_schemes.first);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void NodeInfoPerProc::fillPeriodicPairs(const Array<UInt> & global_pairs,
- std::vector<UInt> & missing_nodes) {
+void NodeInfoPerProc::fillPeriodicPairs(const Array<Idx> & global_pairs,
+ std::vector<Idx> & missing_nodes) {
this->wipePeriodicInfo();
auto & nodes_flags = this->getNodesFlags();
auto checkIsLocal = [&](auto && global_node) {
auto && node = mesh.getNodeLocalId(global_node);
- if (node == UInt(-1)) {
+ if (node == -1) {
auto & global_nodes = this->getNodesGlobalIds();
node = global_nodes.size();
global_nodes.push_back(global_node);
nodes_flags.push_back(NodeFlag::_pure_ghost);
missing_nodes.push_back(global_node);
std::cout << "Missing node " << node << std::endl;
}
return node;
};
for (auto && pairs : make_view(global_pairs, 2)) {
- UInt slave = checkIsLocal(pairs(0));
- UInt master = checkIsLocal(pairs(1));
+ auto slave = checkIsLocal(pairs(0));
+ auto master = checkIsLocal(pairs(1));
this->addPeriodicSlave(slave, master);
}
this->markMeshPeriodic();
}
/* -------------------------------------------------------------------------- */
void NodeInfoPerProc::receiveMissingPeriodic(
DynamicCommunicationBuffer & buffer) {
auto & nodes = this->getNodes();
- Communications<UInt> & communications =
- this->synchronizer.getCommunications();
+ auto & communications = this->synchronizer.getCommunications();
std::size_t nb_nodes;
buffer >> nb_nodes;
for (auto _ [[gnu::unused]] : arange(nb_nodes)) {
Vector<Real> pos(spatial_dimension);
Int prank;
buffer >> pos;
buffer >> prank;
- UInt node = nodes.size();
+ auto node = nodes.size();
this->setNodePrank(node, prank);
nodes.push_back(pos);
auto & scheme = communications.createRecvScheme(prank);
scheme.push_back(node);
}
while (buffer.getLeftToUnpack() != 0) {
Int prank;
- UInt gnode;
+ Idx gnode;
buffer >> gnode;
buffer >> prank;
auto node = mesh.getNodeLocalId(gnode);
- AKANTU_DEBUG_ASSERT(node != UInt(-1),
- "I cannot send the node "
- << gnode << " to proc " << prank
- << " because it is note a local node");
+ AKANTU_DEBUG_ASSERT(node != -1, "I cannot send the node "
+ << gnode << " to proc " << prank
+ << " because it is note a local node");
auto & scheme = communications.createSendScheme(prank);
scheme.push_back(node);
}
}
/* -------------------------------------------------------------------------- */
void NodeInfoPerProc::fillNodalData(DynamicCommunicationBuffer & buffer,
const std::string & tag_name) {
#define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, _, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
auto & nodal_data = \
mesh.getNodalData<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(tag_name); \
nodal_data.resize(mesh.getNbNodes()); \
for (auto && data : make_view(nodal_data)) { \
buffer >> data; \
} \
break; \
}
- MeshDataTypeCode data_type_code =
- mesh.getTypeCode(tag_name, MeshDataType::_nodal);
+ auto data_type_code = mesh.getTypeCode(tag_name, MeshDataType::_nodal);
switch (data_type_code) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, ,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR("Could not obtain the type of tag" << tag_name << "!");
break;
}
#undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
MasterNodeInfoPerProc::MasterNodeInfoPerProc(NodeSynchronizer & synchronizer,
- UInt message_cnt, UInt root)
+ Int message_cnt, Int root)
: NodeInfoPerProc(synchronizer, message_cnt, root),
all_nodes(0, synchronizer.getMesh().getSpatialDimension()) {
- UInt nb_global_nodes = this->mesh.getNbGlobalNodes();
+ auto nb_global_nodes = this->mesh.getNbGlobalNodes();
this->comm.broadcast(nb_global_nodes, this->root);
}
/* -------------------------------------------------------------------------- */
void MasterNodeInfoPerProc::synchronizeNodes() {
this->nodes_per_proc.resize(nb_proc);
this->nb_nodes_per_proc.resize(nb_proc);
Array<Real> local_nodes(0, spatial_dimension);
- Array<Real> & nodes = this->getNodes();
+ auto & nodes = this->getNodes();
all_nodes.copy(nodes);
- nodes_pranks.resize(nodes.size(), UInt(-1));
+ nodes_pranks.resize(nodes.size(), -1);
- for (UInt p = 0; p < nb_proc; ++p) {
- UInt nb_nodes = 0;
- // UInt * buffer;
+ for (Int p = 0; p < nb_proc; ++p) {
+ Int nb_nodes = 0;
+ // Int * buffer;
Array<Real> * nodes_to_send{nullptr};
- Array<UInt> & nodespp = nodes_per_proc[p];
+ auto & nodespp = nodes_per_proc[p];
if (p != root) {
nodes_to_send = new Array<Real>(0, spatial_dimension);
AKANTU_DEBUG_INFO("Receiving number of nodes from proc "
<< p << " " << Tag::genTag(p, 0, Tag::_nb_nodes));
comm.receive(nb_nodes, p, Tag::genTag(p, 0, Tag::_nb_nodes));
nodespp.resize(nb_nodes);
this->nb_nodes_per_proc(p) = nb_nodes;
AKANTU_DEBUG_INFO("Receiving list of nodes from proc "
<< p << " " << Tag::genTag(p, 0, Tag::_nodes));
comm.receive(nodespp, p, Tag::genTag(p, 0, Tag::_nodes));
} else {
- Array<UInt> & local_ids = this->getNodesGlobalIds();
+ auto & local_ids = this->getNodesGlobalIds();
this->nb_nodes_per_proc(p) = local_ids.size();
nodespp.copy(local_ids);
nodes_to_send = &local_nodes;
}
/// get the coordinates for the selected nodes
for (const auto & node : nodespp) {
- Vector<Real> coord(nodes.storage() + spatial_dimension * node,
- spatial_dimension);
+ VectorProxy<Real> coord(nodes.data() + spatial_dimension * node,
+ spatial_dimension);
nodes_to_send->push_back(coord);
}
if (p != root) { /// send them for distant processors
AKANTU_DEBUG_INFO("Sending coordinates to proc "
<< p << " "
<< Tag::genTag(this->rank, 0, Tag::_coordinates));
comm.send(*nodes_to_send, p,
Tag::genTag(this->rank, 0, Tag::_coordinates));
delete nodes_to_send;
}
}
/// construct the local nodes coordinates
nodes.copy(local_nodes);
}
/* -------------------------------------------------------------------------- */
void MasterNodeInfoPerProc::synchronizeTypes() {
// <global_id, <proc, local_id> >
- std::multimap<UInt, std::pair<UInt, UInt>> nodes_to_proc;
+ std::multimap<Idx, std::pair<Int, Idx>> nodes_to_proc;
std::vector<Array<NodeFlag>> nodes_flags_per_proc(nb_proc);
std::vector<Array<Int>> nodes_prank_per_proc(nb_proc);
if (mesh.isPeriodic()) {
all_periodic_flags.copy(this->getNodesFlags());
}
// arrays containing pairs of (proc, node)
- std::vector<Array<UInt>> nodes_to_send_per_proc(nb_proc);
- for (UInt p = 0; p < nb_proc; ++p) {
+ std::vector<Array<Idx>> nodes_to_send_per_proc(nb_proc);
+ for (Int p = 0; p < nb_proc; ++p) {
nodes_flags_per_proc[p].resize(nb_nodes_per_proc(p), NodeFlag(0xFF));
nodes_prank_per_proc[p].resize(nb_nodes_per_proc(p), -1);
}
this->fillNodesType();
auto is_master = [](auto && flag) {
return (flag & NodeFlag::_shared_mask) == NodeFlag::_master;
};
auto is_local = [](auto && flag) {
return (flag & NodeFlag::_shared_mask) == NodeFlag::_normal;
};
for (auto p : arange(nb_proc)) {
auto & nodes_flags = nodes_flags_per_proc[p];
if (p != root) {
AKANTU_DEBUG_INFO(
"Receiving first nodes types from proc "
<< p << " "
<< Tag::genTag(this->rank, this->message_count, Tag::_nodes_type));
comm.receive(nodes_flags, p, Tag::genTag(p, 0, Tag::_nodes_type));
} else {
nodes_flags.copy(this->getNodesFlags());
}
// stack all processors claiming to be master for a node
for (auto local_node : arange(nb_nodes_per_proc(p))) {
auto global_node = nodes_per_proc[p](local_node);
if (is_master(nodes_flags(local_node))) {
nodes_to_proc.insert(
std::make_pair(global_node, std::make_pair(p, local_node)));
} else if (is_local(nodes_flags(local_node))) {
nodes_pranks[global_node] = p;
}
}
}
for (auto i : arange(mesh.getNbGlobalNodes())) {
auto it_range = nodes_to_proc.equal_range(i);
if (it_range.first == nodes_to_proc.end() || it_range.first->first != i) {
continue;
}
// pick the first processor out of the multi-map as the actual master
- UInt master_proc = (it_range.first)->second.first;
+ auto master_proc = (it_range.first)->second.first;
nodes_pranks[i] = master_proc;
for (auto && data : range(it_range.first, it_range.second)) {
auto proc = data.second.first;
auto node = data.second.second;
if (proc != master_proc) {
// store the info on all the slaves for a given master
nodes_flags_per_proc[proc](node) = NodeFlag::_slave;
nodes_to_send_per_proc[master_proc].push_back(proc);
nodes_to_send_per_proc[master_proc].push_back(i);
}
}
}
/// Fills the nodes prank per proc
for (auto && data : zip(arange(nb_proc), nodes_per_proc, nodes_prank_per_proc,
nodes_flags_per_proc)) {
for (auto && node_data :
zip(std::get<1>(data), std::get<2>(data), std::get<3>(data))) {
if (std::get<2>(node_data) == NodeFlag::_normal) {
std::get<1>(node_data) = std::get<0>(data);
} else {
std::get<1>(node_data) = nodes_pranks(std::get<0>(node_data));
}
}
}
std::vector<CommunicationRequest> requests_send_type;
std::vector<CommunicationRequest> requests_send_master_info;
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if (p != root) {
auto tag0 = Tag::genTag(this->rank, 0, Tag::_nodes_type);
AKANTU_DEBUG_INFO("Sending nodes types to proc " << p << " " << tag0);
requests_send_type.push_back(
comm.asyncSend(nodes_flags_per_proc[p], p, tag0));
auto tag2 = Tag::genTag(this->rank, 2, Tag::_nodes_type);
AKANTU_DEBUG_INFO("Sending nodes pranks to proc " << p << " " << tag2);
requests_send_type.push_back(
comm.asyncSend(nodes_prank_per_proc[p], p, tag2));
auto & nodes_to_send = nodes_to_send_per_proc[p];
auto tag1 = Tag::genTag(this->rank, 1, Tag::_nodes_type);
AKANTU_DEBUG_INFO("Sending nodes master info to proc " << p << " "
<< tag1);
requests_send_master_info.push_back(
comm.asyncSend(nodes_to_send, p, tag1));
} else {
this->getNodesFlags().copy(nodes_flags_per_proc[p]);
for (auto && data : enumerate(nodes_prank_per_proc[p])) {
auto node = std::get<0>(data);
if (not(mesh.isMasterNode(node) or mesh.isLocalNode(node))) {
this->setNodePrank(node, std::get<1>(data));
}
}
this->fillCommunicationScheme(nodes_to_send_per_proc[root]);
}
}
Communicator::waitAll(requests_send_type);
Communicator::freeCommunicationRequest(requests_send_type);
Communicator::waitAll(requests_send_master_info);
Communicator::freeCommunicationRequest(requests_send_master_info);
}
/* -------------------------------------------------------------------------- */
void MasterNodeInfoPerProc::synchronizeGroups() {
AKANTU_DEBUG_IN();
- UInt nb_total_nodes = mesh.getNbGlobalNodes();
+ auto nb_total_nodes = mesh.getNbGlobalNodes();
DynamicCommunicationBuffer buffer;
using NodeToGroup = std::vector<std::vector<std::string>>;
NodeToGroup node_to_group;
node_to_group.resize(nb_total_nodes);
for (auto & ng : mesh.iterateNodeGroups()) {
std::string name = ng.getName();
for (auto && node : ng.getNodes()) {
node_to_group[node].push_back(name);
}
ng.clear();
}
buffer << node_to_group;
std::vector<CommunicationRequest> requests;
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if (p == this->rank) {
continue;
}
AKANTU_DEBUG_INFO("Sending node groups to proc "
<< p << " "
<< Tag::genTag(this->rank, p, Tag::_node_group));
requests.push_back(comm.asyncSend(
buffer, p, Tag::genTag(this->rank, p, Tag::_node_group)));
}
this->fillNodeGroupsFromBuffer(buffer);
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
requests.clear();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MasterNodeInfoPerProc::synchronizePeriodicity() {
bool is_periodic = mesh.isPeriodic();
comm.broadcast(is_periodic, root);
if (not is_periodic) {
return;
}
std::vector<CommunicationRequest> requests;
- std::vector<Array<UInt>> periodic_info_to_send_per_proc;
+ std::vector<Array<Idx>> periodic_info_to_send_per_proc;
for (auto p : arange(nb_proc)) {
periodic_info_to_send_per_proc.emplace_back(0, 2);
auto && periodic_info = periodic_info_to_send_per_proc.back();
- for (UInt proc_local_node : arange(nb_nodes_per_proc(p))) {
- UInt global_node = nodes_per_proc[p](proc_local_node);
+ for (Int proc_local_node : arange(nb_nodes_per_proc(p))) {
+ auto global_node = nodes_per_proc[p](proc_local_node);
if ((all_periodic_flags[global_node] & NodeFlag::_periodic_mask) ==
NodeFlag::_periodic_slave) {
periodic_info.push_back(
- Vector<UInt>{global_node, mesh.getPeriodicMaster(global_node)});
+ Vector<Idx>{global_node, mesh.getPeriodicMaster(global_node)});
}
}
if (p == root) {
continue;
}
auto && tag = Tag::genTag(this->rank, p, Tag::_periodic_slaves);
AKANTU_DEBUG_INFO("Sending periodic info to proc " << p << " " << tag);
requests.push_back(comm.asyncSend(periodic_info, p, tag));
}
CommunicationStatus status;
std::vector<DynamicCommunicationBuffer> buffers(nb_proc);
- std::vector<std::vector<UInt>> proc_missings(nb_proc);
+ std::vector<std::vector<Int>> proc_missings(nb_proc);
auto nodes_it = all_nodes.begin(spatial_dimension);
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
auto & proc_missing = proc_missings[p];
if (p != root) {
auto && tag = Tag::genTag(p, 0, Tag::_periodic_nodes);
- comm.probe<UInt>(p, tag, status);
+ comm.probe<Int>(p, tag, status);
proc_missing.resize(status.size());
comm.receive(proc_missing, p, tag);
} else {
fillPeriodicPairs(periodic_info_to_send_per_proc[root], proc_missing);
}
auto & buffer = buffers[p];
buffer.reserve((spatial_dimension * sizeof(Real) + sizeof(Int)) *
proc_missing.size());
buffer << proc_missing.size();
for (auto && node : proc_missing) {
buffer << *(nodes_it + node);
buffer << nodes_pranks(node);
}
}
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
for (auto && node : proc_missings[p]) {
auto & buffer = buffers[nodes_pranks(node)];
buffer << node;
buffer << p;
}
}
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
if (p != root) {
auto && tag_send = Tag::genTag(p, 1, Tag::_periodic_nodes);
requests.push_back(comm.asyncSend(buffers[p], p, tag_send));
} else {
receiveMissingPeriodic(buffers[p]);
}
}
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
}
/* -------------------------------------------------------------------------- */
void MasterNodeInfoPerProc::fillTagBuffers(
std::vector<DynamicCommunicationBuffer> & buffers,
const std::string & tag_name) {
#define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, _, elem) \
case MeshDataTypeCode::BOOST_PP_TUPLE_ELEM(2, 0, elem): { \
auto & nodal_data = \
mesh.getNodalData<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(tag_name); \
for (auto && data : enumerate(nodes_per_proc)) { \
auto proc = std::get<0>(data); \
auto & nodes = std::get<1>(data); \
auto & buffer = buffers[proc]; \
for (auto & node : nodes) { \
for (auto i : arange(nodal_data.getNbComponent())) { \
buffer << nodal_data(node, i); \
} \
} \
} \
break; \
}
- MeshDataTypeCode data_type_code =
- mesh.getTypeCode(tag_name, MeshDataType::_nodal);
+ auto data_type_code = mesh.getTypeCode(tag_name, MeshDataType::_nodal);
switch (data_type_code) {
BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, ,
AKANTU_MESH_DATA_TYPES)
default:
AKANTU_ERROR("Could not obtain the type of tag" << tag_name << "!");
break;
}
#undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA
} // namespace akantu
/* -------------------------------------------------------------------------- */
void MasterNodeInfoPerProc::synchronizeTags() {
/// tag info
auto tag_names = mesh.getTagNames();
DynamicCommunicationBuffer tags_buffer;
for (auto && tag_name : tag_names) {
tags_buffer << tag_name;
tags_buffer << mesh.getTypeCode(tag_name, MeshDataType::_nodal);
tags_buffer << mesh.getNbComponent(tag_name);
}
AKANTU_DEBUG_INFO(
"Broadcasting the information about the nodes mesh data tags: ("
<< tags_buffer.size() << ").");
comm.broadcast(tags_buffer, root);
for (auto && tag_data : enumerate(tag_names)) {
auto tag_count = std::get<0>(tag_data);
auto & tag_name = std::get<1>(tag_data);
std::vector<DynamicCommunicationBuffer> buffers;
std::vector<CommunicationRequest> requests;
buffers.resize(nb_proc);
fillTagBuffers(buffers, tag_name);
for (auto && data : enumerate(buffers)) {
- auto && proc = std::get<0>(data);
+ Int proc = std::get<0>(data);
auto & buffer = std::get<1>(data);
if (proc == root) {
fillNodalData(buffer, tag_name);
} else {
auto && tag = Tag::genTag(this->rank, tag_count, Tag::_mesh_data);
requests.push_back(comm.asyncSend(buffer, proc, tag));
}
}
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
SlaveNodeInfoPerProc::SlaveNodeInfoPerProc(NodeSynchronizer & synchronizer,
- UInt message_cnt, UInt root)
+ Int message_cnt, Int root)
: NodeInfoPerProc(synchronizer, message_cnt, root) {
- UInt nb_global_nodes = 0;
+ Int nb_global_nodes = 0;
comm.broadcast(nb_global_nodes, root);
this->setNbGlobalNodes(nb_global_nodes);
}
/* -------------------------------------------------------------------------- */
void SlaveNodeInfoPerProc::synchronizeNodes() {
AKANTU_DEBUG_INFO("Sending list of nodes to proc "
<< root << " " << Tag::genTag(this->rank, 0, Tag::_nb_nodes)
<< " " << Tag::genTag(this->rank, 0, Tag::_nodes));
- Array<UInt> & local_ids = this->getNodesGlobalIds();
- Array<Real> & nodes = this->getNodes();
+ auto & local_ids = this->getNodesGlobalIds();
+ auto & nodes = this->getNodes();
- UInt nb_nodes = local_ids.size();
+ auto nb_nodes = local_ids.size();
comm.send(nb_nodes, root, Tag::genTag(this->rank, 0, Tag::_nb_nodes));
comm.send(local_ids, root, Tag::genTag(this->rank, 0, Tag::_nodes));
/* --------<<<<-COORDINATES---------------------------------------------- */
nodes.resize(nb_nodes);
AKANTU_DEBUG_INFO("Receiving coordinates from proc "
<< root << " " << Tag::genTag(root, 0, Tag::_coordinates));
comm.receive(nodes, root, Tag::genTag(root, 0, Tag::_coordinates));
}
/* -------------------------------------------------------------------------- */
void SlaveNodeInfoPerProc::synchronizeTypes() {
this->fillNodesType();
auto & nodes_flags = this->getNodesFlags();
AKANTU_DEBUG_INFO("Sending first nodes types to proc "
<< root << ""
<< Tag::genTag(this->rank, 0, Tag::_nodes_type));
comm.send(nodes_flags, root, Tag::genTag(this->rank, 0, Tag::_nodes_type));
AKANTU_DEBUG_INFO("Receiving nodes types from proc "
<< root << " " << Tag::genTag(root, 0, Tag::_nodes_type));
comm.receive(nodes_flags, root, Tag::genTag(root, 0, Tag::_nodes_type));
Array<Int> nodes_prank(nodes_flags.size());
AKANTU_DEBUG_INFO("Receiving nodes pranks from proc "
<< root << " " << Tag::genTag(root, 2, Tag::_nodes_type));
comm.receive(nodes_prank, root, Tag::genTag(root, 2, Tag::_nodes_type));
for (auto && data : enumerate(nodes_prank)) {
auto node = std::get<0>(data);
if (not(mesh.isMasterNode(node) or mesh.isLocalNode(node))) {
this->setNodePrank(node, std::get<1>(data));
}
}
AKANTU_DEBUG_INFO("Receiving nodes master info from proc "
<< root << " " << Tag::genTag(root, 1, Tag::_nodes_type));
CommunicationStatus status;
- comm.probe<UInt>(root, Tag::genTag(root, 1, Tag::_nodes_type), status);
+ comm.probe<Idx>(root, Tag::genTag(root, 1, Tag::_nodes_type), status);
- Array<UInt> nodes_master_info(status.size());
+ Array<Idx> nodes_master_info(status.size());
comm.receive(nodes_master_info, root, Tag::genTag(root, 1, Tag::_nodes_type));
this->fillCommunicationScheme(nodes_master_info);
}
/* -------------------------------------------------------------------------- */
void SlaveNodeInfoPerProc::synchronizeGroups() {
AKANTU_DEBUG_IN();
AKANTU_DEBUG_INFO("Receiving node groups from proc "
<< root << " "
<< Tag::genTag(root, this->rank, Tag::_node_group));
DynamicCommunicationBuffer buffer;
comm.receive(buffer, root, Tag::genTag(root, this->rank, Tag::_node_group));
this->fillNodeGroupsFromBuffer(buffer);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SlaveNodeInfoPerProc::synchronizePeriodicity() {
bool is_periodic;
comm.broadcast(is_periodic, root);
if (not is_periodic) {
return;
}
CommunicationStatus status;
auto && tag = Tag::genTag(root, this->rank, Tag::_periodic_slaves);
- comm.probe<UInt>(root, tag, status);
+ comm.probe<Int>(root, tag, status);
- Array<UInt> periodic_info(status.size() / 2, 2);
+ Array<Int> periodic_info(status.size() / 2, 2);
comm.receive(periodic_info, root, tag);
- std::vector<UInt> proc_missing;
+ std::vector<Int> proc_missing;
fillPeriodicPairs(periodic_info, proc_missing);
auto && tag_missing_request =
Tag::genTag(this->rank, 0, Tag::_periodic_nodes);
comm.send(proc_missing, root, tag_missing_request);
DynamicCommunicationBuffer buffer;
auto && tag_missing = Tag::genTag(this->rank, 1, Tag::_periodic_nodes);
comm.receive(buffer, root, tag_missing);
receiveMissingPeriodic(buffer);
}
/* -------------------------------------------------------------------------- */
void SlaveNodeInfoPerProc::synchronizeTags() {
DynamicCommunicationBuffer tags_buffer;
comm.broadcast(tags_buffer, root);
std::vector<std::string> tag_names;
while (tags_buffer.getLeftToUnpack() > 0) {
std::string name;
MeshDataTypeCode code;
- UInt nb_components;
+ Int nb_components;
tags_buffer >> name;
tags_buffer >> code;
tags_buffer >> nb_components;
mesh.registerNodalData(name, nb_components, code);
tag_names.push_back(name);
}
for (auto && tag_data : enumerate(tag_names)) {
auto tag_count = std::get<0>(tag_data);
auto & tag_name = std::get<1>(tag_data);
DynamicCommunicationBuffer buffer;
auto && tag = Tag::genTag(this->root, tag_count, Tag::_mesh_data);
comm.receive(buffer, this->root, tag);
fillNodalData(buffer, tag_name);
}
}
} // namespace akantu
diff --git a/src/synchronizer/node_info_per_processor.hh b/src/synchronizer/node_info_per_processor.hh
index 9ed2b2181..fd2d2c637 100644
--- a/src/synchronizer/node_info_per_processor.hh
+++ b/src/synchronizer/node_info_per_processor.hh
@@ -1,130 +1,129 @@
/**
* @file node_info_per_processor.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Mar 16 2016
* @date last modification: Fri Jul 24 2020
*
* @brief Helper classes to create the distributed synchronizer and distribute
* a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communication_buffer.hh"
#include "mesh_accessor.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NODE_INFO_PER_PROCESSOR_HH_
#define AKANTU_NODE_INFO_PER_PROCESSOR_HH_
namespace akantu {
class NodeSynchronizer;
class Communicator;
} // namespace akantu
/* -------------------------------------------------------------------------- */
namespace akantu {
class NodeInfoPerProc : protected MeshAccessor {
public:
- NodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt, UInt root);
+ NodeInfoPerProc(NodeSynchronizer & synchronizer, Int message_cnt, Int root);
void synchronize();
protected:
virtual void synchronizeNodes() = 0;
virtual void synchronizeTypes() = 0;
virtual void synchronizeGroups() = 0;
virtual void synchronizePeriodicity() = 0;
virtual void synchronizeTags() = 0;
protected:
template <class CommunicationBuffer>
void fillNodeGroupsFromBuffer(CommunicationBuffer & buffer);
void fillNodesType();
- void fillCommunicationScheme(const Array<UInt> & /*master_info*/);
+ void fillCommunicationScheme(const Array<Idx> &);
void fillNodalData(DynamicCommunicationBuffer & buffer,
const std::string & tag_name);
- void fillPeriodicPairs(const Array<UInt> & /*global_pairs*/,
- std::vector<UInt> & /*missing_nodes*/);
- void receiveMissingPeriodic(DynamicCommunicationBuffer & /*buffer*/);
+ void fillPeriodicPairs(const Array<Idx> &, std::vector<Idx> &);
+ void receiveMissingPeriodic(DynamicCommunicationBuffer &);
protected:
NodeSynchronizer & synchronizer;
const Communicator & comm;
- UInt rank;
- UInt nb_proc;
- UInt root;
+ Int rank;
+ Int nb_proc;
+ Int root;
Mesh & mesh;
- UInt spatial_dimension;
- UInt message_count;
+ Int spatial_dimension;
+ Int message_count;
};
/* -------------------------------------------------------------------------- */
class MasterNodeInfoPerProc : public NodeInfoPerProc {
public:
- MasterNodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt,
- UInt root);
+ MasterNodeInfoPerProc(NodeSynchronizer & synchronizer, Int message_cnt,
+ Int root);
void synchronizeNodes() override;
void synchronizeTypes() override;
void synchronizeGroups() override;
void synchronizePeriodicity() override;
void synchronizeTags() override;
private:
void fillTagBuffers(std::vector<DynamicCommunicationBuffer> & buffers,
const std::string & tag_name);
/// get the list of nodes to send and send them
- std::vector<Array<UInt>> nodes_per_proc;
- Array<UInt> nb_nodes_per_proc;
+ std::vector<Array<Idx>> nodes_per_proc;
+ Array<Int> nb_nodes_per_proc;
Array<Real> all_nodes;
Array<NodeFlag> all_periodic_flags;
Array<Int> nodes_pranks;
};
/* -------------------------------------------------------------------------- */
class SlaveNodeInfoPerProc : public NodeInfoPerProc {
public:
- SlaveNodeInfoPerProc(NodeSynchronizer & synchronizer, UInt message_cnt,
- UInt root);
+ SlaveNodeInfoPerProc(NodeSynchronizer & synchronizer, Int message_cnt,
+ Int root);
void synchronizeNodes() override;
void synchronizeTypes() override;
void synchronizeGroups() override;
void synchronizePeriodicity() override;
void synchronizeTags() override;
private:
};
} // namespace akantu
#endif /* AKANTU_NODE_INFO_PER_PROCESSOR_HH_ */
diff --git a/src/synchronizer/node_synchronizer.cc b/src/synchronizer/node_synchronizer.cc
index a64cd2f07..a61a1490a 100644
--- a/src/synchronizer/node_synchronizer.cc
+++ b/src/synchronizer/node_synchronizer.cc
@@ -1,247 +1,247 @@
/**
* @file node_synchronizer.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Dec 09 2020
*
* @brief Implementation of the node synchronizer
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "node_synchronizer.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
NodeSynchronizer::NodeSynchronizer(Mesh & mesh, const ID & id,
const bool register_to_event_manager,
EventHandlerPriority event_priority)
- : SynchronizerImpl<UInt>(mesh.getCommunicator(), id), mesh(mesh) {
+ : SynchronizerImpl<Idx>(mesh.getCommunicator(), id), mesh(mesh) {
AKANTU_DEBUG_IN();
if (register_to_event_manager) {
this->mesh.registerEventHandler(*this, event_priority);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
NodeSynchronizer::~NodeSynchronizer() = default;
/* -------------------------------------------------------------------------- */
-Int NodeSynchronizer::getRank(const UInt & node) const {
+Int NodeSynchronizer::getRank(const Idx & node) const {
return this->mesh.getNodePrank(node);
}
/* -------------------------------------------------------------------------- */
-void NodeSynchronizer::onNodesAdded(const Array<UInt> & /*nodes_list*/,
- const NewNodesEvent & /*unused*/) {
- std::map<UInt, std::vector<UInt>> nodes_per_proc;
+void NodeSynchronizer::onNodesAdded(const Array<Idx> & /*nodes_list*/,
+ const NewNodesEvent &) {
+ std::map<Int, std::vector<Idx>> nodes_per_proc;
// recreates fully the schemes due to changes of global ids
// \TODO add an event to handle global id changes
for (auto && data : communications.iterateSchemes(_recv)) {
auto & scheme = data.second;
scheme.resize(0);
}
for (auto && local_id : arange(mesh.getNbNodes())) {
if (not mesh.isSlaveNode(local_id)) {
continue; // local, master or pure ghost
}
auto global_id = mesh.getNodeGlobalId(local_id);
auto proc = mesh.getNodePrank(local_id);
AKANTU_DEBUG_ASSERT(
proc != -1,
"The node " << local_id << " does not have a valid associated prank");
nodes_per_proc[proc].push_back(global_id);
auto & scheme = communications.createScheme(proc, _recv);
scheme.push_back(local_id);
}
std::vector<CommunicationRequest> send_requests;
for (auto && pair : communications.iterateSchemes(_recv)) {
auto proc = pair.first;
- AKANTU_DEBUG_ASSERT(proc != UInt(-1),
+ AKANTU_DEBUG_ASSERT(proc != -1,
"For real I should send something to proc -1");
// if proc not in nodes_per_proc this should insert an empty array to send
send_requests.push_back(communicator.asyncSend(
nodes_per_proc[proc], proc, Tag::genTag(rank, proc, 0xcafe)));
}
for (auto && data : communications.iterateSchemes(_send)) {
auto proc = data.first;
auto & scheme = data.second;
CommunicationStatus status;
auto tag = Tag::genTag(proc, rank, 0xcafe);
- communicator.probe<UInt>(proc, tag, status);
+ communicator.probe<Int>(proc, tag, status);
scheme.resize(status.size());
communicator.receive(scheme, proc, tag);
std::transform(scheme.begin(), scheme.end(), scheme.begin(),
[&](auto & gnode) { return mesh.getNodeLocalId(gnode); });
}
// communicator.receiveAnyNumber<UInt>(
// send_requests,
// [&](auto && proc, auto && nodes) {
// auto & scheme = communications.createScheme(proc, _send);
// scheme.resize(nodes.size());
// for (auto && data : enumerate(nodes)) {
// auto global_id = std::get<1>(data);
// auto local_id = mesh.getNodeLocalId(global_id);
// AKANTU_DEBUG_ASSERT(local_id != UInt(-1),
// "The global node " << global_id
// << "is not known on rank "
// << rank);
// scheme[std::get<0>(data)] = local_id;
// }
// },
// Tag::genTag(rank, count, 0xcafe));
// ++count;
Communicator::waitAll(send_requests);
Communicator::freeCommunicationRequest(send_requests);
this->entities_changed = true;
}
/* -------------------------------------------------------------------------- */
-UInt NodeSynchronizer::sanityCheckDataSize(const Array<UInt> & nodes,
- const SynchronizationTag & tag,
- bool from_comm_desc) const {
- UInt size =
- SynchronizerImpl<UInt>::sanityCheckDataSize(nodes, tag, from_comm_desc);
+Int NodeSynchronizer::sanityCheckDataSize(const Array<Idx> & nodes,
+ const SynchronizationTag & tag,
+ bool from_comm_desc) const {
+ auto size =
+ SynchronizerImpl<Idx>::sanityCheckDataSize(nodes, tag, from_comm_desc);
// global id
if (tag != SynchronizationTag::_giu_global_conn) {
- size += sizeof(UInt) * nodes.size();
+ size += sizeof(Idx) * nodes.size();
}
// flag
size += sizeof(NodeFlag) * nodes.size();
// positions
size += mesh.getSpatialDimension() * sizeof(Real) * nodes.size();
return size;
}
/* -------------------------------------------------------------------------- */
void NodeSynchronizer::packSanityCheckData(
- CommunicationBuffer & buffer, const Array<UInt> & nodes,
+ CommunicationBuffer & buffer, const Array<Idx> & nodes,
const SynchronizationTag & tag) const {
auto dim = mesh.getSpatialDimension();
for (auto && node : nodes) {
if (tag != SynchronizationTag::_giu_global_conn) {
buffer << mesh.getNodeGlobalId(node);
}
buffer << mesh.getNodeFlag(node);
buffer << Vector<Real>(mesh.getNodes().begin(dim)[node]);
}
}
/* -------------------------------------------------------------------------- */
void NodeSynchronizer::unpackSanityCheckData(CommunicationBuffer & buffer,
- const Array<UInt> & nodes,
+ const Array<Idx> & nodes,
const SynchronizationTag & tag,
- UInt proc, UInt rank) const {
+ Int proc, Int rank) const {
auto dim = mesh.getSpatialDimension();
#ifndef AKANTU_NDEBUG
auto periodic = [&](auto && flag) { return flag & NodeFlag::_periodic_mask; };
auto distrib = [&](auto && flag) { return flag & NodeFlag::_shared_mask; };
#endif
for (auto && node : nodes) {
if (tag != SynchronizationTag::_giu_global_conn) {
- UInt global_id;
+ Int global_id;
buffer >> global_id;
AKANTU_DEBUG_ASSERT(global_id == mesh.getNodeGlobalId(node),
"The nodes global ids do not match: "
<< global_id
<< " != " << mesh.getNodeGlobalId(node));
}
NodeFlag flag;
buffer >> flag;
AKANTU_DEBUG_ASSERT(
(periodic(flag) == periodic(mesh.getNodeFlag(node))) and
(((distrib(flag) == NodeFlag::_master) and
(distrib(mesh.getNodeFlag(node)) ==
NodeFlag::_slave)) or // master to slave
((distrib(flag) == NodeFlag::_slave) and
(distrib(mesh.getNodeFlag(node)) ==
NodeFlag::_master)) or // reverse comm slave to master
(distrib(mesh.getNodeFlag(node)) ==
NodeFlag::_pure_ghost or // pure ghost nodes
distrib(flag) == NodeFlag::_pure_ghost)),
"The node flags: " << flag << " and " << mesh.getNodeFlag(node));
Vector<Real> pos_remote(dim);
buffer >> pos_remote;
Vector<Real> pos(mesh.getNodes().begin(dim)[node]);
auto dist = pos_remote.distance(pos);
if (not Math::are_float_equal(dist, 0.)) {
AKANTU_EXCEPTION("Unpacking an unknown value for the node "
<< node << "(position " << pos << " != buffer "
<< pos_remote << ") [" << dist << "] - tag: " << tag
<< " comm from " << proc << " to " << rank);
}
}
}
/* -------------------------------------------------------------------------- */
-void NodeSynchronizer::fillEntityToSend(Array<UInt> & nodes_to_send) {
- UInt nb_nodes = mesh.getNbNodes();
+void NodeSynchronizer::fillEntityToSend(Array<Idx> & nodes_to_send) {
+ auto nb_nodes = mesh.getNbNodes();
this->entities_from_root.clear();
nodes_to_send.resize(0);
- for (UInt n : arange(nb_nodes)) {
+ for (Int n : arange(nb_nodes)) {
if (not mesh.isLocalOrMasterNode(n)) {
continue;
}
entities_from_root.push_back(n);
}
for (auto n : entities_from_root) {
- UInt global_node = mesh.getNodeGlobalId(n);
+ auto global_node = mesh.getNodeGlobalId(n);
nodes_to_send.push_back(global_node);
}
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/synchronizer/node_synchronizer.hh b/src/synchronizer/node_synchronizer.hh
index d13c2f628..37a9f240f 100644
--- a/src/synchronizer/node_synchronizer.hh
+++ b/src/synchronizer/node_synchronizer.hh
@@ -1,115 +1,112 @@
/**
* @file node_synchronizer.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Wed Mar 04 2020
*
* @brief Synchronizer for nodal information
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_events.hh"
-#include "synchronizer_impl.hh"
+#include "synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <unordered_map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NODE_SYNCHRONIZER_HH_
#define AKANTU_NODE_SYNCHRONIZER_HH_
namespace akantu {
class NodeSynchronizer : public MeshEventHandler,
- public SynchronizerImpl<UInt> {
+ public SynchronizerImpl<Idx> {
public:
NodeSynchronizer(Mesh & mesh, const ID & id = "element_synchronizer",
bool register_to_event_manager = true,
EventHandlerPriority event_priority = _ehp_synchronizer);
~NodeSynchronizer() override;
- UInt sanityCheckDataSize(const Array<UInt> & nodes,
+ Int sanityCheckDataSize(const Array<Idx> & nodes,
const SynchronizationTag & tag,
bool from_comm_desc) const override;
void packSanityCheckData(CommunicationBuffer & buffer,
- const Array<UInt> & nodes,
+ const Array<Idx> & nodes,
const SynchronizationTag & /*tag*/) const override;
void unpackSanityCheckData(CommunicationBuffer & buffer,
- const Array<UInt> & nodes,
- const SynchronizationTag & tag, UInt proc,
- UInt rank) const override;
+ const Array<Idx> & nodes,
+ const SynchronizationTag & tag, Int proc,
+ Int rank) const override;
/// function to implement to react on akantu::NewNodesEvent
- void onNodesAdded(const Array<UInt> & /*unused*/,
- const NewNodesEvent & /*unused*/) override;
+ void onNodesAdded(const Array<Idx> &, const NewNodesEvent &) override;
/// function to implement to react on akantu::RemovedNodesEvent
- void onNodesRemoved(const Array<UInt> & /*unused*/,
- const Array<UInt> & /*unused*/,
- const RemovedNodesEvent & /*unused*/) override {}
+ void onNodesRemoved(const Array<Idx> &, const Array<Idx> &,
+ const RemovedNodesEvent &) override {}
/// function to implement to react on akantu::NewElementsEvent
void onElementsAdded(const Array<Element> & /*unused*/,
const NewElementsEvent & /*unused*/) override {}
/// function to implement to react on akantu::RemovedElementsEvent
- void onElementsRemoved(const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const RemovedElementsEvent & /*unused*/) override {}
+ void onElementsRemoved(const Array<Element> &,
+ const ElementTypeMapArray<Idx> &,
+ const RemovedElementsEvent &) override {}
/// function to implement to react on akantu::ChangedElementsEvent
- void onElementsChanged(const Array<Element> & /*unused*/,
- const Array<Element> & /*unused*/,
- const ElementTypeMapArray<UInt> & /*unused*/,
- const ChangedElementsEvent & /*unused*/) override {}
+ void onElementsChanged(const Array<Element> &, const Array<Element> &,
+ const ElementTypeMapArray<Idx> &,
+ const ChangedElementsEvent &) override {}
/* ------------------------------------------------------------------------ */
NodeSynchronizer & operator=(const NodeSynchronizer & other) {
copySchemes(other);
return *this;
}
friend class NodeInfoPerProc;
protected:
- void fillEntityToSend(Array<UInt> & nodes_to_send) override;
+ void fillEntityToSend(Array<Idx> & entities_to_send) override;
public:
AKANTU_GET_MACRO(Mesh, mesh, Mesh &);
- inline UInt canScatterSize() override;
- inline UInt gatheredSize() override;
-
- inline UInt localToGlobalEntity(const UInt & local) override;
+ inline Int canScatterSize() override;
+ inline Int gatheredSize() override;
+ inline Idx localToGlobalEntity(const Idx & local) override;
+
protected:
- Int getRank(const UInt & node) const final;
+ Int getRank(const Idx & node) const final;
protected:
Mesh & mesh;
};
} // namespace akantu
#include "node_synchronizer_inline_impl.hh"
#endif /* AKANTU_NODE_SYNCHRONIZER_HH_ */
diff --git a/src/synchronizer/node_synchronizer_inline_impl.hh b/src/synchronizer/node_synchronizer_inline_impl.hh
index 828eb6a20..f738b9e9e 100644
--- a/src/synchronizer/node_synchronizer_inline_impl.hh
+++ b/src/synchronizer/node_synchronizer_inline_impl.hh
@@ -1,55 +1,59 @@
/**
* @file node_synchronizer_inline_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Wed Mar 04 2020
*
* @brief Synchronizer for nodal information
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh.hh"
#include "node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NODE_SYNCHRONIZER_INLINE_IMPL_HH_
#define AKANTU_NODE_SYNCHRONIZER_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-inline UInt NodeSynchronizer::canScatterSize() { return mesh.getNbNodes(); }
+inline Int NodeSynchronizer::canScatterSize() {
+ return mesh.getNbNodes();
+}
/* -------------------------------------------------------------------------- */
-inline UInt NodeSynchronizer::gatheredSize() { return mesh.getNbGlobalNodes(); }
+inline Int NodeSynchronizer::gatheredSize() {
+ return mesh.getNbGlobalNodes();
+}
/* -------------------------------------------------------------------------- */
-inline UInt NodeSynchronizer::localToGlobalEntity(const UInt & local) {
+inline Idx NodeSynchronizer::localToGlobalEntity(const Idx & local) {
return mesh.getNodeGlobalId(local);
}
} // namespace akantu
#endif // AKANTU_NODE_SYNCHRONIZER_INLINE_IMPL_HH_
diff --git a/src/synchronizer/periodic_node_synchronizer.cc b/src/synchronizer/periodic_node_synchronizer.cc
index a74feda8c..7ff9c0fc8 100644
--- a/src/synchronizer/periodic_node_synchronizer.cc
+++ b/src/synchronizer/periodic_node_synchronizer.cc
@@ -1,135 +1,135 @@
/**
* @file periodic_node_synchronizer.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed May 30 2018
* @date last modification: Fri Jul 24 2020
*
* @brief Implementation of the periodic node synchronizer
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "periodic_node_synchronizer.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
PeriodicNodeSynchronizer::PeriodicNodeSynchronizer(
Mesh & mesh, const ID & id, const bool register_to_event_manager,
EventHandlerPriority event_priority)
: NodeSynchronizer(mesh, id + ":masters", register_to_event_manager,
event_priority) {}
/* -------------------------------------------------------------------------- */
void PeriodicNodeSynchronizer::update() {
static int count = 0;
const auto & masters_to_slaves = this->mesh.getPeriodicMasterSlaves();
masters_list.resize(0);
masters_list.reserve(masters_to_slaves.size());
slaves_list.resize(0);
slaves_list.reserve(masters_to_slaves.size());
reset();
- std::set<UInt> masters_to_receive;
+ std::set<Idx> masters_to_receive;
for (auto && data : masters_to_slaves) {
auto master = std::get<0>(data);
auto slave = std::get<1>(data);
masters_list.push_back(master);
slaves_list.push_back(slave);
if (not(mesh.isMasterNode(master) or mesh.isLocalNode(master))) {
masters_to_receive.insert(master);
}
}
if (not mesh.isDistributed() or nb_proc == 1) {
return;
}
- std::map<Int, Array<UInt>> buffers;
+ std::map<Int, Array<Idx>> buffers;
for (auto node : masters_to_receive) {
auto && proc = mesh.getNodePrank(node);
auto && scheme = this->communications.createRecvScheme(proc);
scheme.push_back(node);
buffers[proc].push_back(mesh.getNodeGlobalId(node));
}
auto tag = Tag::genTag(0, count, Tag::_modify_scheme);
std::vector<CommunicationRequest> requests;
for (auto && data : buffers) {
auto proc = std::get<0>(data);
auto & buffer = std::get<1>(data);
requests.push_back(communicator.asyncSend(buffer, proc, tag,
CommunicationMode::_synchronous));
std::cout << "Recv from proc : " << proc << " -> "
<< this->communications.getScheme(proc, _recv).size()
<< std::endl;
}
- communicator.receiveAnyNumber<UInt>(
+ communicator.receiveAnyNumber<Idx>(
requests,
[&](auto && proc, auto && msg) {
auto && scheme = this->communications.createSendScheme(proc);
for (auto node : msg) {
scheme.push_back(mesh.getNodeLocalId(node));
}
std::cout << "Send to proc : " << proc << " -> " << scheme.size()
<< " [" << tag << "]" << std::endl;
},
tag);
++count;
}
/* -------------------------------------------------------------------------- */
void PeriodicNodeSynchronizer::synchronizeOnceImpl(
- DataAccessor<UInt> & data_accessor, const SynchronizationTag & tag) const {
+ DataAccessor<Idx> & data_accessor, const SynchronizationTag & tag) const {
NodeSynchronizer::synchronizeOnceImpl(data_accessor, tag);
auto size = data_accessor.getNbData(masters_list, tag);
CommunicationBuffer buffer(size);
data_accessor.packData(buffer, masters_list, tag);
data_accessor.unpackData(buffer, slaves_list, tag);
}
/* -------------------------------------------------------------------------- */
void PeriodicNodeSynchronizer::waitEndSynchronizeImpl(
- DataAccessor<UInt> & data_accessor, const SynchronizationTag & tag) {
+ DataAccessor<Idx> & data_accessor, const SynchronizationTag & tag) {
NodeSynchronizer::waitEndSynchronizeImpl(data_accessor, tag);
auto size = data_accessor.getNbData(masters_list, tag);
CommunicationBuffer buffer(size);
data_accessor.packData(buffer, masters_list, tag);
data_accessor.unpackData(buffer, slaves_list, tag);
}
} // namespace akantu
diff --git a/src/synchronizer/periodic_node_synchronizer.hh b/src/synchronizer/periodic_node_synchronizer.hh
index 5af1d010c..ebcd972d7 100644
--- a/src/synchronizer/periodic_node_synchronizer.hh
+++ b/src/synchronizer/periodic_node_synchronizer.hh
@@ -1,97 +1,93 @@
/**
* @file periodic_node_synchronizer.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed May 30 2018
* @date last modification: Fri Jul 24 2020
*
* @brief PeriodicNodeSynchronizer definition
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PERIODIC_NODE_SYNCHRONIZER_HH_
#define AKANTU_PERIODIC_NODE_SYNCHRONIZER_HH_
namespace akantu {
class PeriodicNodeSynchronizer : public NodeSynchronizer {
public:
PeriodicNodeSynchronizer(
Mesh & mesh, const ID & id = "periodic_node_synchronizer",
bool register_to_event_manager = true,
EventHandlerPriority event_priority = _ehp_synchronizer);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void update();
/// Uses the synchronizer to perform a reduction on the vector
template <template <class> class Op, typename T>
void reduceSynchronizeWithPBCSlaves(Array<T> & array) const;
/// synchronize ghosts without state
- void synchronizeOnceImpl(DataAccessor<UInt> & data_accessor,
+ void synchronizeOnceImpl(DataAccessor<Idx> & data_accessor,
const SynchronizationTag & tag) const override;
- // /// asynchronous synchronization of ghosts
- // void asynchronousSynchronizeImpl(const DataAccessor<UInt> & data_accessor,
- // const SynchronizationTag & tag) override;
-
/// wait end of asynchronous synchronization of ghosts
- void waitEndSynchronizeImpl(DataAccessor<UInt> & data_accessor,
+ void waitEndSynchronizeImpl(DataAccessor<Idx> & data_accessor,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
// NodeSynchronizer master_to_slaves_synchronizer;
- Array<UInt> masters_list;
- Array<UInt> slaves_list;
+ Array<Idx> masters_list;
+ Array<Idx> slaves_list;
};
/* -------------------------------------------------------------------------- */
template <template <class> class Op, typename T>
void PeriodicNodeSynchronizer::reduceSynchronizeWithPBCSlaves(
Array<T> & array) const {
- ReduceDataAccessor<UInt, Op, T> data_accessor(array,
- SynchronizationTag::_whatever);
+ ReduceDataAccessor<Idx, Op, T> data_accessor(array,
+ SynchronizationTag::_whatever);
auto size =
data_accessor.getNbData(slaves_list, SynchronizationTag::_whatever);
CommunicationBuffer buffer(size);
data_accessor.packData(buffer, slaves_list, SynchronizationTag::_whatever);
data_accessor.unpackData(buffer, masters_list, SynchronizationTag::_whatever);
this->reduceSynchronizeArray<Op>(array);
}
} // namespace akantu
#endif /* AKANTU_PERIODIC_NODE_SYNCHRONIZER_HH_ */
diff --git a/src/synchronizer/slave_element_info_per_processor.cc b/src/synchronizer/slave_element_info_per_processor.cc
index 67ab41230..cce0e7cc6 100644
--- a/src/synchronizer/slave_element_info_per_processor.cc
+++ b/src/synchronizer/slave_element_info_per_processor.cc
@@ -1,195 +1,199 @@
/**
* @file slave_element_info_per_processor.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Mar 16 2016
* @date last modification: Fri Jul 24 2020
*
* @brief Helper class to distribute a mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "element_info_per_processor.hh"
#include "element_synchronizer.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <iostream>
#include <map>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
SlaveElementInfoPerProc::SlaveElementInfoPerProc(
- ElementSynchronizer & synchronizer, UInt message_cnt, UInt root)
+ ElementSynchronizer & synchronizer, Int message_cnt, Int root)
: ElementInfoPerProc(synchronizer, message_cnt, root, _not_defined) {
- Vector<UInt> size(5);
+ Vector<Int> size(5);
comm.receive(size, this->root,
Tag::genTag(this->root, this->message_count, Tag::_sizes));
this->type = (ElementType)size[0];
this->nb_local_element = size[1];
this->nb_ghost_element = size[2];
this->nb_element_to_receive = size[3];
this->nb_tags = size[4];
if (this->type != _not_defined) {
this->nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
}
}
/* -------------------------------------------------------------------------- */
bool SlaveElementInfoPerProc::needSynchronize() {
return this->type != _not_defined;
}
/* -------------------------------------------------------------------------- */
void SlaveElementInfoPerProc::synchronizeConnectivities() {
- Array<UInt> local_connectivity(
+ Array<Idx> local_connectivity(
(this->nb_local_element + this->nb_ghost_element) *
this->nb_nodes_per_element);
AKANTU_DEBUG_INFO("Receiving connectivities from proc " << root);
comm.receive(
local_connectivity, this->root,
Tag::genTag(this->root, this->message_count, Tag::_connectivity));
auto & old_nodes = this->getNodesGlobalIds();
AKANTU_DEBUG_INFO("Renumbering local connectivities");
MeshUtils::renumberMeshNodes(this->mesh, local_connectivity,
this->nb_local_element, this->nb_ghost_element,
this->type, old_nodes);
+
+ MeshAccessor mesh_accessor(mesh);
+ auto & ghost_counter = mesh_accessor.getGhostsCounters(type, _ghost);
+ ghost_counter.resize(nb_ghost_element, 1);
}
/* -------------------------------------------------------------------------- */
void SlaveElementInfoPerProc::synchronizePartitions() {
- Array<UInt> local_partitions(this->nb_element_to_receive +
- this->nb_ghost_element * 2);
+ Array<Idx> local_partitions(this->nb_element_to_receive +
+ this->nb_ghost_element * 2);
AKANTU_DEBUG_INFO("Receiving partition informations from proc " << root);
this->comm.receive(local_partitions, this->root,
Tag::genTag(root, this->message_count, Tag::_partitions));
if (Mesh::getSpatialDimension(this->type) ==
this->mesh.getSpatialDimension()) {
AKANTU_DEBUG_INFO("Creating communications scheme");
this->fillCommunicationScheme(local_partitions);
}
}
/* -------------------------------------------------------------------------- */
void SlaveElementInfoPerProc::synchronizeTags() {
AKANTU_DEBUG_IN();
if (this->nb_tags == 0) {
AKANTU_DEBUG_OUT();
return;
}
/* --------<<<<-TAGS------------------------------------------------- */
DynamicCommunicationBuffer mesh_data_sizes_buffer;
comm.broadcast(mesh_data_sizes_buffer, root);
AKANTU_DEBUG_INFO("Size of the information about the mesh data: "
<< mesh_data_sizes_buffer.size());
if (mesh_data_sizes_buffer.empty()) {
return;
}
AKANTU_DEBUG_INFO("Receiving the information about the mesh data tags, addr "
- << (void *)mesh_data_sizes_buffer.storage());
+ << (void *)mesh_data_sizes_buffer.data());
std::vector<std::string> tag_names;
std::vector<MeshDataTypeCode> tag_type_codes;
- std::vector<UInt> tag_nb_component;
+ std::vector<Int> tag_nb_component;
tag_names.resize(nb_tags);
tag_type_codes.resize(nb_tags);
tag_nb_component.resize(nb_tags);
CommunicationBuffer mesh_data_buffer;
- UInt type_code_int;
- for (UInt i(0); i < nb_tags; ++i) {
+ Int type_code_int;
+ for (Int i(0); i < nb_tags; ++i) {
mesh_data_sizes_buffer >> tag_names[i];
mesh_data_sizes_buffer >> type_code_int;
tag_type_codes[i] = static_cast<MeshDataTypeCode>(type_code_int);
mesh_data_sizes_buffer >> tag_nb_component[i];
}
- std::vector<std::string>::const_iterator names_it = tag_names.begin();
- std::vector<std::string>::const_iterator names_end = tag_names.end();
+ auto names_it = tag_names.begin();
+ auto names_end = tag_names.end();
CommunicationStatus mesh_data_comm_status;
AKANTU_DEBUG_INFO("Checking size of data to receive for mesh data TAG("
<< Tag::genTag(root, this->message_count, Tag::_mesh_data)
<< ")");
comm.probe<char>(root,
Tag::genTag(root, this->message_count, Tag::_mesh_data),
mesh_data_comm_status);
- UInt mesh_data_buffer_size(mesh_data_comm_status.size());
+ Int mesh_data_buffer_size(mesh_data_comm_status.size());
AKANTU_DEBUG_INFO("Receiving "
<< mesh_data_buffer_size << " bytes of mesh data TAG("
<< Tag::genTag(root, this->message_count, Tag::_mesh_data)
<< ")");
mesh_data_buffer.resize(mesh_data_buffer_size);
comm.receive(mesh_data_buffer, root,
Tag::genTag(root, this->message_count, Tag::_mesh_data));
// Loop over each tag for the current type
- UInt k(0);
+ Int k(0);
for (; names_it != names_end; ++names_it, ++k) {
this->fillMeshData(mesh_data_buffer, *names_it, tag_type_codes[k],
tag_nb_component[k]);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SlaveElementInfoPerProc::synchronizeGroups() {
AKANTU_DEBUG_IN();
const Communicator & comm = mesh.getCommunicator();
- UInt my_rank = comm.whoAmI();
+ auto my_rank = comm.whoAmI();
AKANTU_DEBUG_INFO("Receiving element groups from proc "
<< root << " TAG("
<< Tag::genTag(root, my_rank, Tag::_element_group) << ")");
CommunicationStatus status;
comm.probe<char>(root, Tag::genTag(root, my_rank, Tag::_element_group),
status);
CommunicationBuffer buffer(status.size());
comm.receive(buffer, root, Tag::genTag(root, my_rank, Tag::_element_group));
this->fillElementGroupsFromBuffer(buffer);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/synchronizer/synchronizer.hh b/src/synchronizer/synchronizer.hh
index 27c3a9f0f..f21a2f74c 100644
--- a/src/synchronizer/synchronizer.hh
+++ b/src/synchronizer/synchronizer.hh
@@ -1,130 +1,130 @@
/**
* @file synchronizer.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Mar 04 2020
*
* @brief Common interface for synchronizers
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SYNCHRONIZER_HH_
#define AKANTU_SYNCHRONIZER_HH_
namespace akantu {
class Communicator;
}
namespace akantu {
/* -------------------------------------------------------------------------- */
/* Base class for synchronizers */
/* -------------------------------------------------------------------------- */
class Synchronizer {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
Synchronizer(const Communicator & comm, const ID & id = "synchronizer");
Synchronizer(const Synchronizer & other) = default;
virtual ~Synchronizer() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// synchronous communications form slaves to master
template <class DataAccessor>
void slaveReductionOnce(DataAccessor & data_accessor,
const SynchronizationTag & tag) const;
/// synchronize ghosts without state
template <class DataAccessor>
void synchronizeOnce(DataAccessor & data_accessor,
const SynchronizationTag & tag) const;
/// synchronize ghosts
template <class DataAccessor>
void synchronize(DataAccessor & data_accessor,
const SynchronizationTag & tag);
/// asynchronous synchronization of ghosts
template <class DataAccessor>
void asynchronousSynchronize(const DataAccessor & data_accessor,
const SynchronizationTag & tag);
/// wait end of asynchronous synchronization of ghosts
template <class DataAccessor>
void waitEndSynchronize(DataAccessor & data_accessor,
const SynchronizationTag & tag);
/// compute buffer size for a given tag and data accessor
template <class DataAccessor>
void computeBufferSize(const DataAccessor & data_accessor,
const SynchronizationTag & tag);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
AKANTU_GET_MACRO(Communicator, communicator, const Communicator &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// id of the synchronizer
ID id;
/// hashed version of the id
int hash_id;
/// message counter per tag
- std::map<SynchronizationTag, UInt> tag_counter;
+ std::map<SynchronizationTag, Int> tag_counter;
/// the static memory instance
const Communicator & communicator;
/// nb processors in the communicator
- UInt nb_proc;
+ Int nb_proc;
/// rank in the communicator
- UInt rank;
+ Int rank;
};
} // namespace akantu
#include "synchronizer_tmpl.hh"
#endif /* AKANTU_SYNCHRONIZER_HH_ */
diff --git a/src/synchronizer/synchronizer_impl.hh b/src/synchronizer/synchronizer_impl.hh
index 10ac7ef7e..bde3c5ed9 100644
--- a/src/synchronizer/synchronizer_impl.hh
+++ b/src/synchronizer/synchronizer_impl.hh
@@ -1,213 +1,213 @@
/**
* @file synchronizer_impl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Wed Mar 04 2020
*
* @brief Implementation of the generic part of synchronizers
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communications.hh"
-#include "synchronizer.hh"
+//#include "synchronizer.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SYNCHRONIZER_IMPL_HH_
#define AKANTU_SYNCHRONIZER_IMPL_HH_
namespace akantu {
template <class Entity> class SynchronizerImpl : public Synchronizer {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
SynchronizerImpl(const Communicator & communicator,
const ID & id = "synchronizer");
SynchronizerImpl(const SynchronizerImpl & other, const ID & id);
~SynchronizerImpl() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
protected:
void communicateOnce(
const std::tuple<CommunicationSendRecv, CommunicationSendRecv> &
send_recv_schemes,
const Tag::CommTags & comm_tag, DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) const;
public:
/// synchronous synchronization without state
virtual void slaveReductionOnceImpl(DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) const;
/// synchronous synchronization without state
virtual void synchronizeOnceImpl(DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) const;
/// asynchronous synchronization of ghosts
virtual void
asynchronousSynchronizeImpl(const DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag);
/// wait end of asynchronous synchronization of ghosts
virtual void waitEndSynchronizeImpl(DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag);
/// compute all buffer sizes
virtual void
computeAllBufferSizes(const DataAccessor<Entity> & data_accessor);
/// compute buffer size for a given tag and data accessor
virtual void computeBufferSizeImpl(const DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag);
/* ------------------------------------------------------------------------ */
virtual void synchronizeImpl(DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) {
this->asynchronousSynchronizeImpl(data_accessor, tag);
this->waitEndSynchronizeImpl(data_accessor, tag);
}
/* ------------------------------------------------------------------------ */
/// reset send and recv element lists
void reset();
/// extract the elements that have a true predicate from in_synchronizer and
/// store them in the current synchronizer
template <typename Pred>
void split(SynchronizerImpl & in_synchronizer, Pred && pred);
/// update schemes in a synchronizer
template <typename Updater> void updateSchemes(Updater && scheme_updater);
/// filter the send scheme and let the other processor now about iterate
template <typename Pred> void filterScheme(Pred && pred);
/// flip send and receive schemes
void swapSendRecv();
/// copy the schemes of an other communicator.
SynchronizerImpl & operator=(const SynchronizerImpl & other);
/// gather data on the predefined root process (master version)
template <typename T>
void gather(const Array<T> & to_gather, Array<T> & gathered);
/// gather data on the predefined root process (slave version)
template <typename T> void gather(const Array<T> & to_gather);
/// scatter data from the predefined root process (master version)
template <typename T>
void scatter(Array<T> & scattered, const Array<T> & to_scatter);
/// scatter data from the predefined root process (slave version)
template <typename T> void scatter(Array<T> & scattered);
template <typename T> void synchronizeArray(Array<T> & array) const;
/// Uses the synchronizer to perform a reduction on the vector
template <template <class> class Op, typename T>
void reduceSynchronizeArray(Array<T> & array) const;
protected:
/// copy schemes
void copySchemes(const SynchronizerImpl & other);
/// check if dof changed set on at least one processor
inline bool hasChanged();
/// init the scheme for scatter and gather operation, need extra memory
inline void initScatterGatherCommunicationScheme();
/// list the entities to send to root process
virtual void fillEntityToSend(Array<Entity> & /*entities_to_send*/) {
AKANTU_TO_IMPLEMENT();
}
virtual Entity localToGlobalEntity(const Entity & /*local*/) {
AKANTU_TO_IMPLEMENT();
}
- virtual UInt canScatterSize() { AKANTU_TO_IMPLEMENT(); }
- virtual UInt gatheredSize() { AKANTU_TO_IMPLEMENT(); }
+ virtual Int canScatterSize() { AKANTU_TO_IMPLEMENT(); }
+ virtual Int gatheredSize() { AKANTU_TO_IMPLEMENT(); }
public:
/* ------------------------------------------------------------------------ */
- virtual UInt sanityCheckDataSize(const Array<Entity> & elements,
- const SynchronizationTag & tag,
- bool is_comm_desc = true) const;
+ virtual Int sanityCheckDataSize(const Array<Entity> & elements,
+ const SynchronizationTag & tag,
+ bool is_comm_desc = true) const;
virtual void
packSanityCheckData(CommunicationDescriptor<Entity> & comm_desc) const;
virtual void
unpackSanityCheckData(CommunicationDescriptor<Entity> & comm_desc) const;
virtual void packSanityCheckData(CommunicationBuffer & /*buffer*/,
const Array<Entity> & /*elements*/,
const SynchronizationTag & /*tag*/) const {}
virtual void unpackSanityCheckData(CommunicationBuffer & /*buffer*/,
const Array<Entity> & /*elements*/,
const SynchronizationTag & /*tag*/,
- UInt /*proc*/, UInt /*rank*/) const {}
+ Int /*proc*/, Int /*rank*/) const {}
public:
AKANTU_GET_MACRO(Communications, communications,
const Communications<Entity> &);
protected:
AKANTU_GET_MACRO_NOT_CONST(Communications, communications,
Communications<Entity> &);
virtual Int getRank(const Entity & entity) const = 0;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// information on the communications
Communications<Entity> communications;
/// did the scheme change, this is to recreate the scatter/gather data if
/// needed
bool entities_changed{true};
/// Root processor for scatter/gather operations
Int root{0};
/// entities coming/going from/to root
Array<Entity> entities_from_root;
/// entities received from slaves proc (only on master)
- std::map<UInt, Array<Entity>> master_receive_entities;
+ std::map<Int, Array<Entity>> master_receive_entities;
};
} // namespace akantu
#include "synchronizer_impl_tmpl.hh"
#endif /* AKANTU_SYNCHRONIZER_IMPL_HH_ */
diff --git a/src/synchronizer/synchronizer_impl_tmpl.hh b/src/synchronizer/synchronizer_impl_tmpl.hh
index 93bce3446..2a5596e1a 100644
--- a/src/synchronizer/synchronizer_impl_tmpl.hh
+++ b/src/synchronizer/synchronizer_impl_tmpl.hh
@@ -1,869 +1,859 @@
/**
* @file synchronizer_impl_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Wed Dec 09 2020
*
* @brief Implementation of the SynchronizerImpl
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "synchronizer_impl.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <class Entity>
SynchronizerImpl<Entity>::SynchronizerImpl(const Communicator & comm,
const ID & id)
: Synchronizer(comm, id), communications(comm) {}
/* -------------------------------------------------------------------------- */
template <class Entity>
SynchronizerImpl<Entity>::SynchronizerImpl(const SynchronizerImpl & other,
const ID & id)
: Synchronizer(other), communications(other.communications) {
this->id = id;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::communicateOnce(
const std::tuple<CommunicationSendRecv, CommunicationSendRecv> &
send_recv_schemes,
const Tag::CommTags & comm_tag, DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) const {
// no need to synchronize
if (this->nb_proc == 1) {
return;
}
CommunicationSendRecv send_dir;
CommunicationSendRecv recv_dir;
std::tie(send_dir, recv_dir) = send_recv_schemes;
using CommunicationRequests = std::vector<CommunicationRequest>;
- using CommunicationBuffers = std::map<UInt, CommunicationBuffer>;
+ using CommunicationBuffers = std::map<Int, CommunicationBuffer>;
CommunicationRequests send_requests;
CommunicationRequests recv_requests;
CommunicationBuffers send_buffers;
CommunicationBuffers recv_buffers;
auto postComm = [&](const auto & sr, auto & buffers,
auto & requests) -> void {
for (auto && pair : communications.iterateSchemes(sr)) {
auto & proc = pair.first;
const auto & scheme = pair.second;
if (scheme.empty()) {
continue;
}
auto & buffer = buffers[proc];
auto buffer_size = data_accessor.getNbData(scheme, tag);
if (buffer_size == 0) {
continue;
}
#ifndef AKANTU_NDEBUG
buffer_size += this->sanityCheckDataSize(scheme, tag, false);
#endif
buffer.resize(buffer_size);
if (sr == recv_dir) {
requests.push_back(communicator.asyncReceive(
buffer, proc,
- Tag::genTag(this->rank, UInt(tag), comm_tag, this->hash_id)));
+ Tag::genTag(this->rank, Int(tag), comm_tag, this->hash_id)));
} else {
#ifndef AKANTU_NDEBUG
this->packSanityCheckData(buffer, scheme, tag);
#endif
data_accessor.packData(buffer, scheme, tag);
AKANTU_DEBUG_ASSERT(
buffer.getPackedSize() == buffer.size(),
"The data accessor did not pack all the data it "
"promised in communication with tag "
<< tag << " (Promised: " << buffer.size()
<< "bytes, packed: " << buffer.getPackedSize() << "bytes [avg: "
<< Real(buffer.size() - buffer.getPackedSize()) / scheme.size()
<< "bytes per entity missing])");
send_requests.push_back(communicator.asyncSend(
buffer, proc,
- Tag::genTag(proc, UInt(tag), comm_tag, this->hash_id)));
+ Tag::genTag(proc, Int(tag), comm_tag, this->hash_id)));
}
}
};
// post the receive requests
postComm(recv_dir, recv_buffers, recv_requests);
// post the send data requests
postComm(send_dir, send_buffers, send_requests);
// treat the receive requests
- UInt request_ready;
- while ((request_ready = Communicator::waitAny(recv_requests)) != UInt(-1)) {
+ Idx request_ready{-1};
+ while ((request_ready = Communicator::waitAny(recv_requests)) != -1) {
auto & req = recv_requests[request_ready];
auto proc = req.getSource();
auto & buffer = recv_buffers[proc];
const auto & scheme = this->communications.getScheme(proc, recv_dir);
#ifndef AKANTU_NDEBUG
this->unpackSanityCheckData(buffer, scheme, tag, proc, this->rank);
#endif
data_accessor.unpackData(buffer, scheme, tag);
AKANTU_DEBUG_ASSERT(
buffer.getLeftToUnpack() == 0,
"The data accessor ignored some data in communication with tag "
<< tag);
req.free();
recv_requests.erase(recv_requests.begin() + request_ready);
}
Communicator::waitAll(send_requests);
Communicator::freeCommunicationRequest(send_requests);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::slaveReductionOnceImpl(
DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) const {
communicateOnce(std::make_tuple(_recv, _send), Tag::_reduce, data_accessor,
tag);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::synchronizeOnceImpl(
DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) const {
communicateOnce(std::make_tuple(_send, _recv), Tag::_synchronize,
data_accessor, tag);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::asynchronousSynchronizeImpl(
const DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
if (not this->communications.hasCommunicationSize(tag)) {
this->computeBufferSize(data_accessor, tag);
}
this->communications.incrementCounter(tag);
// Posting the receive -------------------------------------------------------
if (this->communications.hasPendingRecv(tag)) {
AKANTU_CUSTOM_EXCEPTION_INFO(
debug::CommunicationException(),
"There must still be some pending receive communications."
<< " Tag is " << tag << " Cannot start new ones");
}
for (auto && comm_desc : this->communications.iterateRecv(tag)) {
comm_desc.postRecv(this->hash_id);
}
// Posting the sends -------------------------------------------------------
if (communications.hasPendingSend(tag)) {
AKANTU_CUSTOM_EXCEPTION_INFO(
debug::CommunicationException(),
"There must be some pending sending communications."
<< " Tag is " << tag);
}
for (auto && comm_desc : this->communications.iterateSend(tag)) {
comm_desc.resetBuffer();
#ifndef AKANTU_NDEBUG
this->packSanityCheckData(comm_desc);
#endif
comm_desc.packData(data_accessor);
comm_desc.postSend(this->hash_id);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::waitEndSynchronizeImpl(
DataAccessor<Entity> & data_accessor, const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
#ifndef AKANTU_NDEBUG
if (this->communications.begin(tag, _recv) !=
this->communications.end(tag, _recv) &&
!this->communications.hasPendingRecv(tag)) {
AKANTU_CUSTOM_EXCEPTION_INFO(debug::CommunicationException(),
"No pending communication with the tag \""
<< tag);
}
#endif
auto recv_end = this->communications.end(tag, _recv);
decltype(recv_end) recv_it;
while ((recv_it = this->communications.waitAnyRecv(tag)) != recv_end) {
auto && comm_desc = *recv_it;
#ifndef AKANTU_NDEBUG
this->unpackSanityCheckData(comm_desc);
#endif
comm_desc.unpackData(data_accessor);
comm_desc.resetBuffer();
comm_desc.freeRequest();
}
this->communications.waitAllSend(tag);
this->communications.freeSendRequests(tag);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::computeAllBufferSizes(
const DataAccessor<Entity> & data_accessor) {
for (auto && tag : this->communications.iterateTags()) {
this->computeBufferSize(data_accessor, tag);
}
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::computeBufferSizeImpl(
const DataAccessor<Entity> & data_accessor,
const SynchronizationTag & tag) {
AKANTU_DEBUG_IN();
if (not this->communications.hasCommunication(tag)) {
this->communications.initializeCommunications(tag);
AKANTU_DEBUG_ASSERT(communications.hasCommunication(tag) == true,
"Communications where not properly initialized");
}
for (auto sr : iterate_send_recv) {
- for (auto && pair : this->communications.iterateSchemes(sr)) {
- auto proc = pair.first;
- const auto & scheme = pair.second;
- UInt size = 0;
+ for (auto && [proc, scheme] : this->communications.iterateSchemes(sr)) {
+ Int size{0};
#ifndef AKANTU_NDEBUG
size += this->sanityCheckDataSize(scheme, tag);
#endif
size += data_accessor.getNbData(scheme, tag);
AKANTU_DEBUG_INFO("I have "
<< size << "(" << printMemorySize<char>(size) << " - "
<< scheme.size() << " element(s)) data to "
<< std::string(sr == _recv ? "receive from" : "send to")
<< proc << " for tag " << tag);
this->communications.setCommunicationSize(tag, proc, size, sr);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename Entity> void SynchronizerImpl<Entity>::reset() {
AKANTU_DEBUG_IN();
communications.resetSchemes();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename Entity>
template <typename Pred>
void SynchronizerImpl<Entity>::split(SynchronizerImpl<Entity> & in_synchronizer,
Pred && pred) {
AKANTU_DEBUG_IN();
auto filter_list = [&](auto & list, auto & new_list) {
auto copy = list;
list.resize(0);
new_list.resize(0);
for (auto && entity : copy) {
if (std::forward<Pred>(pred)(entity)) {
new_list.push_back(entity);
} else {
list.push_back(entity);
}
}
};
for (auto sr : iterate_send_recv) {
for (auto & scheme_pair :
in_synchronizer.communications.iterateSchemes(sr)) {
auto proc = scheme_pair.first;
auto & scheme = scheme_pair.second;
auto & new_scheme = communications.createScheme(proc, sr);
filter_list(scheme, new_scheme);
}
}
in_synchronizer.communications.invalidateSizes();
communications.invalidateSizes();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <typename Entity>
template <typename Updater>
void SynchronizerImpl<Entity>::updateSchemes(Updater && scheme_updater) {
for (auto sr : iterate_send_recv) {
for (auto & scheme_pair : communications.iterateSchemes(sr)) {
auto proc = scheme_pair.first;
auto & scheme = scheme_pair.second;
std::forward<Updater>(scheme_updater)(scheme, proc, sr);
}
}
communications.invalidateSizes();
}
/* -------------------------------------------------------------------------- */
template <typename Entity>
template <typename Pred>
void SynchronizerImpl<Entity>::filterScheme(Pred && pred) {
std::vector<CommunicationRequest> requests;
- std::unordered_map<UInt, Array<UInt>> keep_entities;
+ std::unordered_map<Idx, Array<Idx>> keep_entities;
auto filter_list = [](const auto & keep, auto & list) {
Array<Entity> new_list;
for (const auto & keep_entity : keep) {
const Entity & entity = list(keep_entity);
new_list.push_back(entity);
}
list.copy(new_list);
};
// loop over send_schemes
for (auto & scheme_pair : communications.iterateSchemes(_recv)) {
auto proc = scheme_pair.first;
auto & scheme = scheme_pair.second;
auto & keep_entity = keep_entities[proc];
for (auto && entity : enumerate(scheme)) {
if (pred(std::get<1>(entity))) {
keep_entity.push_back(std::get<0>(entity));
}
}
auto tag = Tag::genTag(this->rank, 0, Tag::_modify_scheme);
AKANTU_DEBUG_INFO("I have " << keep_entity.size()
<< " elements to still receive from processor "
<< proc << " (communication tag : " << tag
<< ")");
filter_list(keep_entity, scheme);
requests.push_back(communicator.asyncSend(keep_entity, proc, tag));
}
// clean the receive scheme
for (auto & scheme_pair : communications.iterateSchemes(_send)) {
auto proc = scheme_pair.first;
auto & scheme = scheme_pair.second;
auto tag = Tag::genTag(proc, 0, Tag::_modify_scheme);
AKANTU_DEBUG_INFO("Waiting list of elements to keep from processor "
<< proc << " (communication tag : " << tag << ")");
CommunicationStatus status;
- communicator.probe<UInt>(proc, tag, status);
+ communicator.probe<Int>(proc, tag, status);
- Array<UInt> keep_entity(status.size(), 1, "keep_element");
+ Array<Int> keep_entity(status.size(), 1, "keep_element");
AKANTU_DEBUG_INFO("I have "
<< keep_entity.size()
<< " elements to keep in my send list to processor "
<< proc << " (communication tag : " << tag << ")");
communicator.receive(keep_entity, proc, tag);
filter_list(keep_entity, scheme);
}
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
communications.invalidateSizes();
}
/* -------------------------------------------------------------------------- */
template <class Entity> void SynchronizerImpl<Entity>::swapSendRecv() {
communications.swapSendRecv();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::copySchemes(const SynchronizerImpl & other) {
reset();
for (auto sr : iterate_send_recv) {
for (auto & scheme_pair : other.communications.iterateSchemes(sr)) {
auto proc = scheme_pair.first;
auto & other_scheme = scheme_pair.second;
auto & scheme = communications.createScheme(proc, sr);
scheme.copy(other_scheme);
}
}
}
/* -------------------------------------------------------------------------- */
template <class Entity>
SynchronizerImpl<Entity> &
SynchronizerImpl<Entity>::operator=(const SynchronizerImpl & other) {
copySchemes(other);
return *this;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
-UInt SynchronizerImpl<Entity>::sanityCheckDataSize(
+Int SynchronizerImpl<Entity>::sanityCheckDataSize(
const Array<Entity> & /*unused*/, const SynchronizationTag & /*unused*/,
bool is_comm_desc) const {
if (not is_comm_desc) {
return 0;
}
- UInt size = 0;
+ Int size = 0;
size += sizeof(SynchronizationTag); // tag
- size += sizeof(UInt); // comm_desc.getNbData();
- size += sizeof(UInt); // comm_desc.getProc();
+ size += sizeof(Int); // comm_desc.getNbData();
+ size += sizeof(Int); // comm_desc.getProc();
size += sizeof(this->rank); // mesh.getCommunicator().whoAmI();
return size;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::packSanityCheckData(
CommunicationDescriptor<Entity> & comm_desc) const {
auto & buffer = comm_desc.getBuffer();
buffer << comm_desc.getTag();
buffer << comm_desc.getNbData();
buffer << comm_desc.getProc();
buffer << this->rank;
const auto & tag = comm_desc.getTag();
const auto & send_element = comm_desc.getScheme();
this->packSanityCheckData(buffer, send_element, tag);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::unpackSanityCheckData(
CommunicationDescriptor<Entity> & comm_desc) const {
auto & buffer = comm_desc.getBuffer();
const auto & tag = comm_desc.getTag();
auto nb_data = comm_desc.getNbData();
auto proc = comm_desc.getProc();
auto rank = this->rank;
decltype(nb_data) recv_nb_data;
decltype(proc) recv_proc;
decltype(rank) recv_rank;
- SynchronizationTag t;
+ SynchronizationTag t{0};
buffer >> t;
buffer >> recv_nb_data;
buffer >> recv_proc;
buffer >> recv_rank;
AKANTU_DEBUG_ASSERT(
t == tag, "The tag received does not correspond to the tag expected");
AKANTU_DEBUG_ASSERT(
nb_data == recv_nb_data,
"The nb_data received does not correspond to the nb_data expected");
- AKANTU_DEBUG_ASSERT(UInt(recv_rank) == proc,
+ AKANTU_DEBUG_ASSERT(recv_rank == proc,
"The rank received does not correspond to the proc");
- AKANTU_DEBUG_ASSERT(recv_proc == UInt(rank),
+ AKANTU_DEBUG_ASSERT(recv_proc == rank,
"The proc received does not correspond to the rank");
auto & recv_element = comm_desc.getScheme();
this->unpackSanityCheckData(buffer, recv_element, tag, proc, rank);
}
/* -------------------------------------------------------------------------- */
template <class Entity> bool SynchronizerImpl<Entity>::hasChanged() {
communicator.allReduce(entities_changed, SynchronizerOperation::_lor);
return entities_changed;
}
/* -------------------------------------------------------------------------- */
template <class Entity>
void SynchronizerImpl<Entity>::initScatterGatherCommunicationScheme() {
if (this->nb_proc == 1) {
entities_changed = false;
AKANTU_DEBUG_OUT();
return;
}
AKANTU_TO_IMPLEMENT();
}
/* -------------------------------------------------------------------------- */
template <>
-inline void SynchronizerImpl<UInt>::initScatterGatherCommunicationScheme() {
- AKANTU_DEBUG_IN();
-
+inline void SynchronizerImpl<Idx>::initScatterGatherCommunicationScheme() {
if (this->nb_proc == 1) {
entities_changed = false;
- AKANTU_DEBUG_OUT();
return;
}
this->entities_from_root.clear();
this->master_receive_entities.clear();
- Array<UInt> entities_to_send;
+ Array<Idx> entities_to_send;
fillEntityToSend(entities_to_send);
std::vector<CommunicationRequest> requests;
- if (this->rank == UInt(this->root)) {
+ if (this->rank == Int(this->root)) {
master_receive_entities[this->root].copy(entities_to_send);
- Array<UInt> nb_entities_per_proc(this->nb_proc);
+ Array<Idx> nb_entities_per_proc(this->nb_proc);
communicator.gather(entities_to_send.size(), nb_entities_per_proc);
- for (UInt p = 0; p < nb_proc; ++p) {
- if (p == UInt(this->root)) {
+ for (Int p = 0; p < nb_proc; ++p) {
+ if (p == Int(this->root)) {
continue;
}
auto & receive_per_proc = master_receive_entities[p];
receive_per_proc.resize(nb_entities_per_proc(p));
if (nb_entities_per_proc(p) == 0) {
continue;
}
requests.push_back(communicator.asyncReceive(
receive_per_proc, p,
Tag::genTag(p, 0, Tag::_gather_initialization, this->hash_id)));
}
} else {
communicator.gather(entities_to_send.size(), this->root);
AKANTU_DEBUG(dblDebug, "I have " << entities_to_send.size()
<< " entities to send to master proc");
if (not entities_to_send.empty()) {
requests.push_back(communicator.asyncSend(
entities_to_send, this->root,
Tag::genTag(this->rank, 0, Tag::_gather_initialization,
this->hash_id)));
}
}
entities_changed = false;
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
template <typename T>
void SynchronizerImpl<Entity>::gather(const Array<T> & to_gather,
Array<T> & gathered) {
if (this->hasChanged()) {
initScatterGatherCommunicationScheme();
}
- AKANTU_DEBUG_ASSERT(this->rank == UInt(this->root),
+ AKANTU_DEBUG_ASSERT(this->rank == this->root,
"This function cannot be called on a slave processor");
AKANTU_DEBUG_ASSERT(to_gather.size() == this->canScatterSize(),
"The array to gather does not have the correct size");
AKANTU_DEBUG_ASSERT(gathered.size() == this->gatheredSize(),
"The gathered array does not have the correct size");
if (this->nb_proc == 1) {
gathered.copy(to_gather, true);
AKANTU_DEBUG_OUT();
return;
}
- std::map<UInt, CommunicationBuffer> buffers;
+ std::map<Int, CommunicationBuffer> buffers;
std::vector<CommunicationRequest> requests;
- for (UInt p = 0; p < this->nb_proc; ++p) {
- if (p == UInt(this->root)) {
+ for (Int p = 0; p < this->nb_proc; ++p) {
+ if (p == this->root) {
continue;
}
auto receive_it = this->master_receive_entities.find(p);
AKANTU_DEBUG_ASSERT(receive_it != this->master_receive_entities.end(),
"Could not find the receive list for dofs of proc "
<< p);
const auto & receive_entities = receive_it->second;
if (receive_entities.empty()) {
continue;
}
- CommunicationBuffer & buffer = buffers[p];
+ auto & buffer = buffers[p];
buffer.resize(receive_entities.size() * to_gather.getNbComponent() *
sizeof(T));
AKANTU_DEBUG_INFO(
"Preparing to receive data for "
<< receive_entities.size() << " entities from processor " << p << " "
<< Tag::genTag(p, this->root, Tag::_gather, this->hash_id));
requests.push_back(communicator.asyncReceive(
buffer, p, Tag::genTag(p, this->root, Tag::_gather, this->hash_id)));
}
auto data_gathered_it = gathered.begin(to_gather.getNbComponent());
{ // copy master data
auto data_to_gather_it = to_gather.begin(to_gather.getNbComponent());
for (auto local_entity : entities_from_root) {
- UInt global_entity = localToGlobalEntity(local_entity);
+ auto global_entity = localToGlobalEntity(local_entity);
- Vector<T> entity_data_gathered = data_gathered_it[global_entity];
- Vector<T> entity_data_to_gather = data_to_gather_it[local_entity];
+ auto && entity_data_gathered = data_gathered_it[global_entity];
+ auto && entity_data_to_gather = data_to_gather_it[local_entity];
entity_data_gathered = entity_data_to_gather;
}
}
- auto rr = UInt(-1);
- while ((rr = Communicator::waitAny(requests)) != UInt(-1)) {
+ auto rr = -1;
+ while ((rr = Communicator::waitAny(requests)) != -1) {
auto & request = requests[rr];
auto sender = request.getSource();
AKANTU_DEBUG_ASSERT(this->master_receive_entities.find(sender) !=
this->master_receive_entities.end() &&
buffers.find(sender) != buffers.end(),
"Missing infos concerning proc " << sender);
const auto & receive_entities =
this->master_receive_entities.find(sender)->second;
auto & buffer = buffers[sender];
for (auto global_entity : receive_entities) {
- Vector<T> entity_data = data_gathered_it[global_entity];
+ auto && entity_data = data_gathered_it[global_entity];
buffer >> entity_data;
}
requests.erase(requests.begin() + rr);
}
}
/* -------------------------------------------------------------------------- */
template <class Entity>
template <typename T>
void SynchronizerImpl<Entity>::gather(const Array<T> & to_gather) {
AKANTU_DEBUG_IN();
if (this->hasChanged()) {
initScatterGatherCommunicationScheme();
}
- AKANTU_DEBUG_ASSERT(this->rank != UInt(this->root),
+ AKANTU_DEBUG_ASSERT(this->rank != this->root,
"This function cannot be called on the root processor");
AKANTU_DEBUG_ASSERT(to_gather.size() == this->canScatterSize(),
"The array to gather does not have the correct size");
if (this->entities_from_root.empty()) {
AKANTU_DEBUG_OUT();
return;
}
CommunicationBuffer buffer(this->entities_from_root.size() *
to_gather.getNbComponent() * sizeof(T));
auto data_it = to_gather.begin(to_gather.getNbComponent());
for (auto entity : this->entities_from_root) {
- Vector<T> data = data_it[entity];
+ auto && data = data_it[entity];
buffer << data;
}
AKANTU_DEBUG_INFO("Gathering data for "
<< to_gather.size() << " dofs on processor " << this->root
<< " "
<< Tag::genTag(this->rank, 0, Tag::_gather, this->hash_id));
communicator.send(buffer, this->root,
Tag::genTag(this->rank, 0, Tag::_gather, this->hash_id));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
template <typename T>
void SynchronizerImpl<Entity>::scatter(Array<T> & scattered,
const Array<T> & to_scatter) {
AKANTU_DEBUG_IN();
if (this->hasChanged()) {
initScatterGatherCommunicationScheme();
}
- AKANTU_DEBUG_ASSERT(this->rank == UInt(this->root),
+ AKANTU_DEBUG_ASSERT(this->rank == this->root,
"This function cannot be called on a slave processor");
AKANTU_DEBUG_ASSERT(scattered.size() == this->canScatterSize(),
"The scattered array does not have the correct size");
AKANTU_DEBUG_ASSERT(to_scatter.size() == this->gatheredSize(),
"The array to scatter does not have the correct size");
if (this->nb_proc == 1) {
scattered.copy(to_scatter, true);
AKANTU_DEBUG_OUT();
return;
}
- std::map<UInt, CommunicationBuffer> buffers;
+ std::map<Idx, CommunicationBuffer> buffers;
std::vector<CommunicationRequest> requests;
- for (UInt p = 0; p < nb_proc; ++p) {
+ for (Int p = 0; p < nb_proc; ++p) {
auto data_to_scatter_it = to_scatter.begin(to_scatter.getNbComponent());
if (p == this->rank) {
auto data_scattered_it = scattered.begin(to_scatter.getNbComponent());
// copy the data for the local processor
for (auto local_entity : entities_from_root) {
auto global_entity = localToGlobalEntity(local_entity);
-
- Vector<T> entity_data_to_scatter = data_to_scatter_it[global_entity];
- Vector<T> entity_data_scattered = data_scattered_it[local_entity];
- entity_data_scattered = entity_data_to_scatter;
+ data_scattered_it[local_entity] = data_to_scatter_it[global_entity];
}
continue;
}
const auto & receive_entities =
this->master_receive_entities.find(p)->second;
// prepare the send buffer
- CommunicationBuffer & buffer = buffers[p];
+ auto & buffer = buffers[p];
buffer.resize(receive_entities.size() * scattered.getNbComponent() *
sizeof(T));
// pack the data
for (auto global_entity : receive_entities) {
- Vector<T> entity_data_to_scatter = data_to_scatter_it[global_entity];
+ auto && entity_data_to_scatter = data_to_scatter_it[global_entity];
buffer << entity_data_to_scatter;
}
// send the data
requests.push_back(communicator.asyncSend(
buffer, p, Tag::genTag(p, 0, Tag::_scatter, this->hash_id)));
}
// wait a clean communications
Communicator::waitAll(requests);
Communicator::freeCommunicationRequest(requests);
// synchronize slave and ghost nodes
synchronizeArray(scattered);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
template <typename T>
void SynchronizerImpl<Entity>::scatter(Array<T> & scattered) {
AKANTU_DEBUG_IN();
if (this->hasChanged()) {
this->initScatterGatherCommunicationScheme();
}
- AKANTU_DEBUG_ASSERT(this->rank != UInt(this->root),
+ AKANTU_DEBUG_ASSERT(this->rank != this->root,
"This function cannot be called on the root processor");
AKANTU_DEBUG_ASSERT(scattered.size() == this->canScatterSize(),
"The scattered array does not have the correct size");
// prepare the data
auto data_scattered_it = scattered.begin(scattered.getNbComponent());
CommunicationBuffer buffer(this->entities_from_root.size() *
scattered.getNbComponent() * sizeof(T));
// receive the data
communicator.receive(
buffer, this->root,
Tag::genTag(this->rank, 0, Tag::_scatter, this->hash_id));
// unpack the data
for (auto local_entity : entities_from_root) {
- Vector<T> data_scattered(data_scattered_it[local_entity]);
+ auto && data_scattered = data_scattered_it[local_entity];
buffer >> data_scattered;
}
// synchronize the ghosts
synchronizeArray(scattered);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Entity>
template <typename T>
void SynchronizerImpl<Entity>::synchronizeArray(Array<T> & array) const {
- static_assert(std::is_same<Entity, UInt>::value,
- "Not implemented for other type than UInt");
- SimpleUIntDataAccessor<T> data_accessor(array, SynchronizationTag::_whatever);
+ static_assert(std::is_same<Entity, Idx>::value,
+ "Not implemented for other type than Idx");
+ SimpleIdxDataAccessor<T> data_accessor(array, SynchronizationTag::_whatever);
this->synchronizeOnce(data_accessor, SynchronizationTag::_whatever);
}
/* -------------------------------------------------------------------------- */
template <class Entity>
template <template <class> class Op, typename T>
void SynchronizerImpl<Entity>::reduceSynchronizeArray(Array<T> & array) const {
- static_assert(std::is_same<Entity, UInt>::value,
- "Not implemented for other type than UInt");
- ReduceDataAccessor<UInt, Op, T> data_accessor(array,
- SynchronizationTag::_whatever);
+ static_assert(std::is_same<Entity, Idx>::value,
+ "Not implemented for other type than Idx");
+ ReduceDataAccessor<Idx, Op, T> data_accessor(array,
+ SynchronizationTag::_whatever);
this->slaveReductionOnceImpl(data_accessor, SynchronizationTag::_whatever);
this->synchronizeArray(array);
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/synchronizer/synchronizer_tmpl.hh b/src/synchronizer/synchronizer_tmpl.hh
index de3fa71ea..7cf36c2ef 100644
--- a/src/synchronizer/synchronizer_tmpl.hh
+++ b/src/synchronizer/synchronizer_tmpl.hh
@@ -1,138 +1,138 @@
/**
* @file synchronizer_tmpl.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Dec 02 2016
* @date last modification: Mon Feb 26 2018
*
* @brief Implementation of the helper classes for the synchronizer
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "data_accessor.hh"
#include "synchronizer.hh"
#include "synchronizer_impl.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SYNCHRONIZER_TMPL_HH_
#define AKANTU_SYNCHRONIZER_TMPL_HH_
namespace akantu {
template <class DataAccessorT>
void Synchronizer::slaveReductionOnce(DataAccessorT & data_accessor,
const SynchronizationTag & tag) const {
if (const auto * synch_el =
dynamic_cast<const SynchronizerImpl<Element> *>(this)) {
synch_el->slaveReductionOnceImpl(
dynamic_cast<DataAccessor<Element> &>(data_accessor), tag);
} else if (const auto * synch_dof =
- dynamic_cast<const SynchronizerImpl<UInt> *>(this)) {
+ dynamic_cast<const SynchronizerImpl<Idx> *>(this)) {
synch_dof->slaveReductionOnceImpl(
- dynamic_cast<DataAccessor<UInt> &>(data_accessor), tag);
+ dynamic_cast<DataAccessor<Idx> &>(data_accessor), tag);
} else {
AKANTU_EXCEPTION("You synchronizer is not of a known type");
}
}
template <class DataAccessorT>
void Synchronizer::synchronizeOnce(DataAccessorT & data_accessor,
const SynchronizationTag & tag) const {
if (const auto * synch_el =
dynamic_cast<const SynchronizerImpl<Element> *>(this)) {
synch_el->synchronizeOnceImpl(
dynamic_cast<DataAccessor<Element> &>(data_accessor), tag);
} else if (const auto * synch_dof =
- dynamic_cast<const SynchronizerImpl<UInt> *>(this)) {
+ dynamic_cast<const SynchronizerImpl<Idx> *>(this)) {
synch_dof->synchronizeOnceImpl(
- dynamic_cast<DataAccessor<UInt> &>(data_accessor), tag);
+ dynamic_cast<DataAccessor<Idx> &>(data_accessor), tag);
} else {
AKANTU_EXCEPTION("You synchronizer is not of a known type");
}
}
/// synchronize ghosts
template <class DataAccessorT>
void Synchronizer::synchronize(DataAccessorT & data_accessor,
const SynchronizationTag & tag) {
if (auto * synch_el = dynamic_cast<SynchronizerImpl<Element> *>(this)) {
synch_el->synchronizeImpl(
dynamic_cast<DataAccessor<Element> &>(data_accessor), tag);
- } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<UInt> *>(this)) {
- synch_dof->synchronizeImpl(
- dynamic_cast<DataAccessor<UInt> &>(data_accessor), tag);
+ } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<Idx> *>(this)) {
+ synch_dof->synchronizeImpl(dynamic_cast<DataAccessor<Idx> &>(data_accessor),
+ tag);
} else {
AKANTU_EXCEPTION("You synchronizer is not of a known type");
}
}
/* -------------------------------------------------------------------------- */
template <class DataAccessorT>
void Synchronizer::asynchronousSynchronize(const DataAccessorT & data_accessor,
const SynchronizationTag & tag) {
if (auto * synch_el = dynamic_cast<SynchronizerImpl<Element> *>(this)) {
synch_el->asynchronousSynchronizeImpl(
dynamic_cast<const DataAccessor<Element> &>(data_accessor), tag);
- } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<UInt> *>(this)) {
+ } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<Idx> *>(this)) {
synch_dof->asynchronousSynchronizeImpl(
- dynamic_cast<const DataAccessor<UInt> &>(data_accessor), tag);
+ dynamic_cast<const DataAccessor<Idx> &>(data_accessor), tag);
} else {
AKANTU_EXCEPTION("You synchronizer is not of a known type");
}
}
/* -------------------------------------------------------------------------- */
template <class DataAccessorT>
void Synchronizer::waitEndSynchronize(DataAccessorT & data_accessor,
const SynchronizationTag & tag) {
if (auto * synch_el = dynamic_cast<SynchronizerImpl<Element> *>(this)) {
synch_el->waitEndSynchronizeImpl(
dynamic_cast<DataAccessor<Element> &>(data_accessor), tag);
- } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<UInt> *>(this)) {
+ } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<Idx> *>(this)) {
synch_dof->waitEndSynchronizeImpl(
- dynamic_cast<DataAccessor<UInt> &>(data_accessor), tag);
+ dynamic_cast<DataAccessor<Idx> &>(data_accessor), tag);
} else {
AKANTU_EXCEPTION("You synchronizer is not of a known type");
}
}
/// compute buffer size for a given tag and data accessor
template <class DataAccessorT>
void Synchronizer::computeBufferSize(const DataAccessorT & data_accessor,
const SynchronizationTag & tag) {
if (auto * synch_el = dynamic_cast<SynchronizerImpl<Element> *>(this)) {
synch_el->computeBufferSizeImpl(
dynamic_cast<const DataAccessor<Element> &>(data_accessor), tag);
- } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<UInt> *>(this)) {
+ } else if (auto * synch_dof = dynamic_cast<SynchronizerImpl<Idx> *>(this)) {
synch_dof->computeBufferSizeImpl(
- dynamic_cast<const DataAccessor<UInt> &>(data_accessor), tag);
+ dynamic_cast<const DataAccessor<Idx> &>(data_accessor), tag);
} else {
AKANTU_EXCEPTION("You synchronizer is not of a known type");
}
}
} // namespace akantu
#endif /* AKANTU_SYNCHRONIZER_TMPL_HH_ */
diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py
index 8c1c746d1..b16a6fb8e 100644
--- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py
+++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py
@@ -1,87 +1,87 @@
-
-""" command.py: command to run clang-tidy in codeclimate"""
+"""command.py: command to run clang-tidy in codeclimate."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import json
import os
import re
class Command:
"""Returns command line arguments by parsing codeclimate config file."""
+
def __init__(self, config, workspace):
self.config = config
self._workspace = workspace
def build(self):
command = ['/usr/src/app/bin/run-clang-tidy',
'-clang-tidy-binary',
'/usr/bin/clang-tidy']
if 'checks' in self.config:
checks = self.config["checks"]
if not isinstance(checks, list):
command.extend(['-checks', f'\'{checks}\''])
else:
command.extend(['-checks', f'\'{",".join(checks)}\''])
if 'config' in self.config:
command.extend(['-config', self.config["config"]])
if 'header-filter' in self.config:
command.extend(['-header-filter', self.config["header-file"]])
extra_args = []
if 'extra-arg' in self.config:
tmp_extra_args = self.config['extra-arg']
if not isinstance(extra_args, list):
tmp_extra_args = [extra_args]
extra_args = []
includes_re = re.compile(r'-I(.*)')
for arg in tmp_extra_args:
match = includes_re.match(arg)
if match:
path = os.path.abspath(match.group(1))
extra_args.append(f'-I{path}')
else:
extra_args.append(arg)
if 'compilation-database-path' in self.config:
for arg in extra_args:
command.extend(['-extra-arg', arg])
if 'compilation-database-path' in self.config:
command.extend(['-p', self.config['compilation-database-path']])
else:
include_flags = ' -I'.join(self._workspace.include_paths)
compile_commands = []
for file_ in self._workspace.files:
cmd = {
'directory': os.path.dirname(file_),
'file': file_,
- 'command': f'/usr/bin/clang++ {include_flags} {" ".join(extra_args)} -c {file_} -o dummy.o', # noqa
+ 'command': f'/usr/bin/clang++ {include_flags} {" ".join(extra_args)} -c {file_} -o dummy.o', # noqa
}
compile_commands.append(cmd)
location = '/tmp'
compile_database = os.path.join(location, 'compile_commands.json')
with open(compile_database, 'w') as db:
json.dump(compile_commands, db)
command.extend(['-p', location])
command.extend([f'{path}.*' if os.path.isdir(path) else path
for path in self._workspace.paths])
return command
diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py
index ad81b761c..8107adf26 100644
--- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py
+++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py
@@ -1,104 +1,104 @@
-""" issue_formatter.py: issue_formater for clang-tidy in codeclimate (inspired
-from cpp-check)"""
+"""Issue_formater for clang-tidy in codeclimate (inspired from cpp-check)."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import hashlib
import os
class IssueFormatter:
CLASSIFICATIONS = {
'bugprone': {
'categories': ['Bug Risk'],
'severity': 'major',
},
'modernize': {
'categories': ['Clarity', 'Compatibility', 'Style'],
'severity': 'info'
},
'mpi': {
'categories': ['Bug Risk', 'Performance'],
'severity': 'critical',
},
'openmp': {
'categories': ['Bug Risk', 'Performance'],
'severity': 'critical',
},
'performance': {
'categories': ['Performance'],
'severity': 'minor',
},
'readability': {
'categories': ['Clarity', 'Style'],
'severity': 'info'
},
}
def _get_classifiaction(self, type_):
categories = ['Bug Risk']
severity = 'blocker'
if type_ in self.CLASSIFICATIONS:
categories = self.CLASSIFICATIONS[type_]['categories']
severity = self.CLASSIFICATIONS[type_]['severity']
elif type_[0] == 'clang':
if type_[1] == 'diagnostic':
categories = ['Bug Risk']
severity = 'blocker'
elif type_[1] == 'analyzer':
categories = ['Bug Risk']
severity = 'major'
return (categories, severity)
def __init__(self, issue):
self.issue_dict = issue
def format(self):
self.issue_dict['file'] = os.path.relpath(self.issue_dict['file'])
issue = {
'type': 'issue',
'check_name': self.issue_dict['type'],
'description': self.issue_dict['detail'],
'location': {
"path": self.issue_dict['file'],
"lines": {
"begin": int(self.issue_dict['line']),
"end": int(self.issue_dict['line']),
},
"positions": {
"begin": {
"line": int(self.issue_dict['line']),
"column": int(self.issue_dict['column']),
},
"end": {
"line": int(self.issue_dict['line']),
"column": int(self.issue_dict['column']),
},
},
},
}
if 'content' in self.issue_dict:
issue['content'] = {
'body': '```\n' +
'\n'.join(self.issue_dict['content']) +
'\n```'
}
issue['fingerprint'] = hashlib.md5(
'{file}:{line}:{column}:{type}'.format(**self.issue_dict).encode()
).hexdigest()
type_ = self.issue_dict['type'].split('-')[0]
- issue['categories'], issue['severity'] = self._get_classifiaction(type_)
+ issue['categories'], issue['severity'] = \
+ self._get_classifiaction(type_)
return issue
diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py
index 98097e29b..fc3eeb991 100644
--- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py
+++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py
@@ -1,114 +1,118 @@
-"""runner.py: runner for clang-tidy in codeclimate (inspired from cpp-check)"""
+"""Runner for clang-tidy in codeclimate (inspired from cpp-check)."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import json
import subprocess
import sys
import re
import os
try:
from termcolor import colored
except ImportError:
def colored(text, color):
+ """Remplace termcolor if not installed."""
return text
from command import Command
from issue_formatter import IssueFormatter
from workspace import Workspace
class Runner:
+ """Runs clang-tidy, collects and reports results."""
+
CONFIG_FILE_PATH = '/config.json'
- """Runs clang-tidy, collects and reports results."""
def __init__(self):
+ """Initialize the runner."""
self._config_file_path = self.CONFIG_FILE_PATH
self._config = {}
self._decode_config()
- self._ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
+ self._ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') # noqa
self._issue_parse = re.compile(r'(?P<file>.*\.(cc|hh)):(?P<line>[0-9]+):(?P<column>[0-9]+): (warning|error): (?P<detail>.*) \[(?P<type>.*)\]') # noqa
self._issues_fpr = []
self._workspace = Workspace(self._config.get('include_paths', []))
self._files = self._workspace.files
self._include_paths = self._workspace.include_paths
def run(self):
+ """Run the checks."""
if not len(self._files) > 0:
return
self._print_debug(f'[clang-tidy] analyzing {len(self._files)} files')
command = Command(self._config, self._workspace).build()
self._print_debug(f'[clang-tidy] command: {command}')
self._generate_issues(command)
def _decode_config(self):
self._print_debug(f"Decoding config file {self._config_file_path}")
contents = ""
with open(self._config_file_path, "r") as config:
contents = config.read()
self._config = json.loads(contents)
self._print_debug(f'[clang-tidy] config: {self._config}')
def _print_issue(self, issue):
issue_ = IssueFormatter(issue).format()
path = os.path.dirname(os.path.abspath(issue_["location"]["path"]))
if path not in self._include_paths:
return
if issue_['fingerprint'] in self._issues_fpr:
return
self._issues_fpr.append(issue_['fingerprint'])
print('{}\0'.format(json.dumps(issue_)))
def _generate_issues(self, command):
issue = None
for line in self._run_command(command):
clean_line = self._ansi_escape.sub('', line)
match = self._issue_parse.match(clean_line)
if match:
if issue is not None:
self._print_issue(issue)
issue = match.groupdict()
elif issue:
if 'content' in issue:
issue['content'].append(line)
else:
issue['content'] = [line]
self._print_issue(issue)
def _run_command(self, command):
popen = subprocess.Popen(command,
stdout=subprocess.PIPE,
universal_newlines=True)
for stdout_line in iter(popen.stdout.readline, ""):
self._print_debug(stdout_line)
yield stdout_line
popen.stdout.close()
return_code = popen.wait()
if return_code:
self._print_debug(
f"[clang-tidy] {command} ReturnCode {return_code}")
# raise subprocess.CalledProcessError(return_code, command)
def _print_debug(self, message):
print(message, file=sys.stderr, flush=True)
diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/workspace.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/workspace.py
index 864a72e40..e31e8a278 100644
--- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/workspace.py
+++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/workspace.py
@@ -1,54 +1,53 @@
-
-""" workspace.py: workspace for clang-tidy in codeclimate (inspired from cpp-
-check)"""
+"""Workspace for clang-tidy in codeclimate (inspired from cpp-check)."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
-
import os
class Workspace:
def __init__(self, include_paths, suffixes=['.c', '.cpp', '.cc', '.cxx']):
self._include_paths = include_paths
self._suffixes = suffixes
@property
def files(self):
paths = self._walk()
return [path for path in paths
if self._should_include(path)]
@property
def include_paths(self):
paths = self._walk()
return [path for path in paths if os.path.isdir(path)]
@property
def paths(self):
return [path for path in self._include_paths
if self._should_include(path) or os.path.isdir(path)]
def _should_include(self, name):
_, ext = os.path.splitext(name)
return ext in self._suffixes
def _walk(self):
paths = []
for path in self._include_paths:
if os.path.isdir(path):
for root, dirs, files in os.walk(path):
- paths.extend([os.path.join(root, dir_) for dir_ in dirs])
- paths.extend([os.path.join(root, file_) for file_ in files])
+ paths.extend(
+ [os.path.join(root, dir_) for dir_ in dirs])
+ paths.extend(
+ [os.path.join(root, file_) for file_ in files])
else:
paths.append(path)
return [os.path.abspath(path) for path in paths]
diff --git a/test/ci/debian:bullseye/Dockerfile b/test/ci/debian:bullseye/Dockerfile
index 33e17ad7f..c58571b90 100644
--- a/test/ci/debian:bullseye/Dockerfile
+++ b/test/ci/debian:bullseye/Dockerfile
@@ -1,38 +1,38 @@
FROM debian:bullseye
-MAINTAINER Nicolas Richart <nicolas.richart@epfl.ch>
# library dependencies
RUN apt -qq update && apt -qq -y install \
g++ gfortran clang cmake \
openmpi-bin libmumps-dev libscotch-dev \
libboost-dev libopenblas-dev \
+ libeigen3-dev \
python3 python3-dev python3-numpy python3-scipy python3-mpi4py \
&& rm -rf /var/lib/apt/lists/*
# for documentation
RUN apt -qq update && apt -qq -y install \
python3-sphinx \
python3-sphinxcontrib.bibtex \
python3-sphinx-rtd-theme \
python3-breathe \
python3-git python3-jinja2 \
doxygen graphviz \
&& rm -rf /var/lib/apt/lists/*
# for ci
RUN apt -qq update && apt -qq -y install \
gmsh python3-pytest python3-click python3-termcolor \
ccache clang-format python3-flake8 python3-pip clang-tidy \
curl git xsltproc jq \
gcovr llvm binutils \
ninja-build \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install warning_parser
COPY .openmpi /root/.openmpi
# for debug
RUN apt -qq update && apt -qq -y install \
gdb valgrind \
&& rm -rf /var/lib/apt/lists/*
diff --git a/test/ci/manylinux:2014_x86_64/Dockerfile b/test/ci/manylinux:2014_x86_64/Dockerfile
index 309e92c98..1ed6ccdc1 100644
--- a/test/ci/manylinux:2014_x86_64/Dockerfile
+++ b/test/ci/manylinux:2014_x86_64/Dockerfile
@@ -1,76 +1,75 @@
FROM quay.io/pypa/manylinux2014_x86_64 as builder
-MAINTAINER Nicolas Richart <nicolas.richart@epfl.ch>
ENV LANG en_US.UTF-8
RUN yum install -y xz zlib-devel openssl-devel
# What we want to install and how we want to install it
# is specified in a manifest file (spack.yaml)
RUN mkdir -p /softs/spack-environment
COPY spack.yaml /softs/spack-environment
RUN adduser -u 1000 -s /bin/false app
RUN mkdir -p /softs && chown -R app:app /softs
USER app
RUN cd /softs && git clone https://github.com/spack/spack.git -b v0.19.0
RUN cd /softs && git clone https://gitlab.com/epfl-lsms/spack-packages.git
COPY packages.yaml /softs/spack/etc/spack
COPY repos.yaml /softs/spack/etc/spack
# Install the software, remove unnecessary deps
RUN /opt/python/cp36-cp36m/bin/python /softs/spack/bin/spack -e /softs/spack-environment install && \
/opt/python/cp36-cp36m/bin/python /softs/spack/bin/spack gc -y
# Strip all the binaries
RUN find -L /softs/view/* -type f -exec readlink -f '{}' \; | \
xargs file -i | \
grep 'charset=binary' | \
grep 'x-executable\|x-archive\|x-sharedlib' | \
awk -F: '{print $1}' | xargs strip -s
USER root
# Modifications to the environment that are necessary to run
RUN cd /softs/spack-environment && \
/opt/python/cp36-cp36m/bin/python /softs/spack/bin/spack env activate --sh -d . >> /etc/profile.d/z10_spack_environment.sh
# Bare OS image to run the installed executables
FROM quay.io/pypa/manylinux2014_x86_64
RUN yum install -y xz zlib-devel ccache
RUN adduser -u 1000 -s /bin/false app
COPY --from=builder /softs/spack /softs/spack
COPY --from=builder /softs/spack-environment /softs/spack-environment
COPY --from=builder /softs/software /softs/software
COPY --from=builder /softs/view /softs/view
COPY --from=builder /etc/profile.d/z10_spack_environment.sh /etc/profile.d/z10_spack_environment.sh
RUN chown -R app:app /softs
RUN mkdir -p /build && chown app:app /build
ENV CROSS_ROOT /opt/rh/devtoolset-8/root/usr/bin
ENV AS=${CROSS_ROOT}/as \
AR=${CROSS_ROOT}/ar \
CC=${CROSS_ROOT}/gcc \
CPP=${CROSS_ROOT}/cpp \
CXX=${CROSS_ROOT}/g++ \
LD=${CROSS_ROOT}/ld \
FC=${CROSS_ROOT}/gfortran \
CMAKE_PREFIX_PATH=/soft/view
COPY install-pip.sh /build
RUN /build/install-pip.sh
COPY Toolchain.cmake ${CROSS_ROOT}/../lib/
ENV CMAKE_TOOLCHAIN_FILE ${CROSS_ROOT}/../lib/Toolchain.cmake
USER app
#ENTRYPOINT ["/bin/bash", "--rcfile", "/etc/profile", "-l"]
diff --git a/test/ci/manylinux:2014_x86_64/spack.yaml b/test/ci/manylinux:2014_x86_64/spack.yaml
index 571305786..d4df5a262 100644
--- a/test/ci/manylinux:2014_x86_64/spack.yaml
+++ b/test/ci/manylinux:2014_x86_64/spack.yaml
@@ -1,33 +1,34 @@
spack:
compilers:
- compiler:
paths:
cc: /opt/rh/devtoolset-10/root/usr/bin/gcc
cxx: /opt/rh/devtoolset-10/root/usr/bin/g++
f77: /opt/rh/devtoolset-10/root/usr/bin/gfortran
fc: /opt/rh/devtoolset-10/root/usr/bin/gfortran
operating_system: centos7
target: x86_64
modules: []
environment:
set:
LD_LIBRARY_PATH: /usr/local/lib
extra_rpaths: []
flags: {}
spec: gcc@10.2.1
include:
- /softs/spack/etc/spack/packages.yaml
config:
install_tree: /softs/software
specs:
- cmake@3.18.2 ~ncurses
- zlib
- boost ~atomic ~chrono ~clanglibcpp ~container ~context ~coroutine ~date_time ~debug ~exception ~fiber ~filesystem ~graph ~icu~iostreams ~locale ~log ~math ~mpi ~multithreaded ~numpy ~pic ~program_options ~python ~random ~regex ~serialization ~shared ~signals ~singlethreaded ~system ~taggedlayout ~test ~thread ~timer ~wave
- openblas +pic
+ - eigen
- mumps ~mpi ~complex ~float
view: /softs/view
concretizer:
unify: true
diff --git a/test/ci/scripts/codequality/issue_generator_clang_format.py b/test/ci/scripts/codequality/issue_generator_clang_format.py
index 296f86c7b..683bd55d8 100644
--- a/test/ci/scripts/codequality/issue_generator_clang_format.py
+++ b/test/ci/scripts/codequality/issue_generator_clang_format.py
@@ -1,54 +1,59 @@
#!/usr/bin/env python3
-from . import print_debug, print_info
from .issue_generator_clang_tool import ClangToolIssueGenerator
-import os
-import re
import copy
import difflib
-import subprocess
class ClangFormatIssueGenerator(ClangToolIssueGenerator):
"""issue generator for clang format"""
def __init__(self, **kwargs):
kwargs['clang_tool_executable'] = kwargs.pop('clang_format_executable',
'clang-format')
super().__init__('clang-format', **kwargs)
def _get_classifiaction(self, issue):
return (['Style'], 'info')
def generate_issues(self):
issue = {}
for filename in self._files:
with open(filename, 'r') as fh:
unformated_file = fh.readlines()
command = copy.copy(self._command)
command.append(filename)
formated_file = list(self._run_command(command))
# diffs = difflib.unified_diff(unformated_file, formated_file, n=0)
# print(diffs)
# for diff in diffs:
# print(diff, end='')
s = difflib.SequenceMatcher(None, unformated_file, formated_file)
for tag, i1, i2, j1, j2 in s.get_opcodes():
- if tag != 'equal':
- diff = list(
- difflib.unified_diff(
- unformated_file[i1:i2],
- formated_file[j1:j2]))
- issue = {
- 'name': f'''clang-format:{tag}''',
- 'description': ''.join(diff[3:]),
- 'file': filename,
- 'line': i1,
- 'column': 1,
- 'end_line': i2,
- }
- self.add_issue(issue)
+ if tag == 'equal':
+ continue
+ # diff = list(
+ # difflib.unified_diff(
+ # unformated_file[i1:i2],
+ # formated_file[j1:j2]))
+ description = ''
+ if tag == 'delete':
+ description = f'```suggestion:-0+{i2-i1}\n```'
+ if tag == 'insert':
+ description = f'''```suggestion:-0+0\n{''.join(unformated_file[i1:i2])}{''.join(formated_file[j1:j2])}```''' # noqa
+ if tag == 'replace':
+ description = f'''```suggestion:-0+{i2-i1}\n{''.join(formated_file[j1:j2])}```''' # noqa
+
+ issue = {
+ 'name': f'''clang-format:{tag}''',
+ 'description': ''.join(description),
+ 'file': filename,
+ 'line': i1 + 1, # lines start at 1 not 0
+ 'column': 1,
+ 'end_line': i2 + 1,
+ }
+ self.add_issue(issue)
diff --git a/test/ci/scripts/codequality/issue_generator_warnings.py b/test/ci/scripts/codequality/issue_generator_warnings.py
index d5506045d..006caf4be 100644
--- a/test/ci/scripts/codequality/issue_generator_warnings.py
+++ b/test/ci/scripts/codequality/issue_generator_warnings.py
@@ -1,83 +1,81 @@
#!/usr/bin/env python3
"""clang-tidy2code-quality.py: Conversion of clang-tidy output 2
code-quality"""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = (
"Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale"
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation"
" en Mécanique des Solides)"
)
__license__ = "LGPLv3"
-from . import print_debug, print_info
+from . import print_info
from .issue_generator import IssueGenerator
import re
-import sys
import warning_parser as warn
class WarningsIssueGenerator(IssueGenerator):
- """
- Main class to run and convert the results of clang-tidy to the code-quality
- format
+ """Main class to run and convert the results of clang-tidy to the
+ code-quality format.
"""
CLASSIFICATIONS = {
"gcc": {
"uninitialized": {
"categories": ["Bug Risk"],
"severity": "major",
},
"sign-compare": {"categories": ["Bug Risk"], "severity": "minor"},
},
}
def __init__(self, **kwargs):
super().__init__(**kwargs)
files = kwargs.pop("files")
self._input_files = {}
- compiler_re = re.compile(".*build.*(gcc|clang)-err\.log")
+ compiler_re = re.compile(r".*build.*(gcc|clang)-err\.log")
for _file in files:
match = compiler_re.search(_file)
if match:
self._input_files[match.group(1)] = _file
else:
print_info(f"Skipped {_file}, could not determine compiler")
def generate_issues(self):
"""parse warning files"""
for compiler, _file in self._input_files.items():
warnings = warn.get_warnings(_file, compiler)
for warning in warnings:
issue = {
"name": f"warning:{compiler}-{warning.get_category()}",
"description": warning.get_message(),
"file": warning.get_filepath(),
"line": warning.get_line(),
"column": warning.get_column(),
"raw": warning,
}
self.add_issue(issue)
def _get_classifiaction(self, warning):
categories = ["Clarity"]
severity = "info"
tool = warning["raw"].get_tool()
cat = warning["raw"].get_category()
if tool in self.CLASSIFICATIONS:
classifications = self.CLASSIFICATIONS[tool]
if cat in classifications:
categories = classifications[cat]["categories"]
severity = classifications[cat]["severity"]
return (categories, severity)
diff --git a/test/ci/scripts/codequality2emacs.sh b/test/ci/scripts/codequality2emacs.sh
new file mode 100755
index 000000000..ab1e1b60c
--- /dev/null
+++ b/test/ci/scripts/codequality2emacs.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env sh
+
+# This script requires jq, it converts the code quality json file to an output usable as errors in emacs `M-x compile`
+
+jq -r 'unique_by(.fingerprint) | map(select(.location.lines.begin).line = .location.lines.begin) | map(select(.location.positions.begin).line = .location.positions.begin.line) | map({"path":.location.path, "line": .line, "description": .description, "engine": .engine_name, "check": .check_name}) | sort_by(.path, .line) | .[] | "/home/richart/akantu-eigen/" + (.path) + ":" + (.line | tostring) + ": " + (.description) + " [" + (.engine) + ":" + (.check) + "]"' $1
diff --git a/test/ci/ubuntu:lts/Dockerfile b/test/ci/ubuntu:lts/Dockerfile
index ed52389e3..859ab9f79 100644
--- a/test/ci/ubuntu:lts/Dockerfile
+++ b/test/ci/ubuntu:lts/Dockerfile
@@ -1,32 +1,32 @@
-FROM ubuntu:xenial
-MAINTAINER Nicolas Richart <nicolas.richart@epfl.ch>
+FROM ubuntu:20.04
ENV TZ=Europe/Zurich
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# Install akantu dependencies
RUN apt-get -qq update && apt-get -qq -y install \
- g++ gfortran cmake \
+ g++-8 gfortran-8 cmake gfortran g++\
openmpi-bin libmumps-dev libscotch-dev \
libboost-dev libopenblas-dev libcgal-dev \
+ libeigen3-dev \
python3 python3-dev python3-numpy python3-scipy python3-pip \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install mpi4py
# Install test utilities
RUN apt-get -qq update && apt-get -qq -y install \
python3-yaml python3-pytest python3-termcolor python3-click \
ccache gmsh curl git xsltproc \
gcovr binutils \
ninja-build \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install warning_parser
COPY .openmpi /root/.openmpi
# for debug
RUN apt-get -qq update && apt-get -qq -y install \
- gdb valgrind \
+ gdb valgrind emacs-nox \
&& rm -rf /var/lib/apt/lists/*
diff --git a/test/test_common/test_array.cc b/test/test_common/test_array.cc
index f156f0267..92701228f 100644
--- a/test/test_common/test_array.cc
+++ b/test/test_common/test_array.cc
@@ -1,292 +1,421 @@
/**
* @file test_array.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Nov 09 2017
* @date last modification: Wed Nov 18 2020
*
* @brief Test the arry class
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <aka_array.hh>
#include <aka_types.hh>
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <memory>
#include <typeindex>
#include <typeinfo>
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace {
class NonTrivial {
public:
NonTrivial() = default;
NonTrivial(int a) : a(a){};
bool operator==(const NonTrivial & rhs) { return a == rhs.a; }
int a{0};
};
bool operator==(const int & a, const NonTrivial & rhs) { return a == rhs.a; }
std::ostream & operator<<(std::ostream & stream, const NonTrivial & _this) {
stream << _this.a;
return stream;
}
/* -------------------------------------------------------------------------- */
using TestTypes = ::testing::Types<Real, UInt, NonTrivial>;
/* -------------------------------------------------------------------------- */
::testing::AssertionResult AssertType(const char * /*a_expr*/,
const char * /*b_expr*/,
const std::type_info & a,
const std::type_info & b) {
if (std::type_index(a) == std::type_index(b))
return ::testing::AssertionSuccess();
return ::testing::AssertionFailure()
<< debug::demangle(a.name()) << " != " << debug::demangle(b.name())
<< ") are different";
}
/* -------------------------------------------------------------------------- */
template <typename T> class ArrayConstructor : public ::testing::Test {
protected:
using type = T;
void SetUp() override { type_str = debug::demangle(typeid(T).name()); }
template <typename... P> decltype(auto) construct(P &&... params) {
return std::make_unique<Array<T>>(std::forward<P>(params)...);
}
protected:
std::string type_str;
};
TYPED_TEST_SUITE(ArrayConstructor, TestTypes, );
TYPED_TEST(ArrayConstructor, ConstructDefault1) {
auto array = this->construct();
EXPECT_EQ(0, array->size());
EXPECT_EQ(1, array->getNbComponent());
EXPECT_STREQ("", array->getID().c_str());
}
TYPED_TEST(ArrayConstructor, ConstructDefault2) {
auto array = this->construct(1000);
EXPECT_EQ(1000, array->size());
EXPECT_EQ(1, array->getNbComponent());
EXPECT_STREQ("", array->getID().c_str());
}
TYPED_TEST(ArrayConstructor, ConstructDefault3) {
auto array = this->construct(1000, 10);
EXPECT_EQ(1000, array->size());
EXPECT_EQ(10, array->getNbComponent());
EXPECT_STREQ("", array->getID().c_str());
}
TYPED_TEST(ArrayConstructor, ConstructDefault4) {
auto array = this->construct(1000, 10, "test");
EXPECT_EQ(1000, array->size());
EXPECT_EQ(10, array->getNbComponent());
EXPECT_STREQ("test", array->getID().c_str());
}
TYPED_TEST(ArrayConstructor, ConstructDefault5) {
auto array = this->construct(1000, 10, 1);
EXPECT_EQ(1000, array->size());
EXPECT_EQ(10, array->getNbComponent());
EXPECT_EQ(1, array->operator()(10, 6));
EXPECT_STREQ("", array->getID().c_str());
}
-// TYPED_TEST(ArrayConstructor, ConstructDefault6) {
-// typename TestFixture::type defaultv[2] = {0, 1};
-
-// auto array = this->construct(1000, 2, defaultv);
-// EXPECT_EQ(1000, array->size());
-// EXPECT_EQ(2, array->getNbComponent());
-// EXPECT_EQ(1, array->operator()(10, 1));
-// EXPECT_EQ(0, array->operator()(603, 0));
-// EXPECT_STREQ("", array->getID().c_str());
-// }
-
/* -------------------------------------------------------------------------- */
template <typename T> class ArrayFixture : public ArrayConstructor<T> {
public:
void SetUp() override {
ArrayConstructor<T>::SetUp();
array = this->construct(1000, 10);
}
void TearDown() override { array.reset(nullptr); }
protected:
std::unique_ptr<Array<T>> array;
};
TYPED_TEST_SUITE(ArrayFixture, TestTypes, );
TYPED_TEST(ArrayFixture, Copy) {
Array<typename TestFixture::type> copy(*this->array);
EXPECT_EQ(1000, copy.size());
EXPECT_EQ(10, copy.getNbComponent());
- EXPECT_NE(this->array->storage(), copy.storage());
+ EXPECT_NE(this->array->data(), copy.data());
}
TYPED_TEST(ArrayFixture, Set) {
auto & arr = *(this->array);
arr.set(12);
EXPECT_EQ(12, arr(156, 5));
EXPECT_EQ(12, arr(520, 7));
EXPECT_EQ(12, arr(999, 9));
}
TYPED_TEST(ArrayFixture, Resize) {
auto & arr = *(this->array);
- auto * ptr = arr.storage();
+ auto * ptr = arr.data();
arr.resize(0);
EXPECT_EQ(0, arr.size());
- EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+ EXPECT_TRUE(arr.data() == nullptr or arr.data() == ptr);
EXPECT_LE(0, arr.getAllocatedSize());
arr.resize(3000);
EXPECT_EQ(3000, arr.size());
EXPECT_LE(3000, arr.getAllocatedSize());
- ptr = arr.storage();
+ ptr = arr.data();
arr.resize(0);
EXPECT_EQ(0, arr.size());
- EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+ EXPECT_TRUE(arr.data() == nullptr or arr.data() == ptr);
EXPECT_LE(0, arr.getAllocatedSize());
}
TYPED_TEST(ArrayFixture, PushBack) {
auto & arr = *(this->array);
- auto * ptr = arr.storage();
+ auto * ptr = arr.data();
arr.resize(0);
EXPECT_EQ(0, arr.size());
- EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+ EXPECT_TRUE(arr.data() == nullptr or arr.data() == ptr);
EXPECT_LE(0, arr.getAllocatedSize());
arr.resize(3000);
EXPECT_EQ(3000, arr.size());
EXPECT_LE(3000, arr.getAllocatedSize());
- ptr = arr.storage();
+ ptr = arr.data();
arr.resize(0);
EXPECT_EQ(0, arr.size());
- EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+ EXPECT_TRUE(arr.data() == nullptr or arr.data() == ptr);
EXPECT_LE(0, arr.getAllocatedSize());
}
-TYPED_TEST(ArrayFixture, ViewVector) {
+TYPED_TEST(ArrayFixture, ViewVectorDynamic) {
auto && view = make_view(*this->array, 10);
EXPECT_NO_THROW(view.begin());
{
auto it = view.begin();
EXPECT_EQ(10, it->size());
EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
- typeid(Vector<typename TestFixture::type>));
+ typeid(VectorProxy<typename TestFixture::type>));
EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
typeid(VectorProxy<typename TestFixture::type>));
}
}
-TYPED_TEST(ArrayFixture, ViewMatrix) {
+TYPED_TEST(ArrayFixture, ViewVectorStatic) {
+ auto && view = make_view<10>(*this->array);
+ EXPECT_NO_THROW(view.begin());
+ {
+ auto it = view.begin();
+ EXPECT_EQ(10, it->size());
+ EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
+ typeid(VectorProxy<typename TestFixture::type, 10>));
+ EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
+ typeid(VectorProxy<typename TestFixture::type, 10>));
+ }
+}
+
+TYPED_TEST(ArrayFixture, ViewMatrixStatic) {
+ auto && view = make_view(*this->array, 2, 5);
+
+ EXPECT_NO_THROW(view.begin());
+ {
+ auto it = view.begin();
+ EXPECT_EQ(10, it->size());
+ EXPECT_EQ(2, it->size(0));
+ EXPECT_EQ(5, it->size(1));
+
+ EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
+ typeid(MatrixProxy<typename TestFixture::type>));
+ EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
+ typeid(MatrixProxy<typename TestFixture::type>));
+ }
+}
+
+TYPED_TEST(ArrayFixture, ViewMatrixDynamic) {
+ auto && view = make_view<2, 5>(*this->array);
+
+ EXPECT_NO_THROW(view.begin());
{
- auto && view = make_view(*this->array, 2, 5);
-
- EXPECT_NO_THROW(view.begin());
- {
- auto it = view.begin();
- EXPECT_EQ(10, it->size());
- EXPECT_EQ(2, it->size(0));
- EXPECT_EQ(5, it->size(1));
-
- EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
- typeid(Matrix<typename TestFixture::type>));
- EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
- typeid(MatrixProxy<typename TestFixture::type>));
- }
+ auto it = view.begin();
+ EXPECT_EQ(10, it->size());
+ EXPECT_EQ(2, it->size(0));
+ EXPECT_EQ(5, it->size(1));
+ EXPECT_EQ(2, it->rows());
+ EXPECT_EQ(5, it->cols());
+
+ EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
+ typeid(MatrixProxy<typename TestFixture::type, 2, 5>));
+ EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
+ typeid(MatrixProxy<typename TestFixture::type, 2, 5>));
}
}
TYPED_TEST(ArrayFixture, ViewVectorWrong) {
auto && view = make_view(*this->array, 11);
EXPECT_THROW(view.begin(), debug::ArrayException);
}
TYPED_TEST(ArrayFixture, ViewMatrixWrong) {
auto && view = make_view(*this->array, 3, 7);
EXPECT_THROW(view.begin(), debug::ArrayException);
}
TYPED_TEST(ArrayFixture, ViewMatrixIter) {
std::size_t count = 0;
for (auto && mat : make_view(*this->array, 10, 10)) {
EXPECT_EQ(100, mat.size());
EXPECT_EQ(10, mat.size(0));
EXPECT_EQ(10, mat.size(1));
EXPECT_PRED_FORMAT2(AssertType, typeid(mat),
- typeid(Matrix<typename TestFixture::type>));
+ typeid(MatrixProxy<typename TestFixture::type>));
++count;
}
EXPECT_EQ(100, count);
}
TYPED_TEST(ArrayFixture, ConstViewVector) {
const auto & carray = *this->array;
auto && view = make_view(carray, 10);
EXPECT_NO_THROW(view.begin());
{
auto it = view.begin();
EXPECT_EQ(10, it->size());
EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
- typeid(Vector<typename TestFixture::type>));
+ typeid(VectorProxy<typename TestFixture::type>));
EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
typeid(VectorProxy<typename TestFixture::type>));
}
}
+TYPED_TEST(ArrayFixture, EnumerateArray) {
+ this->array->set(12);
+ const auto & carray = *this->array;
+ auto && view = enumerate(make_view(carray, 2));
+ int i = 0;
+ for (auto && data : view) {
+ EXPECT_EQ(i, std::get<0>(data));
+ EXPECT_EQ(12, std::get<1>(data)[0]);
+ EXPECT_EQ(12, std::get<1>(data)[1]);
+ ++i;
+ }
+}
+
+TYPED_TEST(ArrayFixture, ZipArray) {
+ this->array->set(12);
+ const auto & carray = *this->array;
+ auto && view = zip(arange(carray.size() * carray.getNbComponent() / 2),
+ make_view(carray, 2));
+ int i = 0;
+ for (auto && data : view) {
+ EXPECT_EQ(i, std::get<0>(data));
+ EXPECT_EQ(12, std::get<1>(data)[0]);
+ ++i;
+ }
+}
+
+TYPED_TEST(ArrayFixture, IteratorIncrement) {
+ this->array->set(12);
+
+ auto it = make_view(*this->array, this->array->getNbComponent()).begin() + 10;
+
+ EXPECT_EQ(12, (*it)[0]);
+}
+
+TYPED_TEST(ArrayFixture, IteratorFixSize) {
+ this->array->set(12);
+
+ auto it = make_view<10>(*this->array).begin();
+ EXPECT_EQ(12, (*it)[0]);
+
+ auto && vect = *it;
+ vect(0) = 120;
+ EXPECT_EQ(120, (*this->array)(0, 0));
+}
+
+TYPED_TEST(ArrayFixture, IteratorBracket) {
+ this->array->set(12);
+
+ auto && vect =
+ make_view(*this->array, this->array->getNbComponent()).begin()[10];
+
+ EXPECT_EQ(12, vect[0]);
+}
+
+TYPED_TEST(ArrayFixture, IteratorSimple) {
+ this->array->set(12);
+
+ auto it = this->array->begin(this->array->getNbComponent());
+
+ EXPECT_EQ(12, (*it)[0]);
+}
+
+TYPED_TEST(ArrayFixture, IteratorThrow) {
+ this->array->set(12);
+
+ EXPECT_THROW(this->array->begin(2 * this->array->getNbComponent()),
+ debug::Exception);
+}
+
+TYPED_TEST(ArrayFixture, IteratorRange) {
+ this->array->set(12);
+
+ auto && view = make_view(*this->array, this->array->getNbComponent());
+
+ auto begin = view.begin();
+ auto end = view.end();
+
+ for (auto && data : range(begin, end)) {
+ EXPECT_EQ(12, data[0]);
+ }
+}
+
+TYPED_TEST(ArrayFixture, DynamicSizeIteratorFilter) {
+ this->array->set(12);
+ (*this->array)(3) = 13;
+ (*this->array)(50) = 13;
+
+ std::vector<Idx> list_filter{3, 50};
+ auto && view = make_view(*this->array, 10);
+
+ for (auto && data : filter(list_filter, view)) {
+ EXPECT_EQ(13, data[0]);
+ EXPECT_EQ(12, data[1]);
+ }
+}
+
+TYPED_TEST(ArrayFixture, IteratorFilter) {
+ this->array->set(12);
+ (*this->array)(3) = 13;
+ (*this->array)(50) = 13;
+
+ std::vector<Idx> list_filter{3, 50};
+ auto && view = make_view<10>(*this->array);
+
+ for (auto && data : filter(list_filter, view)) {
+ EXPECT_EQ(13, data[0]);
+ EXPECT_EQ(12, data[1]);
+ }
+}
+
} // namespace
diff --git a/test/test_common/test_csr.cc b/test/test_common/test_csr.cc
index f1f570196..eb3731beb 100644
--- a/test/test_common/test_csr.cc
+++ b/test/test_common/test_csr.cc
@@ -1,103 +1,103 @@
/**
* @file test_csr.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Sun Dec 03 2017
*
* @brief Test the CSR (compressed sparse row) data structure
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_csr.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
class TestCsrFixture : public ::testing::Test {
protected:
void SetUp() override {
csr.resizeRows(N);
csr.clearRows();
- for (UInt i = 0; i < N; ++i) {
- UInt nb_cols(UInt(rand() * double(N) / (RAND_MAX + 1.)));
+ for (Int i = 0; i < N; ++i) {
+ Int nb_cols(Int(rand() * double(N) / (RAND_MAX + 1.)));
nb_cols_per_row.push_back(nb_cols);
- for (UInt j = 0; j < nb_cols; ++j) {
+ for (Int j = 0; j < nb_cols; ++j) {
++csr.rowOffset(i);
}
}
csr.countToCSR();
csr.resizeCols();
csr.beginInsertions();
- for (UInt i = 0; i < N; ++i) {
- UInt nb_cols = nb_cols_per_row[i];
- for (UInt j = 0; j < nb_cols; ++j) {
+ for (Int i = 0; i < N; ++i) {
+ Int nb_cols = nb_cols_per_row[i];
+ for (Int j = 0; j < nb_cols; ++j) {
csr.insertInRow(i, nb_cols - j);
}
}
csr.endInsertions();
}
- std::vector<UInt> nb_cols_per_row;
- CSR<UInt> csr;
- size_t N = 1000;
+ std::vector<Int> nb_cols_per_row;
+ CSR<Idx> csr;
+ Int N = 1000;
};
TEST_F(TestCsrFixture, CheckInsertion) { EXPECT_EQ(N, this->csr.getNbRows()); }
TEST_F(TestCsrFixture, Iteration) {
- for (UInt i = 0; i < this->csr.getNbRows(); ++i) {
+ for (Int i = 0; i < this->csr.getNbRows(); ++i) {
auto it = this->csr.begin(i);
auto end = this->csr.end(i);
UInt nb_cols = this->nb_cols_per_row[i];
for (; it != end; ++it) {
EXPECT_EQ(nb_cols, *it);
nb_cols--;
}
EXPECT_EQ(0, nb_cols);
}
}
TEST_F(TestCsrFixture, ReverseIteration) {
- for (UInt i = 0; i < csr.getNbRows(); ++i) {
+ for (Int i = 0; i < csr.getNbRows(); ++i) {
auto it = csr.rbegin(i);
auto end = csr.rend(i);
UInt nb_cols = nb_cols_per_row[i];
UInt j = nb_cols;
for (; it != end; --it) {
EXPECT_EQ((nb_cols - j + 1), *it);
j--;
}
EXPECT_EQ(0, j);
}
}
diff --git a/test/test_common/test_grid.cc b/test/test_common/test_grid.cc
index c54c5724b..54d95acfa 100644
--- a/test/test_common/test_grid.cc
+++ b/test/test_common/test_grid.cc
@@ -1,85 +1,80 @@
/**
* @file test_grid.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Nov 02 2018
*
* @brief Test the grid object
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_grid_dynamic.hh"
#include "mesh.hh"
#include "mesh_io.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
akantu::initialize(argc, argv);
Mesh circle(spatial_dimension);
circle.read("circle.msh");
const auto & l = circle.getLocalLowerBounds();
const auto & u = circle.getLocalUpperBounds();
- Real spacing[spatial_dimension] = {0.2, 0.2};
-
- Vector<Real> s(spacing, spatial_dimension);
-
- Vector<Real> c = u;
- c += l;
- c /= 2.;
+ Vector<Real> s{.2, .2};
+ Vector<Real> c = (u + l) / 2;
SpatialGrid<Element> grid(spatial_dimension, s, c);
Vector<Real> bary(spatial_dimension);
Element el;
el.ghost_type = _not_ghost;
- for (auto & type : circle.elementTypes(spatial_dimension)) {
- UInt nb_element = circle.getNbElement(type);
+ for (const auto & type : circle.elementTypes(spatial_dimension)) {
+ Int nb_element = circle.getNbElement(type);
el.type = type;
- for (UInt e = 0; e < nb_element; ++e) {
+ for (Int e = 0; e < nb_element; ++e) {
el.element = e;
circle.getBarycenter(el, bary);
grid.insert(el, bary);
}
}
std::cout << grid << std::endl;
Mesh mesh(spatial_dimension, "save");
grid.saveAsMesh(mesh);
mesh.write("grid.msh");
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_common/test_tensors.cc b/test/test_common/test_tensors.cc
index 8af7dcaa3..ac8935f2b 100644
--- a/test/test_common/test_tensors.cc
+++ b/test/test_common/test_tensors.cc
@@ -1,594 +1,579 @@
/**
* @file test_tensors.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Nov 14 2017
* @date last modification: Tue Feb 05 2019
*
* @brief test the tensors types
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_array.hh"
#include "aka_iterators.hh"
#include "aka_types.hh"
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <gtest/gtest.h>
#include <memory>
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace {
/* -------------------------------------------------------------------------- */
class TensorConstructorFixture : public ::testing::Test {
public:
void SetUp() override {
for (auto & r : reference) {
r = rand(); // google-test seeds srand()
}
}
void TearDown() override {}
template <typename V> void compareToRef(const V & v) {
for (int i = 0; i < size_; ++i) {
- EXPECT_DOUBLE_EQ(reference[i], v.storage()[i]);
+ EXPECT_DOUBLE_EQ(reference[i], v.data()[i]);
}
}
protected:
const int size_{24};
const std::array<int, 2> mat_size{{4, 6}};
// const std::array<int, 3> tens3_size{{4, 2, 3}};
std::array<double, 24> reference;
};
/* -------------------------------------------------------------------------- */
class TensorFixture : public TensorConstructorFixture {
public:
TensorFixture()
: vref(reference.data(), size_),
mref(reference.data(), mat_size[0], mat_size[1]) {}
protected:
- Vector<double> vref;
- Matrix<double> mref;
+ VectorProxy<double> vref;
+ MatrixProxy<double> mref;
};
/* -------------------------------------------------------------------------- */
// Vector ----------------------------------------------------------------------
TEST_F(TensorConstructorFixture, VectorDefaultConstruct) {
Vector<double> v;
EXPECT_EQ(0, v.size());
- EXPECT_EQ(nullptr, v.storage());
- EXPECT_EQ(false, v.isWrapped());
+ EXPECT_EQ(nullptr, v.data());
}
TEST_F(TensorConstructorFixture, VectorConstruct1) {
- double r = rand();
- Vector<double> v(size_, r);
+ Vector<double> v(size_);
EXPECT_EQ(size_, v.size());
- EXPECT_EQ(false, v.isWrapped());
-
- for (int i = 0; i < size_; ++i) {
- EXPECT_DOUBLE_EQ(r, v(i));
- EXPECT_DOUBLE_EQ(r, v[i]);
- }
}
TEST_F(TensorConstructorFixture, VectorConstructWrapped) {
- Vector<double> v(reference.data(), size_);
+ VectorProxy<double> v(reference.data(), size_);
EXPECT_EQ(size_, v.size());
- EXPECT_EQ(true, v.isWrapped());
+ EXPECT_EQ(v.data(), reference.data());
for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i], v(i));
EXPECT_DOUBLE_EQ(reference[i], v[i]);
}
}
TEST_F(TensorConstructorFixture, VectorConstructInitializer) {
Vector<double> v{0., 1., 2., 3., 4., 5.};
EXPECT_EQ(6, v.size());
- EXPECT_EQ(false, v.isWrapped());
-
for (int i = 0; i < 6; ++i) {
EXPECT_DOUBLE_EQ(i, v(i));
}
}
TEST_F(TensorConstructorFixture, VectorConstructCopy1) {
- Vector<double> vref(reference.data(), reference.size());
+ VectorProxy<double> vref(reference.data(), reference.size());
Vector<double> v(vref);
EXPECT_EQ(size_, v.size());
- EXPECT_EQ(false, v.isWrapped());
- compareToRef(v);
-}
-
-TEST_F(TensorConstructorFixture, VectorConstructCopy2) {
- Vector<double> vref(reference.data(), reference.size());
- Vector<double> v(vref, false);
- EXPECT_EQ(size_, v.size());
- EXPECT_EQ(true, v.isWrapped());
compareToRef(v);
}
TEST_F(TensorConstructorFixture, VectorConstructProxy1) {
VectorProxy<double> vref(reference.data(), reference.size());
EXPECT_EQ(size_, vref.size());
compareToRef(vref);
Vector<double> v(vref);
EXPECT_EQ(size_, v.size());
- EXPECT_EQ(true, v.isWrapped());
- compareToRef(v);
-}
-
-TEST_F(TensorConstructorFixture, VectorConstructProxy2) {
- Vector<double> vref(reference.data(), reference.size());
- VectorProxy<double> v(vref);
- EXPECT_EQ(size_, v.size());
compareToRef(v);
}
/* -------------------------------------------------------------------------- */
TEST_F(TensorFixture, VectorEqual) {
Vector<double> v;
v = vref;
compareToRef(v);
EXPECT_EQ(size_, v.size());
- EXPECT_EQ(false, v.isWrapped());
}
TEST_F(TensorFixture, VectorEqualProxy) {
VectorProxy<double> vref_proxy(vref);
Vector<double> v;
v = vref;
compareToRef(v);
EXPECT_EQ(size_, v.size());
- EXPECT_EQ(false, v.isWrapped());
}
TEST_F(TensorFixture, VectorEqualProxy2) {
- Vector<double> v_store(size_, 0.);
- VectorProxy<double> v(v_store);
+ Vector<double> v_store(size_);
+ v_store.zero();
+ VectorProxy<double> v(v_store.data(), size_);
v = vref;
compareToRef(v);
compareToRef(v_store);
}
/* -------------------------------------------------------------------------- */
TEST_F(TensorFixture, VectorSet) {
Vector<double> v(vref);
compareToRef(v);
double r = rand();
v.set(r);
for (int i = 0; i < size_; ++i)
EXPECT_DOUBLE_EQ(r, v[i]);
}
TEST_F(TensorFixture, VectorClear) {
Vector<double> v(vref);
compareToRef(v);
v.zero();
for (int i = 0; i < size_; ++i)
EXPECT_DOUBLE_EQ(0, v[i]);
}
/* -------------------------------------------------------------------------- */
TEST_F(TensorFixture, VectorDivide) {
Vector<double> v;
double r = rand();
v = vref / r;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] / r, v[i]);
+ }
}
TEST_F(TensorFixture, VectorMultiply1) {
Vector<double> v;
double r = rand();
v = vref * r;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] * r, v[i]);
+ }
}
TEST_F(TensorFixture, VectorMultiply2) {
Vector<double> v;
double r = rand();
v = r * vref;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] * r, v[i]);
+ }
}
TEST_F(TensorFixture, VectorAddition) {
Vector<double> v;
v = vref + vref;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] * 2., v[i]);
+ }
}
TEST_F(TensorFixture, VectorSubstract) {
Vector<double> v;
v = vref - vref;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(0., v[i]);
+ }
}
TEST_F(TensorFixture, VectorDivideEqual) {
Vector<double> v(vref);
double r = rand();
v /= r;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] / r, v[i]);
+ }
}
TEST_F(TensorFixture, VectorMultiplyEqual1) {
Vector<double> v(vref);
double r = rand();
v *= r;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] * r, v[i]);
+ }
}
TEST_F(TensorFixture, VectorMultiplyEqual2) {
Vector<double> v(vref);
- v *= v;
+ v.array() *= v.array();
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] * reference[i], v[i]);
+ }
}
TEST_F(TensorFixture, VectorAdditionEqual) {
Vector<double> v(vref);
v += vref;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(reference[i] * 2., v[i]);
+ }
}
TEST_F(TensorFixture, VectorSubstractEqual) {
Vector<double> v(vref);
v -= vref;
- for (int i = 0; i < size_; ++i)
+ for (int i = 0; i < size_; ++i) {
EXPECT_DOUBLE_EQ(0., v[i]);
+ }
}
/* -------------------------------------------------------------------------- */
// Matrix ----------------------------------------------------------------------
TEST_F(TensorConstructorFixture, MatrixDefaultConstruct) {
Matrix<double> m;
EXPECT_EQ(0, m.size());
EXPECT_EQ(0, m.rows());
EXPECT_EQ(0, m.cols());
- EXPECT_EQ(nullptr, m.storage());
- EXPECT_EQ(false, m.isWrapped());
+ EXPECT_EQ(nullptr, m.data());
}
TEST_F(TensorConstructorFixture, MatrixConstruct1) {
- double r = rand();
- Matrix<double> m(mat_size[0], mat_size[1], r);
+ Matrix<double> m(mat_size[0], mat_size[1]);
EXPECT_EQ(size_, m.size());
EXPECT_EQ(mat_size[0], m.rows());
EXPECT_EQ(mat_size[1], m.cols());
- EXPECT_EQ(false, m.isWrapped());
-
- for (int i = 0; i < mat_size[0]; ++i) {
- for (int j = 0; j < mat_size[1]; ++j) {
- EXPECT_EQ(r, m(i, j));
- EXPECT_EQ(r, m[i + j * mat_size[0]]);
- }
- }
}
TEST_F(TensorConstructorFixture, MatrixConstructWrapped) {
- Matrix<double> m(reference.data(), mat_size[0], mat_size[1]);
+ MatrixProxy<double> m(reference.data(), mat_size[0], mat_size[1]);
EXPECT_EQ(size_, m.size());
EXPECT_EQ(mat_size[0], m.rows());
EXPECT_EQ(mat_size[1], m.cols());
- EXPECT_EQ(true, m.isWrapped());
for (int i = 0; i < mat_size[0]; ++i) {
for (int j = 0; j < mat_size[1]; ++j) {
EXPECT_DOUBLE_EQ(reference[i + j * mat_size[0]], m(i, j));
}
}
compareToRef(m);
}
TEST_F(TensorConstructorFixture, MatrixConstructInitializer) {
Matrix<double> m{{0., 1., 2.}, {3., 4., 5.}};
EXPECT_EQ(6, m.size());
EXPECT_EQ(2, m.rows());
EXPECT_EQ(3, m.cols());
- EXPECT_EQ(false, m.isWrapped());
-
int c = 0;
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j, ++c) {
EXPECT_DOUBLE_EQ(c, m(i, j));
}
}
}
TEST_F(TensorConstructorFixture, MatrixConstructCopy1) {
- Matrix<double> mref(reference.data(), mat_size[0], mat_size[1]);
- Matrix<double> m(mref);
- EXPECT_EQ(size_, m.size());
- EXPECT_EQ(mat_size[0], m.rows());
- EXPECT_EQ(mat_size[1], m.cols());
- EXPECT_EQ(false, m.isWrapped());
- compareToRef(m);
-}
-
-TEST_F(TensorConstructorFixture, MatrixConstructCopy2) {
- Matrix<double> mref(reference.data(), mat_size[0], mat_size[1]);
+ MatrixProxy<double> mref(reference.data(), mat_size[0], mat_size[1]);
Matrix<double> m(mref);
EXPECT_EQ(size_, m.size());
EXPECT_EQ(mat_size[0], m.rows());
EXPECT_EQ(mat_size[1], m.cols());
- EXPECT_EQ(false, m.isWrapped());
compareToRef(m);
}
TEST_F(TensorConstructorFixture, MatrixConstructProxy1) {
MatrixProxy<double> mref(reference.data(), mat_size[0], mat_size[1]);
EXPECT_EQ(size_, mref.size());
EXPECT_EQ(mat_size[0], mref.size(0));
EXPECT_EQ(mat_size[1], mref.size(1));
compareToRef(mref);
Matrix<double> m(mref);
EXPECT_EQ(size_, m.size());
EXPECT_EQ(mat_size[0], m.rows());
EXPECT_EQ(mat_size[1], m.cols());
- EXPECT_EQ(true, m.isWrapped());
- compareToRef(m);
-}
-
-TEST_F(TensorConstructorFixture, MatrixConstructProxy2) {
- Matrix<double> mref(reference.data(), mat_size[0], mat_size[1]);
- MatrixProxy<double> m(mref);
- EXPECT_EQ(size_, m.size());
- EXPECT_EQ(mat_size[0], m.size(0));
- EXPECT_EQ(mat_size[1], m.size(1));
compareToRef(m);
}
/* -------------------------------------------------------------------------- */
TEST_F(TensorFixture, MatrixEqual) {
Matrix<double> m;
m = mref;
compareToRef(m);
EXPECT_EQ(size_, m.size());
EXPECT_EQ(mat_size[0], m.rows());
EXPECT_EQ(mat_size[1], m.cols());
- EXPECT_EQ(false, m.isWrapped());
}
TEST_F(TensorFixture, MatrixEqualProxy1) {
- MatrixProxy<double> mref_proxy(mref);
+ MatrixProxy<double> mref_proxy(mref.data(), mref.rows(), mref.cols());
Matrix<double> m;
m = mref;
compareToRef(m);
EXPECT_EQ(size_, m.size());
EXPECT_EQ(mat_size[0], m.rows());
EXPECT_EQ(mat_size[1], m.cols());
- EXPECT_EQ(false, m.isWrapped());
}
TEST_F(TensorFixture, MatrixEqualProxy2) {
- Matrix<double> m_store(mat_size[0], mat_size[1], 0.);
- MatrixProxy<double> m(m_store);
+ Matrix<double> m_store(mat_size[0], mat_size[1]);
+ m_store.zero();
+ MatrixProxy<double> m(m_store.data(), mat_size[0], mat_size[1]);
m = mref;
compareToRef(m);
compareToRef(m_store);
}
TEST_F(TensorFixture, MatrixEqualSlice) {
- Matrix<double> m(mat_size[0], mat_size[1], 0.);
+ Matrix<double> m(mat_size[0], mat_size[1]);
+ m.zero();
- for (unsigned int i = 0; i < m.cols(); ++i)
- m(i) = Vector<Real>(mref(i));
+ for (Int i = 0; i < m.cols(); ++i) {
+ m(i) = mref(i);
+ }
compareToRef(m);
}
/* -------------------------------------------------------------------------- */
TEST_F(TensorFixture, MatrixSet) {
Matrix<double> m(mref);
compareToRef(m);
double r = rand();
m.set(r);
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(r, m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(r, m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixClear) {
Matrix<double> m(mref);
compareToRef(m);
m.zero();
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(0, m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(0, m.array()(i));
+ }
}
/* -------------------------------------------------------------------------- */
TEST_F(TensorFixture, MatrixDivide) {
Matrix<double> m;
double r = rand();
m = mref / r;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(reference[i] / r, m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(reference[i] / r, m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixMultiply1) {
Matrix<double> m;
double r = rand();
m = mref * r;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(reference[i] * r, m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(reference[i] * r, m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixMultiply2) {
Matrix<double> m;
double r = rand();
m = r * mref;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(reference[i] * r, m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(reference[i] * r, m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixAddition) {
Matrix<double> m;
m = mref + mref;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(reference[i] * 2., m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(reference[i] * 2., m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixSubstract) {
Matrix<double> m;
m = mref - mref;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(0., m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(0., m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixDivideEqual) {
Matrix<double> m(mref);
double r = rand();
m /= r;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(reference[i] / r, m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(reference[i] / r, m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixMultiplyEqual1) {
Matrix<double> m(mref);
double r = rand();
m *= r;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(reference[i] * r, m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(reference[i] * r, m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixAdditionEqual) {
Matrix<double> m(mref);
m += mref;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(reference[i] * 2., m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(reference[i] * 2., m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixSubstractEqual) {
Matrix<double> m(mref);
m -= mref;
- for (int i = 0; i < size_; ++i)
- EXPECT_DOUBLE_EQ(0., m[i]);
+ for (int i = 0; i < size_; ++i) {
+ EXPECT_DOUBLE_EQ(0., m.array()(i));
+ }
}
TEST_F(TensorFixture, MatrixIterator) {
Matrix<double> m(mref);
UInt col_count = 0;
for (auto && col : m) {
- Vector<Real> col_hand(m.storage() + col_count * m.rows(), m.rows());
+ VectorProxy<Real> col_hand(m.data() + col_count * m.rows(), m.rows());
Vector<Real> col_wrap(col);
- auto comp = (col_wrap - col_hand).norm<L_inf>();
+ auto comp = (col_wrap - col_hand).lpNorm<Eigen::Infinity>();
EXPECT_DOUBLE_EQ(0., comp);
++col_count;
}
}
TEST_F(TensorFixture, MatrixIteratorZip) {
Matrix<double> m1(mref);
Matrix<double> m2(mref);
UInt col_count = 0;
for (auto && col : zip(m1, m2)) {
Vector<Real> col1(std::get<0>(col));
Vector<Real> col2(std::get<1>(col));
- auto comp = (col1 - col2).norm<L_inf>();
+ auto comp = (col1 - col2).lpNorm<Eigen::Infinity>();
EXPECT_DOUBLE_EQ(0., comp);
++col_count;
}
}
#if defined(AKANTU_USE_LAPACK)
TEST_F(TensorFixture, MatrixEigs) {
- Matrix<double> m{{0, 1, 0, 0}, {1., 0, 0, 0}, {0, 1, 0, 1}, {0, 0, 4, 0}};
+ Matrix<double, 4, 4> A{
+ {0, 1., 0, 0}, {1., 0, 0, 0}, {0, 1., 0, 1.}, {0, 0, 4., 0}};
- Matrix<double> eig_vects(4, 4);
- Vector<double> eigs(4);
- m.eig(eigs, eig_vects);
+ Matrix<double, 4, 4> v;
+ Vector<double, 4> lambda;
+ lambda.zero();
+ v.zero();
+ A.eig(lambda, v);
Vector<double> eigs_ref{2, 1., -1., -2};
- auto lambda_v = m * eig_vects;
+
+ auto Av = (A * v).eval();
+
+ // Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic>
+ // perm(lambda.size()); perm.setIdentity();
+
+ // std::sort(perm.indices().data(),
+ // perm.indices().data() + perm.indices().size(),
+ // [&lambda](const Eigen::Index & a, const Eigen::Index & b) {
+ // return (lambda(a) - lambda(b)) > 0;
+ // });
+
+ // std::cout << v << std::endl;
+ // std::cout << lambda << std::endl;
+
+ // std::cout << v * perm << std::endl;
+ // std::cout << perm.transpose() * lambda << std::endl;
+
+ // std::cout << (Av(0) - lambda(0) * v(0)).eval() << std::endl;
for (int i = 0; i < 4; ++i) {
- EXPECT_NEAR(eigs_ref(i), eigs(i), 1e-14);
- for (int j = 0; j < 4; ++j) {
- EXPECT_NEAR(lambda_v(i)(j), eigs(i) * eig_vects(i)(j), 1e-14);
- }
+ EXPECT_NEAR(eigs_ref(i), lambda(i), 1e-14);
+ }
+
+ for (int i = 0; i < 4; ++i) {
+ auto lambda_v_minus_a_v =
+ (lambda(i) * v(i) - Av(i)).template lpNorm<Eigen::Infinity>();
+
+ EXPECT_NEAR(lambda_v_minus_a_v, 0., 1e-14);
}
}
#endif
/* -------------------------------------------------------------------------- */
} // namespace
diff --git a/test/test_common/test_types.cc b/test/test_common/test_types.cc
deleted file mode 100644
index 09ca3ad93..000000000
--- a/test/test_common/test_types.cc
+++ /dev/null
@@ -1,356 +0,0 @@
-/**
- * @file test_types.cc
- *
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
- *
- * @date creation: Fri May 15 2015
- * @date last modification: Wed Jun 14 2017
- *
- * @brief Test the types declared in aka_types.hh
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "aka_types.hh"
-
-#include <iostream>
-#include <sstream>
-#include <stdexcept>
-
-using namespace akantu;
-
-const Real tolerance = 1e-15;
-
-std::string itoa(UInt a) {
- std::stringstream sstr;
- sstr << a;
- return sstr.str();
-}
-
-UInt testcounter = 0;
-
-struct wrap_error : std::runtime_error {
- wrap_error(const std::string & msg) : std::runtime_error(msg) {}
-};
-
-struct size_error : std::runtime_error {
- size_error(const std::string & msg) : std::runtime_error(msg) {}
-};
-
-struct data_error : std::runtime_error {
- data_error(const std::string & msg, UInt i)
- : std::runtime_error(msg), index(i) {}
- UInt index;
-};
-
-template <class type>
-void compare_storages_with_ref(const type & a, Real * ref, UInt size, UInt line,
- const std::string & txt) {
- std::cout << std::setw(3) << (testcounter++) << ": " << std::setw(10) << txt
- << " - " << a << " - wrapped: " << std::boolalpha << a.isWrapped()
- << std::endl;
-
- if (a.size() != size)
- throw size_error("the size is not correct " + itoa(a.size()) +
- " instead of " + itoa(size) +
- " [Test at line: " + itoa(line) + "]");
-
- Real * a_ptr = a.storage();
- for (UInt i = 0; i < a.size(); ++i) {
- if (!((std::abs(a_ptr[i]) < tolerance && std::abs(ref[i]) < tolerance) ||
- std::abs((a_ptr[i] - ref[i]) / a_ptr[i]) < tolerance)) {
- std::stringstream txt;
- txt << " std::abs(" << a_ptr[i] << " - " << ref[i]
- << " [= " << std::abs(a_ptr[i] - ref[i]) << "] ) > " << tolerance;
- throw data_error("storage differs at index " + itoa(i) +
- " [Test at line: " + itoa(line) + "]" + txt.str(),
- i);
- }
- }
-
- if (a_ptr == ref && !a.isWrapped())
- throw wrap_error(
- "the storage should be wrapped but it is not [Test at line: " +
- itoa(line) + "]");
- if (a_ptr != ref && a.isWrapped())
- throw wrap_error(
- "the storage should not be wrapped but it is [Test at line: " +
- itoa(line) + "]");
-}
-
-#define COMPARE(a, aref, txt) \
- compare_storages_with_ref(a, aref, sizeof(aref) / sizeof(aref[0]), __LINE__, \
- txt)
-#define COMPARE_STORAGE(a, aref, txt) \
- compare_storages_with_ref(a, aref.storage(), aref.size(), __LINE__, txt)
-
-const UInt ref_size = 10;
-
-// clang-format off
-/* -------------------------------------------------------------------------- */
-void test_constructor() {
- std::cout << "=== Test constructors ===" << std::endl;
- Real ref1[ref_size] = { 0. };
- Real ref2[ref_size] = { 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58 };
- Real ref3[ref_size] = { 23.1594, 79.6184, 77.9052, 47.9922, 12.8674, 37.1445, 64.8991, 80.3364, 98.4064, 73.7858 };
-
- std::cout << "-- Vectors: " << std::endl;
- Vector<Real> v0 = { 23.1594, 79.6184, 77.9052, 47.9922, 12.8674, 37.1445, 64.8991, 80.3364, 98.4064, 73.7858 };
- ; COMPARE ( v0, ref3, "init_list" );
- Vector<Real> v1(ref_size); COMPARE ( v1, ref1, "normal" );
- Vector<Real> v2(ref_size, 1563.58); COMPARE ( v2, ref2, "defval" );
- Vector<Real> v3(ref3, ref_size); COMPARE ( v3, ref3, "wrapped" );
- Vector<Real> v3dcw(v3); COMPARE ( v3dcw, ref3, "wdeepcopy" );
- Vector<Real> v3scw(v3, false); COMPARE ( v3scw, ref3, "wshallow" );
- Vector<Real> v3dc(v3dcw); COMPARE_STORAGE( v3dc, v3dcw, "deepcopy" );
- Vector<Real> v3sc(v3dcw, false); COMPARE_STORAGE( v3sc, v3dcw, "shallow" );
- VectorProxy<Real> vp1(ref3, ref_size);
- Vector<Real> v4(vp1); COMPARE ( v4, ref3, "proxyptr" );
- VectorProxy<Real> vp2(v3dcw);
- Vector<Real> v5(vp2); COMPARE_STORAGE( v5, v3dcw, "proxyvdc" );
- VectorProxy<Real> vp3(v3scw);
- Vector<Real> v6(vp3); COMPARE ( v6, ref3, "proxyvsc" );
-
- /* ------------------------------------------------------------------------ */
- std::cout << "-- Matrices: " << std::endl;
- Matrix<Real> m0 = {{23.1594, 37.1445},
- {79.6184, 64.8991},
- {77.9052, 80.3364},
- {47.9922, 98.4064},
- {12.8674, 73.7858}};
- COMPARE ( m0, ref3 , "init_list" );
- Matrix<Real> m1(5, 2); COMPARE ( m1, ref1 , "normal" );
- Matrix<Real> m1t(2, 5); COMPARE ( m1t, ref1 , "tnormal" );
- Matrix<Real> m2(5, 2, 1563.58); COMPARE ( m2, ref2 , "defval" );
- Matrix<Real> m2t(2, 5, 1563.58); COMPARE ( m2t, ref2 , "tdefval" );
- Matrix<Real> m3(ref3, 5, 2); COMPARE ( m3, ref3 , "wrapped" );
- Matrix<Real> m3t(ref3, 2, 5); COMPARE ( m3t, ref3 , "twrapped" );
- Matrix<Real> m3dcw(m3); COMPARE ( m3dcw, ref3 , "wdeepcopy" );
- Matrix<Real> m3scw(m3, false); COMPARE ( m3scw, ref3 , "wshallow" );
- Matrix<Real> m3dc(m3dcw); COMPARE_STORAGE( m3dc, m3dcw , "deepcopy" );
- Matrix<Real> m3sc(m3dcw, false); COMPARE_STORAGE( m3sc, m3dcw , "shallow" );
- Matrix<Real> m3tdcw(m3t); COMPARE (m3tdcw, ref3 , "twdeepcopy");
- Matrix<Real> m3tscw(m3t, false); COMPARE (m3tscw, ref3 , "twshallow" );
- Matrix<Real> m3tdc(m3tdcw); COMPARE_STORAGE( m3tdc, m3tdcw, "tdeepcopy" );
- Matrix<Real> m3tsc(m3tdcw, false); COMPARE_STORAGE( m3tsc, m3tdcw, "tshallow" );
- MatrixProxy<Real> mp1(ref3, 5, 2);
- Matrix<Real> m4(mp1); COMPARE ( m4, ref3, "proxyptr" );
- MatrixProxy<Real> mp2(m3dcw);
- Matrix<Real> m5(mp2); COMPARE_STORAGE( m5, m3dcw, "proxyvdc" );
- MatrixProxy<Real> mp3(m3scw);
- Matrix<Real> m6(mp3); COMPARE ( m6, ref3, "proxyvsc" );
- MatrixProxy<Real> mp1t(ref3, 2, 5);
- Matrix<Real> m4t(mp1t); COMPARE ( m4t, ref3, "tproxyptr" );
- MatrixProxy<Real> mp2t(m3tdcw);
- Matrix<Real> m5t(mp2t); COMPARE_STORAGE( m5t, m3tdcw, "tproxyvdc" );
- MatrixProxy<Real> mp3t(m3tscw);
- Matrix<Real> m6t(mp3t); COMPARE ( m6t, ref3, "tproxyvsc" );
-}
-
-/* -------------------------------------------------------------------------- */
-void test_equal_and_accessors() {
- std::cout << "=== Test operator=() ===" << std::endl;
- Real ref[ref_size] = { 23.1594, 79.6184, 77.9052, 47.9922, 12.8674, 37.1445, 64.8991, 80.3364, 98.4064, 73.7858 };
- Real mod[ref_size] = { 98.7982, 72.1227, 19.7815, 57.6722, 47.1088, 14.9865, 13.3171, 62.7973, 33.9493, 98.3052 };
-
- std::cout << "-- Vectors: " << std::endl;
- Vector<Real> v (ref, ref_size);
- Vector<Real> vm(mod, ref_size);
- Vector<Real> vref1(v);
- Vector<Real> v1;
- v1 = vref1; COMPARE_STORAGE(v1, vref1, "simple=" );
- for (UInt i = 0; i < ref_size; ++i) v1 (i) = mod[i]; COMPARE (v1, mod, "s_acces" );
- COMPARE_STORAGE(vref1, v, "refcheck1");
-
- Vector<Real> v2 = vref1; COMPARE_STORAGE(v2, vref1, "construc=");
- for (UInt i = 0; i < ref_size; ++i) v2 (i) = mod[i]; COMPARE (v2, mod, "c_acces" );
- COMPARE_STORAGE(vref1, v, "refcheck2");
-
- Vector<Real> vref2(vref1, false);
- Vector<Real> v1w;
- v1w = vref2; COMPARE_STORAGE(v1w, vref1, "w_simple=" );
- for (UInt i = 0; i < ref_size; ++i) v1w(i) = mod[i]; COMPARE (v1w, mod, "ws_acces" );
- try { COMPARE(vref2, ref, "refcheck3"); } catch(wrap_error &) {}
-
- Vector<Real> v2w = vref2; COMPARE_STORAGE(v2w, vref1, "w_constru=");
- for (UInt i = 0; i < ref_size; ++i) v2w(i) = mod[i]; COMPARE (v2w, mod, "wc_acces" );
- try { COMPARE(vref2, ref, "refcheck4"); } catch(wrap_error &) {}
-
- VectorProxy<Real> vp1(vref1);
- Vector<Real> v3;
- v3 = vp1; COMPARE_STORAGE(v3, vref1, "p_simple=" );
- for (UInt i = 0; i < ref_size; ++i) v3(i) = mod[i]; COMPARE (v3, mod, "ps_acces" );
- COMPARE_STORAGE(vref1, v, "refcheck5");
-
- Vector<Real> v4 = vp1; COMPARE_STORAGE(v4, vref1, "p_constru=");
- for (UInt i = 0; i < ref_size; ++i) v4(i) = mod[i];
- try { COMPARE(v4, mod, "pc_acces" ); } catch (wrap_error &) {}
-
- COMPARE(vref1, mod, "refcheck6");
- try { COMPARE(vref2, mod, "refcheck7"); } catch(wrap_error &) {}
-
- vref2 = v;
-
- VectorProxy<Real> vp2(vref2);
- Vector<Real> v3w;
- v3w = vp2; COMPARE_STORAGE(v3w, vref1, "pw_simpl=");
- for (UInt i = 0; i < ref_size; ++i) v3w(i) = mod[i]; COMPARE (v3w, mod, "pws_acces");
- try { COMPARE(vref2, ref, "refcheck8"); } catch(wrap_error &) {}
-
- Vector<Real> v4w = vp2; COMPARE_STORAGE( v4w, vref1, "pw_constr=");
- for (UInt i = 0; i < ref_size; ++i) v4w(i) = mod[i];
- try { COMPARE(v4w, mod, "pwc_acces"); } catch (wrap_error &) {}
- COMPARE_STORAGE(v4w, vref2, "refcheck9");
- try { COMPARE(vref2, mod, "refcheck10"); } catch(wrap_error &) {}
-
- vref1 = v;
-
- Real store[ref_size] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
- Vector<Real> vs(store, 10);
- VectorProxy<Real> vp3(vs);
- vp3 = vref1;
- try { COMPARE(vref1, store, "vp_equal_v"); } catch(wrap_error &) {}
-
- // Vector<Real> vref3(vm);
- // VectorProxy<Real> vp4 = vref3;
- // vp3 = vp4;
- // try { COMPARE(vs, mod, "vp_equal_vp"); } catch(wrap_error &) {}
-
- /* ------------------------------------------------------------------------ */
- std::cout << "-- Matrices: " << std::endl;
-
- Matrix<Real> m (ref, 5, 2);
- Matrix<Real> mt(ref, 2, 5);
-
- Matrix<Real> m1 (5, 2);
- Matrix<Real> m1t(2, 5);
-
- for (UInt i = 0; i < 5; ++i) {
- for (UInt j = 0; j < 2; ++j) {
- m1(i, j) = ref[i + j*5];
- m1t(j, i) = ref[j + i*2];
- }
- }
- COMPARE_STORAGE( m1, m, "access" );
- COMPARE_STORAGE(m1t, m, "t_access");
-
- Matrix<Real> mm (mod, 5, 2);
- Matrix<Real> mmt(mod, 2, 5);
-
- Matrix<Real> m2(m);
- Matrix<Real> m3(m);
- for (UInt j = 0; j < 2; ++j) {
- Vector<Real> v = m2(j);
- for (UInt i = 0; i < 5; ++i)
- v(i) = mm(i, j);
- }
- COMPARE_STORAGE(m2, mm, "slicing");
-
- for (UInt j = 0; j < 2; ++j)
- m3(j) = mm(j);
-
- COMPARE_STORAGE(m3, mm, "slic_slic");
- COMPARE(mm, mod, "refcheck");
-
-
- Real mod_1[ref_size] = { 98.7982, 72.1227, 197.815, 57.6722, 47.1088, 14.9865, 13.3171, 627.973, 33.9493, 98.3052 };
-
- Matrix<Real> m4 (mm);
- m4 (2,0) = 197.815;
- m4 (2,1) = 627.973;
- COMPARE(m4, mod_1, "partial");
-
- Matrix<Real> m4t(mmt);
- m4t(0,1) = 197.815;
- m4t(1,3) = 627.973;
- COMPARE(m4t, mod_1, "t_partial");
-}
-
-/* -------------------------------------------------------------------------- */
-void test_simple_operators() {
- std::cout << "=== Test simple operation ===" << std::endl;
- Real ref[ref_size] = { 23.1594, 79.6184, 77.9052, 47.9922, 12.8674, 37.1445, 64.8991, 80.3364, 98.4064, 73.7858 };
- Real mod[ref_size] = { 98.7982, 72.1227, 19.7815, 57.6722, 47.1088, 14.9865, 13.3171, 62.7973, 33.9493, 98.3052 };
-
- Real ref_div[ref_size] = { 1.163905920192984e+00, 4.001326766509196e+00,
- 3.915227661071464e+00, 2.411910744798472e+00,
- 6.466680068348578e-01, 1.866745401547894e+00,
- 3.261589104432606e+00, 4.037410795054780e+00,
- 4.945542265554328e+00, 3.708201829329581e+00 };
- Real ref_tim[ref_size] = { 4.608257412000000e+02, 1.584246923200000e+03,
- 1.550157669600000e+03, 9.549487955999999e+02,
- 2.560355252000000e+02, 7.391012610000000e+02,
- 1.291362291800000e+03, 1.598533687200000e+03,
- 1.958090547200000e+03, 1.468189848400000e+03 };
- Real ref_p_mod[ref_size] = { 1.219576000000000e+02, 1.517411000000000e+02,
- 9.768670000000000e+01, 1.056644000000000e+02,
- 5.997620000000001e+01, 5.213100000000000e+01,
- 7.821620000000000e+01, 1.431337000000000e+02,
- 1.323557000000000e+02, 1.720910000000000e+02 };
- Real ref_m_mod[ref_size] = { -7.563879999999999e+01, 7.495699999999999e+00,
- 5.812369999999999e+01, -9.680000000000000e+00,
- -3.424140000000000e+01, 2.215800000000000e+01,
- 5.158200000000001e+01, 1.753910000000000e+01,
- 6.445710000000000e+01, -2.451940000000000e+01 };
- std::cout << "-- Vectors: " << std::endl;
- Vector<Real> v (ref, ref_size);
- Vector<Real> vm(mod, ref_size);
- Vector<Real> vref(v);
- Vector<Real> vmod(vm);
-
- Vector<Real> v1 = vref / 19.898; COMPARE(v1, ref_div, "v / s" );
- Vector<Real> v2 = vref * 19.898; COMPARE(v2, ref_tim, "v * s" );
- Vector<Real> v3 = 19.898 * vref; COMPARE(v3, ref_tim, "s * v" );
- Vector<Real> v4 = vref + vmod; COMPARE(v4, ref_p_mod, "v1 + v2" );
- Vector<Real> v5 = vref - vmod; COMPARE(v5, ref_m_mod, "v1 - v2" );
- Vector<Real> v6 = vref; v6 *= 19.898; COMPARE(v6, ref_tim, "v *= s" );
- Vector<Real> v7 = vref; v7 /= 19.898; COMPARE(v7, ref_div, "v /= s" );
- Vector<Real> v8 = vref; v8 += vmod; COMPARE(v8, ref_p_mod, "v1 += v2");
- Vector<Real> v9 = vref; v9 -= vmod; COMPARE(v9, ref_m_mod, "v1 -= v2");
-
- std::cout << "-- Matrices: " << std::endl;
- Matrix<Real> m (ref, 5, 2);
- Matrix<Real> mm(mod, 5, 2);
- Matrix<Real> mref(m);
- Matrix<Real> mmod(mm);
-
- Matrix<Real> m1 = mref / 19.898; COMPARE(m1, ref_div, "m / s" );
- Matrix<Real> m2 = mref * 19.898; COMPARE(m2, ref_tim, "m * s" );
- Matrix<Real> m3 = 19.898 * mref; COMPARE(m3, ref_tim, "s * m" );
- Matrix<Real> m4 = mref + mmod; COMPARE(m4, ref_p_mod, "m1 + m2" );
- Matrix<Real> m5 = mref - mmod; COMPARE(m5, ref_m_mod, "m1 - m2" );
- Matrix<Real> m6 = mref; m6 *= 19.898; COMPARE(m6, ref_tim, "m *= s" );
- Matrix<Real> m7 = mref; m7 /= 19.898; COMPARE(m7, ref_div, "m /= s" );
- Matrix<Real> m8 = mref; m8 += mmod; COMPARE(m8, ref_p_mod, "m1 += m2");
- Matrix<Real> m9 = mref; m9 -= mmod; COMPARE(m9, ref_m_mod, "m1 -= m2");
-}
-// clang-format on
-
-/* -------------------------------------------------------------------------- */
-int main() {
- test_constructor();
- test_equal_and_accessors();
- test_simple_operators();
-
- return 0;
-}
diff --git a/test/test_common/test_voigt_helper.cc b/test/test_common/test_voigt_helper.cc
index a587b1927..c4b1b387b 100644
--- a/test/test_common/test_voigt_helper.cc
+++ b/test/test_common/test_voigt_helper.cc
@@ -1,164 +1,164 @@
/**
* @file test_voigt_helper.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 27 2019
* @date last modification: Wed Nov 18 2020
*
* @brief unit tests for VoigtHelper
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <aka_voigthelper.hh>
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
using namespace akantu;
template <class Dim_v> class VoigtHelperFixture : public ::testing::Test {
protected:
using voigt_h = VoigtHelper<Dim_v::value>;
- constexpr static UInt dim = Dim_v::value;
+ constexpr static Int dim = Dim_v::value;
VoigtHelperFixture() {
switch (this->dim) {
case 1: {
indices.push_back({0, 0});
matrix = Matrix<Real>{{10}};
vector = Vector<Real>{10};
vector_factor = Vector<Real>{10};
break;
}
case 2: {
indices.push_back({0, 0});
indices.push_back({1, 1});
indices.push_back({0, 1});
matrix = Matrix<Real>{{10, 33}, {0, 56}};
vector = Vector<Real>{10, 56, 33};
vector_factor = Vector<Real>{10, 56, 2 * 33};
break;
}
case 3: {
indices.push_back({0, 0});
indices.push_back({1, 1});
indices.push_back({2, 2});
indices.push_back({1, 2});
indices.push_back({0, 2});
indices.push_back({0, 1});
matrix = Matrix<Real>{{10, 33, 20}, {0, 56, 27}, {0, 0, 98}};
vector = Vector<Real>{10, 56, 98, 27, 20, 33};
vector_factor = Vector<Real>{10, 56, 98, 2 * 27, 2 * 20, 2 * 33};
break;
}
}
}
void SetUp() override {}
std::vector<std::pair<UInt, UInt>> indices;
Matrix<Real> matrix;
Vector<Real> vector;
Vector<Real> vector_factor;
};
-template <UInt dim>
+template <Int dim>
using spatial_dimension_t = std::integral_constant<UInt, dim>;
using TestTypes =
::testing::Types<spatial_dimension_t<1>, spatial_dimension_t<2>,
spatial_dimension_t<3>>;
TYPED_TEST_SUITE(VoigtHelperFixture, TestTypes, );
TYPED_TEST(VoigtHelperFixture, Size) {
using voigt_h = typename TestFixture::voigt_h;
switch (this->dim) {
case 1:
EXPECT_EQ(voigt_h::size, 1);
break;
case 2:
EXPECT_EQ(voigt_h::size, 3);
break;
case 3:
EXPECT_EQ(voigt_h::size, 6);
break;
}
}
TYPED_TEST(VoigtHelperFixture, Indicies) {
using voigt_h = typename TestFixture::voigt_h;
- for (UInt I = 0; I < voigt_h::size; ++I) {
+ for (Int I = 0; I < voigt_h::size; ++I) {
EXPECT_EQ(this->indices[I].first, voigt_h::vec[I][0]);
EXPECT_EQ(this->indices[I].second, voigt_h::vec[I][1]);
}
}
TYPED_TEST(VoigtHelperFixture, Factors) {
using voigt_h = typename TestFixture::voigt_h;
- for (UInt I = 0; I < voigt_h::size; ++I) {
+ for (Int I = 0; I < voigt_h::size; ++I) {
if (I < this->dim) {
EXPECT_EQ(voigt_h::factors[I], 1);
} else {
EXPECT_EQ(voigt_h::factors[I], 2);
}
}
}
TYPED_TEST(VoigtHelperFixture, MatrixToVoight) {
using voigt_h = typename TestFixture::voigt_h;
auto voigt = voigt_h::matrixToVoigt(this->matrix);
- for (UInt I = 0; I < voigt_h::size; ++I) {
+ for (Int I = 0; I < voigt_h::size; ++I) {
EXPECT_EQ(voigt(I), this->vector(I));
}
}
TYPED_TEST(VoigtHelperFixture, MatrixToVoightFactors) {
using voigt_h = typename TestFixture::voigt_h;
auto voigt = voigt_h::matrixToVoigtWithFactors(this->matrix);
- for (UInt I = 0; I < voigt_h::size; ++I) {
+ for (Int I = 0; I < voigt_h::size; ++I) {
EXPECT_EQ(voigt(I), this->vector_factor(I));
}
}
TYPED_TEST(VoigtHelperFixture, VoightToMatrix) {
using voigt_h = typename TestFixture::voigt_h;
auto matrix = voigt_h::voigtToMatrix(this->vector);
- for (UInt i = 0; i < this->dim; ++i) {
- for (UInt j = 0; j < this->dim; ++j) {
+ for (Int i = 0; i < this->dim; ++i) {
+ for (Int j = 0; j < this->dim; ++j) {
EXPECT_EQ(matrix(i, j), this->matrix(std::min(i, j), std::max(i, j)));
}
}
}
diff --git a/test/test_fe_engine/CMakeLists.txt b/test/test_fe_engine/CMakeLists.txt
index a59407e82..c9d3db802 100644
--- a/test/test_fe_engine/CMakeLists.txt
+++ b/test/test_fe_engine/CMakeLists.txt
@@ -1,142 +1,156 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
# @author Lucas Frerot <lucas.frerot@epfl.ch>
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Sun Oct 19 2014
# @date last modification: Tue Jun 30 2020
#
# @brief configuration for FEM tests
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
# @section DESCRIPTION
#
#===============================================================================
#===============================================================================
function(register_fem_test operation type)
set(_target test_${operation}${type})
-
register_test(${_target}
SOURCES test_${operation}.cc
FILES_TO_COPY ${type}.msh
COMPILE_OPTIONS TYPE=${type}
PACKAGE core
)
endfunction()
#===============================================================================
macro(register_mesh_types package)
- package_get_element_types(${package} _types)
+ set(_types ${ARGN})
foreach(_type ${_types})
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_type}.msh)
list(APPEND _meshes ${_type}.msh)
else()
if(NOT ${_type} STREQUAL _point_1)
message("The mesh ${_type}.msh is missing, the fe_engine test cannot be activated without it")
endif()
endif()
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_type}.csv)
list(APPEND _csvs ${_type}.csv)
endif()
endforeach()
endmacro(register_mesh_types)
set(_meshes)
set(_csvs)
+set(_regular_types
+ _hexahedron_8
+ _hexahedron_20
+ _pentahedron_6
+ _pentahedron_15
+ _quadrangle_4
+ _quadrangle_8
+ _segment_2
+ _segment_3
+ _tetrahedron_4
+ _tetrahedron_10
+ _triangle_3
+ _triangle_6
+ )
+
-register_mesh_types(core)
+register_mesh_types(core ${_regular_types})
package_is_activated(structural_mechanics has_structural_mechanics)
if(has_structural_mechanics)
- register_mesh_types(structural_mechanics)
+ register_mesh_types(structural_mechanics _bernoulli_beam_2;_bernoulli_beam_3;_discrete_kirchhoff_triangle_18)
endif()
# Tests for class MeshData
macro(register_typed_test test_name type value1 value2)
set(target test_${test_name}_${type})
register_test(${target}
SOURCES test_${test_name}.cc
COMPILE_OPTIONS "TYPE=${type};VALUE1=${value1};VALUE2=${value2}"
PACKAGE core
)
endmacro()
register_typed_test(mesh_data string \"5\" \"10\")
register_typed_test(mesh_data UInt 5 10)
add_mesh(test_boundary_msh cube.geo 3 1)
add_mesh(test_boundary_msh_physical_names cube_physical_names.geo 3 1)
register_test(test_mesh_boundary
SOURCES test_mesh_boundary.cc
DEPENDS test_boundary_msh test_boundary_msh_physical_names
PACKAGE core)
register_test(test_facet_element_mapping
SOURCES test_facet_element_mapping.cc
DEPENDS test_boundary_msh_physical_names
PACKAGE core)
register_gtest_sources(
SOURCES test_fe_engine_precomputation.cc
PACKAGE core python_interface
INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/python
FILES_TO_COPY
)
register_gtest_sources(
SOURCES test_fe_engine_precomputation_structural.cc
PACKAGE structural_mechanics
)
register_gtest_sources(
SOURCES test_fe_engine_inradius.cc
PACKAGE core
)
register_gtest_sources(
SOURCES test_fe_engine_gauss_integration.cc
PACKAGE core
)
register_gtest_sources(
SOURCES test_gradient.cc
PACKAGE core
)
register_gtest_sources(
SOURCES test_integrate.cc
PACKAGE core
)
register_gtest_sources(
SOURCES test_inverse_map.cc
PACKAGE core
)
register_gtest_test(test_fe_engine
FILES_TO_COPY ${_meshes} ${_csvs}
)
diff --git a/test/test_fe_engine/py_engine/py_engine.py b/test/test_fe_engine/py_engine/py_engine.py
index 158820c3b..4cd76f635 100644
--- a/test/test_fe_engine/py_engine/py_engine.py
+++ b/test/test_fe_engine/py_engine/py_engine.py
@@ -1,363 +1,364 @@
#!/usr/bin/env python3
-""" py_engine.py: feengine tester"""
+"""py_engine.py: fe_engine tester."""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
__all__ = ['Shapes']
import numpy as np
import numpy.polynomial.polynomial as poly
# pylint: disable=missing-docstring, invalid-name, too-many-instance-attributes
# flake8: noqa
class Shapes:
- """Python version of the shape functions for test purposes"""
+ """Python version of the shape functions for test purposes."""
+
# pylint: disable=bad-whitespace, line-too-long
NATURAL_COORDS = {
(1, 'quadrangle'): np.array([[-1.], [1.], [0.]]),
(2, 'quadrangle'): np.array([[-1., -1.], [ 1., -1.], [ 1., 1.], [-1., 1.],
[ 0., -1.], [ 1., 0.], [ 0., 1.], [-1., 0.]]),
(3, 'quadrangle'): np.array([[-1., -1., -1.], [ 1., -1., -1.], [ 1., 1., -1.], [-1., 1., -1.],
[-1., -1., 1.], [ 1., -1., 1.], [ 1., 1., 1.], [-1., 1., 1.],
[ 0., -1., -1.], [ 1., 0., -1.], [ 0., 1., -1.], [-1., 0., -1.],
[-1., -1., 0.], [ 1., -1., 0.], [ 1., 1., 0.], [-1., 1., 0.],
[ 0., -1., 1.], [ 1., 0., 1.], [ 0., 1., 1.], [-1., 0., 1.]]),
(2, 'triangle'): np.array([[0., 0.], [1., 0.], [0., 1], [.5, 0.], [.5, .5], [0., .5]]),
(3, 'triangle'): np.array([[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.],
[.5, 0., 0.], [.5, .5, 0.], [0., .5, 0.],
[0., 0., .5], [.5, 0., .5], [0., .5, .5]]),
(3, 'pentahedron'): np.array([[-1., 1., 0.], [-1., 0., 1.], [-1., 0., 0.],
[ 1., 1., 0.], [ 1., 0., 1.], [ 1., 0., 0.],
[-1., .5, .5], [-1., 0., .5], [-1., .5, 0.],
[ 0., 1., 0.], [ 0., 0., 1.], [ 0., 0., 0.],
[ 1., .5, .5], [ 1., 0., .5], [ 1., .5, 0.],
[ 0., .5, .5], [ 0., 0., .5], [ 0., .5, 0.]]),
}
QUADRATURE_W = {
(1, 'quadrangle', 1): np.array([2.]),
(1, 'quadrangle', 2): np.array([1., 1.]),
(2, 'triangle', 1): np.array([1./2.]),
(2, 'triangle', 2): np.array([1., 1., 1.])/6.,
(3, 'triangle', 1): np.array([1./6.]),
(3, 'triangle', 2): np.array([1., 1., 1., 1.])/24.,
(2, 'quadrangle', 1): np.array([1., 1., 1., 1.]),
(2, 'quadrangle', 2): np.array([1., 1., 1., 1.]),
(3, 'quadrangle', 1): np.array([1., 1., 1., 1.,
1., 1., 1., 1.]),
(3, 'quadrangle', 2): np.array([1., 1., 1., 1.,
1., 1., 1., 1.]),
(3, 'pentahedron', 1): np.array([1., 1., 1., 1., 1., 1.])/6.,
(3, 'pentahedron', 2): np.array([1., 1., 1., 1., 1., 1.])/6.,
}
_tet_a = (5. - np.sqrt(5.))/20.
_tet_b = (5. + 3.*np.sqrt(5.))/20.
QUADRATURE_G = {
(1, 'quadrangle', 1): np.array([[0.]]),
(1, 'quadrangle', 2): np.array([[-1.], [1.]])/np.sqrt(3.),
(2, 'triangle', 1): np.array([[1., 1.]])/3.,
(2, 'triangle', 2): np.array([[1./6., 1./6.], [2./3, 1./6], [1./6., 2./3.]]),
(3, 'triangle', 1): np.array([[1., 1., 1.]])/4.,
(3, 'triangle', 2): np.array([[_tet_a, _tet_a, _tet_a],
[_tet_b, _tet_a, _tet_a],
[_tet_a, _tet_b, _tet_a],
[_tet_a, _tet_a, _tet_b]]),
(2, 'quadrangle', 1): np.array([[-1., -1.], [ 1., -1.],
[-1., 1.], [ 1., 1.]])/np.sqrt(3.),
(2, 'quadrangle', 2): np.array([[-1., -1.], [ 1., -1.],
[-1., 1.], [ 1., 1.]])/np.sqrt(3.),
(3, 'quadrangle', 1): np.array([[-1., -1., -1.],
[ 1., -1., -1.],
[-1., 1., -1.],
[ 1., 1., -1.],
[-1., -1., 1.],
[ 1., -1., 1.],
[-1., 1., 1.],
[ 1., 1., 1.]])/np.sqrt(3.),
(3, 'quadrangle', 2): np.array([[-1., -1., -1.],
[ 1., -1., -1.],
[-1., 1., -1.],
[ 1., 1., -1.],
[-1., -1., 1.],
[ 1., -1., 1.],
[-1., 1., 1.],
[ 1., 1., 1.]])/np.sqrt(3.),
(3, 'pentahedron', 1): np.array([[-1./np.sqrt(3.), 1./6., 1./6.],
[-1./np.sqrt(3.), 2./3., 1./6.],
[-1./np.sqrt(3.), 1./6., 2./3.],
[ 1./np.sqrt(3.), 1./6., 1./6.],
[ 1./np.sqrt(3.), 2./3., 1./6.],
[ 1./np.sqrt(3.), 1./6., 2./3.]]),
(3, 'pentahedron', 2): np.array([[-1./np.sqrt(3.), 1./6., 1./6.],
[-1./np.sqrt(3.), 2./3., 1./6.],
[-1./np.sqrt(3.), 1./6., 2./3.],
[ 1./np.sqrt(3.), 1./6., 1./6.],
[ 1./np.sqrt(3.), 2./3., 1./6.],
[ 1./np.sqrt(3.), 1./6., 2./3.]]),
}
ELEMENT_TYPES = {
'_segment_2': ('quadrangle', 1, 'lagrange', 1, 2),
'_segment_3': ('quadrangle', 2, 'lagrange', 1, 3),
'_triangle_3': ('triangle', 1, 'lagrange', 2, 3),
'_triangle_6': ('triangle', 2, 'lagrange', 2, 6),
'_quadrangle_4': ('quadrangle', 1, 'serendip', 2, 4),
'_quadrangle_8': ('quadrangle', 2, 'serendip', 2, 8),
'_tetrahedron_4': ('triangle', 1, 'lagrange', 3, 4),
'_tetrahedron_10': ('triangle', 2, 'lagrange', 3, 10),
'_pentahedron_6': ('pentahedron', 1, 'lagrange', 3, 6),
'_pentahedron_15': ('pentahedron', 2, 'lagrange', 3, 15),
'_hexahedron_8': ('quadrangle', 1, 'serendip', 3, 8),
'_hexahedron_20': ('quadrangle', 2, 'serendip', 3, 20),
}
MONOMES = {(1, 'quadrangle'): np.array([[0], [1], [2], [3], [4], [5]]),
(2, 'triangle'): np.array([[0, 0], # 1
[1, 0], [0, 1], # x y
[2, 0], [1, 1], [0, 2]]), # x^2 x.y y^2
(2, 'quadrangle'): np.array([[0, 0],
[1, 0], [1, 1], [0, 1],
[2, 0], [2, 1], [1, 2], [0, 2]]),
(3, 'triangle'): np.array([[0, 0, 0],
[1, 0, 0], [0, 1, 0], [0, 0, 1],
[2, 0, 0], [1, 1, 0], [0, 2, 0], [0, 1, 1], [0, 0, 2],
[1, 0, 1]]),
(3, 'quadrangle'): np.array([[0, 0, 0],
[1, 0, 0], [0, 1, 0], [0, 0, 1],
[1, 1, 0], [1, 0, 1],
[0, 1, 1], [1, 1, 1],
[2, 0, 0], [0, 2, 0], [0, 0, 2],
[2, 1, 0], [2, 0, 1], [2, 1, 1],
[1, 2, 0], [0, 2, 1], [1, 2, 1],
[1, 0, 2], [0, 1, 2], [1, 1, 2]])}
SHAPES = {
(3, 'pentahedron', 1): np.array([
[[[ 0., 0.], [ 1., 0.]], [[ 0., 0.], [-1., 0.]]],
[[[ 0., 1.], [ 0., 0.]], [[ 0., -1.], [ 0., 0.]]],
[[[ 1., -1.], [-1., 0.]], [[-1., 1.], [ 1., 0.]]],
[[[ 0., 0.], [ 1., 0.]], [[ 0., 0.], [ 1., 0.]]],
[[[ 0., 1.], [ 0., 0.]], [[ 0., 1.], [ 0., 0.]]],
[[[ 1., -1.], [-1., 0.]], [[ 1., -1.], [-1., 0.]]]
])/2.,
(3, 'pentahedron', 2): np.array([
# 0
[[[ 0. , 0. , 0. ], [-1. , 0. , 0. ], [ 1. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0.5, 0. , 0. ], [-1. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0.5, 0. , 0. ], [ 0. , 0. , 0. ]]],
# 1
[[[ 0. , -1. , 1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0.5, -1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0.5, 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 2
[[[ 0. , -1. , 1. ], [-1. , 2. , 0. ], [ 1. , 0. , 0. ]],
[[-0.5, 1.5, -1. ], [ 1.5, -2. , 0. ], [-1. , 0. , 0. ]],
[[ 0.5, -0.5, 0. ], [-0.5, 0. , 0. ], [ 0. , 0. , 0. ]]],
# 3
[[[ 0. , 0. , 0. ], [-1. , 0. , 0. ], [ 1. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [-0.5, 0. , 0. ], [ 1. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0.5, 0. , 0. ], [ 0. , 0. , 0. ]]],
# 4
[[[ 0. , -1. , 1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , -0.5, 1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0.5, 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 5
[[[ 0. , -1. , 1. ], [-1. , 2. , 0. ], [ 1. , 0. , 0. ]],
[[ 0.5, -1.5, 1. ], [-1.5, 2. , 0. ], [ 1. , 0. , 0. ]],
[[ 0.5, -0.5, 0. ], [-0.5, 0. , 0. ], [ 0. , 0. , 0. ]]],
# 6
[[[ 0. , 0. , 0. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 7
[[[ 0. , 2. , -2. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , -2. , 2. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 8
[[[ 0. , 0. , 0. ], [ 2. , -2. , 0. ], [-2. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [-2. , 2. , 0. ], [ 2. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 9
[[[ 0. , 0. , 0. ], [ 1. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [-1. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 10
[[[ 0. , 1. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , -1. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 11
[[[ 1. , -1. , 0. ], [-1. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]],
[[-1. , 1. , 0. ], [ 1. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 12
[[[ 0. , 0. , 0. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 13
[[[ 0. , 2. , -2. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 2. , -2. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
# 14
[[[ 0. , 0. , 0. ], [ 2. , -2. , 0. ], [-2. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 2. , -2. , 0. ], [-2. , 0. , 0. ]],
[[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]],
])}
# pylint: enable=bad-whitespace, line-too-long
def __init__(self, element):
self._shape, self._order, self._inter_poly, self._dim, \
self._nnodes = self.ELEMENT_TYPES[element]
self._ksi = self.NATURAL_COORDS[(self._dim, self._shape)][:self._nnodes]
self._g = self.QUADRATURE_G[(self._dim, self._shape, self._order)]
self._w = self.QUADRATURE_W[(self._dim, self._shape, self._order)]
self._poly_shape = ()
self._monome = []
def polyval(self, x, p):
if self._dim == 1:
return poly.polyval(x[0], p)
if self._dim == 2:
return poly.polyval2d(x[0], x[1], p)
if self._dim == 3:
return poly.polyval3d(x[0], x[1], x[2], p)
return None
def shape_from_monomes(self):
momo = self.MONOMES[(self._dim, self._shape)][:self._nnodes]
_shapes = list(momo[0])
for s, _ in enumerate(_shapes):
_shapes[s] = max(momo[:, s])+1
self._poly_shape = tuple(_shapes)
self._monome = []
for m in momo:
p = np.zeros(self._poly_shape)
p[tuple(m)] = 1
self._monome.append(p)
# evaluate polynomial constant for shapes
_x = self._ksi
_xe = np.zeros((self._nnodes, self._nnodes))
for n in range(self._nnodes):
_xe[:, n] = [self.polyval(_x[n], m) for m in self._monome]
_a = np.linalg.inv(_xe)
_n = np.zeros((self._nnodes,) + self._monome[0].shape)
# set shapes polynomials
for n in range(self._nnodes):
for m in range(len(self._monome)):
_n[n] += _a[n, m] * self._monome[m]
return _n
def compute_shapes(self):
if (self._dim, self._shape) in self.MONOMES:
return self.shape_from_monomes()
_n = self.SHAPES[(self._dim, self._shape, self._order)]
self._poly_shape = _n[0].shape
return _n
# pylint: disable=too-many-locals,too-many-branches
def precompute(self, **kwargs):
X = np.array(kwargs["X"], copy=False)
nb_element = X.shape[0]
X = X.reshape(nb_element, self._nnodes, self._dim)
_x = self._ksi
_n = self.compute_shapes()
# sanity check on shapes
for n in range(self._nnodes):
for m in range(self._nnodes):
v = self.polyval(_x[n], _n[m])
ve = 1. if n == m else 0.
test = np.isclose(v, ve)
if not test:
raise Exception("Most probably an error in the shapes evaluation")
# compute shapes derivatives
_b = np.zeros((self._dim, self._nnodes,) + self._poly_shape)
for d in range(self._dim):
for n in range(self._nnodes):
_der = poly.polyder(_n[n], axis=d)
_mshape = np.array(self._poly_shape)
_mshape[d] = _mshape[d] - _der.shape[d]
_mshape = tuple(_mshape)
_comp = np.zeros(_mshape)
if self._dim == 1:
_bt = np.hstack((_der, _comp))
else:
if d == 0:
_bt = np.vstack((_der, _comp))
if d == 1:
_bt = np.hstack((_der, _comp))
if d == 2:
_bt = np.dstack((_der, _comp))
_b[d, n] = _bt
_nb_quads = len(self._g)
_nq = np.zeros((_nb_quads, self._nnodes))
_bq = np.zeros((_nb_quads, self._dim, self._nnodes))
# evaluate shapes and shapes derivatives on gauss points
for q in range(_nb_quads):
_g = self._g[q]
for n in range(self._nnodes):
_nq[q, n] = self.polyval(_g, _n[n])
for d in range(self._dim):
_bq[q, d, n] = self.polyval(_g, _b[d, n])
_j = np.array(kwargs['j'], copy=False).reshape((nb_element, _nb_quads))
_B = np.array(kwargs['B'], copy=False).reshape((nb_element, _nb_quads,
self._nnodes, self._dim))
_N = np.array(kwargs['N'], copy=False).reshape((nb_element, _nb_quads, self._nnodes))
_Q = kwargs['Q']
if np.linalg.norm(_Q - self._g.T) > 1e-15:
raise Exception('Not using the same quadrature'
' points norm({0} - {1}) = {2}'.format(_Q, self._g.T,
np.linalg.norm(_Q - self._g.T)))
for e in range(nb_element):
for q in range(_nb_quads):
_J = np.matmul(_bq[q], X[e])
if np.linalg.norm(_N[e, q] - _nq[q]) > 1e-10:
print("{0},{1}".format(e, q))
print(_N[e, q])
print(_nq[q])
_N[e, q] = _nq[q]
_tmp = np.matmul(np.linalg.inv(_J), _bq[q])
_B[e, q] = _tmp.T
_j[e, q] = np.linalg.det(_J) * self._w[q]
diff --git a/test/test_fe_engine/test_facet_element_mapping.cc b/test/test_fe_engine/test_facet_element_mapping.cc
index 88c976dcd..76bcc65ae 100644
--- a/test/test_fe_engine/test_facet_element_mapping.cc
+++ b/test/test_fe_engine/test_facet_element_mapping.cc
@@ -1,128 +1,128 @@
/**
* @file test_facet_element_mapping.cc
*
* @author Dana Christen <dana.christen@gmail.com>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Nov 02 2018
*
* @brief Test of the MeshData class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_error.hh"
#include "mesh.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
#include <string>
/* -------------------------------------------------------------------------- */
using namespace akantu;
using namespace std;
int main(int argc, char * argv[]) {
// Testing the subelement-to-element mappings
- UInt spatial_dimension(3);
+ Int spatial_dimension(3);
akantu::initialize(argc, argv);
Mesh mesh(spatial_dimension, "my_mesh");
mesh.read("./cube_physical_names.msh");
- typedef Array<std::vector<Element>> ElemToSubelemMapping;
- typedef Array<Element> SubelemToElemMapping;
+ using SubelemToElemMapping = Array<Element>;
std::cout << "ELEMENT-SUBELEMENT MAPPING:" << std::endl;
for (auto ghost_type : ghost_types) {
std::cout << " "
<< "Ghost type: " << ghost_type << std::endl;
- for (auto & type : mesh.elementTypes(spatial_dimension, ghost_type)) {
+ for (const auto & type : mesh.elementTypes(spatial_dimension, ghost_type)) {
const SubelemToElemMapping & subelement_to_element =
mesh.getSubelementToElement(type, ghost_type);
std::cout << " "
<< " "
<< "Element type: " << type << std::endl;
std::cout << " "
<< " "
<< " "
<< "subelement_to_element:" << std::endl;
subelement_to_element.printself(std::cout, 8);
- for (UInt i(0); i < subelement_to_element.size(); ++i) {
+ for (Int i(0); i < subelement_to_element.size(); ++i) {
std::cout << " ";
- for (UInt j(0); j < mesh.getNbFacetsPerElement(type); ++j) {
+ for (Int j(0); j < mesh.getNbFacetsPerElement(type); ++j) {
if (subelement_to_element(i, j) != ElementNull) {
std::cout << subelement_to_element(i, j);
std::cout << ", ";
} else {
std::cout << "ElementNull"
<< ", ";
}
}
std::cout << "for element " << i << std::endl;
}
}
- for (auto & type : mesh.elementTypes(spatial_dimension - 1, ghost_type)) {
- const ElemToSubelemMapping & element_to_subelement =
+ for (const auto & type :
+ mesh.elementTypes(spatial_dimension - 1, ghost_type)) {
+ const auto & element_to_subelement =
mesh.getElementToSubelement(type, ghost_type);
std::cout << " "
<< " "
<< "Element type: " << type << std::endl;
std::cout << " "
<< " "
<< " "
<< "element_to_subelement:" << std::endl;
element_to_subelement.printself(std::cout, 8);
- for (UInt i(0); i < element_to_subelement.size(); ++i) {
- const std::vector<Element> & vec = element_to_subelement(i);
+ for (Int i(0); i < element_to_subelement.size(); ++i) {
+ const auto & vec = element_to_subelement(i);
std::cout << " ";
std::cout << "item " << i << ": [ ";
if (vec.size() > 0) {
- for (UInt j(0); j < vec.size(); ++j) {
+ for (Int j(0); j < Int(vec.size()); ++j) {
if (vec[j] != ElementNull) {
std::cout << vec[j] << ", ";
} else {
std::cout << "ElementNull"
<< ", ";
}
}
} else {
std::cout << "empty, ";
}
std::cout << "]"
<< ", " << std::endl;
}
std::cout << std::endl;
}
}
return 0;
}
diff --git a/test/test_fe_engine/test_fe_engine_fixture.hh b/test/test_fe_engine/test_fe_engine_fixture.hh
index 07378f5b9..648bd495f 100644
--- a/test/test_fe_engine/test_fe_engine_fixture.hh
+++ b/test/test_fe_engine/test_fe_engine_fixture.hh
@@ -1,114 +1,113 @@
/**
* @file test_fe_engine_fixture.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Nov 14 2017
* @date last modification: Wed Nov 18 2020
*
* @brief Fixture for feengine tests
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <element_class.hh>
#include <fe_engine.hh>
#include <integrator_gauss.hh>
#include <shape_lagrange.hh>
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TEST_FE_ENGINE_FIXTURE_HH_
#define AKANTU_TEST_FE_ENGINE_FIXTURE_HH_
using namespace akantu;
/// Generic class for FEEngine tests
template <typename type_, template <ElementKind> class shape_t,
ElementKind kind = _ek_regular>
class TestFEMBaseFixture : public ::testing::Test {
public:
static constexpr const ElementType type = type_::value;
- static constexpr const size_t dim = ElementClass<type>::getSpatialDimension();
+ static constexpr const Int dim = ElementClass<type>::getSpatialDimension();
using FEM = FEEngineTemplate<IntegratorGauss, shape_t, kind>;
/// Setup reads mesh corresponding to element type and initializes an FEEngine
void SetUp() override {
const auto dim = this->dim;
mesh = std::make_unique<Mesh>(dim);
std::stringstream meshfilename;
meshfilename << type << ".msh";
this->readMesh(meshfilename.str());
lower = mesh->getLowerBounds();
upper = mesh->getUpperBounds();
nb_element = this->mesh->getNbElement(type);
fem = std::make_unique<FEM>(*mesh, dim, "my_fem");
nb_quadrature_points_total =
GaussIntegrationElement<type>::getNbQuadraturePoints() * nb_element;
SCOPED_TRACE(std::to_string(type));
}
void TearDown() override {
fem.reset(nullptr);
mesh.reset(nullptr);
}
/// Should be reimplemented if further treatment of the mesh is needed
virtual void readMesh(std::string file_name) { mesh->read(file_name); }
protected:
std::unique_ptr<FEM> fem;
std::unique_ptr<Mesh> mesh;
- UInt nb_element;
- UInt nb_quadrature_points_total;
+ Int nb_element;
+ Int nb_quadrature_points_total;
Vector<Real> lower;
Vector<Real> upper;
};
template <typename type_, template <ElementKind> class shape_t,
ElementKind kind>
constexpr const ElementType TestFEMBaseFixture<type_, shape_t, kind>::type;
template <typename type_, template <ElementKind> class shape_t,
ElementKind kind>
-constexpr const size_t TestFEMBaseFixture<type_, shape_t, kind>::dim;
+constexpr const Int TestFEMBaseFixture<type_, shape_t, kind>::dim;
/* -------------------------------------------------------------------------- */
/// Base class for test with Lagrange FEEngine and regular elements
template <typename type_>
using TestFEMFixture = TestFEMBaseFixture<type_, ShapeLagrange, _ek_regular>;
/* -------------------------------------------------------------------------- */
-
using fe_engine_types = gtest_list_t<TestElementTypes>;
TYPED_TEST_SUITE(TestFEMFixture, fe_engine_types, );
#endif /* AKANTU_TEST_FE_ENGINE_FIXTURE_HH_ */
diff --git a/test/test_fe_engine/test_fe_engine_inradius.cc b/test/test_fe_engine/test_fe_engine_inradius.cc
index b928ca85b..73bbb1f95 100644
--- a/test/test_fe_engine/test_fe_engine_inradius.cc
+++ b/test/test_fe_engine/test_fe_engine_inradius.cc
@@ -1,85 +1,85 @@
/**
* @file test_fe_engine_precomputation.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Nov 18 2020
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <fstream>
/* -------------------------------------------------------------------------- */
#include "test_fe_engine_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
TYPED_TEST(TestFEMFixture, Inradius) {
const auto & connectivities = this->mesh->getConnectivity(this->type);
- const auto & nodes = this->mesh->getNodes().begin(this->dim);
+ auto nodes = this->mesh->getNodes().cbegin(this->dim);
std::ifstream fin;
fin.open(std::to_string(this->type) + ".csv");
if (not fin.is_open()) {
throw std::runtime_error("Could not open file " +
std::to_string(this->type) + ".csv");
}
int id;
std::vector<Real> inradiuses(connectivities.size());
Real inradius;
std::string line;
while (std::getline(fin, line)) {
// Create a stringstream of the current line
std::stringstream ss(line);
ss >> id;
// If the next token is a comma, ignore it and move on
if (ss.peek() == ',') {
ss.ignore();
}
ss >> inradius;
inradiuses[id] = inradius;
}
Matrix<Real> X(this->dim, connectivities.getNbComponent());
Element element{this->type, 0, _not_ghost};
for (auto && conn :
make_view(connectivities, connectivities.getNbComponent())) {
for (auto s : arange(conn.size())) {
- Vector<Real>(X(s)) = Vector<Real>(nodes[conn(s)]);
+ X(s) = nodes[conn(s)];
}
auto inradius_coor = this->fem->getElementInradius(X, this->type);
auto inradius_elem = this->fem->getElementInradius(element);
auto inradius_file = inradiuses[element.element];
// Files was written in simple precision...
EXPECT_NEAR(inradius_elem, inradius_file, 1e-6);
EXPECT_NEAR(inradius_coor, inradius_file, 1e-6);
++element.element;
}
}
diff --git a/test/test_fe_engine/test_fe_engine_precomputation.cc b/test/test_fe_engine/test_fe_engine_precomputation.cc
index 0778ecb98..f0c7f8636 100644
--- a/test/test_fe_engine/test_fe_engine_precomputation.cc
+++ b/test/test_fe_engine/test_fe_engine_precomputation.cc
@@ -1,115 +1,116 @@
/**
* @file test_fe_engine_precomputation.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Nov 18 2020
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_aka_array.hh"
#include "test_fe_engine_fixture.hh"
/* -------------------------------------------------------------------------- */
#include <pybind11/embed.h>
#include <pybind11/numpy.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace py = pybind11;
using namespace py::literals;
template <class T> decltype(auto) make_proxy(Array<T> & array) {
return detail::ArrayProxy<T>(array);
}
template <typename type_>
class TestFEMPyFixture : public TestFEMFixture<type_> {
using parent = TestFEMFixture<type_>;
public:
void SetUp() override {
parent::SetUp();
const auto & connectivities = this->mesh->getConnectivity(this->type);
- const auto & nodes = this->mesh->getNodes().begin(this->dim);
+ auto nodes = this->mesh->getNodes().cbegin(this->dim);
coordinates = std::make_unique<Array<Real>>(
connectivities.size(), connectivities.getNbComponent() * this->dim);
for (auto && tuple :
zip(make_view(connectivities, connectivities.getNbComponent()),
make_view(*coordinates, this->dim,
connectivities.getNbComponent()))) {
- const auto & conn = std::get<0>(tuple);
- const auto & X = std::get<1>(tuple);
+ auto && conn = std::get<0>(tuple);
+ auto & X = std::get<1>(tuple);
for (auto s : arange(conn.size())) {
- Vector<Real>(X(s)) = Vector<Real>(nodes[conn(s)]);
+ X(s) = nodes[conn(s)];
}
}
}
void TearDown() override {
parent::TearDown();
coordinates.reset(nullptr);
}
protected:
std::unique_ptr<Array<Real>> coordinates;
};
TYPED_TEST_SUITE(TestFEMPyFixture, fe_engine_types, );
TYPED_TEST(TestFEMPyFixture, Precompute) {
SCOPED_TRACE(std::to_string(this->type));
this->fem->initShapeFunctions();
const auto & N = this->fem->getShapeFunctions().getShapes(this->type);
const auto & B =
this->fem->getShapeFunctions().getShapesDerivatives(this->type);
const auto & j = this->fem->getIntegrator().getJacobians(this->type);
// Array<Real> ref_N(this->nb_quadrature_points_total, N.getNbComponent());
// Array<Real> ref_B(this->nb_quadrature_points_total, B.getNbComponent());
Array<Real> ref_j(this->nb_quadrature_points_total, j.getNbComponent());
auto ref_N(N);
auto ref_B(B);
py::module py_engine = py::module::import("py_engine");
auto py_shape = py_engine.attr("Shapes")(py::str(std::to_string(this->type)));
auto kwargs = py::dict("N"_a = ref_N, "B"_a = ref_B, "j"_a = ref_j,
"X"_a = *this->coordinates,
"Q"_a = this->fem->getIntegrationPoints(this->type));
auto ret = py_shape.attr("precompute")(**kwargs);
auto check = [&](auto & ref_A, auto & A, const auto & id) {
SCOPED_TRACE(std::to_string(this->type) + " " + id);
for (auto && n : zip(make_view(ref_A, ref_A.getNbComponent()),
make_view(A, A.getNbComponent()))) {
- auto diff = (std::get<0>(n) - std::get<1>(n)).template norm<L_inf>();
+ auto diff =
+ (std::get<0>(n) - std::get<1>(n)).template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0., diff, 1e-10);
}
};
check(ref_N, N, "N");
check(ref_B, B, "B");
check(ref_j, j, "j");
}
diff --git a/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_2.cc b/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_2.cc
index d355b65a9..6701168a8 100644
--- a/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_2.cc
+++ b/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_2.cc
@@ -1,154 +1,153 @@
/**
* @file test_fe_engine_precomputation_bernoulli_2.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Jan 25 2018
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "integrator_gauss.hh"
#include "shape_structural.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <functional>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
Matrix<Real> globalToLocalRotation(Real theta) {
// clang-format off
return {{ std::cos(theta), std::sin(theta), 0},
{-std::sin(theta), std::cos(theta), 0},
{ 0, 0, 1}};
// clang-format on
}
Vector<Real> axialReference(Real xq) {
return {(1. - xq) / 2, 0, 0, (1. + xq) / 2, 0, 0};
}
Vector<Real> bendingReference(Real xq) {
return {0,
1. / 4. * Math::pow<2>(xq - 1) * (xq + 2),
1. / 4. * Math::pow<2>(xq - 1) * (xq + 1),
0,
1. / 4. * Math::pow<2>(xq + 1) * (2 - xq),
1. / 4. * Math::pow<2>(xq + 1) * (xq - 1)};
}
Vector<Real> bendingRotationReference(Real xq) {
return {0, 3. / 4. * (xq * xq - 1), 1. / 4. * (3 * xq * xq - 2 * xq - 1),
0, 3. / 4. * (1 - xq * xq), 1. / 4. * (3 * xq * xq + 2 * xq - 1)};
}
bool testBending(const Array<Real> & shape_functions, UInt shape_line_index,
std::function<Vector<Real>(Real)> reference) {
Real xq = -1. / std::sqrt(3.);
// Testing values for bending rotations shapes on quadrature points
for (auto && N : make_view(shape_functions, 3, 6)) {
auto Nt = N.transpose();
Vector<Real> N_bending = Nt(shape_line_index);
auto bending_reference = reference(xq);
- if (!Math::are_vector_equal(6, N_bending.storage(),
- bending_reference.storage()))
+ if (!Math::are_vector_equal(6, N_bending.data(), bending_reference.data()))
return false;
xq *= -1;
}
std::cout.flush();
return true;
}
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
// debug::setDebugLevel(dblTest);
constexpr ElementType type = _bernoulli_beam_2;
- UInt dim = ElementClass<type>::getSpatialDimension();
+ Int dim = ElementClass<type>::getSpatialDimension();
Mesh mesh(dim);
// creating nodes
Vector<Real> node = {0, 0};
mesh.getNodes().push_back(node);
node = {3. / 5., 4. / 5.};
mesh.getNodes().push_back(node);
node = {2 * 3. / 5., 0};
mesh.getNodes().push_back(node);
mesh.addConnectivityType(type);
auto & connectivity = mesh.getConnectivity(type);
// creating elements
Vector<UInt> elem = {0, 1};
connectivity.push_back(elem);
elem = {1, 2};
connectivity.push_back(elem);
elem = {0, 2};
connectivity.push_back(elem);
using FE = FEEngineTemplate<IntegratorGauss, ShapeStructural, _ek_structural>;
using ShapeStruct = ShapeStructural<_ek_structural>;
auto fem = std::make_unique<FE>(mesh, dim, "test_fem");
fem->initShapeFunctions();
auto & shape = dynamic_cast<const ShapeStruct &>(fem->getShapeFunctions());
Array<Real> angles;
angles.push_back(std::atan(4. / 3.));
angles.push_back(-std::atan(4. / 3.));
angles.push_back(0);
/// Testing the rotation matrices
for (auto && tuple : zip(make_view(shape.getRotations(type), 3, 3), angles)) {
auto && rotation = std::get<0>(tuple);
auto theta = std::get<1>(tuple);
auto reference = globalToLocalRotation(theta);
- if (!Math::are_vector_equal(9, reference.storage(), rotation.storage()))
+ if (!Math::are_vector_equal(9, reference.data(), rotation.data()))
return 1;
}
auto & shape_functions = shape.getShapes(type);
if (!testBending(shape_functions, 0, axialReference))
return 1;
// if (!testBending(shape_functions, 1, bendingReference))
// return 1;
// if (!testBending(shape_functions, 2, bendingRotationReference))
// return 1;
std::cout.flush();
finalize();
return 0;
}
diff --git a/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_3.cc b/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_3.cc
index b820e4431..0ee8c7ea4 100644
--- a/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_3.cc
+++ b/test/test_fe_engine/test_fe_engine_precomputation_bernoulli_3.cc
@@ -1,107 +1,107 @@
/**
* @file test_fe_engine_precomputation_bernoulli_3.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Jan 24 2018
* @date last modification: Wed Sep 12 2018
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "integrator_gauss.hh"
#include "shape_structural.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <functional>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/**
* Reference: p. 285, example 5.7 - A First Course in the Finite Elements Method
* Logan, 6th Edition, 2016
* ISBN-13: 978-1-305-63734-4
*/
Matrix<Real> rotationReference() {
return {{3. / 13, 4. / 13, 12. / 13},
{-4. / 5, 3. / 5, 0},
{-36. / 65, -48. / 65, 5. / 13}};
}
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
// debug::setDebugLevel(dblTest);
constexpr ElementType type = _bernoulli_beam_3;
- UInt dim = ElementClass<type>::getSpatialDimension();
+ Int dim = ElementClass<type>::getSpatialDimension();
Mesh mesh(dim);
// Pushing nodes
Vector<Real> node = {0, 0, 0};
mesh.getNodes().push_back(node);
node = {3, 4, 12};
mesh.getNodes().push_back(node);
// Pushing connectivity
mesh.addConnectivityType(type);
auto & connectivity = mesh.getConnectivity(type);
Vector<UInt> elem = {0, 1};
connectivity.push_back(elem);
// Pushing normals
auto & normals = mesh.registerElementalData<Real>("extra_normal")
.alloc(0, dim, type, _not_ghost);
Vector<Real> normal = {-36. / 65, -48. / 65, 5. / 13};
normals.push_back(normal);
normals.push_back(normal);
using FE = FEEngineTemplate<IntegratorGauss, ShapeStructural, _ek_structural>;
using ShapeStruct = ShapeStructural<_ek_structural>;
auto fem = std::make_unique<FE>(mesh, dim, "test_fem");
fem->initShapeFunctions();
auto & shape = dynamic_cast<const ShapeStruct &>(fem->getShapeFunctions());
Matrix<Real> rot_ref = rotationReference();
Matrix<Real> solution(6, 6);
solution.block(rot_ref, 0, 0);
solution.block(rot_ref, 3, 3);
for (auto && rot : make_view(shape.getRotations(type), 6, 6)) {
- if (!Math::are_vector_equal(6 * 6, solution.storage(), rot.storage()))
+ if (!Math::are_vector_equal(6 * 6, solution.data(), rot.data()))
return 1;
}
/// TODO check shape functions and shape derivatives
finalize();
return 0;
}
diff --git a/test/test_fe_engine/test_fe_engine_precomputation_structural.cc b/test/test_fe_engine/test_fe_engine_precomputation_structural.cc
index e3edfe698..9b7cbc646 100644
--- a/test/test_fe_engine/test_fe_engine_precomputation_structural.cc
+++ b/test/test_fe_engine/test_fe_engine_precomputation_structural.cc
@@ -1,127 +1,128 @@
/**
* @file test_fe_engine_precomputation_structural.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri Jan 26 2018
* @date last modification: Wed Sep 12 2018
*
* @brief test of the structural precomputations
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fe_engine.hh"
#include "integrator_gauss.hh"
#include "shape_structural.hh"
#include "test_fe_engine_structural_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
// Need a special fixture for the extra normal
class TestBernoulliB3
: public TestFEMStructuralFixture<element_type_t<_bernoulli_beam_3>> {
using parent = TestFEMStructuralFixture<element_type_t<_bernoulli_beam_3>>;
public:
/// Load the mesh and provide extra normal direction
void readMesh(std::string filename) override {
parent::readMesh(filename);
auto & normals = this->mesh->getElementalData<Real>("extra_normal")
.alloc(0, dim, type, _not_ghost);
Vector<Real> normal = {-36. / 65, -48. / 65, 5. / 13};
normals.push_back(normal);
}
};
/* -------------------------------------------------------------------------- */
/// Type alias
using TestBernoulliB2 =
TestFEMStructuralFixture<element_type_t<_bernoulli_beam_2>>;
using TestDKT18 =
TestFEMStructuralFixture<element_type_t<_discrete_kirchhoff_triangle_18>>;
/* -------------------------------------------------------------------------- */
/// Solution for 2D rotation matrices
-Matrix<Real> globalToLocalRotation(Real theta) {
+auto globalToLocalRotation(Real theta) {
auto c = std::cos(theta);
auto s = std::sin(theta);
- return {{c, s, 0}, {-s, c, 0}, {0, 0, 1}};
+ return Matrix<Real, 3, 3>{{c, s, 0}, {-s, c, 0}, {0, 0, 1}};
}
/* -------------------------------------------------------------------------- */
TEST_F(TestBernoulliB2, PrecomputeRotations) {
this->fem->initShapeFunctions();
using ShapeStruct = ShapeStructural<_ek_structural>;
auto & shape = dynamic_cast<const ShapeStruct &>(fem->getShapeFunctions());
auto & rot = shape.getRotations(type);
- Real a = std::atan(4. / 3);
- std::vector<Real> angles = {a, -a, 0};
+ Real a = std::atan(4. / 3.);
+ std::vector<Real> angles = {a, -a, 0.};
Math::setTolerance(1e-15);
for (auto && tuple : zip(make_view(rot, ndof, ndof), angles)) {
auto rotation = std::get<0>(tuple);
auto angle = std::get<1>(tuple);
- auto rotation_error = (rotation - globalToLocalRotation(angle)).norm<L_2>();
+ auto rotation_error = (rotation - globalToLocalRotation(angle)).norm();
EXPECT_NEAR(rotation_error, 0., Math::getTolerance());
}
}
/* -------------------------------------------------------------------------- */
TEST_F(TestBernoulliB3, PrecomputeRotations) {
this->fem->initShapeFunctions();
using ShapeStruct = ShapeStructural<_ek_structural>;
auto & shape = dynamic_cast<const ShapeStruct &>(fem->getShapeFunctions());
auto & rot = shape.getRotations(type);
- Matrix<Real> ref = {{3. / 13, 4. / 13, 12. / 13},
- {-4. / 5, 3. / 5, 0},
- {-36. / 65, -48. / 65, 5. / 13}};
+ Matrix<Real, 3, 3> ref{{3. / 13, 4. / 13, 12. / 13},
+ {-4. / 5, 3. / 5, 0},
+ {-36. / 65, -48. / 65, 5. / 13}};
Matrix<Real> solution{ndof, ndof};
- solution.block(ref, 0, 0);
- solution.block(ref, dim, dim);
+ solution.zero();
+ solution.block<3, 3>(0, 0) = ref;
+ solution.block<3, 3>(3, 3) = ref;
// The default tolerance is too much, really
Math::setTolerance(1e-15);
for (auto & rotation : make_view(rot, ndof, ndof)) {
- auto rotation_error = (rotation - solution).norm<L_2>();
+ auto rotation_error = (rotation - solution).norm();
EXPECT_NEAR(rotation_error, 0., Math::getTolerance());
}
}
/* -------------------------------------------------------------------------- */
TEST_F(TestDKT18, DISABLED_PrecomputeRotations) {
this->fem->initShapeFunctions();
using ShapeStruct = ShapeStructural<_ek_structural>;
auto & shape = dynamic_cast<const ShapeStruct &>(fem->getShapeFunctions());
auto & rot = shape.getRotations(type);
for (auto & rotation : make_view(rot, ndof, ndof)) {
std::cout << rotation << "\n";
}
std::cout.flush();
}
diff --git a/test/test_fe_engine/test_gradient.cc b/test/test_fe_engine/test_gradient.cc
index 98f746aa8..4242f9ecc 100644
--- a/test/test_fe_engine/test_gradient.cc
+++ b/test/test_fe_engine/test_gradient.cc
@@ -1,104 +1,104 @@
/**
* @file test_gradient.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Peter Spijker <peter.spijker@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Feb 19 2018
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
* @section DESCRIPTION
*
* This code is computing the gradient of a linear field and check that it gives
* a constant result. It also compute the gradient the coordinates of the mesh
* and check that it gives the identity
*
*/
/* -------------------------------------------------------------------------- */
#include "test_fe_engine_fixture.hh"
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
TYPED_TEST(TestFEMFixture, GradientPoly) {
this->fem->initShapeFunctions();
Real alpha[2][3] = {{13, 23, 31}, {11, 7, 5}};
const auto dim = this->dim;
const auto type = this->type;
const auto & position = this->fem->getMesh().getNodes();
Array<Real> const_val(this->fem->getMesh().getNbNodes(), 2, "const_val");
for (auto && pair : zip(make_view(position, dim), make_view(const_val, 2))) {
auto & pos = std::get<0>(pair);
auto & const_ = std::get<1>(pair);
const_.set(0.);
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
const_(0) += alpha[0][d] * pos(d);
const_(1) += alpha[1][d] * pos(d);
}
}
/// compute the gradient
Array<Real> grad_on_quad(this->nb_quadrature_points_total, 2 * dim,
"grad_on_quad");
this->fem->gradientOnIntegrationPoints(const_val, grad_on_quad, 2, type);
/// check the results
for (auto && grad : make_view(grad_on_quad, 2, dim)) {
- for (UInt d = 0; d < dim; ++d) {
+ for (Int d = 0; d < dim; ++d) {
EXPECT_NEAR(grad(0, d), alpha[0][d], 5e-13);
EXPECT_NEAR(grad(1, d), alpha[1][d], 5e-13);
}
}
}
TYPED_TEST(TestFEMFixture, GradientPositions) {
this->fem->initShapeFunctions();
- const auto dim = this->dim;
- const auto type = this->type;
+ const auto dim = TestFixture::dim;
+ const auto type = TestFixture::type;
UInt nb_quadrature_points =
this->fem->getNbIntegrationPoints(type) * this->nb_element;
Array<Real> grad_coord_on_quad(nb_quadrature_points, dim * dim,
"grad_coord_on_quad");
const auto & position = this->mesh->getNodes();
this->fem->gradientOnIntegrationPoints(position, grad_coord_on_quad, dim,
type);
- auto I = Matrix<Real>::eye(UInt(dim));
+ auto I = Matrix<Real, dim, dim>::Identity();
for (auto && grad : make_view(grad_coord_on_quad, dim, dim)) {
- auto diff = (I - grad).template norm<L_inf>();
+ auto diff = (I - grad).template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0., diff, 2e-14);
}
}
diff --git a/test/test_fe_engine/test_integrate.cc b/test/test_fe_engine/test_integrate.cc
index c2b506c12..c15283765 100644
--- a/test/test_fe_engine/test_integrate.cc
+++ b/test/test_fe_engine/test_integrate.cc
@@ -1,74 +1,74 @@
/**
* @file test_integrate.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Peter Spijker <peter.spijker@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Feb 19 2018
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_fe_engine_fixture.hh"
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
TYPED_TEST(TestFEMFixture, IntegrateConstant) {
this->fem->initShapeFunctions();
const auto type = this->type;
const auto & position = this->fem->getMesh().getNodes();
Array<Real> const_val(position.size(), 2, "const_val");
Array<Real> val_on_quad(this->nb_quadrature_points_total, 2, "val_on_quad");
Vector<Real> value{1, 2};
for (auto && const_ : make_view(const_val, 2)) {
const_ = value;
}
// interpolate function on quadrature points
this->fem->interpolateOnIntegrationPoints(const_val, val_on_quad, 2, type);
// integrate function on elements
Array<Real> int_val_on_elem(this->nb_element, 2, "int_val_on_elem");
this->fem->integrate(val_on_quad, int_val_on_elem, 2, type);
// get global integration value
Vector<Real> sum{0., 0.};
for (auto && int_ : make_view(int_val_on_elem, 2)) {
sum += int_;
}
- auto diff = (value - sum).template norm<L_inf>();
+ auto diff = (value - sum).lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0, diff, 1e-14);
}
diff --git a/test/test_fe_engine/test_interpolate.cc b/test/test_fe_engine/test_interpolate.cc
index 18bf77992..0e09022a9 100644
--- a/test/test_fe_engine/test_interpolate.cc
+++ b/test/test_fe_engine/test_interpolate.cc
@@ -1,73 +1,73 @@
/**
* @file test_interpolate.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Nov 14 2017
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_fe_engine_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace {
TYPED_TEST(TestFEMFixture, InterpolateConstant) {
const auto type = this->type;
const auto & position = this->fem->getMesh().getNodes();
Array<Real> const_val(position.size(), 2, "const_val");
Array<Real> val_on_quad(this->nb_quadrature_points_total, 2, "val_on_quad");
Vector<Real> value{1, 2};
for (auto && const_ : make_view(const_val, 2)) {
const_ = value;
}
// interpolate function on quadrature points
this->fem->interpolateOnIntegrationPoints(const_val, val_on_quad, 2, type);
for (auto && int_ : make_view(val_on_quad, 2)) {
- auto diff = (value - int_).template norm<L_inf>();
+ auto diff = (value - int_).template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0, diff, 1e-14);
}
}
// TYPED_TEST(TestFEMFixture, InterpolatePosition) {
// const auto dim = this->dim;
// const auto type = this->type;
// const auto & position = this->fem->getMesh().getNodes();
// Array<Real> coord_on_quad(this->nb_quadrature_points_total, dim,
// "coord_on_quad");
// this->fem->interpolateOnIntegrationPoints(position, coord_on_quad, dim,
// type);
// }
} // namespace
diff --git a/test/test_fe_engine/test_interpolate_bernoulli_beam_2.cc b/test/test_fe_engine/test_interpolate_bernoulli_beam_2.cc
index 9388b3d4a..81bc24166 100644
--- a/test/test_fe_engine/test_interpolate_bernoulli_beam_2.cc
+++ b/test/test_fe_engine/test_interpolate_bernoulli_beam_2.cc
@@ -1,119 +1,119 @@
/**
* @file test_interpolate_bernoulli_beam_2.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Sat Jan 23 2016
*
* @brief Test of the interpolation on the type _bernoulli_beam_2
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <fstream>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "fe_engine.hh"
#include "fe_engine_template.hh"
#include "integrator_gauss.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_io_msh.hh"
#include "shape_linked.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main() {
Mesh beams(2);
/* --------------------------------------------------------------------------
*/
// Defining the mesh
Array<Real> & nodes = const_cast<Array<Real> &>(beams.getNodes());
nodes.resize(4);
beams.addConnectivityType(_bernoulli_beam_2);
Array<UInt> & connectivity =
const_cast<Array<UInt> &>(beams.getConnectivity(_bernoulli_beam_2));
connectivity.resize(3);
- for (UInt i = 0; i < 4; ++i) {
+ for (Int i = 0; i < 4; ++i) {
nodes(i, 0) = (i + 1) * 2;
nodes(i, 1) = 1;
}
- for (UInt i = 0; i < 3; ++i) {
+ for (Int i = 0; i < 3; ++i) {
connectivity(i, 0) = i;
connectivity(i, 1) = i + 1;
}
akantu::MeshIOMSH mesh_io;
mesh_io.write("b_beam_2.msh", beams);
/* --------------------------------------------------------------------------
*/
// Interpolation
FEEngineTemplate<IntegratorGauss, ShapeLinked> * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLinked>(beams, 2);
fem->initShapeFunctions();
Array<Real> displ_on_nodes(4, 3);
Array<Real> displ_on_quad(0, 3);
- for (UInt i = 0; i < 4; ++i) {
+ for (Int i = 0; i < 4; ++i) {
displ_on_nodes(i, 0) = (i + 1) * 2; // Definition of the displacement
displ_on_nodes(i, 1) = 0;
displ_on_nodes(i, 2) = 0;
}
fem->getShapeFunctions().interpolateOnControlPoints<_bernoulli_beam_2>(
displ_on_nodes, displ_on_quad, 3, _not_ghost, NULL, false, 0, 0, 0);
fem->getShapeFunctions().interpolateOnControlPoints<_bernoulli_beam_2>(
displ_on_nodes, displ_on_quad, 3, _not_ghost, NULL, false, 1, 1, 1);
fem->getShapeFunctions().interpolateOnControlPoints<_bernoulli_beam_2>(
displ_on_nodes, displ_on_quad, 3, _not_ghost, NULL, true, 2, 2, 1);
fem->getShapeFunctions().interpolateOnControlPoints<_bernoulli_beam_2>(
displ_on_nodes, displ_on_quad, 3, _not_ghost, NULL, false, 3, 2, 3);
fem->getShapeFunctions().interpolateOnControlPoints<_bernoulli_beam_2>(
displ_on_nodes, displ_on_quad, 3, _not_ghost, NULL, true, 4, 3, 3);
- Real * don = displ_on_nodes.storage();
- Real * doq = displ_on_quad.storage();
+ Real * don = displ_on_nodes.data();
+ Real * doq = displ_on_quad.data();
std::ofstream my_file("out.txt");
my_file << don << std::endl;
my_file << doq << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_fe_engine/test_inverse_map.cc b/test/test_fe_engine/test_inverse_map.cc
index bf1f42a6a..891e63559 100644
--- a/test/test_fe_engine/test_inverse_map.cc
+++ b/test/test_fe_engine/test_inverse_map.cc
@@ -1,71 +1,71 @@
/**
* @file test_inverse_map.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Mar 13 2018
*
* @brief test of the fem class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_fe_engine_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
TYPED_TEST(TestFEMFixture, InverseMap) {
this->fem->initShapeFunctions();
Matrix<Real> quad =
GaussIntegrationElement<TestFixture::type>::getQuadraturePoints();
const auto & position = this->fem->getMesh().getNodes();
/// get the quadrature points coordinates
Array<Real> coord_on_quad(quad.cols() * this->nb_element, this->dim,
"coord_on_quad");
this->fem->interpolateOnIntegrationPoints(position, coord_on_quad, this->dim,
this->type);
Vector<Real> natural_coords(this->dim);
- auto length = (this->upper - this->lower).template norm<L_inf>();
+ auto length = (this->upper - this->lower).template lpNorm<Eigen::Infinity>();
for (auto && enum_ :
enumerate(make_view(coord_on_quad, this->dim, quad.cols()))) {
auto el = std::get<0>(enum_);
const auto & quads_coords = std::get<1>(enum_);
for (auto q : arange(quad.cols())) {
Vector<Real> quad_coord = quads_coords(q);
Vector<Real> ref_quad_coord = quad(q);
this->fem->inverseMap(quad_coord, el, this->type, natural_coords);
auto dis_normalized = ref_quad_coord.distance(natural_coords) / length;
EXPECT_NEAR(0., dis_normalized, 3.5e-11);
}
}
}
diff --git a/test/test_fe_engine/test_mesh_data.cc b/test/test_fe_engine/test_mesh_data.cc
index 15cbeccbc..725db1484 100644
--- a/test/test_fe_engine/test_mesh_data.cc
+++ b/test/test_fe_engine/test_mesh_data.cc
@@ -1,87 +1,87 @@
/**
* @file test_mesh_data.cc
*
* @author Dana Christen <dana.christen@gmail.com>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Jul 13 2015
*
* @brief Test of the MeshData class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
#include <string>
#define QUOTES(x) #x
#define ADD_QUOTES(x) QUOTES(x)
#define CAT(x, y) x##_##y
#define CONCAT(x, y) CAT(x, y)
//#define TYPE std::string
//#define VALUE1 "abc"
//#define VALUE2 "qwe"
#define ELEMENT _triangle_6
#define NAME CONCAT(TYPE, data)
/* -------------------------------------------------------------------------- */
using namespace akantu;
using namespace std;
int main() {
std::cout << "Testing with type " << ADD_QUOTES(TYPE) << " and values "
<< ADD_QUOTES(VALUE1) << "," << ADD_QUOTES(VALUE2) << "..."
<< std::endl;
MeshData mesh_data;
ElementType elem_type = ELEMENT;
const std::string name = ADD_QUOTES(NAME);
Array<TYPE> & vec =
mesh_data.getElementalDataArrayAlloc<TYPE>(name, elem_type);
// XXX TO DELETE
// vec.copy(mesh_data.getElementalDataArrayAlloc<TYPE>(name, elem_type));
TYPE value[2] = {VALUE1, VALUE2};
vec.push_back(value[0]);
vec.push_back(value[1]);
- for (UInt i(0); i < 2; i++) {
+ for (Int i(0); i < 2; i++) {
AKANTU_DEBUG_ASSERT(vec(i) == value[i], "The Array accessed through the "
"getElementDataArray method does "
"not contain the right value.");
}
std::cout << vec << std::endl;
std::cout << mesh_data.getTypeCode(name) << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_geometry/test_segment_intersection_tetrahedron_4.cc b/test/test_geometry/test_segment_intersection_tetrahedron_4.cc
index 185aae1cb..ea82557c3 100644
--- a/test/test_geometry/test_segment_intersection_tetrahedron_4.cc
+++ b/test/test_geometry/test_segment_intersection_tetrahedron_4.cc
@@ -1,144 +1,144 @@
/**
* @file test_segment_intersection_tetrahedron_4.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Fri Feb 27 2015
* @date last modification: Tue Mar 13 2018
*
* @brief Tests the intersection module with _tetrahedron_4 elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "mesh_segment_intersector.hh"
#include "mesh_geom_common.hh"
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
typedef cgal::Cartesian K;
typedef K::Point_3 Point;
typedef K::Segment_3 Segment;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("", argc, argv);
debug::setDebugLevel(dblError);
Mesh mesh(3), interface_mesh(3, "interface_mesh");
mesh.read("test_geometry_tetrahedron.msh");
MeshSegmentIntersector<3, _tetrahedron_4> intersector(mesh, interface_mesh);
intersector.constructData();
// Testing a segment going through the cube
Point point(1., 1., 1.);
Segment segment(CGAL::ORIGIN, point);
intersector.computeIntersectionQuery(segment);
std::cout << "number of seg_2 : " << interface_mesh.getNbElement(_segment_2)
<< std::endl;
if (interface_mesh.getNbElement(_segment_2) != 2)
return EXIT_FAILURE;
Vector<Real> bary(2), bary1(2), bary2(2);
Element test{_segment_2, 0, _not_ghost};
interface_mesh.getBarycenter(test, bary1);
test.element = 1;
interface_mesh.getBarycenter(test, bary2);
Real first_bary[] = {1. / 6., 1. / 6., 1. / 6.};
Real second_bary[] = {2. / 3., 2. / 3., 2. / 3.};
// We don't know the order of the elements, so here we test permutations
- if (!((Math::are_vector_equal(3, bary1.storage(), first_bary) &&
- Math::are_vector_equal(3, bary2.storage(), second_bary)) ||
- (Math::are_vector_equal(3, bary1.storage(), second_bary) &&
- Math::are_vector_equal(3, bary2.storage(), first_bary))))
+ if (!((Math::are_vector_equal(3, bary1.data(), first_bary) &&
+ Math::are_vector_equal(3, bary2.data(), second_bary)) ||
+ (Math::are_vector_equal(3, bary1.data(), second_bary) &&
+ Math::are_vector_equal(3, bary2.data(), first_bary))))
return EXIT_FAILURE;
// Testing a segment completely inside one element
Point a(0.05, 0.05, 0.05), b(0.06, 0.06, 0.06);
Segment inside_segment(a, b);
intersector.computeIntersectionQuery(inside_segment);
test.element = interface_mesh.getNbElement(_segment_2) - 1;
interface_mesh.getBarycenter(test, bary);
Real third_bary[] = {0.055, 0.055, 0.055};
- if (!Math::are_vector_equal(3, bary.storage(), third_bary))
+ if (!Math::are_vector_equal(3, bary.data(), third_bary))
return EXIT_FAILURE;
// Testing a segment whose end points are inside elements
Point c(0.1, 0.1, 0.1), d(0.9, 0.9, 0.9);
Segment crossing_segment(c, d);
intersector.computeIntersectionQuery(crossing_segment);
- UInt el1 = interface_mesh.getNbElement(_segment_2) - 2;
- UInt el2 = el1 + 1;
+ auto el1 = interface_mesh.getNbElement(_segment_2) - 2;
+ auto el2 = el1 + 1;
test.element = el1;
interface_mesh.getBarycenter(test, bary1);
test.element = el2;
interface_mesh.getBarycenter(test, bary2);
Real fourth_bary[] = {13. / 60., 13. / 60., 13. / 60.};
Real fifth_bary[] = {37. / 60., 37. / 60., 37. / 60.};
// We don't know the order of the elements, so here we test permutations
- if (!((Math::are_vector_equal(3, bary1.storage(), fourth_bary) &&
- Math::are_vector_equal(3, bary2.storage(), fifth_bary)) ||
- (Math::are_vector_equal(3, bary1.storage(), fifth_bary) &&
- Math::are_vector_equal(3, bary2.storage(), fourth_bary))))
+ if (!((Math::are_vector_equal(3, bary1.data(), fourth_bary) &&
+ Math::are_vector_equal(3, bary2.data(), fifth_bary)) ||
+ (Math::are_vector_equal(3, bary1.data(), fifth_bary) &&
+ Math::are_vector_equal(3, bary2.data(), fourth_bary))))
return EXIT_FAILURE;
// Testing a segment along the edge of elements
Point e(1, 0, 0), f(0, 1, 0);
Segment edge_segment(e, f);
- UInt current_nb_elements = interface_mesh.getNbElement(_segment_2);
+ auto current_nb_elements = interface_mesh.getNbElement(_segment_2);
intersector.computeIntersectionQuery(edge_segment);
if (interface_mesh.getNbElement(_segment_2) != current_nb_elements + 1)
return EXIT_FAILURE;
test.element = interface_mesh.getNbElement(_segment_2) - 1;
interface_mesh.getBarycenter(test, bary);
Real sixth_bary[] = {0.5, 0.5, 0};
- if (!Math::are_vector_equal(3, bary.storage(), sixth_bary))
+ if (!Math::are_vector_equal(3, bary.data(), sixth_bary))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
diff --git a/test/test_geometry/test_segment_intersection_triangle_3.cc b/test/test_geometry/test_segment_intersection_triangle_3.cc
index 08266bc2e..135a27a6d 100644
--- a/test/test_geometry/test_segment_intersection_triangle_3.cc
+++ b/test/test_geometry/test_segment_intersection_triangle_3.cc
@@ -1,137 +1,137 @@
/**
* @file test_segment_intersection_triangle_3.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
*
* @date creation: Fri Feb 27 2015
* @date last modification: Tue Mar 13 2018
*
* @brief Tests the interface mesh generation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "geom_helper_functions.hh"
#include "mesh_geom_common.hh"
#include "mesh_segment_intersector.hh"
#include "mesh_sphere_intersector.hh"
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
typedef cgal::Cartesian K;
typedef cgal::Spherical SK;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("", argc, argv);
debug::setDebugLevel(dblError);
Math::setTolerance(1e-10);
Mesh mesh(2), interface_mesh(2, "interface_mesh");
mesh.read("test_geometry_triangle.msh");
MeshSegmentIntersector<2, _triangle_3> intersector(mesh, interface_mesh);
intersector.constructData();
// Testing a segment going out of the mesh
K::Point_3 a(0, 0.25, 0), b(1, 0.25, 0), c(0.25, 0, 0), d(0.25, 1, 0);
K::Segment_3 h_interface(a, b), v_interface(c, d);
std::list<K::Segment_3> interface_list;
interface_list.push_back(h_interface);
interface_list.push_back(v_interface);
intersector.computeIntersectionQueryList(interface_list);
if (interface_mesh.getNbElement(_segment_2) != 4)
return EXIT_FAILURE;
Vector<Real> bary(2);
Element test{_segment_2, 0, _not_ghost};
interface_mesh.getBarycenter(test, bary);
Real first_bary[] = {0.125, 0.25};
- if (!Math::are_vector_equal(2, bary.storage(), first_bary))
+ if (!Math::are_vector_equal(2, bary.data(), first_bary))
return EXIT_FAILURE;
// Testing a segment completely inside an element
K::Point_3 e(0.1, 0.33, 0), f(0.1, 0.67, 0);
K::Segment_3 inside_segment(e, f);
intersector.computeIntersectionQuery(inside_segment);
test.element = interface_mesh.getNbElement(_segment_2) - 1;
interface_mesh.getBarycenter(test, bary);
Real second_bary[] = {0.1, 0.5};
- if (!Math::are_vector_equal(2, bary.storage(), second_bary))
+ if (!Math::are_vector_equal(2, bary.data(), second_bary))
return EXIT_FAILURE;
#if 0
// cgal::Spherical kernel testing the addition of nodes
std::cout << "initial mesh size = " << mesh.getNodes().size() << " nodes" << std::endl;
SK::Sphere_3 sphere(SK::Point_3(0, 1, 0), 0.2*0.2);
SK::Sphere_3 sphere2(SK::Point_3(1, 0, 0), 0.4999999999);
MeshSphereIntersector<2, _triangle_3> intersector_sphere(mesh);
intersector_sphere.constructData();
std::list<SK::Sphere_3> sphere_list;
sphere_list.push_back(sphere);
sphere_list.push_back(sphere2);
intersector_sphere.computeIntersectionQueryList(sphere_list);
std::cout << "final mesh size = " << mesh.getNodes().size() << std::endl;
- const Array<UInt> new_node_triangle_3 = intersector_sphere.getNewNodePerElem();
+ const Array<Idx> new_node_triangle_3 = intersector_sphere.getNewNodePerElem();
const Array<Real> & nodes = mesh.getNodes();
std::cout << "New nodes :" << std::endl;
std::cout << "node 5, x=" << nodes(4,0) << ", y=" << nodes(4,1) << std::endl;
std::cout << "node 6, x=" << nodes(5,0) << ", y=" << nodes(5,1) << std::endl;
std::cout << "node 7, x=" << nodes(6,0) << ", y=" << nodes(6,1) << std::endl;
if ( (new_node_triangle_3(0,0) != 1) || (new_node_triangle_3(1,0) != 2)){
- for(UInt k=0; k != new_node_triangle_3.size(); ++k){
+ for(Int k=0; k != new_node_triangle_3.size(); ++k){
std::cout << new_node_triangle_3(k,0) << " new nodes in element " << k << ", node(s): "
<< new_node_triangle_3(k,1) << ", " << new_node_triangle_3(k,3)
<< ", on segment(s):" << new_node_triangle_3(k,2) << ", "
<< new_node_triangle_3(k,4) << std::endl;
}
return EXIT_FAILURE;
}
#endif
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_gtest_utils.hh b/test/test_gtest_utils.hh
index e98e8c6c8..72cde6047 100644
--- a/test/test_gtest_utils.hh
+++ b/test/test_gtest_utils.hh
@@ -1,259 +1,245 @@
/**
* @file test_gtest_utils.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Nov 14 2017
* @date last modification: Fri Jan 10 2020
*
* @brief Utils to help write tests
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_iterators.hh"
/* -------------------------------------------------------------------------- */
#include <boost/preprocessor.hpp>
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TEST_GTEST_UTILS_HH_
#define AKANTU_TEST_GTEST_UTILS_HH_
#if !defined(TYPED_TEST_SUITE)
#define TYPED_TEST_SUITE(...) TYPED_TEST_CASE(__VA_ARGS__)
#endif
#if !defined(TYPED_TEST_SUITE_P)
#define TYPED_TEST_SUITE_P(...) TYPED_TEST_CASE_P(__VA_ARGS__)
#endif
#if !defined(REGISTER_TYPED_TEST_SUITE_P)
#define REGISTER_TYPED_TEST_SUITE_P(...) REGISTER_TYPED_TEST_CASE_P(__VA_ARGS__)
#endif
#if !defined(INSTANTIATE_TYPED_TEST_SUITE_P)
#define INSTANTIATE_TYPED_TEST_SUITE_P(...) \
INSTANTIATE_TYPED_TEST_CASE_P(__VA_ARGS__)
#endif
namespace {
-/* -------------------------------------------------------------------------- */
-template <::akantu::ElementType t>
-using element_type_t = std::integral_constant<::akantu::ElementType, t>;
-
/* -------------------------------------------------------------------------- */
template <typename... T> struct gtest_list {};
template <typename... Ts> struct gtest_list<std::tuple<Ts...>> {
using type = ::testing::Types<Ts...>;
};
template <typename... T> using gtest_list_t = typename gtest_list<T...>::type;
/* -------------------------------------------------------------------------- */
// template <typename... T> struct tuple_concat {};
template <typename... Ts> struct tuple_concat {
using type = decltype(std::tuple_cat(std::declval<Ts>()...));
};
template <typename... T>
using tuple_concat_t = typename tuple_concat<T...>::type;
/* -------------------------------------------------------------------------- */
template <template <typename> class Pred, typename... Ts>
struct tuple_filter {};
template <template <typename> class Pred, typename T>
struct tuple_filter<Pred, std::tuple<T>> {
using type = std::conditional_t<Pred<T>::value, std::tuple<T>, std::tuple<>>;
};
template <template <typename> class Pred, typename T, typename... Ts>
struct tuple_filter<Pred, std::tuple<T, Ts...>> {
using type =
tuple_concat_t<typename tuple_filter<Pred, std::tuple<T>>::type,
typename tuple_filter<Pred, std::tuple<Ts...>>::type>;
};
template <template <typename> class Pred, typename... Ts>
using tuple_filter_t = typename tuple_filter<Pred, Ts...>::type;
/* -------------------------------------------------------------------------- */
template <size_t N, typename... Ts> struct tuple_split {};
template <size_t N, typename T, typename... Ts>
struct tuple_split<N, std::tuple<T, Ts...>> {
protected:
using split = tuple_split<N - 1, std::tuple<Ts...>>;
public:
- using type = tuple_concat_t<std::tuple<T>, typename split::type>;
+ using type = akantu::tuple::cat_t<std::tuple<T>, typename split::type>;
using type_tail = typename split::type_tail;
};
template <typename T, typename... Ts>
struct tuple_split<1, std::tuple<T, Ts...>> {
using type = std::tuple<T>;
using type_tail = std::tuple<Ts...>;
};
template <size_t N, typename... T>
using tuple_split_t = typename tuple_split<N, T...>::type;
template <size_t N, typename... T>
using tuple_split_tail_t = typename tuple_split<N, T...>::type_tail;
/* -------------------------------------------------------------------------- */
template <typename... T> struct cross_product {};
template <typename... T2s>
struct cross_product<std::tuple<>, std::tuple<T2s...>> {
using type = std::tuple<>;
};
template <typename T1, typename... T1s, typename... T2s>
struct cross_product<std::tuple<T1, T1s...>, std::tuple<T2s...>> {
- using type = tuple_concat_t<
+ using type = akantu::tuple::cat_t<
std::tuple<std::tuple<T1, T2s>...>,
typename cross_product<std::tuple<T1s...>, std::tuple<T2s...>>::type>;
};
template <typename... T>
using cross_product_t = typename cross_product<T...>::type;
/* -------------------------------------------------------------------------- */
} // namespace
#define OP_CAT(s, data, elem) BOOST_PP_CAT(_element_type, elem)
-// creating a type instead of a using helps to debug
-#define AKANTU_DECLARE_ELEMENT_TYPE_STRUCT(r, data, elem) \
- struct BOOST_PP_CAT(_element_type, elem) \
- : public element_type_t<::akantu::elem> {};
-
-BOOST_PP_SEQ_FOR_EACH(AKANTU_DECLARE_ELEMENT_TYPE_STRUCT, _,
- AKANTU_ALL_ELEMENT_TYPE)
-
-#undef AKANTU_DECLARE_ELEMENT_TYPE_STRUCT
-
-using TestElementTypesAll = std::tuple<BOOST_PP_SEQ_ENUM(
- BOOST_PP_SEQ_TRANSFORM(OP_CAT, _, AKANTU_ek_regular_ELEMENT_TYPE))>;
+using TestElementTypesAll = akantu::ElementTypes_t<akantu::_ek_regular>;
#if defined(AKANTU_COHESIVE_ELEMENT)
-using TestCohesiveElementTypes = std::tuple<BOOST_PP_SEQ_ENUM(
- BOOST_PP_SEQ_TRANSFORM(OP_CAT, _, AKANTU_ek_cohesive_ELEMENT_TYPE))>;
+using TestCohesiveElementTypes = akantu::ElementTypes_t<akantu::_ek_cohesive>;
#endif
#if defined(AKANTU_STRUCTURAL_MECHANICS)
-using TestElementTypesStructural = std::tuple<BOOST_PP_SEQ_ENUM(
- BOOST_PP_SEQ_TRANSFORM(OP_CAT, _, AKANTU_ek_structural_ELEMENT_TYPE))>;
+using TestElementTypesStructural =
+ akantu::ElementTypes_t<akantu::_ek_structural>;
+
#endif
using TestAllDimensions = std::tuple<std::integral_constant<unsigned int, 1>,
std::integral_constant<unsigned int, 2>,
std::integral_constant<unsigned int, 3>>;
template <typename T, ::akantu::ElementType type>
using is_element = aka::bool_constant<T::value == type>;
template <typename T>
using not_is_point_1 = aka::negation<is_element<T, ::akantu::_point_1>>;
-using TestElementTypes = tuple_filter_t<not_is_point_1, TestElementTypesAll>;
+using TestElementTypes =
+ akantu::tuple::filter_t<not_is_point_1, TestElementTypesAll>;
#if defined(AKANTU_STRUCTURAL_MECHANICS)
using StructuralTestElementTypes =
- tuple_filter_t<not_is_point_1, TestElementTypesStructural>;
+ akantu::tuple::filter_t<not_is_point_1, TestElementTypesStructural>;
#endif
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <size_t degree> class Polynomial {
public:
Polynomial() = default;
- Polynomial(std::initializer_list<double> && init) {
- for (auto && pair : akantu::zip(init, constants))
+ Polynomial(std::initializer_list<double> &&init) {
+ for (auto &&pair : akantu::zip(init, constants))
std::get<1>(pair) = std::get<0>(pair);
}
double operator()(double x) {
double res = 0.;
- for (auto && vals : akantu::enumerate(constants)) {
+ for (auto &&vals : akantu::enumerate(constants)) {
double a;
int k;
std::tie(k, a) = vals;
res += a * std::pow(x, k);
}
return res;
}
Polynomial extract(size_t pdegree) {
Polynomial<degree> extract(*this);
for (size_t d = pdegree + 1; d < degree + 1; ++d)
extract.constants[d] = 0;
return extract;
}
auto integral() {
Polynomial<degree + 1> integral_;
integral_.set(0, 0.);
;
for (size_t d = 0; d < degree + 1; ++d) {
integral_.set(1 + d, get(d) / double(d + 1));
}
return integral_;
}
auto integrate(double a, double b) {
auto primitive = integral();
return (primitive(b) - primitive(a));
}
double get(int i) const { return constants[i]; }
void set(int i, double a) { constants[i] = a; }
protected:
std::array<double, degree + 1> constants;
};
template <size_t degree>
-std::ostream & operator<<(std::ostream & stream, const Polynomial<degree> & p) {
+std::ostream &operator<<(std::ostream &stream, const Polynomial<degree> &p) {
for (size_t d = 0; d < degree + 1; ++d) {
if (d != 0)
stream << " + ";
stream << p.get(degree - d);
if (d != degree)
stream << "x ^ " << degree - d;
}
return stream;
}
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_TEST_GTEST_UTILS_HH_ */
diff --git a/test/test_io/test_dumper/test_dumper.cc b/test/test_io/test_dumper/test_dumper.cc
index 77c453dcb..c588b510d 100644
--- a/test/test_io/test_dumper/test_dumper.cc
+++ b/test/test_io/test_dumper/test_dumper.cc
@@ -1,162 +1,167 @@
/**
* @file test_dumper.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue May 21 2019
*
* @brief test dumper
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "dumpable.hh"
#include "dumper_iohelper_paraview.hh"
#include "dumper_nodal_field.hh"
#include "dumper_text.hh"
#include "dumper_variable.hh"
+
+#include "dumpable_inline_impl.hh"
#include "solid_mechanics_model.hh"
+
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("input_file.dat", argc, argv);
- UInt spatial_dimension = 3;
+ Int spatial_dimension = 3;
Mesh mesh(spatial_dimension);
mesh.read("test_dumper.msh");
SolidMechanicsModel model(mesh);
auto && mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
model.initFull();
model.assembleInternalForces();
Real time_step = 0.1;
const Array<Real> & coord = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & bound = model.getBlockedDOFs();
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
Real dist = 0.;
- for (UInt d = 0; d < spatial_dimension; ++d) {
+ for (Int d = 0; d < spatial_dimension; ++d) {
dist += coord(n, d) * coord(n, d);
}
dist = sqrt(dist);
- for (UInt d = 0; d < spatial_dimension; ++d) {
+ for (Int d = 0; d < spatial_dimension; ++d) {
disp(n, d) = (d + 1) * dist;
bound(n, d) = bool((n % 2) + d);
}
}
// dump boundary bottom as reference
model.setGroupDirectory("paraview", "Bottom");
model.setGroupBaseName("paraview_bottom", "Bottom");
model.addDumpGroupField("displacement", "Bottom");
model.addDumpGroupField("blocked_dofs", "Bottom");
- UInt nbp = 3;
+ Int nbp = 3;
DumperParaview prvdumper("paraview_bottom_parallel", "paraview", false);
iohelper::Dumper & prvdpr = prvdumper.getDumper();
- for (UInt p = 0; p < nbp; ++p) {
+ for (Int p = 0; p < nbp; ++p) {
prvdpr.setParallelContext(p, nbp, 0);
if (p != 0) {
prvdumper.unRegisterField("connectivities");
prvdumper.unRegisterField("element_type");
prvdumper.unRegisterField("positions");
prvdumper.unRegisterField("displacement");
}
prvdumper.registerFilteredMesh(
mesh, mesh.getElementGroup("Bottom").getElements(),
mesh.getElementGroup("Bottom").getNodeGroup().getNodes());
prvdumper.registerField(
"displacement",
std::make_shared<dumpers::NodalField<Real, true>>(
model.getDisplacement(), 0, 0,
&(mesh.getElementGroup("Bottom").getNodeGroup().getNodes())));
prvdumper.dump(0);
}
DumperText txtdumper("text_bottom", iohelper::_tdm_csv);
txtdumper.setDirectory("paraview");
txtdumper.setPrecision(8);
txtdumper.setTimeStep(time_step);
txtdumper.registerFilteredMesh(
mesh, mesh.getElementGroup("Bottom").getElements(),
mesh.getElementGroup("Bottom").getNodeGroup().getNodes());
txtdumper.registerField(
"displacement",
std::make_shared<dumpers::NodalField<Real, true>>(
model.getDisplacement(), 0, 0,
&(mesh.getElementGroup("Bottom").getNodeGroup().getNodes())));
txtdumper.registerField(
"blocked_dofs",
std::make_shared<dumpers::NodalField<bool, true>>(
model.getBlockedDOFs(), 0, 0,
&(mesh.getElementGroup("Bottom").getNodeGroup().getNodes())));
Real pot_energy = 1.2345567891;
- Vector<Real> gforces(2, 1.);
+ Vector<Real> gforces(2);
+ gforces.fill(1.);
txtdumper.registerVariable(
"potential_energy",
std::make_shared<dumpers::Variable<Real>>(pot_energy));
txtdumper.registerVariable(
"global_forces",
std::make_shared<dumpers::Variable<Vector<Real>>>(gforces));
// dump a first time before the main loop
model.dumpGroup("Bottom");
txtdumper.dump();
Real time = 0.;
- for (UInt i = 1; i < 5; ++i) {
+ for (Int i = 1; i < 5; ++i) {
pot_energy += 2.;
gforces(0) += 0.1;
gforces(1) += 0.2;
// pre -> cor
// increment time after all steps of integration
time += time_step;
// dump after time increment
if (i % 2 == 0) {
txtdumper.dump(time, i);
model.dumpGroup("Bottom");
// parallel test
- for (UInt p = 0; p < nbp; ++p) {
+ for (Int p = 0; p < nbp; ++p) {
prvdpr.setParallelContext(p, nbp, 0);
prvdumper.dump(i);
}
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_io/test_parser/test_parser.cc b/test/test_io/test_parser/test_parser.cc
index 87f03b77f..4e1851194 100644
--- a/test/test_io/test_parser/test_parser.cc
+++ b/test/test_io/test_parser/test_parser.cc
@@ -1,76 +1,76 @@
/**
* @file test_parser.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Sun Jul 09 2017
*
* @brief test the input file parser
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_random_generator.hh"
#include "parser.hh"
#include <iostream>
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("input_file.dat", argc, argv);
const Parser & p = getStaticParser();
- std::cout << RandomGenerator<UInt>::seed() << "==123456" << std::endl;
+ std::cout << RandomGenerator<Int>::seed() << "==123456" << std::endl;
std::cout << p << std::endl;
Real toto = p.getParameter("toto");
std::cout << toto;
Real ref = 2 * M_PI + std::max(2., 50.);
if (std::abs(toto - ref) > std::numeric_limits<Real>::epsilon()) {
std::cout << "!=" << ref << std::endl;
return 1;
}
std::cout << "==" << ref << std::endl;
Vector<Real> vect = p.getParameter("vect");
- std::cout << vect << std::endl;
+ std::cout << vect.transpose() << std::endl;
Matrix<Real> mat = p.getParameter("mat");
std::cout << mat << std::endl;
RandomParameter<Real> rand1 = p.getParameter("rand1");
std::cout << rand1 << std::endl;
RandomParameter<Real> rand2 = p.getParameter("rand2");
std::cout << rand2 << std::endl;
RandomParameter<Real> rand3 = p.getParameter("rand3");
std::cout << rand3 << std::endl;
finalize();
return 0;
}
diff --git a/test/test_io/test_parser/test_parser.verified b/test/test_io/test_parser/test_parser.verified
index dfaeb2086..831a6dca6 100644
--- a/test/test_io/test_parser/test_parser.verified
+++ b/test/test_io/test_parser/test_parser.verified
@@ -1,44 +1,44 @@
123456==123456
Section(global) global [
Parameters [
+ debug_level: 1 (input_file.dat:2:1)
+ general: 50 (input_file.dat:22:1)
+ mat: [[ 1, 23+2, 5, toto ],[ 0, 10, general, 5+8] ] (input_file.dat:27:1)
+ rand1: 10 uniform [0.2, 0.5 ] (input_file.dat:30:1)
+ rand2: 10 weibull [0.2, 0.5 ] (input_file.dat:31:1)
+ rand3: 10 (input_file.dat:32:1)
+ seed: 123456 (input_file.dat:1:1)
+ toto: 2*pi + max(2, general) (input_file.dat:24:1)
+ vect: [ 1, 23+2, 5, toto ] (input_file.dat:26:1)
]
Subsections [
Section(material) elastic opt1 [
Parameters [
+ E: 1 (input_file.dat:5:9)
+ X135: 1 + 3* debug_level (input_file.dat:6:9)
+ a: c (input_file.dat:11:9)
+ name: toto (input_file.dat:4:9)
+ yop: yop (input_file.dat:9:9)
]
Subsections [
Section(rules) material [
Parameters [
+ E: 1 (input_file.dat:15:17)
+ X135: 1 + 1 (input_file.dat:16:17)
+ name: toto (input_file.dat:14:17)
+ yop: yop (input_file.dat:18:17)
]
]
]
]
]
]
56.2832==56.2832
-[1, 25, 5, 56.2832]
+[[1, 25, 5, 56.2832]]
[[1, 25, 5, 56.2832], [0, 10, 50, 13]]
10 + uniform [ 2.00000000000000011e-01 5.00000000000000000e-01 ]
10 + weibull [ 5.00000000000000000e-01 2.00000000000000011e-01 ]
10 + uniform [ 0.00000000000000000e+00 0.00000000000000000e+00 ]
diff --git a/test/test_mesh/test_mesh_periodic.cc b/test/test_mesh/test_mesh_periodic.cc
index 963e02c83..63261cc94 100644
--- a/test/test_mesh/test_mesh_periodic.cc
+++ b/test/test_mesh/test_mesh_periodic.cc
@@ -1,143 +1,143 @@
/**
* @file test_mesh_periodic.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Feb 12 2018
* @date last modification: Sun Dec 30 2018
*
* @brief test makePeriodic
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "data_accessor.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
//#include "mesh_partition_scotch.hh"
#include "periodic_node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
//#include "dumper_element_partition.hh"
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char ** argv) {
initialize(argc, argv);
- constexpr UInt dim = 3;
+ constexpr Int dim = 3;
auto prank = Communicator::getStaticCommunicator().whoAmI();
// auto psize = Communicator::getStaticCommunicator().getNbProc();
Mesh mesh(dim);
if (prank == 0) {
mesh.read("cube_periodic.msh");
}
MeshAccessor mesh_accessor(mesh);
// mesh_accessor.wipePeriodicInfo();
// mesh.makePeriodic(_z);
// if (prank == 0) {
// MeshPartitionScotch partition(mesh, dim);
// partition.partitionate(psize);
// }
UInt offset = 0;
for (auto && type : mesh.elementTypes()) {
- auto & g_ids = mesh.getDataPointer<UInt>("global_ids", type);
+ auto & g_ids = mesh.getDataPointer<Int>("global_ids", type);
for (auto && data : enumerate(g_ids)) {
std::get<1>(data) = offset + std::get<0>(data);
}
offset += g_ids.size();
}
mesh.distribute();
mesh.makePeriodic(_x);
mesh.makePeriodic(_y);
mesh.makePeriodic(_z);
auto * dumper = new DumperParaview("periodic", "./paraview");
mesh.registerExternalDumper(*dumper, "periodic", true);
mesh.addDumpMesh(mesh);
if (mesh.isDistributed()) {
mesh.addDumpFieldExternalToDumper(
"periodic", "node_type",
const_cast<const Mesh &>(mesh).getNodesFlags());
}
mesh.dump();
Array<Int> periodic(mesh.getNbNodes(), 1, 0.);
Array<Int> masters(mesh.getNbNodes(), 1, 0.);
Array<Int> global_ids(mesh.getNbNodes(), 1, 0.);
UInt prev_node = -1;
UInt value = 0;
const auto & periodic_ms = mesh.getPeriodicMasterSlaves();
for (auto & pair : periodic_ms) {
if (prev_node != pair.first) {
++value;
}
prev_node = pair.first;
periodic(pair.first) = value;
periodic(pair.second) = value;
masters(pair.first) = 1;
global_ids(pair.first) = mesh.getNodeGlobalId(pair.second);
auto it = periodic_ms.find(pair.second);
if (it != periodic_ms.end()) {
AKANTU_EXCEPTION(pair.second << " is slave of " << pair.first
<< " and master of " << it->second);
}
}
mesh.addDumpFieldExternalToDumper("periodic", "periodic", periodic);
mesh.addDumpFieldExternalToDumper("periodic", "masters", masters);
mesh.addDumpFieldExternalToDumper("periodic", "global_ids", global_ids);
mesh.addDumpFieldExternalToDumper("periodic", "element_global_ids",
mesh.getData<UInt>("global_ids"));
mesh.dump();
Array<Int> data(mesh.getNbNodes(), 1, 0.);
mesh.addDumpFieldExternalToDumper("periodic", "data", data);
for (auto node : arange(mesh.getNbNodes())) {
if (mesh.isPeriodicMaster(node)) {
data(node) = 1 * (prank + 1);
if (mesh.isMasterNode(node) or mesh.isLocalNode(node)) {
data(node) = 10 * (prank + 1);
}
}
}
mesh.dump();
// SimpleUIntDataAccessor<Int> data_accessor(data,
// SynchronizationTag::_user_1);
// mesh.getPeriodicNodeSynchronizer().synchronizeOnce(data_accessor,
// SynchronizationTag::_user_1);
mesh.dump();
}
diff --git a/test/test_mesh_utils/test_buildfacets/CMakeLists.txt b/test/test_mesh_utils/test_buildfacets/CMakeLists.txt
index 5563c8a6d..20cfc5743 100644
--- a/test/test_mesh_utils/test_buildfacets/CMakeLists.txt
+++ b/test/test_mesh_utils/test_buildfacets/CMakeLists.txt
@@ -1,112 +1,58 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Mauro Corrado <mauro.corrado@epfl.ch>
# @author Marco Vocialta <marco.vocialta@epfl.ch>
#
# @date creation: Sun Oct 19 2014
# @date last modification: Mon Sep 28 2015
#
# @brief configuration for build facets test
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
# @section DESCRIPTION
#
#===============================================================================
-
-register_test(test_buildfacets_triangle_3
- SOURCES test_buildfacets_triangle_3.cc
- FILES_TO_COPY triangle_3.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_triangle_6
- SOURCES test_buildfacets_triangle_6.cc
- FILES_TO_COPY triangle_6.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_quadrangle_4
- SOURCES test_buildfacets_quadrangle_4.cc
- FILES_TO_COPY quadrangle_4.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_quadrangle_8
- SOURCES test_buildfacets_quadrangle_8.cc
- FILES_TO_COPY quadrangle_8.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_mixed2d_linear
- SOURCES test_buildfacets_mixed2d_linear.cc
- FILES_TO_COPY mixed2d_linear.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_mixed2d_quadratic
- SOURCES test_buildfacets_mixed2d_quadratic.cc
- FILES_TO_COPY mixed2d_quadratic.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_tetrahedron_10
- SOURCES test_buildfacets_tetrahedron_10.cc
- FILES_TO_COPY tetrahedron_10.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_hexahedron_8
- SOURCES test_buildfacets_hexahedron_8.cc
- FILES_TO_COPY hexahedron_8.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_hexahedron_20
- SOURCES test_buildfacets_hexahedron_20.cc
- FILES_TO_COPY hexahedron_20.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_pentahedron_6
- SOURCES test_buildfacets_pentahedron_6.cc
- FILES_TO_COPY pentahedron_6.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_pentahedron_15
- SOURCES test_buildfacets_pentahedron_15.cc
- FILES_TO_COPY pentahedron_15.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_mixed3d_linear
- SOURCES test_buildfacets_mixed3d_linear.cc
- FILES_TO_COPY mixed3d_linear.msh
- PACKAGE cohesive_element
- )
-
-register_test(test_buildfacets_mixed3d_quadratic
- SOURCES test_buildfacets_mixed3d_quadratic.cc
- FILES_TO_COPY mixed3d_quadratic.msh
- PACKAGE cohesive_element
+set(_meshes
+ _triangle_3.msh
+ _triangle_6.msh
+ _quadrangle_4.msh
+ _quadrangle_8.msh
+ _quadrangle_4_triangle_3.msh
+ _quadrangle_8_triangle_6.msh
+ _tetrahedron_10.msh
+ _hexahedron_8.msh
+ _hexahedron_20.msh
+ _pentahedron_6.msh
+ _pentahedron_15.msh
+ _hexahedron_8_pentahedron_6.msh
+ _hexahedron_20_pentahedron_15.msh
+ )
+
+register_gtest_sources(
+ SOURCES test_buildfacets.cc
+ PACKAGE core
+ )
+
+register_gtest_test(test_buildfacets
+ FILES_TO_COPY ${_meshes}
)
diff --git a/test/test_mesh_utils/test_buildfacets/hexahedron_20.msh b/test/test_mesh_utils/test_buildfacets/_hexahedron_20.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/hexahedron_20.msh
rename to test/test_mesh_utils/test_buildfacets/_hexahedron_20.msh
diff --git a/test/test_mesh_utils/test_buildfacets/mixed3d_quadratic.msh b/test/test_mesh_utils/test_buildfacets/_hexahedron_20_pentahedron_15.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/mixed3d_quadratic.msh
rename to test/test_mesh_utils/test_buildfacets/_hexahedron_20_pentahedron_15.msh
diff --git a/test/test_mesh_utils/test_buildfacets/hexahedron_8.msh b/test/test_mesh_utils/test_buildfacets/_hexahedron_8.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/hexahedron_8.msh
rename to test/test_mesh_utils/test_buildfacets/_hexahedron_8.msh
diff --git a/test/test_mesh_utils/test_buildfacets/mixed3d_linear.msh b/test/test_mesh_utils/test_buildfacets/_hexahedron_8_pentahedron_6.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/mixed3d_linear.msh
rename to test/test_mesh_utils/test_buildfacets/_hexahedron_8_pentahedron_6.msh
diff --git a/test/test_mesh_utils/test_buildfacets/pentahedron_15.msh b/test/test_mesh_utils/test_buildfacets/_pentahedron_15.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/pentahedron_15.msh
rename to test/test_mesh_utils/test_buildfacets/_pentahedron_15.msh
diff --git a/test/test_mesh_utils/test_buildfacets/pentahedron_6.msh b/test/test_mesh_utils/test_buildfacets/_pentahedron_6.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/pentahedron_6.msh
rename to test/test_mesh_utils/test_buildfacets/_pentahedron_6.msh
diff --git a/test/test_mesh_utils/test_buildfacets/quadrangle_4.msh b/test/test_mesh_utils/test_buildfacets/_quadrangle_4.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/quadrangle_4.msh
rename to test/test_mesh_utils/test_buildfacets/_quadrangle_4.msh
diff --git a/test/test_mesh_utils/test_buildfacets/mixed2d_linear.msh b/test/test_mesh_utils/test_buildfacets/_quadrangle_4_triangle_3.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/mixed2d_linear.msh
rename to test/test_mesh_utils/test_buildfacets/_quadrangle_4_triangle_3.msh
diff --git a/test/test_mesh_utils/test_buildfacets/quadrangle_8.msh b/test/test_mesh_utils/test_buildfacets/_quadrangle_8.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/quadrangle_8.msh
rename to test/test_mesh_utils/test_buildfacets/_quadrangle_8.msh
diff --git a/test/test_mesh_utils/test_buildfacets/mixed2d_quadratic.msh b/test/test_mesh_utils/test_buildfacets/_quadrangle_8_triangle_6.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/mixed2d_quadratic.msh
rename to test/test_mesh_utils/test_buildfacets/_quadrangle_8_triangle_6.msh
diff --git a/test/test_mesh_utils/test_buildfacets/tetrahedron_10.msh b/test/test_mesh_utils/test_buildfacets/_tetrahedron_10.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/tetrahedron_10.msh
rename to test/test_mesh_utils/test_buildfacets/_tetrahedron_10.msh
diff --git a/test/test_mesh_utils/test_buildfacets/triangle_3.msh b/test/test_mesh_utils/test_buildfacets/_triangle_3.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/triangle_3.msh
rename to test/test_mesh_utils/test_buildfacets/_triangle_3.msh
diff --git a/test/test_mesh_utils/test_buildfacets/triangle_6.msh b/test/test_mesh_utils/test_buildfacets/_triangle_6.msh
similarity index 100%
rename from test/test_mesh_utils/test_buildfacets/triangle_6.msh
rename to test/test_mesh_utils/test_buildfacets/_triangle_6.msh
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets.cc
new file mode 100644
index 000000000..fce9027d2
--- /dev/null
+++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets.cc
@@ -0,0 +1,181 @@
+/**
+ * @file test_buildfacets_triangle_3.cc
+ *
+ * @author Mauro Corrado <mauro.corrado@epfl.ch>
+ *
+ * @date creation: Fri Sep 18 2015
+ * @date last modification: Wed Nov 08 2017
+ *
+ * @brief Test to check the building of the facets. Mesh with triangles
+ *
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "test_gtest_utils.hh"
+/* -------------------------------------------------------------------------- */
+#include "aka_common.hh"
+#include "mesh.hh"
+#include "mesh_utils.hh"
+/* -------------------------------------------------------------------------- */
+
+using namespace akantu;
+
+template <typename types_>
+class TestBuildFacetFixture : public ::testing::Test {
+public:
+ static constexpr const ElementType type1 =
+ std::tuple_element_t<0, types_>::value;
+ static constexpr const ElementType type2 =
+ std::tuple_element_t<1, types_>::value;
+ static constexpr const size_t dim =
+ ElementClass<type1>::getSpatialDimension();
+
+ void SetUp() override {
+ mesh = std::make_unique<Mesh>(dim);
+ mesh->read(std::to_string(type1) +
+ ((type2 != _not_defined) ? std::to_string(type2) : "") + ".msh");
+ }
+
+ void TearDown() override { mesh.reset(nullptr); }
+
+ template <class List>
+ void print_connection(const std::string & name, ElementType type,
+ const List & list) {
+ std::cout << name << std::endl;
+ for (auto && outer : enumerate(list)) {
+ std::cout << type << " " << std::get<0>(outer) << " connected to ";
+ for (auto && inner : std::get<1>(outer)) {
+ std::cout << inner << ", ";
+ }
+ std::cout << " " << std::endl;
+ }
+ }
+
+protected:
+ std::unique_ptr<Mesh> mesh;
+};
+
+template <typename type_>
+constexpr const ElementType TestBuildFacetFixture<type_>::type1;
+template <typename type_>
+constexpr const ElementType TestBuildFacetFixture<type_>::type2;
+
+template <typename type_>
+constexpr const size_t TestBuildFacetFixture<type_>::dim;
+
+template <typename T1, typename T2 = element_type_t<_not_defined>>
+struct element_pair {
+ using type = std::tuple<T1, T2>;
+};
+
+template <typename T1, typename T2 = element_type_t<_not_defined>>
+using element_pair_t = typename element_pair<T1, T2>::type;
+
+using buildfacets_types = ::testing::Types<
+ element_pair_t<_element_type_triangle_3>,
+ element_pair_t<_element_type_triangle_6>,
+ element_pair_t<_element_type_quadrangle_4>,
+ element_pair_t<_element_type_quadrangle_8>,
+ element_pair_t<_element_type_tetrahedron_10>,
+ element_pair_t<_element_type_hexahedron_8>,
+ element_pair_t<_element_type_hexahedron_20>,
+ element_pair_t<_element_type_pentahedron_6>,
+ element_pair_t<_element_type_pentahedron_15>,
+ element_pair_t<_element_type_quadrangle_4, _element_type_triangle_3>,
+ element_pair_t<_element_type_quadrangle_8, _element_type_triangle_6>,
+ element_pair_t<_element_type_hexahedron_8, _element_type_pentahedron_6>,
+ element_pair_t<_element_type_hexahedron_20, _element_type_pentahedron_15>>;
+
+TYPED_TEST_SUITE(TestBuildFacetFixture, buildfacets_types, );
+
+TYPED_TEST(TestBuildFacetFixture, Buildfacets) {
+ const auto & mesh_facets = this->mesh->initMeshFacets("mesh_facets");
+
+ /* ------------------------------------------------------------------------ */
+ /* Element to Subelement testing */
+ /* ------------------------------------------------------------------------ */
+ const auto types_facet1{this->mesh->getAllFacetTypes(this->type1)};
+
+ std::set<ElementType> types_facet;
+ for (auto type : types_facet1) {
+ types_facet.insert(type);
+ }
+
+ if (this->type2 != _not_defined) {
+ const auto types_facet2{this->mesh->getAllFacetTypes(this->type2)};
+ for (auto type : types_facet2) {
+ types_facet.insert(type);
+ }
+ }
+
+ for (auto type_facet : types_facet) {
+ const auto & el_to_subel1 = mesh_facets.getElementToSubelement(type_facet);
+ this->print_connection("ElementToSubelement1", type_facet, el_to_subel1);
+ }
+
+ const auto type_subfacet = this->mesh->getFacetType(*types_facet.begin());
+ const auto & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet);
+ this->print_connection("ElementToSubelement2", type_subfacet, el_to_subel2);
+
+ if (this->dim == 3) {
+ const auto type_subsubfacet = this->mesh->getFacetType(type_subfacet);
+ const auto & el_to_subel3 =
+ mesh_facets.getElementToSubelement(type_subsubfacet);
+ this->print_connection("ElementToSubelement3", type_subsubfacet,
+ el_to_subel3);
+ }
+
+ /* ------------------------------------------------------------------------ */
+ /* Subelement to Element testing */
+ /* ------------------------------------------------------------------------ */
+ std::cout << std::endl;
+ const auto & subel_to_el1 = mesh_facets.getSubelementToElement(this->type1);
+ this->print_connection("SubelementToElement1", this->type1,
+ MatrixProxy<Element>(subel_to_el1.data(),
+ subel_to_el1.getNbComponent(),
+ subel_to_el1.size()));
+
+ if (this->type2 != _not_defined) {
+ const auto & subel_to_el1 = mesh_facets.getSubelementToElement(this->type2);
+ this->print_connection("SubelementToElement1", this->type2,
+ MatrixProxy<Element>(subel_to_el1.data(),
+ subel_to_el1.getNbComponent(),
+ subel_to_el1.size()));
+ }
+
+ for (auto type_facet : types_facet) {
+ auto && subel_to_el2 = mesh_facets.getSubelementToElement(type_facet);
+ this->print_connection("SubelementToElement2", type_facet,
+ MatrixProxy<Element>(subel_to_el2.data(),
+ subel_to_el2.getNbComponent(),
+ subel_to_el2.size()));
+ }
+
+ if (this->dim == 3) {
+ const auto & subel_to_el3 =
+ mesh_facets.getSubelementToElement(type_subfacet);
+ this->print_connection("SubelementToElement3", type_subfacet,
+ MatrixProxy<Element>(subel_to_el3.data(),
+ subel_to_el3.getNbComponent(),
+ subel_to_el3.size()));
+ }
+}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_gtest.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_gtest.verified
new file mode 100644
index 000000000..0d339a4e7
--- /dev/null
+++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_gtest.verified
@@ -0,0 +1,1363 @@
+[==========] Running 13 tests from 13 test suites.
+[----------] Global test environment set-up.
+[----------] 1 test from TestBuildFacetFixture/0, where TypeParam = std::tuple<akantu::_element_type_triangle_3, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/0.Buildfacets
+ElementToSubelement1
+_segment_2 0 connected to Element [_triangle_3, 0, 0], ElementNull,
+_segment_2 1 connected to Element [_triangle_3, 0, 0], Element [_triangle_3, 1, 0],
+_segment_2 2 connected to Element [_triangle_3, 0, 0], ElementNull,
+_segment_2 3 connected to Element [_triangle_3, 1, 0], Element [_triangle_3, 4, 0],
+_segment_2 4 connected to Element [_triangle_3, 1, 0], Element [_triangle_3, 2, 0],
+_segment_2 5 connected to Element [_triangle_3, 2, 0], Element [_triangle_3, 3, 0],
+_segment_2 6 connected to Element [_triangle_3, 2, 0], ElementNull,
+_segment_2 7 connected to Element [_triangle_3, 3, 0], Element [_triangle_3, 6, 0],
+_segment_2 8 connected to Element [_triangle_3, 3, 0], ElementNull,
+_segment_2 9 connected to Element [_triangle_3, 4, 0], ElementNull,
+_segment_2 10 connected to Element [_triangle_3, 4, 0], Element [_triangle_3, 5, 0],
+_segment_2 11 connected to Element [_triangle_3, 5, 0], ElementNull,
+_segment_2 12 connected to Element [_triangle_3, 5, 0], Element [_triangle_3, 6, 0],
+_segment_2 13 connected to Element [_triangle_3, 6, 0], Element [_triangle_3, 7, 0],
+_segment_2 14 connected to Element [_triangle_3, 7, 0], ElementNull,
+_segment_2 15 connected to Element [_triangle_3, 7, 0], ElementNull,
+ElementToSubelement2
+_point_1 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 2, 0],
+_point_1 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 3, 0], Element [_segment_2, 9, 0],
+_point_1 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 4, 0], Element [_segment_2, 6, 0],
+_point_1 3 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 7, 0], Element [_segment_2, 10, 0], Element [_segment_2, 12, 0],
+_point_1 4 connected to Element [_segment_2, 5, 0], Element [_segment_2, 6, 0], Element [_segment_2, 8, 0],
+_point_1 5 connected to Element [_segment_2, 7, 0], Element [_segment_2, 8, 0], Element [_segment_2, 13, 0], Element [_segment_2, 15, 0],
+_point_1 6 connected to Element [_segment_2, 9, 0], Element [_segment_2, 10, 0], Element [_segment_2, 11, 0],
+_point_1 7 connected to Element [_segment_2, 11, 0], Element [_segment_2, 12, 0], Element [_segment_2, 13, 0], Element [_segment_2, 14, 0],
+_point_1 8 connected to Element [_segment_2, 14, 0], Element [_segment_2, 15, 0],
+
+SubelementToElement1
+_triangle_3 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 2, 0],
+_triangle_3 1 connected to Element [_segment_2, 1, 0], Element [_segment_2, 3, 0], Element [_segment_2, 4, 0],
+_triangle_3 2 connected to Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 6, 0],
+_triangle_3 3 connected to Element [_segment_2, 5, 0], Element [_segment_2, 7, 0], Element [_segment_2, 8, 0],
+_triangle_3 4 connected to Element [_segment_2, 3, 0], Element [_segment_2, 9, 0], Element [_segment_2, 10, 0],
+_triangle_3 5 connected to Element [_segment_2, 10, 0], Element [_segment_2, 11, 0], Element [_segment_2, 12, 0],
+_triangle_3 6 connected to Element [_segment_2, 7, 0], Element [_segment_2, 12, 0], Element [_segment_2, 13, 0],
+_triangle_3 7 connected to Element [_segment_2, 13, 0], Element [_segment_2, 14, 0], Element [_segment_2, 15, 0],
+SubelementToElement2
+_segment_2 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_2 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_2 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_2 3 connected to Element [_point_1, 1, 0], Element [_point_1, 3, 0],
+_segment_2 4 connected to Element [_point_1, 2, 0], Element [_point_1, 3, 0],
+_segment_2 5 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_2 6 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_2 7 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_2 8 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_2 9 connected to Element [_point_1, 1, 0], Element [_point_1, 6, 0],
+_segment_2 10 connected to Element [_point_1, 3, 0], Element [_point_1, 6, 0],
+_segment_2 11 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_2 12 connected to Element [_point_1, 3, 0], Element [_point_1, 7, 0],
+_segment_2 13 connected to Element [_point_1, 5, 0], Element [_point_1, 7, 0],
+_segment_2 14 connected to Element [_point_1, 7, 0], Element [_point_1, 8, 0],
+_segment_2 15 connected to Element [_point_1, 5, 0], Element [_point_1, 8, 0],
+[ OK ] TestBuildFacetFixture/0.Buildfacets (6 ms)
+[----------] 1 test from TestBuildFacetFixture/0 (6 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/1, where TypeParam = std::tuple<akantu::_element_type_triangle_6, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/1.Buildfacets
+ElementToSubelement1
+_segment_3 0 connected to Element [_triangle_6, 0, 0], ElementNull,
+_segment_3 1 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 1, 0],
+_segment_3 2 connected to Element [_triangle_6, 0, 0], ElementNull,
+_segment_3 3 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 4, 0],
+_segment_3 4 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 2, 0],
+_segment_3 5 connected to Element [_triangle_6, 2, 0], Element [_triangle_6, 3, 0],
+_segment_3 6 connected to Element [_triangle_6, 2, 0], ElementNull,
+_segment_3 7 connected to Element [_triangle_6, 3, 0], Element [_triangle_6, 6, 0],
+_segment_3 8 connected to Element [_triangle_6, 3, 0], ElementNull,
+_segment_3 9 connected to Element [_triangle_6, 4, 0], ElementNull,
+_segment_3 10 connected to Element [_triangle_6, 4, 0], Element [_triangle_6, 5, 0],
+_segment_3 11 connected to Element [_triangle_6, 5, 0], ElementNull,
+_segment_3 12 connected to Element [_triangle_6, 5, 0], Element [_triangle_6, 6, 0],
+_segment_3 13 connected to Element [_triangle_6, 6, 0], Element [_triangle_6, 7, 0],
+_segment_3 14 connected to Element [_triangle_6, 7, 0], ElementNull,
+_segment_3 15 connected to Element [_triangle_6, 7, 0], ElementNull,
+ElementToSubelement2
+_point_1 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 2, 0],
+_point_1 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 3, 0], Element [_segment_3, 9, 0],
+_point_1 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 4, 0], Element [_segment_3, 6, 0],
+_point_1 3 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 7, 0], Element [_segment_3, 10, 0], Element [_segment_3, 12, 0],
+_point_1 4 connected to Element [_segment_3, 5, 0], Element [_segment_3, 6, 0], Element [_segment_3, 8, 0],
+_point_1 5 connected to Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 13, 0], Element [_segment_3, 15, 0],
+_point_1 6 connected to Element [_segment_3, 9, 0], Element [_segment_3, 10, 0], Element [_segment_3, 11, 0],
+_point_1 7 connected to Element [_segment_3, 11, 0], Element [_segment_3, 12, 0], Element [_segment_3, 13, 0], Element [_segment_3, 14, 0],
+_point_1 8 connected to Element [_segment_3, 14, 0], Element [_segment_3, 15, 0],
+
+SubelementToElement1
+_triangle_6 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 2, 0],
+_triangle_6 1 connected to Element [_segment_3, 1, 0], Element [_segment_3, 3, 0], Element [_segment_3, 4, 0],
+_triangle_6 2 connected to Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 6, 0],
+_triangle_6 3 connected to Element [_segment_3, 5, 0], Element [_segment_3, 7, 0], Element [_segment_3, 8, 0],
+_triangle_6 4 connected to Element [_segment_3, 3, 0], Element [_segment_3, 9, 0], Element [_segment_3, 10, 0],
+_triangle_6 5 connected to Element [_segment_3, 10, 0], Element [_segment_3, 11, 0], Element [_segment_3, 12, 0],
+_triangle_6 6 connected to Element [_segment_3, 7, 0], Element [_segment_3, 12, 0], Element [_segment_3, 13, 0],
+_triangle_6 7 connected to Element [_segment_3, 13, 0], Element [_segment_3, 14, 0], Element [_segment_3, 15, 0],
+SubelementToElement2
+_segment_3 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_3 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_3 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_3 3 connected to Element [_point_1, 1, 0], Element [_point_1, 3, 0],
+_segment_3 4 connected to Element [_point_1, 2, 0], Element [_point_1, 3, 0],
+_segment_3 5 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_3 6 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_3 7 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_3 8 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_3 9 connected to Element [_point_1, 1, 0], Element [_point_1, 6, 0],
+_segment_3 10 connected to Element [_point_1, 3, 0], Element [_point_1, 6, 0],
+_segment_3 11 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_3 12 connected to Element [_point_1, 3, 0], Element [_point_1, 7, 0],
+_segment_3 13 connected to Element [_point_1, 5, 0], Element [_point_1, 7, 0],
+_segment_3 14 connected to Element [_point_1, 7, 0], Element [_point_1, 8, 0],
+_segment_3 15 connected to Element [_point_1, 5, 0], Element [_point_1, 8, 0],
+[ OK ] TestBuildFacetFixture/1.Buildfacets (1 ms)
+[----------] 1 test from TestBuildFacetFixture/1 (1 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/2, where TypeParam = std::tuple<akantu::_element_type_quadrangle_4, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/2.Buildfacets
+ElementToSubelement1
+_segment_2 0 connected to Element [_quadrangle_4, 0, 0], ElementNull,
+_segment_2 1 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 2, 0],
+_segment_2 2 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0],
+_segment_2 3 connected to Element [_quadrangle_4, 0, 0], ElementNull,
+_segment_2 4 connected to Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 3, 0],
+_segment_2 5 connected to Element [_quadrangle_4, 1, 0], ElementNull,
+_segment_2 6 connected to Element [_quadrangle_4, 1, 0], ElementNull,
+_segment_2 7 connected to Element [_quadrangle_4, 2, 0], ElementNull,
+_segment_2 8 connected to Element [_quadrangle_4, 2, 0], ElementNull,
+_segment_2 9 connected to Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 3, 0],
+_segment_2 10 connected to Element [_quadrangle_4, 3, 0], ElementNull,
+_segment_2 11 connected to Element [_quadrangle_4, 3, 0], ElementNull,
+ElementToSubelement2
+_point_1 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 3, 0],
+_point_1 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 7, 0],
+_point_1 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 4, 0], Element [_segment_2, 9, 0],
+_point_1 3 connected to Element [_segment_2, 2, 0], Element [_segment_2, 3, 0], Element [_segment_2, 6, 0],
+_point_1 4 connected to Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 11, 0],
+_point_1 5 connected to Element [_segment_2, 5, 0], Element [_segment_2, 6, 0],
+_point_1 6 connected to Element [_segment_2, 7, 0], Element [_segment_2, 8, 0],
+_point_1 7 connected to Element [_segment_2, 8, 0], Element [_segment_2, 9, 0], Element [_segment_2, 10, 0],
+_point_1 8 connected to Element [_segment_2, 10, 0], Element [_segment_2, 11, 0],
+
+SubelementToElement1
+_quadrangle_4 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 3, 0],
+_quadrangle_4 1 connected to Element [_segment_2, 2, 0], Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 6, 0],
+_quadrangle_4 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 7, 0], Element [_segment_2, 8, 0], Element [_segment_2, 9, 0],
+_quadrangle_4 3 connected to Element [_segment_2, 4, 0], Element [_segment_2, 9, 0], Element [_segment_2, 10, 0], Element [_segment_2, 11, 0],
+SubelementToElement2
+_segment_2 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_2 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_2 2 connected to Element [_point_1, 2, 0], Element [_point_1, 3, 0],
+_segment_2 3 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_2 4 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_2 5 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_2 6 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_2 7 connected to Element [_point_1, 1, 0], Element [_point_1, 6, 0],
+_segment_2 8 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_2 9 connected to Element [_point_1, 2, 0], Element [_point_1, 7, 0],
+_segment_2 10 connected to Element [_point_1, 7, 0], Element [_point_1, 8, 0],
+_segment_2 11 connected to Element [_point_1, 4, 0], Element [_point_1, 8, 0],
+[ OK ] TestBuildFacetFixture/2.Buildfacets (1 ms)
+[----------] 1 test from TestBuildFacetFixture/2 (1 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/3, where TypeParam = std::tuple<akantu::_element_type_quadrangle_8, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/3.Buildfacets
+ElementToSubelement1
+_segment_3 0 connected to Element [_quadrangle_8, 0, 0], ElementNull,
+_segment_3 1 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 2, 0],
+_segment_3 2 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0],
+_segment_3 3 connected to Element [_quadrangle_8, 0, 0], ElementNull,
+_segment_3 4 connected to Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 3, 0],
+_segment_3 5 connected to Element [_quadrangle_8, 1, 0], ElementNull,
+_segment_3 6 connected to Element [_quadrangle_8, 1, 0], ElementNull,
+_segment_3 7 connected to Element [_quadrangle_8, 2, 0], ElementNull,
+_segment_3 8 connected to Element [_quadrangle_8, 2, 0], ElementNull,
+_segment_3 9 connected to Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 3, 0],
+_segment_3 10 connected to Element [_quadrangle_8, 3, 0], ElementNull,
+_segment_3 11 connected to Element [_quadrangle_8, 3, 0], ElementNull,
+ElementToSubelement2
+_point_1 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 3, 0],
+_point_1 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 7, 0],
+_point_1 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 4, 0], Element [_segment_3, 9, 0],
+_point_1 3 connected to Element [_segment_3, 2, 0], Element [_segment_3, 3, 0], Element [_segment_3, 6, 0],
+_point_1 4 connected to Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 11, 0],
+_point_1 5 connected to Element [_segment_3, 5, 0], Element [_segment_3, 6, 0],
+_point_1 6 connected to Element [_segment_3, 7, 0], Element [_segment_3, 8, 0],
+_point_1 7 connected to Element [_segment_3, 8, 0], Element [_segment_3, 9, 0], Element [_segment_3, 10, 0],
+_point_1 8 connected to Element [_segment_3, 10, 0], Element [_segment_3, 11, 0],
+
+SubelementToElement1
+_quadrangle_8 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 3, 0],
+_quadrangle_8 1 connected to Element [_segment_3, 2, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 6, 0],
+_quadrangle_8 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 9, 0],
+_quadrangle_8 3 connected to Element [_segment_3, 4, 0], Element [_segment_3, 9, 0], Element [_segment_3, 10, 0], Element [_segment_3, 11, 0],
+SubelementToElement2
+_segment_3 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_3 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_3 2 connected to Element [_point_1, 2, 0], Element [_point_1, 3, 0],
+_segment_3 3 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_3 4 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_3 5 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_3 6 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_3 7 connected to Element [_point_1, 1, 0], Element [_point_1, 6, 0],
+_segment_3 8 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_3 9 connected to Element [_point_1, 2, 0], Element [_point_1, 7, 0],
+_segment_3 10 connected to Element [_point_1, 7, 0], Element [_point_1, 8, 0],
+_segment_3 11 connected to Element [_point_1, 4, 0], Element [_point_1, 8, 0],
+[ OK ] TestBuildFacetFixture/3.Buildfacets (1 ms)
+[----------] 1 test from TestBuildFacetFixture/3 (1 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/4, where TypeParam = std::tuple<akantu::_element_type_tetrahedron_10, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/4.Buildfacets
+ElementToSubelement1
+_triangle_6 0 connected to Element [_tetrahedron_10, 0, 0], Element [_tetrahedron_10, 11, 0],
+_triangle_6 1 connected to Element [_tetrahedron_10, 0, 0], Element [_tetrahedron_10, 12, 0],
+_triangle_6 2 connected to Element [_tetrahedron_10, 0, 0], Element [_tetrahedron_10, 6, 0],
+_triangle_6 3 connected to Element [_tetrahedron_10, 0, 0], ElementNull,
+_triangle_6 4 connected to Element [_tetrahedron_10, 1, 0], Element [_tetrahedron_10, 11, 0],
+_triangle_6 5 connected to Element [_tetrahedron_10, 1, 0], Element [_tetrahedron_10, 15, 0],
+_triangle_6 6 connected to Element [_tetrahedron_10, 1, 0], ElementNull,
+_triangle_6 7 connected to Element [_tetrahedron_10, 1, 0], Element [_tetrahedron_10, 13, 0],
+_triangle_6 8 connected to Element [_tetrahedron_10, 2, 0], ElementNull,
+_triangle_6 9 connected to Element [_tetrahedron_10, 2, 0], Element [_tetrahedron_10, 12, 0],
+_triangle_6 10 connected to Element [_tetrahedron_10, 2, 0], ElementNull,
+_triangle_6 11 connected to Element [_tetrahedron_10, 2, 0], Element [_tetrahedron_10, 6, 0],
+_triangle_6 12 connected to Element [_tetrahedron_10, 3, 0], Element [_tetrahedron_10, 5, 0],
+_triangle_6 13 connected to Element [_tetrahedron_10, 3, 0], ElementNull,
+_triangle_6 14 connected to Element [_tetrahedron_10, 3, 0], ElementNull,
+_triangle_6 15 connected to Element [_tetrahedron_10, 3, 0], Element [_tetrahedron_10, 8, 0],
+_triangle_6 16 connected to Element [_tetrahedron_10, 4, 0], Element [_tetrahedron_10, 8, 0],
+_triangle_6 17 connected to Element [_tetrahedron_10, 4, 0], ElementNull,
+_triangle_6 18 connected to Element [_tetrahedron_10, 4, 0], Element [_tetrahedron_10, 6, 0],
+_triangle_6 19 connected to Element [_tetrahedron_10, 4, 0], Element [_tetrahedron_10, 5, 0],
+_triangle_6 20 connected to Element [_tetrahedron_10, 5, 0], ElementNull,
+_triangle_6 21 connected to Element [_tetrahedron_10, 5, 0], ElementNull,
+_triangle_6 22 connected to Element [_tetrahedron_10, 6, 0], ElementNull,
+_triangle_6 23 connected to Element [_tetrahedron_10, 7, 0], Element [_tetrahedron_10, 9, 0],
+_triangle_6 24 connected to Element [_tetrahedron_10, 7, 0], Element [_tetrahedron_10, 8, 0],
+_triangle_6 25 connected to Element [_tetrahedron_10, 7, 0], ElementNull,
+_triangle_6 26 connected to Element [_tetrahedron_10, 7, 0], Element [_tetrahedron_10, 13, 0],
+_triangle_6 27 connected to Element [_tetrahedron_10, 8, 0], ElementNull,
+_triangle_6 28 connected to Element [_tetrahedron_10, 9, 0], ElementNull,
+_triangle_6 29 connected to Element [_tetrahedron_10, 9, 0], ElementNull,
+_triangle_6 30 connected to Element [_tetrahedron_10, 9, 0], Element [_tetrahedron_10, 14, 0],
+_triangle_6 31 connected to Element [_tetrahedron_10, 10, 0], Element [_tetrahedron_10, 15, 0],
+_triangle_6 32 connected to Element [_tetrahedron_10, 10, 0], Element [_tetrahedron_10, 11, 0],
+_triangle_6 33 connected to Element [_tetrahedron_10, 10, 0], ElementNull,
+_triangle_6 34 connected to Element [_tetrahedron_10, 10, 0], ElementNull,
+_triangle_6 35 connected to Element [_tetrahedron_10, 11, 0], ElementNull,
+_triangle_6 36 connected to Element [_tetrahedron_10, 12, 0], ElementNull,
+_triangle_6 37 connected to Element [_tetrahedron_10, 12, 0], ElementNull,
+_triangle_6 38 connected to Element [_tetrahedron_10, 13, 0], ElementNull,
+_triangle_6 39 connected to Element [_tetrahedron_10, 13, 0], Element [_tetrahedron_10, 14, 0],
+_triangle_6 40 connected to Element [_tetrahedron_10, 14, 0], ElementNull,
+_triangle_6 41 connected to Element [_tetrahedron_10, 14, 0], ElementNull,
+_triangle_6 42 connected to Element [_tetrahedron_10, 15, 0], ElementNull,
+_triangle_6 43 connected to Element [_tetrahedron_10, 15, 0], ElementNull,
+ElementToSubelement2
+_segment_3 0 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 2, 0], Element [_triangle_6, 4, 0], Element [_triangle_6, 7, 0], Element [_triangle_6, 16, 0], Element [_triangle_6, 18, 0], Element [_triangle_6, 24, 0], Element [_triangle_6, 26, 0],
+_segment_3 1 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 1, 0], Element [_triangle_6, 32, 0], Element [_triangle_6, 34, 0], Element [_triangle_6, 37, 0],
+_segment_3 2 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 3, 0], Element [_triangle_6, 35, 0],
+_segment_3 3 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 2, 0], Element [_triangle_6, 9, 0], Element [_triangle_6, 11, 0],
+_segment_3 4 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 3, 0], Element [_triangle_6, 36, 0],
+_segment_3 5 connected to Element [_triangle_6, 2, 0], Element [_triangle_6, 3, 0], Element [_triangle_6, 22, 0],
+_segment_3 6 connected to Element [_triangle_6, 4, 0], Element [_triangle_6, 6, 0], Element [_triangle_6, 35, 0],
+_segment_3 7 connected to Element [_triangle_6, 4, 0], Element [_triangle_6, 5, 0], Element [_triangle_6, 31, 0], Element [_triangle_6, 32, 0],
+_segment_3 8 connected to Element [_triangle_6, 5, 0], Element [_triangle_6, 6, 0], Element [_triangle_6, 42, 0],
+_segment_3 9 connected to Element [_triangle_6, 5, 0], Element [_triangle_6, 7, 0], Element [_triangle_6, 39, 0], Element [_triangle_6, 40, 0], Element [_triangle_6, 43, 0],
+_segment_3 10 connected to Element [_triangle_6, 6, 0], Element [_triangle_6, 7, 0], Element [_triangle_6, 38, 0],
+_segment_3 11 connected to Element [_triangle_6, 8, 0], Element [_triangle_6, 10, 0],
+_segment_3 12 connected to Element [_triangle_6, 8, 0], Element [_triangle_6, 9, 0], Element [_triangle_6, 37, 0],
+_segment_3 13 connected to Element [_triangle_6, 8, 0], Element [_triangle_6, 11, 0], Element [_triangle_6, 18, 0], Element [_triangle_6, 19, 0], Element [_triangle_6, 20, 0],
+_segment_3 14 connected to Element [_triangle_6, 9, 0], Element [_triangle_6, 10, 0], Element [_triangle_6, 36, 0],
+_segment_3 15 connected to Element [_triangle_6, 10, 0], Element [_triangle_6, 11, 0], Element [_triangle_6, 22, 0],
+_segment_3 16 connected to Element [_triangle_6, 12, 0], Element [_triangle_6, 14, 0], Element [_triangle_6, 20, 0],
+_segment_3 17 connected to Element [_triangle_6, 12, 0], Element [_triangle_6, 13, 0], Element [_triangle_6, 21, 0],
+_segment_3 18 connected to Element [_triangle_6, 12, 0], Element [_triangle_6, 15, 0], Element [_triangle_6, 16, 0], Element [_triangle_6, 19, 0],
+_segment_3 19 connected to Element [_triangle_6, 13, 0], Element [_triangle_6, 14, 0],
+_segment_3 20 connected to Element [_triangle_6, 13, 0], Element [_triangle_6, 15, 0], Element [_triangle_6, 27, 0],
+_segment_3 21 connected to Element [_triangle_6, 14, 0], Element [_triangle_6, 15, 0], Element [_triangle_6, 23, 0], Element [_triangle_6, 24, 0], Element [_triangle_6, 29, 0],
+_segment_3 22 connected to Element [_triangle_6, 16, 0], Element [_triangle_6, 17, 0], Element [_triangle_6, 27, 0],
+_segment_3 23 connected to Element [_triangle_6, 17, 0], Element [_triangle_6, 18, 0], Element [_triangle_6, 22, 0],
+_segment_3 24 connected to Element [_triangle_6, 17, 0], Element [_triangle_6, 19, 0], Element [_triangle_6, 21, 0],
+_segment_3 25 connected to Element [_triangle_6, 20, 0], Element [_triangle_6, 21, 0],
+_segment_3 26 connected to Element [_triangle_6, 23, 0], Element [_triangle_6, 25, 0], Element [_triangle_6, 28, 0],
+_segment_3 27 connected to Element [_triangle_6, 23, 0], Element [_triangle_6, 26, 0], Element [_triangle_6, 30, 0], Element [_triangle_6, 39, 0],
+_segment_3 28 connected to Element [_triangle_6, 24, 0], Element [_triangle_6, 25, 0], Element [_triangle_6, 27, 0],
+_segment_3 29 connected to Element [_triangle_6, 25, 0], Element [_triangle_6, 26, 0], Element [_triangle_6, 38, 0],
+_segment_3 30 connected to Element [_triangle_6, 28, 0], Element [_triangle_6, 29, 0],
+_segment_3 31 connected to Element [_triangle_6, 28, 0], Element [_triangle_6, 30, 0], Element [_triangle_6, 41, 0],
+_segment_3 32 connected to Element [_triangle_6, 29, 0], Element [_triangle_6, 30, 0], Element [_triangle_6, 40, 0],
+_segment_3 33 connected to Element [_triangle_6, 31, 0], Element [_triangle_6, 33, 0], Element [_triangle_6, 42, 0],
+_segment_3 34 connected to Element [_triangle_6, 31, 0], Element [_triangle_6, 34, 0], Element [_triangle_6, 43, 0],
+_segment_3 35 connected to Element [_triangle_6, 32, 0], Element [_triangle_6, 33, 0], Element [_triangle_6, 35, 0],
+_segment_3 36 connected to Element [_triangle_6, 33, 0], Element [_triangle_6, 34, 0],
+_segment_3 37 connected to Element [_triangle_6, 36, 0], Element [_triangle_6, 37, 0],
+_segment_3 38 connected to Element [_triangle_6, 38, 0], Element [_triangle_6, 39, 0], Element [_triangle_6, 41, 0],
+_segment_3 39 connected to Element [_triangle_6, 40, 0], Element [_triangle_6, 41, 0],
+_segment_3 40 connected to Element [_triangle_6, 42, 0], Element [_triangle_6, 43, 0],
+ElementToSubelement3
+_point_1 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 2, 0], Element [_segment_3, 5, 0], Element [_segment_3, 6, 0], Element [_segment_3, 10, 0], Element [_segment_3, 22, 0], Element [_segment_3, 23, 0], Element [_segment_3, 28, 0], Element [_segment_3, 29, 0],
+_point_1 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 3, 0], Element [_segment_3, 7, 0], Element [_segment_3, 9, 0], Element [_segment_3, 12, 0], Element [_segment_3, 13, 0], Element [_segment_3, 16, 0], Element [_segment_3, 18, 0], Element [_segment_3, 21, 0], Element [_segment_3, 27, 0], Element [_segment_3, 32, 0], Element [_segment_3, 34, 0],
+_point_1 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 4, 0], Element [_segment_3, 35, 0], Element [_segment_3, 36, 0], Element [_segment_3, 37, 0],
+_point_1 3 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 14, 0], Element [_segment_3, 15, 0],
+_point_1 4 connected to Element [_segment_3, 6, 0], Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 33, 0], Element [_segment_3, 35, 0],
+_point_1 5 connected to Element [_segment_3, 8, 0], Element [_segment_3, 9, 0], Element [_segment_3, 10, 0], Element [_segment_3, 38, 0], Element [_segment_3, 39, 0], Element [_segment_3, 40, 0],
+_point_1 6 connected to Element [_segment_3, 11, 0], Element [_segment_3, 13, 0], Element [_segment_3, 15, 0], Element [_segment_3, 23, 0], Element [_segment_3, 24, 0], Element [_segment_3, 25, 0],
+_point_1 7 connected to Element [_segment_3, 11, 0], Element [_segment_3, 12, 0], Element [_segment_3, 14, 0], Element [_segment_3, 37, 0],
+_point_1 8 connected to Element [_segment_3, 16, 0], Element [_segment_3, 17, 0], Element [_segment_3, 19, 0], Element [_segment_3, 25, 0],
+_point_1 9 connected to Element [_segment_3, 17, 0], Element [_segment_3, 18, 0], Element [_segment_3, 20, 0], Element [_segment_3, 22, 0], Element [_segment_3, 24, 0],
+_point_1 10 connected to Element [_segment_3, 19, 0], Element [_segment_3, 20, 0], Element [_segment_3, 21, 0], Element [_segment_3, 26, 0], Element [_segment_3, 28, 0], Element [_segment_3, 30, 0],
+_point_1 11 connected to Element [_segment_3, 26, 0], Element [_segment_3, 27, 0], Element [_segment_3, 29, 0], Element [_segment_3, 31, 0], Element [_segment_3, 38, 0],
+_point_1 12 connected to Element [_segment_3, 30, 0], Element [_segment_3, 31, 0], Element [_segment_3, 32, 0], Element [_segment_3, 39, 0],
+_point_1 13 connected to Element [_segment_3, 33, 0], Element [_segment_3, 34, 0], Element [_segment_3, 36, 0], Element [_segment_3, 40, 0],
+
+SubelementToElement1
+_tetrahedron_10 0 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 1, 0], Element [_triangle_6, 2, 0], Element [_triangle_6, 3, 0],
+_tetrahedron_10 1 connected to Element [_triangle_6, 4, 0], Element [_triangle_6, 5, 0], Element [_triangle_6, 6, 0], Element [_triangle_6, 7, 0],
+_tetrahedron_10 2 connected to Element [_triangle_6, 8, 0], Element [_triangle_6, 9, 0], Element [_triangle_6, 10, 0], Element [_triangle_6, 11, 0],
+_tetrahedron_10 3 connected to Element [_triangle_6, 12, 0], Element [_triangle_6, 13, 0], Element [_triangle_6, 14, 0], Element [_triangle_6, 15, 0],
+_tetrahedron_10 4 connected to Element [_triangle_6, 16, 0], Element [_triangle_6, 17, 0], Element [_triangle_6, 18, 0], Element [_triangle_6, 19, 0],
+_tetrahedron_10 5 connected to Element [_triangle_6, 12, 0], Element [_triangle_6, 19, 0], Element [_triangle_6, 20, 0], Element [_triangle_6, 21, 0],
+_tetrahedron_10 6 connected to Element [_triangle_6, 2, 0], Element [_triangle_6, 11, 0], Element [_triangle_6, 18, 0], Element [_triangle_6, 22, 0],
+_tetrahedron_10 7 connected to Element [_triangle_6, 23, 0], Element [_triangle_6, 24, 0], Element [_triangle_6, 25, 0], Element [_triangle_6, 26, 0],
+_tetrahedron_10 8 connected to Element [_triangle_6, 15, 0], Element [_triangle_6, 16, 0], Element [_triangle_6, 24, 0], Element [_triangle_6, 27, 0],
+_tetrahedron_10 9 connected to Element [_triangle_6, 23, 0], Element [_triangle_6, 28, 0], Element [_triangle_6, 29, 0], Element [_triangle_6, 30, 0],
+_tetrahedron_10 10 connected to Element [_triangle_6, 31, 0], Element [_triangle_6, 32, 0], Element [_triangle_6, 33, 0], Element [_triangle_6, 34, 0],
+_tetrahedron_10 11 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 4, 0], Element [_triangle_6, 32, 0], Element [_triangle_6, 35, 0],
+_tetrahedron_10 12 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 9, 0], Element [_triangle_6, 36, 0], Element [_triangle_6, 37, 0],
+_tetrahedron_10 13 connected to Element [_triangle_6, 7, 0], Element [_triangle_6, 26, 0], Element [_triangle_6, 38, 0], Element [_triangle_6, 39, 0],
+_tetrahedron_10 14 connected to Element [_triangle_6, 30, 0], Element [_triangle_6, 39, 0], Element [_triangle_6, 40, 0], Element [_triangle_6, 41, 0],
+_tetrahedron_10 15 connected to Element [_triangle_6, 5, 0], Element [_triangle_6, 31, 0], Element [_triangle_6, 42, 0], Element [_triangle_6, 43, 0],
+SubelementToElement2
+_triangle_6 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 2, 0],
+_triangle_6 1 connected to Element [_segment_3, 1, 0], Element [_segment_3, 3, 0], Element [_segment_3, 4, 0],
+_triangle_6 2 connected to Element [_segment_3, 0, 0], Element [_segment_3, 3, 0], Element [_segment_3, 5, 0],
+_triangle_6 3 connected to Element [_segment_3, 2, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0],
+_triangle_6 4 connected to Element [_segment_3, 0, 0], Element [_segment_3, 6, 0], Element [_segment_3, 7, 0],
+_triangle_6 5 connected to Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 9, 0],
+_triangle_6 6 connected to Element [_segment_3, 6, 0], Element [_segment_3, 8, 0], Element [_segment_3, 10, 0],
+_triangle_6 7 connected to Element [_segment_3, 0, 0], Element [_segment_3, 9, 0], Element [_segment_3, 10, 0],
+_triangle_6 8 connected to Element [_segment_3, 11, 0], Element [_segment_3, 12, 0], Element [_segment_3, 13, 0],
+_triangle_6 9 connected to Element [_segment_3, 3, 0], Element [_segment_3, 12, 0], Element [_segment_3, 14, 0],
+_triangle_6 10 connected to Element [_segment_3, 11, 0], Element [_segment_3, 14, 0], Element [_segment_3, 15, 0],
+_triangle_6 11 connected to Element [_segment_3, 3, 0], Element [_segment_3, 13, 0], Element [_segment_3, 15, 0],
+_triangle_6 12 connected to Element [_segment_3, 16, 0], Element [_segment_3, 17, 0], Element [_segment_3, 18, 0],
+_triangle_6 13 connected to Element [_segment_3, 17, 0], Element [_segment_3, 19, 0], Element [_segment_3, 20, 0],
+_triangle_6 14 connected to Element [_segment_3, 16, 0], Element [_segment_3, 19, 0], Element [_segment_3, 21, 0],
+_triangle_6 15 connected to Element [_segment_3, 18, 0], Element [_segment_3, 20, 0], Element [_segment_3, 21, 0],
+_triangle_6 16 connected to Element [_segment_3, 0, 0], Element [_segment_3, 18, 0], Element [_segment_3, 22, 0],
+_triangle_6 17 connected to Element [_segment_3, 22, 0], Element [_segment_3, 23, 0], Element [_segment_3, 24, 0],
+_triangle_6 18 connected to Element [_segment_3, 0, 0], Element [_segment_3, 13, 0], Element [_segment_3, 23, 0],
+_triangle_6 19 connected to Element [_segment_3, 13, 0], Element [_segment_3, 18, 0], Element [_segment_3, 24, 0],
+_triangle_6 20 connected to Element [_segment_3, 13, 0], Element [_segment_3, 16, 0], Element [_segment_3, 25, 0],
+_triangle_6 21 connected to Element [_segment_3, 17, 0], Element [_segment_3, 24, 0], Element [_segment_3, 25, 0],
+_triangle_6 22 connected to Element [_segment_3, 5, 0], Element [_segment_3, 15, 0], Element [_segment_3, 23, 0],
+_triangle_6 23 connected to Element [_segment_3, 21, 0], Element [_segment_3, 26, 0], Element [_segment_3, 27, 0],
+_triangle_6 24 connected to Element [_segment_3, 0, 0], Element [_segment_3, 21, 0], Element [_segment_3, 28, 0],
+_triangle_6 25 connected to Element [_segment_3, 26, 0], Element [_segment_3, 28, 0], Element [_segment_3, 29, 0],
+_triangle_6 26 connected to Element [_segment_3, 0, 0], Element [_segment_3, 27, 0], Element [_segment_3, 29, 0],
+_triangle_6 27 connected to Element [_segment_3, 20, 0], Element [_segment_3, 22, 0], Element [_segment_3, 28, 0],
+_triangle_6 28 connected to Element [_segment_3, 26, 0], Element [_segment_3, 30, 0], Element [_segment_3, 31, 0],
+_triangle_6 29 connected to Element [_segment_3, 21, 0], Element [_segment_3, 30, 0], Element [_segment_3, 32, 0],
+_triangle_6 30 connected to Element [_segment_3, 27, 0], Element [_segment_3, 31, 0], Element [_segment_3, 32, 0],
+_triangle_6 31 connected to Element [_segment_3, 7, 0], Element [_segment_3, 33, 0], Element [_segment_3, 34, 0],
+_triangle_6 32 connected to Element [_segment_3, 1, 0], Element [_segment_3, 7, 0], Element [_segment_3, 35, 0],
+_triangle_6 33 connected to Element [_segment_3, 33, 0], Element [_segment_3, 35, 0], Element [_segment_3, 36, 0],
+_triangle_6 34 connected to Element [_segment_3, 1, 0], Element [_segment_3, 34, 0], Element [_segment_3, 36, 0],
+_triangle_6 35 connected to Element [_segment_3, 2, 0], Element [_segment_3, 6, 0], Element [_segment_3, 35, 0],
+_triangle_6 36 connected to Element [_segment_3, 4, 0], Element [_segment_3, 14, 0], Element [_segment_3, 37, 0],
+_triangle_6 37 connected to Element [_segment_3, 1, 0], Element [_segment_3, 12, 0], Element [_segment_3, 37, 0],
+_triangle_6 38 connected to Element [_segment_3, 10, 0], Element [_segment_3, 29, 0], Element [_segment_3, 38, 0],
+_triangle_6 39 connected to Element [_segment_3, 9, 0], Element [_segment_3, 27, 0], Element [_segment_3, 38, 0],
+_triangle_6 40 connected to Element [_segment_3, 9, 0], Element [_segment_3, 32, 0], Element [_segment_3, 39, 0],
+_triangle_6 41 connected to Element [_segment_3, 31, 0], Element [_segment_3, 38, 0], Element [_segment_3, 39, 0],
+_triangle_6 42 connected to Element [_segment_3, 8, 0], Element [_segment_3, 33, 0], Element [_segment_3, 40, 0],
+_triangle_6 43 connected to Element [_segment_3, 9, 0], Element [_segment_3, 34, 0], Element [_segment_3, 40, 0],
+SubelementToElement3
+_segment_3 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_3 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_3 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_3 3 connected to Element [_point_1, 1, 0], Element [_point_1, 3, 0],
+_segment_3 4 connected to Element [_point_1, 2, 0], Element [_point_1, 3, 0],
+_segment_3 5 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_3 6 connected to Element [_point_1, 0, 0], Element [_point_1, 4, 0],
+_segment_3 7 connected to Element [_point_1, 1, 0], Element [_point_1, 4, 0],
+_segment_3 8 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_3 9 connected to Element [_point_1, 1, 0], Element [_point_1, 5, 0],
+_segment_3 10 connected to Element [_point_1, 0, 0], Element [_point_1, 5, 0],
+_segment_3 11 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_3 12 connected to Element [_point_1, 1, 0], Element [_point_1, 7, 0],
+_segment_3 13 connected to Element [_point_1, 1, 0], Element [_point_1, 6, 0],
+_segment_3 14 connected to Element [_point_1, 3, 0], Element [_point_1, 7, 0],
+_segment_3 15 connected to Element [_point_1, 3, 0], Element [_point_1, 6, 0],
+_segment_3 16 connected to Element [_point_1, 1, 0], Element [_point_1, 8, 0],
+_segment_3 17 connected to Element [_point_1, 8, 0], Element [_point_1, 9, 0],
+_segment_3 18 connected to Element [_point_1, 1, 0], Element [_point_1, 9, 0],
+_segment_3 19 connected to Element [_point_1, 8, 0], Element [_point_1, 10, 0],
+_segment_3 20 connected to Element [_point_1, 9, 0], Element [_point_1, 10, 0],
+_segment_3 21 connected to Element [_point_1, 1, 0], Element [_point_1, 10, 0],
+_segment_3 22 connected to Element [_point_1, 0, 0], Element [_point_1, 9, 0],
+_segment_3 23 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_3 24 connected to Element [_point_1, 6, 0], Element [_point_1, 9, 0],
+_segment_3 25 connected to Element [_point_1, 6, 0], Element [_point_1, 8, 0],
+_segment_3 26 connected to Element [_point_1, 10, 0], Element [_point_1, 11, 0],
+_segment_3 27 connected to Element [_point_1, 1, 0], Element [_point_1, 11, 0],
+_segment_3 28 connected to Element [_point_1, 0, 0], Element [_point_1, 10, 0],
+_segment_3 29 connected to Element [_point_1, 0, 0], Element [_point_1, 11, 0],
+_segment_3 30 connected to Element [_point_1, 10, 0], Element [_point_1, 12, 0],
+_segment_3 31 connected to Element [_point_1, 11, 0], Element [_point_1, 12, 0],
+_segment_3 32 connected to Element [_point_1, 1, 0], Element [_point_1, 12, 0],
+_segment_3 33 connected to Element [_point_1, 4, 0], Element [_point_1, 13, 0],
+_segment_3 34 connected to Element [_point_1, 1, 0], Element [_point_1, 13, 0],
+_segment_3 35 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_3 36 connected to Element [_point_1, 2, 0], Element [_point_1, 13, 0],
+_segment_3 37 connected to Element [_point_1, 2, 0], Element [_point_1, 7, 0],
+_segment_3 38 connected to Element [_point_1, 5, 0], Element [_point_1, 11, 0],
+_segment_3 39 connected to Element [_point_1, 5, 0], Element [_point_1, 12, 0],
+_segment_3 40 connected to Element [_point_1, 5, 0], Element [_point_1, 13, 0],
+[ OK ] TestBuildFacetFixture/4.Buildfacets (9 ms)
+[----------] 1 test from TestBuildFacetFixture/4 (9 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/5, where TypeParam = std::tuple<akantu::_element_type_hexahedron_8, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/5.Buildfacets
+ElementToSubelement1
+_quadrangle_4 0 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 1 connected to Element [_hexahedron_8, 0, 0], Element [_hexahedron_8, 3, 0],
+_quadrangle_4 2 connected to Element [_hexahedron_8, 0, 0], Element [_hexahedron_8, 1, 0],
+_quadrangle_4 3 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 4 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 5 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 6 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+_quadrangle_4 7 connected to Element [_hexahedron_8, 1, 0], Element [_hexahedron_8, 2, 0],
+_quadrangle_4 8 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+_quadrangle_4 9 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+_quadrangle_4 10 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+_quadrangle_4 11 connected to Element [_hexahedron_8, 2, 0], Element [_hexahedron_8, 3, 0],
+_quadrangle_4 12 connected to Element [_hexahedron_8, 2, 0], ElementNull,
+_quadrangle_4 13 connected to Element [_hexahedron_8, 2, 0], ElementNull,
+_quadrangle_4 14 connected to Element [_hexahedron_8, 2, 0], ElementNull,
+_quadrangle_4 15 connected to Element [_hexahedron_8, 2, 0], ElementNull,
+_quadrangle_4 16 connected to Element [_hexahedron_8, 3, 0], ElementNull,
+_quadrangle_4 17 connected to Element [_hexahedron_8, 3, 0], ElementNull,
+_quadrangle_4 18 connected to Element [_hexahedron_8, 3, 0], ElementNull,
+_quadrangle_4 19 connected to Element [_hexahedron_8, 3, 0], ElementNull,
+ElementToSubelement2
+_segment_2 0 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 4, 0],
+_segment_2 1 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 3, 0],
+_segment_2 2 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 3 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 17, 0],
+_segment_2 4 connected to Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 11, 0],
+_segment_2 5 connected to Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 16, 0],
+_segment_2 6 connected to Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 19, 0],
+_segment_2 7 connected to Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 9, 0],
+_segment_2 8 connected to Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 6, 0],
+_segment_2 9 connected to Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 4, 0],
+_segment_2 10 connected to Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 5, 0],
+_segment_2 11 connected to Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 5, 0],
+_segment_2 12 connected to Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 12, 0],
+_segment_2 13 connected to Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 10, 0],
+_segment_2 14 connected to Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 9, 0],
+_segment_2 15 connected to Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 8, 0], Element [_quadrangle_4, 14, 0],
+_segment_2 16 connected to Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 10, 0], Element [_quadrangle_4, 15, 0],
+_segment_2 17 connected to Element [_quadrangle_4, 8, 0], Element [_quadrangle_4, 9, 0],
+_segment_2 18 connected to Element [_quadrangle_4, 8, 0], Element [_quadrangle_4, 10, 0],
+_segment_2 19 connected to Element [_quadrangle_4, 9, 0], Element [_quadrangle_4, 10, 0],
+_segment_2 20 connected to Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 14, 0], Element [_quadrangle_4, 17, 0],
+_segment_2 21 connected to Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 13, 0], Element [_quadrangle_4, 18, 0],
+_segment_2 22 connected to Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 12, 0], Element [_quadrangle_4, 16, 0],
+_segment_2 23 connected to Element [_quadrangle_4, 12, 0], Element [_quadrangle_4, 13, 0],
+_segment_2 24 connected to Element [_quadrangle_4, 12, 0], Element [_quadrangle_4, 15, 0],
+_segment_2 25 connected to Element [_quadrangle_4, 13, 0], Element [_quadrangle_4, 14, 0],
+_segment_2 26 connected to Element [_quadrangle_4, 13, 0], Element [_quadrangle_4, 15, 0],
+_segment_2 27 connected to Element [_quadrangle_4, 14, 0], Element [_quadrangle_4, 15, 0],
+_segment_2 28 connected to Element [_quadrangle_4, 16, 0], Element [_quadrangle_4, 19, 0],
+_segment_2 29 connected to Element [_quadrangle_4, 16, 0], Element [_quadrangle_4, 18, 0],
+_segment_2 30 connected to Element [_quadrangle_4, 17, 0], Element [_quadrangle_4, 18, 0],
+_segment_2 31 connected to Element [_quadrangle_4, 17, 0], Element [_quadrangle_4, 19, 0],
+_segment_2 32 connected to Element [_quadrangle_4, 18, 0], Element [_quadrangle_4, 19, 0],
+ElementToSubelement3
+_point_1 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 3, 0], Element [_segment_2, 6, 0], Element [_segment_2, 31, 0],
+_point_1 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 9, 0],
+_point_1 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 7, 0], Element [_segment_2, 17, 0],
+_point_1 3 connected to Element [_segment_2, 2, 0], Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 15, 0], Element [_segment_2, 20, 0],
+_point_1 4 connected to Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 8, 0], Element [_segment_2, 12, 0], Element [_segment_2, 22, 0],
+_point_1 5 connected to Element [_segment_2, 5, 0], Element [_segment_2, 6, 0], Element [_segment_2, 11, 0], Element [_segment_2, 28, 0],
+_point_1 6 connected to Element [_segment_2, 7, 0], Element [_segment_2, 8, 0], Element [_segment_2, 10, 0], Element [_segment_2, 14, 0],
+_point_1 7 connected to Element [_segment_2, 9, 0], Element [_segment_2, 10, 0], Element [_segment_2, 11, 0],
+_point_1 8 connected to Element [_segment_2, 12, 0], Element [_segment_2, 13, 0], Element [_segment_2, 16, 0], Element [_segment_2, 24, 0],
+_point_1 9 connected to Element [_segment_2, 13, 0], Element [_segment_2, 14, 0], Element [_segment_2, 19, 0],
+_point_1 10 connected to Element [_segment_2, 15, 0], Element [_segment_2, 16, 0], Element [_segment_2, 18, 0], Element [_segment_2, 27, 0],
+_point_1 11 connected to Element [_segment_2, 17, 0], Element [_segment_2, 18, 0], Element [_segment_2, 19, 0],
+_point_1 12 connected to Element [_segment_2, 20, 0], Element [_segment_2, 21, 0], Element [_segment_2, 25, 0], Element [_segment_2, 30, 0],
+_point_1 13 connected to Element [_segment_2, 21, 0], Element [_segment_2, 22, 0], Element [_segment_2, 23, 0], Element [_segment_2, 29, 0],
+_point_1 14 connected to Element [_segment_2, 23, 0], Element [_segment_2, 24, 0], Element [_segment_2, 26, 0],
+_point_1 15 connected to Element [_segment_2, 25, 0], Element [_segment_2, 26, 0], Element [_segment_2, 27, 0],
+_point_1 16 connected to Element [_segment_2, 28, 0], Element [_segment_2, 29, 0], Element [_segment_2, 32, 0],
+_point_1 17 connected to Element [_segment_2, 30, 0], Element [_segment_2, 31, 0], Element [_segment_2, 32, 0],
+
+SubelementToElement1
+_hexahedron_8 0 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 5, 0],
+_hexahedron_8 1 connected to Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 8, 0], Element [_quadrangle_4, 9, 0], Element [_quadrangle_4, 10, 0],
+_hexahedron_8 2 connected to Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 12, 0], Element [_quadrangle_4, 13, 0], Element [_quadrangle_4, 14, 0], Element [_quadrangle_4, 15, 0],
+_hexahedron_8 3 connected to Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 16, 0], Element [_quadrangle_4, 17, 0], Element [_quadrangle_4, 18, 0], Element [_quadrangle_4, 19, 0],
+SubelementToElement2
+_quadrangle_4 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 3, 0],
+_quadrangle_4 1 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 6, 0],
+_quadrangle_4 2 connected to Element [_segment_2, 2, 0], Element [_segment_2, 4, 0], Element [_segment_2, 7, 0], Element [_segment_2, 8, 0],
+_quadrangle_4 3 connected to Element [_segment_2, 1, 0], Element [_segment_2, 7, 0], Element [_segment_2, 9, 0], Element [_segment_2, 10, 0],
+_quadrangle_4 4 connected to Element [_segment_2, 0, 0], Element [_segment_2, 6, 0], Element [_segment_2, 9, 0], Element [_segment_2, 11, 0],
+_quadrangle_4 5 connected to Element [_segment_2, 5, 0], Element [_segment_2, 8, 0], Element [_segment_2, 10, 0], Element [_segment_2, 11, 0],
+_quadrangle_4 6 connected to Element [_segment_2, 8, 0], Element [_segment_2, 12, 0], Element [_segment_2, 13, 0], Element [_segment_2, 14, 0],
+_quadrangle_4 7 connected to Element [_segment_2, 4, 0], Element [_segment_2, 12, 0], Element [_segment_2, 15, 0], Element [_segment_2, 16, 0],
+_quadrangle_4 8 connected to Element [_segment_2, 2, 0], Element [_segment_2, 15, 0], Element [_segment_2, 17, 0], Element [_segment_2, 18, 0],
+_quadrangle_4 9 connected to Element [_segment_2, 7, 0], Element [_segment_2, 14, 0], Element [_segment_2, 17, 0], Element [_segment_2, 19, 0],
+_quadrangle_4 10 connected to Element [_segment_2, 13, 0], Element [_segment_2, 16, 0], Element [_segment_2, 18, 0], Element [_segment_2, 19, 0],
+_quadrangle_4 11 connected to Element [_segment_2, 4, 0], Element [_segment_2, 20, 0], Element [_segment_2, 21, 0], Element [_segment_2, 22, 0],
+_quadrangle_4 12 connected to Element [_segment_2, 12, 0], Element [_segment_2, 22, 0], Element [_segment_2, 23, 0], Element [_segment_2, 24, 0],
+_quadrangle_4 13 connected to Element [_segment_2, 21, 0], Element [_segment_2, 23, 0], Element [_segment_2, 25, 0], Element [_segment_2, 26, 0],
+_quadrangle_4 14 connected to Element [_segment_2, 15, 0], Element [_segment_2, 20, 0], Element [_segment_2, 25, 0], Element [_segment_2, 27, 0],
+_quadrangle_4 15 connected to Element [_segment_2, 16, 0], Element [_segment_2, 24, 0], Element [_segment_2, 26, 0], Element [_segment_2, 27, 0],
+_quadrangle_4 16 connected to Element [_segment_2, 5, 0], Element [_segment_2, 22, 0], Element [_segment_2, 28, 0], Element [_segment_2, 29, 0],
+_quadrangle_4 17 connected to Element [_segment_2, 3, 0], Element [_segment_2, 20, 0], Element [_segment_2, 30, 0], Element [_segment_2, 31, 0],
+_quadrangle_4 18 connected to Element [_segment_2, 21, 0], Element [_segment_2, 29, 0], Element [_segment_2, 30, 0], Element [_segment_2, 32, 0],
+_quadrangle_4 19 connected to Element [_segment_2, 6, 0], Element [_segment_2, 28, 0], Element [_segment_2, 31, 0], Element [_segment_2, 32, 0],
+SubelementToElement3
+_segment_2 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_2 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_2 2 connected to Element [_point_1, 2, 0], Element [_point_1, 3, 0],
+_segment_2 3 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_2 4 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_2 5 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_2 6 connected to Element [_point_1, 0, 0], Element [_point_1, 5, 0],
+_segment_2 7 connected to Element [_point_1, 2, 0], Element [_point_1, 6, 0],
+_segment_2 8 connected to Element [_point_1, 4, 0], Element [_point_1, 6, 0],
+_segment_2 9 connected to Element [_point_1, 1, 0], Element [_point_1, 7, 0],
+_segment_2 10 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_2 11 connected to Element [_point_1, 5, 0], Element [_point_1, 7, 0],
+_segment_2 12 connected to Element [_point_1, 4, 0], Element [_point_1, 8, 0],
+_segment_2 13 connected to Element [_point_1, 8, 0], Element [_point_1, 9, 0],
+_segment_2 14 connected to Element [_point_1, 6, 0], Element [_point_1, 9, 0],
+_segment_2 15 connected to Element [_point_1, 3, 0], Element [_point_1, 10, 0],
+_segment_2 16 connected to Element [_point_1, 8, 0], Element [_point_1, 10, 0],
+_segment_2 17 connected to Element [_point_1, 2, 0], Element [_point_1, 11, 0],
+_segment_2 18 connected to Element [_point_1, 10, 0], Element [_point_1, 11, 0],
+_segment_2 19 connected to Element [_point_1, 9, 0], Element [_point_1, 11, 0],
+_segment_2 20 connected to Element [_point_1, 3, 0], Element [_point_1, 12, 0],
+_segment_2 21 connected to Element [_point_1, 12, 0], Element [_point_1, 13, 0],
+_segment_2 22 connected to Element [_point_1, 4, 0], Element [_point_1, 13, 0],
+_segment_2 23 connected to Element [_point_1, 13, 0], Element [_point_1, 14, 0],
+_segment_2 24 connected to Element [_point_1, 8, 0], Element [_point_1, 14, 0],
+_segment_2 25 connected to Element [_point_1, 12, 0], Element [_point_1, 15, 0],
+_segment_2 26 connected to Element [_point_1, 14, 0], Element [_point_1, 15, 0],
+_segment_2 27 connected to Element [_point_1, 10, 0], Element [_point_1, 15, 0],
+_segment_2 28 connected to Element [_point_1, 5, 0], Element [_point_1, 16, 0],
+_segment_2 29 connected to Element [_point_1, 13, 0], Element [_point_1, 16, 0],
+_segment_2 30 connected to Element [_point_1, 12, 0], Element [_point_1, 17, 0],
+_segment_2 31 connected to Element [_point_1, 0, 0], Element [_point_1, 17, 0],
+_segment_2 32 connected to Element [_point_1, 16, 0], Element [_point_1, 17, 0],
+[ OK ] TestBuildFacetFixture/5.Buildfacets (3 ms)
+[----------] 1 test from TestBuildFacetFixture/5 (3 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/6, where TypeParam = std::tuple<akantu::_element_type_hexahedron_20, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/6.Buildfacets
+ElementToSubelement1
+_quadrangle_8 0 connected to Element [_hexahedron_20, 0, 0], Element [_hexahedron_20, 3, 0],
+_quadrangle_8 1 connected to Element [_hexahedron_20, 0, 0], Element [_hexahedron_20, 1, 0],
+_quadrangle_8 2 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 3 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 4 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 5 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 6 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+_quadrangle_8 7 connected to Element [_hexahedron_20, 1, 0], Element [_hexahedron_20, 2, 0],
+_quadrangle_8 8 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+_quadrangle_8 9 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+_quadrangle_8 10 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+_quadrangle_8 11 connected to Element [_hexahedron_20, 2, 0], ElementNull,
+_quadrangle_8 12 connected to Element [_hexahedron_20, 2, 0], ElementNull,
+_quadrangle_8 13 connected to Element [_hexahedron_20, 2, 0], ElementNull,
+_quadrangle_8 14 connected to Element [_hexahedron_20, 2, 0], Element [_hexahedron_20, 3, 0],
+_quadrangle_8 15 connected to Element [_hexahedron_20, 2, 0], ElementNull,
+_quadrangle_8 16 connected to Element [_hexahedron_20, 3, 0], ElementNull,
+_quadrangle_8 17 connected to Element [_hexahedron_20, 3, 0], ElementNull,
+_quadrangle_8 18 connected to Element [_hexahedron_20, 3, 0], ElementNull,
+_quadrangle_8 19 connected to Element [_hexahedron_20, 3, 0], ElementNull,
+ElementToSubelement2
+_segment_3 0 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 17, 0],
+_segment_3 1 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 14, 0],
+_segment_3 2 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 16, 0],
+_segment_3 3 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 19, 0],
+_segment_3 4 connected to Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 5 connected to Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 9, 0],
+_segment_3 6 connected to Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 6, 0],
+_segment_3 7 connected to Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 4, 0],
+_segment_3 8 connected to Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 3, 0],
+_segment_3 9 connected to Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 5, 0],
+_segment_3 10 connected to Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 4, 0],
+_segment_3 11 connected to Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 5, 0],
+_segment_3 12 connected to Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 11, 0],
+_segment_3 13 connected to Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 10, 0],
+_segment_3 14 connected to Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 9, 0],
+_segment_3 15 connected to Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 8, 0], Element [_quadrangle_8, 13, 0],
+_segment_3 16 connected to Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 10, 0], Element [_quadrangle_8, 15, 0],
+_segment_3 17 connected to Element [_quadrangle_8, 8, 0], Element [_quadrangle_8, 9, 0],
+_segment_3 18 connected to Element [_quadrangle_8, 8, 0], Element [_quadrangle_8, 10, 0],
+_segment_3 19 connected to Element [_quadrangle_8, 9, 0], Element [_quadrangle_8, 10, 0],
+_segment_3 20 connected to Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 16, 0],
+_segment_3 21 connected to Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 12, 0],
+_segment_3 22 connected to Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 15, 0],
+_segment_3 23 connected to Element [_quadrangle_8, 12, 0], Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 18, 0],
+_segment_3 24 connected to Element [_quadrangle_8, 12, 0], Element [_quadrangle_8, 13, 0],
+_segment_3 25 connected to Element [_quadrangle_8, 12, 0], Element [_quadrangle_8, 15, 0],
+_segment_3 26 connected to Element [_quadrangle_8, 13, 0], Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 17, 0],
+_segment_3 27 connected to Element [_quadrangle_8, 13, 0], Element [_quadrangle_8, 15, 0],
+_segment_3 28 connected to Element [_quadrangle_8, 16, 0], Element [_quadrangle_8, 19, 0],
+_segment_3 29 connected to Element [_quadrangle_8, 16, 0], Element [_quadrangle_8, 18, 0],
+_segment_3 30 connected to Element [_quadrangle_8, 17, 0], Element [_quadrangle_8, 18, 0],
+_segment_3 31 connected to Element [_quadrangle_8, 17, 0], Element [_quadrangle_8, 19, 0],
+_segment_3 32 connected to Element [_quadrangle_8, 18, 0], Element [_quadrangle_8, 19, 0],
+ElementToSubelement3
+_point_1 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 3, 0], Element [_segment_3, 10, 0], Element [_segment_3, 31, 0],
+_point_1 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 4, 0], Element [_segment_3, 15, 0], Element [_segment_3, 26, 0],
+_point_1 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 6, 0], Element [_segment_3, 12, 0], Element [_segment_3, 20, 0],
+_point_1 3 connected to Element [_segment_3, 2, 0], Element [_segment_3, 3, 0], Element [_segment_3, 11, 0], Element [_segment_3, 28, 0],
+_point_1 4 connected to Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 7, 0], Element [_segment_3, 17, 0],
+_point_1 5 connected to Element [_segment_3, 5, 0], Element [_segment_3, 6, 0], Element [_segment_3, 9, 0], Element [_segment_3, 14, 0],
+_point_1 6 connected to Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 10, 0],
+_point_1 7 connected to Element [_segment_3, 8, 0], Element [_segment_3, 9, 0], Element [_segment_3, 11, 0],
+_point_1 8 connected to Element [_segment_3, 12, 0], Element [_segment_3, 13, 0], Element [_segment_3, 16, 0], Element [_segment_3, 22, 0],
+_point_1 9 connected to Element [_segment_3, 13, 0], Element [_segment_3, 14, 0], Element [_segment_3, 19, 0],
+_point_1 10 connected to Element [_segment_3, 15, 0], Element [_segment_3, 16, 0], Element [_segment_3, 18, 0], Element [_segment_3, 27, 0],
+_point_1 11 connected to Element [_segment_3, 17, 0], Element [_segment_3, 18, 0], Element [_segment_3, 19, 0],
+_point_1 12 connected to Element [_segment_3, 20, 0], Element [_segment_3, 21, 0], Element [_segment_3, 23, 0], Element [_segment_3, 29, 0],
+_point_1 13 connected to Element [_segment_3, 21, 0], Element [_segment_3, 22, 0], Element [_segment_3, 25, 0],
+_point_1 14 connected to Element [_segment_3, 23, 0], Element [_segment_3, 24, 0], Element [_segment_3, 26, 0], Element [_segment_3, 30, 0],
+_point_1 15 connected to Element [_segment_3, 24, 0], Element [_segment_3, 25, 0], Element [_segment_3, 27, 0],
+_point_1 16 connected to Element [_segment_3, 28, 0], Element [_segment_3, 29, 0], Element [_segment_3, 32, 0],
+_point_1 17 connected to Element [_segment_3, 30, 0], Element [_segment_3, 31, 0], Element [_segment_3, 32, 0],
+
+SubelementToElement1
+_hexahedron_20 0 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 5, 0],
+_hexahedron_20 1 connected to Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 8, 0], Element [_quadrangle_8, 9, 0], Element [_quadrangle_8, 10, 0],
+_hexahedron_20 2 connected to Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 12, 0], Element [_quadrangle_8, 13, 0], Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 15, 0],
+_hexahedron_20 3 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 16, 0], Element [_quadrangle_8, 17, 0], Element [_quadrangle_8, 18, 0], Element [_quadrangle_8, 19, 0],
+SubelementToElement2
+_quadrangle_8 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 3, 0],
+_quadrangle_8 1 connected to Element [_segment_3, 1, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 6, 0],
+_quadrangle_8 2 connected to Element [_segment_3, 5, 0], Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 9, 0],
+_quadrangle_8 3 connected to Element [_segment_3, 3, 0], Element [_segment_3, 8, 0], Element [_segment_3, 10, 0], Element [_segment_3, 11, 0],
+_quadrangle_8 4 connected to Element [_segment_3, 0, 0], Element [_segment_3, 4, 0], Element [_segment_3, 7, 0], Element [_segment_3, 10, 0],
+_quadrangle_8 5 connected to Element [_segment_3, 2, 0], Element [_segment_3, 6, 0], Element [_segment_3, 9, 0], Element [_segment_3, 11, 0],
+_quadrangle_8 6 connected to Element [_segment_3, 6, 0], Element [_segment_3, 12, 0], Element [_segment_3, 13, 0], Element [_segment_3, 14, 0],
+_quadrangle_8 7 connected to Element [_segment_3, 1, 0], Element [_segment_3, 12, 0], Element [_segment_3, 15, 0], Element [_segment_3, 16, 0],
+_quadrangle_8 8 connected to Element [_segment_3, 4, 0], Element [_segment_3, 15, 0], Element [_segment_3, 17, 0], Element [_segment_3, 18, 0],
+_quadrangle_8 9 connected to Element [_segment_3, 5, 0], Element [_segment_3, 14, 0], Element [_segment_3, 17, 0], Element [_segment_3, 19, 0],
+_quadrangle_8 10 connected to Element [_segment_3, 13, 0], Element [_segment_3, 16, 0], Element [_segment_3, 18, 0], Element [_segment_3, 19, 0],
+_quadrangle_8 11 connected to Element [_segment_3, 12, 0], Element [_segment_3, 20, 0], Element [_segment_3, 21, 0], Element [_segment_3, 22, 0],
+_quadrangle_8 12 connected to Element [_segment_3, 21, 0], Element [_segment_3, 23, 0], Element [_segment_3, 24, 0], Element [_segment_3, 25, 0],
+_quadrangle_8 13 connected to Element [_segment_3, 15, 0], Element [_segment_3, 24, 0], Element [_segment_3, 26, 0], Element [_segment_3, 27, 0],
+_quadrangle_8 14 connected to Element [_segment_3, 1, 0], Element [_segment_3, 20, 0], Element [_segment_3, 23, 0], Element [_segment_3, 26, 0],
+_quadrangle_8 15 connected to Element [_segment_3, 16, 0], Element [_segment_3, 22, 0], Element [_segment_3, 25, 0], Element [_segment_3, 27, 0],
+_quadrangle_8 16 connected to Element [_segment_3, 2, 0], Element [_segment_3, 20, 0], Element [_segment_3, 28, 0], Element [_segment_3, 29, 0],
+_quadrangle_8 17 connected to Element [_segment_3, 0, 0], Element [_segment_3, 26, 0], Element [_segment_3, 30, 0], Element [_segment_3, 31, 0],
+_quadrangle_8 18 connected to Element [_segment_3, 23, 0], Element [_segment_3, 29, 0], Element [_segment_3, 30, 0], Element [_segment_3, 32, 0],
+_quadrangle_8 19 connected to Element [_segment_3, 3, 0], Element [_segment_3, 28, 0], Element [_segment_3, 31, 0], Element [_segment_3, 32, 0],
+SubelementToElement3
+_segment_3 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_3 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_3 2 connected to Element [_point_1, 2, 0], Element [_point_1, 3, 0],
+_segment_3 3 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_3 4 connected to Element [_point_1, 1, 0], Element [_point_1, 4, 0],
+_segment_3 5 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_3 6 connected to Element [_point_1, 2, 0], Element [_point_1, 5, 0],
+_segment_3 7 connected to Element [_point_1, 4, 0], Element [_point_1, 6, 0],
+_segment_3 8 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_3 9 connected to Element [_point_1, 5, 0], Element [_point_1, 7, 0],
+_segment_3 10 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_3 11 connected to Element [_point_1, 3, 0], Element [_point_1, 7, 0],
+_segment_3 12 connected to Element [_point_1, 2, 0], Element [_point_1, 8, 0],
+_segment_3 13 connected to Element [_point_1, 8, 0], Element [_point_1, 9, 0],
+_segment_3 14 connected to Element [_point_1, 5, 0], Element [_point_1, 9, 0],
+_segment_3 15 connected to Element [_point_1, 1, 0], Element [_point_1, 10, 0],
+_segment_3 16 connected to Element [_point_1, 8, 0], Element [_point_1, 10, 0],
+_segment_3 17 connected to Element [_point_1, 4, 0], Element [_point_1, 11, 0],
+_segment_3 18 connected to Element [_point_1, 10, 0], Element [_point_1, 11, 0],
+_segment_3 19 connected to Element [_point_1, 9, 0], Element [_point_1, 11, 0],
+_segment_3 20 connected to Element [_point_1, 2, 0], Element [_point_1, 12, 0],
+_segment_3 21 connected to Element [_point_1, 12, 0], Element [_point_1, 13, 0],
+_segment_3 22 connected to Element [_point_1, 8, 0], Element [_point_1, 13, 0],
+_segment_3 23 connected to Element [_point_1, 12, 0], Element [_point_1, 14, 0],
+_segment_3 24 connected to Element [_point_1, 14, 0], Element [_point_1, 15, 0],
+_segment_3 25 connected to Element [_point_1, 13, 0], Element [_point_1, 15, 0],
+_segment_3 26 connected to Element [_point_1, 1, 0], Element [_point_1, 14, 0],
+_segment_3 27 connected to Element [_point_1, 10, 0], Element [_point_1, 15, 0],
+_segment_3 28 connected to Element [_point_1, 3, 0], Element [_point_1, 16, 0],
+_segment_3 29 connected to Element [_point_1, 12, 0], Element [_point_1, 16, 0],
+_segment_3 30 connected to Element [_point_1, 14, 0], Element [_point_1, 17, 0],
+_segment_3 31 connected to Element [_point_1, 0, 0], Element [_point_1, 17, 0],
+_segment_3 32 connected to Element [_point_1, 16, 0], Element [_point_1, 17, 0],
+[ OK ] TestBuildFacetFixture/6.Buildfacets (3 ms)
+[----------] 1 test from TestBuildFacetFixture/6 (3 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/7, where TypeParam = std::tuple<akantu::_element_type_pentahedron_6, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/7.Buildfacets
+ElementToSubelement1
+_triangle_3 0 connected to Element [_pentahedron_6, 0, 0], ElementNull,
+_triangle_3 1 connected to Element [_pentahedron_6, 0, 0], Element [_pentahedron_6, 2, 0],
+_triangle_3 2 connected to Element [_pentahedron_6, 1, 0], ElementNull,
+_triangle_3 3 connected to Element [_pentahedron_6, 1, 0], Element [_pentahedron_6, 3, 0],
+_triangle_3 4 connected to Element [_pentahedron_6, 2, 0], ElementNull,
+_triangle_3 5 connected to Element [_pentahedron_6, 3, 0], ElementNull,
+ElementToSubelement1
+_quadrangle_4 0 connected to Element [_pentahedron_6, 0, 0], Element [_pentahedron_6, 1, 0],
+_quadrangle_4 1 connected to Element [_pentahedron_6, 0, 0], ElementNull,
+_quadrangle_4 2 connected to Element [_pentahedron_6, 0, 0], ElementNull,
+_quadrangle_4 3 connected to Element [_pentahedron_6, 1, 0], ElementNull,
+_quadrangle_4 4 connected to Element [_pentahedron_6, 1, 0], ElementNull,
+_quadrangle_4 5 connected to Element [_pentahedron_6, 2, 0], Element [_pentahedron_6, 3, 0],
+_quadrangle_4 6 connected to Element [_pentahedron_6, 2, 0], ElementNull,
+_quadrangle_4 7 connected to Element [_pentahedron_6, 2, 0], ElementNull,
+_quadrangle_4 8 connected to Element [_pentahedron_6, 3, 0], ElementNull,
+_quadrangle_4 9 connected to Element [_pentahedron_6, 3, 0], ElementNull,
+ElementToSubelement2
+_segment_2 0 connected to Element [_triangle_3, 0, 0], Element [_quadrangle_4, 1, 0],
+_segment_2 1 connected to Element [_triangle_3, 0, 0], Element [_quadrangle_4, 2, 0],
+_segment_2 2 connected to Element [_triangle_3, 0, 0], Element [_triangle_3, 2, 0], Element [_quadrangle_4, 0, 0],
+_segment_2 3 connected to Element [_triangle_3, 1, 0], Element [_triangle_3, 3, 0], Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 5, 0],
+_segment_2 4 connected to Element [_triangle_3, 1, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 7, 0],
+_segment_2 5 connected to Element [_triangle_3, 1, 0], Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 6, 0],
+_segment_2 6 connected to Element [_triangle_3, 2, 0], Element [_quadrangle_4, 4, 0],
+_segment_2 7 connected to Element [_triangle_3, 2, 0], Element [_quadrangle_4, 3, 0],
+_segment_2 8 connected to Element [_triangle_3, 3, 0], Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 9 connected to Element [_triangle_3, 3, 0], Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 9, 0],
+_segment_2 10 connected to Element [_triangle_3, 4, 0], Element [_triangle_3, 5, 0], Element [_quadrangle_4, 5, 0],
+_segment_2 11 connected to Element [_triangle_3, 4, 0], Element [_quadrangle_4, 7, 0],
+_segment_2 12 connected to Element [_triangle_3, 4, 0], Element [_quadrangle_4, 6, 0],
+_segment_2 13 connected to Element [_triangle_3, 5, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 14 connected to Element [_triangle_3, 5, 0], Element [_quadrangle_4, 9, 0],
+_segment_2 15 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 3, 0],
+_segment_2 16 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 4, 0],
+_segment_2 17 connected to Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 2, 0],
+_segment_2 18 connected to Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 4, 0],
+_segment_2 19 connected to Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 20 connected to Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 9, 0],
+_segment_2 21 connected to Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 7, 0],
+_segment_2 22 connected to Element [_quadrangle_4, 8, 0], Element [_quadrangle_4, 9, 0],
+ElementToSubelement3
+_point_1 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 2, 0], Element [_segment_2, 6, 0], Element [_segment_2, 16, 0],
+_point_1 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 17, 0],
+_point_1 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 7, 0], Element [_segment_2, 15, 0],
+_point_1 3 connected to Element [_segment_2, 3, 0], Element [_segment_2, 5, 0], Element [_segment_2, 9, 0], Element [_segment_2, 16, 0], Element [_segment_2, 20, 0],
+_point_1 4 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 8, 0], Element [_segment_2, 15, 0], Element [_segment_2, 19, 0],
+_point_1 5 connected to Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 17, 0], Element [_segment_2, 21, 0],
+_point_1 6 connected to Element [_segment_2, 6, 0], Element [_segment_2, 7, 0], Element [_segment_2, 18, 0],
+_point_1 7 connected to Element [_segment_2, 8, 0], Element [_segment_2, 9, 0], Element [_segment_2, 18, 0], Element [_segment_2, 22, 0],
+_point_1 8 connected to Element [_segment_2, 10, 0], Element [_segment_2, 12, 0], Element [_segment_2, 14, 0], Element [_segment_2, 20, 0],
+_point_1 9 connected to Element [_segment_2, 10, 0], Element [_segment_2, 11, 0], Element [_segment_2, 13, 0], Element [_segment_2, 19, 0],
+_point_1 10 connected to Element [_segment_2, 11, 0], Element [_segment_2, 12, 0], Element [_segment_2, 21, 0],
+_point_1 11 connected to Element [_segment_2, 13, 0], Element [_segment_2, 14, 0], Element [_segment_2, 22, 0],
+
+SubelementToElement1
+_pentahedron_6 0 connected to Element [_triangle_3, 0, 0], Element [_triangle_3, 1, 0], Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 2, 0],
+_pentahedron_6 1 connected to Element [_triangle_3, 2, 0], Element [_triangle_3, 3, 0], Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 4, 0],
+_pentahedron_6 2 connected to Element [_triangle_3, 1, 0], Element [_triangle_3, 4, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 7, 0],
+_pentahedron_6 3 connected to Element [_triangle_3, 3, 0], Element [_triangle_3, 5, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 8, 0], Element [_quadrangle_4, 9, 0],
+SubelementToElement2
+_triangle_3 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 2, 0],
+_triangle_3 1 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 5, 0],
+_triangle_3 2 connected to Element [_segment_2, 2, 0], Element [_segment_2, 6, 0], Element [_segment_2, 7, 0],
+_triangle_3 3 connected to Element [_segment_2, 3, 0], Element [_segment_2, 8, 0], Element [_segment_2, 9, 0],
+_triangle_3 4 connected to Element [_segment_2, 10, 0], Element [_segment_2, 11, 0], Element [_segment_2, 12, 0],
+_triangle_3 5 connected to Element [_segment_2, 10, 0], Element [_segment_2, 13, 0], Element [_segment_2, 14, 0],
+SubelementToElement2
+_quadrangle_4 0 connected to Element [_segment_2, 2, 0], Element [_segment_2, 3, 0], Element [_segment_2, 15, 0], Element [_segment_2, 16, 0],
+_quadrangle_4 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 5, 0], Element [_segment_2, 16, 0], Element [_segment_2, 17, 0],
+_quadrangle_4 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 4, 0], Element [_segment_2, 15, 0], Element [_segment_2, 17, 0],
+_quadrangle_4 3 connected to Element [_segment_2, 7, 0], Element [_segment_2, 8, 0], Element [_segment_2, 15, 0], Element [_segment_2, 18, 0],
+_quadrangle_4 4 connected to Element [_segment_2, 6, 0], Element [_segment_2, 9, 0], Element [_segment_2, 16, 0], Element [_segment_2, 18, 0],
+_quadrangle_4 5 connected to Element [_segment_2, 3, 0], Element [_segment_2, 10, 0], Element [_segment_2, 19, 0], Element [_segment_2, 20, 0],
+_quadrangle_4 6 connected to Element [_segment_2, 5, 0], Element [_segment_2, 12, 0], Element [_segment_2, 20, 0], Element [_segment_2, 21, 0],
+_quadrangle_4 7 connected to Element [_segment_2, 4, 0], Element [_segment_2, 11, 0], Element [_segment_2, 19, 0], Element [_segment_2, 21, 0],
+_quadrangle_4 8 connected to Element [_segment_2, 8, 0], Element [_segment_2, 13, 0], Element [_segment_2, 19, 0], Element [_segment_2, 22, 0],
+_quadrangle_4 9 connected to Element [_segment_2, 9, 0], Element [_segment_2, 14, 0], Element [_segment_2, 20, 0], Element [_segment_2, 22, 0],
+SubelementToElement3
+_segment_2 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_2 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_2 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_2 3 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_2 4 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_2 5 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_2 6 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_2 7 connected to Element [_point_1, 2, 0], Element [_point_1, 6, 0],
+_segment_2 8 connected to Element [_point_1, 4, 0], Element [_point_1, 7, 0],
+_segment_2 9 connected to Element [_point_1, 3, 0], Element [_point_1, 7, 0],
+_segment_2 10 connected to Element [_point_1, 8, 0], Element [_point_1, 9, 0],
+_segment_2 11 connected to Element [_point_1, 9, 0], Element [_point_1, 10, 0],
+_segment_2 12 connected to Element [_point_1, 8, 0], Element [_point_1, 10, 0],
+_segment_2 13 connected to Element [_point_1, 9, 0], Element [_point_1, 11, 0],
+_segment_2 14 connected to Element [_point_1, 8, 0], Element [_point_1, 11, 0],
+_segment_2 15 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_2 16 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_2 17 connected to Element [_point_1, 1, 0], Element [_point_1, 5, 0],
+_segment_2 18 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_2 19 connected to Element [_point_1, 4, 0], Element [_point_1, 9, 0],
+_segment_2 20 connected to Element [_point_1, 3, 0], Element [_point_1, 8, 0],
+_segment_2 21 connected to Element [_point_1, 5, 0], Element [_point_1, 10, 0],
+_segment_2 22 connected to Element [_point_1, 7, 0], Element [_point_1, 11, 0],
+[ OK ] TestBuildFacetFixture/7.Buildfacets (2 ms)
+[----------] 1 test from TestBuildFacetFixture/7 (2 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/8, where TypeParam = std::tuple<akantu::_element_type_pentahedron_15, std::integral_constant<akantu::ElementType, (akantu::ElementType)0> >
+[ RUN ] TestBuildFacetFixture/8.Buildfacets
+ElementToSubelement1
+_triangle_6 0 connected to Element [_pentahedron_15, 0, 0], ElementNull,
+_triangle_6 1 connected to Element [_pentahedron_15, 0, 0], Element [_pentahedron_15, 2, 0],
+_triangle_6 2 connected to Element [_pentahedron_15, 1, 0], ElementNull,
+_triangle_6 3 connected to Element [_pentahedron_15, 1, 0], Element [_pentahedron_15, 3, 0],
+_triangle_6 4 connected to Element [_pentahedron_15, 2, 0], ElementNull,
+_triangle_6 5 connected to Element [_pentahedron_15, 3, 0], ElementNull,
+ElementToSubelement1
+_quadrangle_8 0 connected to Element [_pentahedron_15, 0, 0], Element [_pentahedron_15, 1, 0],
+_quadrangle_8 1 connected to Element [_pentahedron_15, 0, 0], ElementNull,
+_quadrangle_8 2 connected to Element [_pentahedron_15, 0, 0], ElementNull,
+_quadrangle_8 3 connected to Element [_pentahedron_15, 1, 0], ElementNull,
+_quadrangle_8 4 connected to Element [_pentahedron_15, 1, 0], ElementNull,
+_quadrangle_8 5 connected to Element [_pentahedron_15, 2, 0], Element [_pentahedron_15, 3, 0],
+_quadrangle_8 6 connected to Element [_pentahedron_15, 2, 0], ElementNull,
+_quadrangle_8 7 connected to Element [_pentahedron_15, 2, 0], ElementNull,
+_quadrangle_8 8 connected to Element [_pentahedron_15, 3, 0], ElementNull,
+_quadrangle_8 9 connected to Element [_pentahedron_15, 3, 0], ElementNull,
+ElementToSubelement2
+_segment_3 0 connected to Element [_triangle_6, 0, 0], Element [_quadrangle_8, 1, 0],
+_segment_3 1 connected to Element [_triangle_6, 0, 0], Element [_quadrangle_8, 2, 0],
+_segment_3 2 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 2, 0], Element [_quadrangle_8, 0, 0],
+_segment_3 3 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 3, 0], Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 5, 0],
+_segment_3 4 connected to Element [_triangle_6, 1, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 7, 0],
+_segment_3 5 connected to Element [_triangle_6, 1, 0], Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 6, 0],
+_segment_3 6 connected to Element [_triangle_6, 2, 0], Element [_quadrangle_8, 4, 0],
+_segment_3 7 connected to Element [_triangle_6, 2, 0], Element [_quadrangle_8, 3, 0],
+_segment_3 8 connected to Element [_triangle_6, 3, 0], Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 9 connected to Element [_triangle_6, 3, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 9, 0],
+_segment_3 10 connected to Element [_triangle_6, 4, 0], Element [_triangle_6, 5, 0], Element [_quadrangle_8, 5, 0],
+_segment_3 11 connected to Element [_triangle_6, 4, 0], Element [_quadrangle_8, 7, 0],
+_segment_3 12 connected to Element [_triangle_6, 4, 0], Element [_quadrangle_8, 6, 0],
+_segment_3 13 connected to Element [_triangle_6, 5, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 14 connected to Element [_triangle_6, 5, 0], Element [_quadrangle_8, 9, 0],
+_segment_3 15 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 3, 0],
+_segment_3 16 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 4, 0],
+_segment_3 17 connected to Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 2, 0],
+_segment_3 18 connected to Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 4, 0],
+_segment_3 19 connected to Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 20 connected to Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 9, 0],
+_segment_3 21 connected to Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 7, 0],
+_segment_3 22 connected to Element [_quadrangle_8, 8, 0], Element [_quadrangle_8, 9, 0],
+ElementToSubelement3
+_point_1 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 2, 0], Element [_segment_3, 6, 0], Element [_segment_3, 16, 0],
+_point_1 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 17, 0],
+_point_1 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 7, 0], Element [_segment_3, 15, 0],
+_point_1 3 connected to Element [_segment_3, 3, 0], Element [_segment_3, 5, 0], Element [_segment_3, 9, 0], Element [_segment_3, 16, 0], Element [_segment_3, 20, 0],
+_point_1 4 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 8, 0], Element [_segment_3, 15, 0], Element [_segment_3, 19, 0],
+_point_1 5 connected to Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 17, 0], Element [_segment_3, 21, 0],
+_point_1 6 connected to Element [_segment_3, 6, 0], Element [_segment_3, 7, 0], Element [_segment_3, 18, 0],
+_point_1 7 connected to Element [_segment_3, 8, 0], Element [_segment_3, 9, 0], Element [_segment_3, 18, 0], Element [_segment_3, 22, 0],
+_point_1 8 connected to Element [_segment_3, 10, 0], Element [_segment_3, 12, 0], Element [_segment_3, 14, 0], Element [_segment_3, 20, 0],
+_point_1 9 connected to Element [_segment_3, 10, 0], Element [_segment_3, 11, 0], Element [_segment_3, 13, 0], Element [_segment_3, 19, 0],
+_point_1 10 connected to Element [_segment_3, 11, 0], Element [_segment_3, 12, 0], Element [_segment_3, 21, 0],
+_point_1 11 connected to Element [_segment_3, 13, 0], Element [_segment_3, 14, 0], Element [_segment_3, 22, 0],
+
+SubelementToElement1
+_pentahedron_15 0 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 1, 0], Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 2, 0],
+_pentahedron_15 1 connected to Element [_triangle_6, 2, 0], Element [_triangle_6, 3, 0], Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 4, 0],
+_pentahedron_15 2 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 4, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 7, 0],
+_pentahedron_15 3 connected to Element [_triangle_6, 3, 0], Element [_triangle_6, 5, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 8, 0], Element [_quadrangle_8, 9, 0],
+SubelementToElement2
+_triangle_6 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 2, 0],
+_triangle_6 1 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0],
+_triangle_6 2 connected to Element [_segment_3, 2, 0], Element [_segment_3, 6, 0], Element [_segment_3, 7, 0],
+_triangle_6 3 connected to Element [_segment_3, 3, 0], Element [_segment_3, 8, 0], Element [_segment_3, 9, 0],
+_triangle_6 4 connected to Element [_segment_3, 10, 0], Element [_segment_3, 11, 0], Element [_segment_3, 12, 0],
+_triangle_6 5 connected to Element [_segment_3, 10, 0], Element [_segment_3, 13, 0], Element [_segment_3, 14, 0],
+SubelementToElement2
+_quadrangle_8 0 connected to Element [_segment_3, 2, 0], Element [_segment_3, 3, 0], Element [_segment_3, 15, 0], Element [_segment_3, 16, 0],
+_quadrangle_8 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 5, 0], Element [_segment_3, 16, 0], Element [_segment_3, 17, 0],
+_quadrangle_8 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 4, 0], Element [_segment_3, 15, 0], Element [_segment_3, 17, 0],
+_quadrangle_8 3 connected to Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 15, 0], Element [_segment_3, 18, 0],
+_quadrangle_8 4 connected to Element [_segment_3, 6, 0], Element [_segment_3, 9, 0], Element [_segment_3, 16, 0], Element [_segment_3, 18, 0],
+_quadrangle_8 5 connected to Element [_segment_3, 3, 0], Element [_segment_3, 10, 0], Element [_segment_3, 19, 0], Element [_segment_3, 20, 0],
+_quadrangle_8 6 connected to Element [_segment_3, 5, 0], Element [_segment_3, 12, 0], Element [_segment_3, 20, 0], Element [_segment_3, 21, 0],
+_quadrangle_8 7 connected to Element [_segment_3, 4, 0], Element [_segment_3, 11, 0], Element [_segment_3, 19, 0], Element [_segment_3, 21, 0],
+_quadrangle_8 8 connected to Element [_segment_3, 8, 0], Element [_segment_3, 13, 0], Element [_segment_3, 19, 0], Element [_segment_3, 22, 0],
+_quadrangle_8 9 connected to Element [_segment_3, 9, 0], Element [_segment_3, 14, 0], Element [_segment_3, 20, 0], Element [_segment_3, 22, 0],
+SubelementToElement3
+_segment_3 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_3 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_3 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_3 3 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_3 4 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_3 5 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_3 6 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_3 7 connected to Element [_point_1, 2, 0], Element [_point_1, 6, 0],
+_segment_3 8 connected to Element [_point_1, 4, 0], Element [_point_1, 7, 0],
+_segment_3 9 connected to Element [_point_1, 3, 0], Element [_point_1, 7, 0],
+_segment_3 10 connected to Element [_point_1, 8, 0], Element [_point_1, 9, 0],
+_segment_3 11 connected to Element [_point_1, 9, 0], Element [_point_1, 10, 0],
+_segment_3 12 connected to Element [_point_1, 8, 0], Element [_point_1, 10, 0],
+_segment_3 13 connected to Element [_point_1, 9, 0], Element [_point_1, 11, 0],
+_segment_3 14 connected to Element [_point_1, 8, 0], Element [_point_1, 11, 0],
+_segment_3 15 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_3 16 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_3 17 connected to Element [_point_1, 1, 0], Element [_point_1, 5, 0],
+_segment_3 18 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_3 19 connected to Element [_point_1, 4, 0], Element [_point_1, 9, 0],
+_segment_3 20 connected to Element [_point_1, 3, 0], Element [_point_1, 8, 0],
+_segment_3 21 connected to Element [_point_1, 5, 0], Element [_point_1, 10, 0],
+_segment_3 22 connected to Element [_point_1, 7, 0], Element [_point_1, 11, 0],
+[ OK ] TestBuildFacetFixture/8.Buildfacets (3 ms)
+[----------] 1 test from TestBuildFacetFixture/8 (3 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/9, where TypeParam = std::tuple<akantu::_element_type_quadrangle_4, akantu::_element_type_triangle_3>
+[ RUN ] TestBuildFacetFixture/9.Buildfacets
+ElementToSubelement1
+_segment_2 0 connected to Element [_triangle_3, 0, 0], Element [_quadrangle_4, 0, 0],
+_segment_2 1 connected to Element [_triangle_3, 0, 0], Element [_triangle_3, 2, 0],
+_segment_2 2 connected to Element [_triangle_3, 0, 0], ElementNull,
+_segment_2 3 connected to Element [_triangle_3, 1, 0], Element [_quadrangle_4, 1, 0],
+_segment_2 4 connected to Element [_triangle_3, 1, 0], Element [_triangle_3, 3, 0],
+_segment_2 5 connected to Element [_triangle_3, 1, 0], Element [_triangle_3, 2, 0],
+_segment_2 6 connected to Element [_triangle_3, 2, 0], ElementNull,
+_segment_2 7 connected to Element [_triangle_3, 3, 0], ElementNull,
+_segment_2 8 connected to Element [_triangle_3, 3, 0], ElementNull,
+_segment_2 9 connected to Element [_quadrangle_4, 0, 0], ElementNull,
+_segment_2 10 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0],
+_segment_2 11 connected to Element [_quadrangle_4, 0, 0], ElementNull,
+_segment_2 12 connected to Element [_quadrangle_4, 1, 0], ElementNull,
+_segment_2 13 connected to Element [_quadrangle_4, 1, 0], ElementNull,
+ElementToSubelement2
+_point_1 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 2, 0], Element [_segment_2, 11, 0],
+_point_1 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 3, 0], Element [_segment_2, 5, 0], Element [_segment_2, 10, 0],
+_point_1 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 6, 0],
+_point_1 3 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 8, 0], Element [_segment_2, 13, 0],
+_point_1 4 connected to Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 6, 0], Element [_segment_2, 7, 0],
+_point_1 5 connected to Element [_segment_2, 7, 0], Element [_segment_2, 8, 0],
+_point_1 6 connected to Element [_segment_2, 9, 0], Element [_segment_2, 11, 0],
+_point_1 7 connected to Element [_segment_2, 9, 0], Element [_segment_2, 10, 0], Element [_segment_2, 12, 0],
+_point_1 8 connected to Element [_segment_2, 12, 0], Element [_segment_2, 13, 0],
+
+SubelementToElement1
+_quadrangle_4 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 9, 0], Element [_segment_2, 10, 0], Element [_segment_2, 11, 0],
+_quadrangle_4 1 connected to Element [_segment_2, 3, 0], Element [_segment_2, 10, 0], Element [_segment_2, 12, 0], Element [_segment_2, 13, 0],
+SubelementToElement1
+_triangle_3 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 2, 0],
+_triangle_3 1 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 5, 0],
+_triangle_3 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 5, 0], Element [_segment_2, 6, 0],
+_triangle_3 3 connected to Element [_segment_2, 4, 0], Element [_segment_2, 7, 0], Element [_segment_2, 8, 0],
+SubelementToElement2
+_segment_2 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_2 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_2 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_2 3 connected to Element [_point_1, 1, 0], Element [_point_1, 3, 0],
+_segment_2 4 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_2 5 connected to Element [_point_1, 1, 0], Element [_point_1, 4, 0],
+_segment_2 6 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_2 7 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_2 8 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_2 9 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_2 10 connected to Element [_point_1, 1, 0], Element [_point_1, 7, 0],
+_segment_2 11 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_2 12 connected to Element [_point_1, 7, 0], Element [_point_1, 8, 0],
+_segment_2 13 connected to Element [_point_1, 3, 0], Element [_point_1, 8, 0],
+[ OK ] TestBuildFacetFixture/9.Buildfacets (1 ms)
+[----------] 1 test from TestBuildFacetFixture/9 (1 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/10, where TypeParam = std::tuple<akantu::_element_type_quadrangle_8, akantu::_element_type_triangle_6>
+[ RUN ] TestBuildFacetFixture/10.Buildfacets
+ElementToSubelement1
+_segment_3 0 connected to Element [_triangle_6, 0, 0], Element [_quadrangle_8, 0, 0],
+_segment_3 1 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 2, 0],
+_segment_3 2 connected to Element [_triangle_6, 0, 0], ElementNull,
+_segment_3 3 connected to Element [_triangle_6, 1, 0], Element [_quadrangle_8, 1, 0],
+_segment_3 4 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 3, 0],
+_segment_3 5 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 2, 0],
+_segment_3 6 connected to Element [_triangle_6, 2, 0], ElementNull,
+_segment_3 7 connected to Element [_triangle_6, 3, 0], ElementNull,
+_segment_3 8 connected to Element [_triangle_6, 3, 0], ElementNull,
+_segment_3 9 connected to Element [_quadrangle_8, 0, 0], ElementNull,
+_segment_3 10 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0],
+_segment_3 11 connected to Element [_quadrangle_8, 0, 0], ElementNull,
+_segment_3 12 connected to Element [_quadrangle_8, 1, 0], ElementNull,
+_segment_3 13 connected to Element [_quadrangle_8, 1, 0], ElementNull,
+ElementToSubelement2
+_point_1 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 2, 0], Element [_segment_3, 11, 0],
+_point_1 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 3, 0], Element [_segment_3, 5, 0], Element [_segment_3, 10, 0],
+_point_1 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 6, 0],
+_point_1 3 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 8, 0], Element [_segment_3, 13, 0],
+_point_1 4 connected to Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 6, 0], Element [_segment_3, 7, 0],
+_point_1 5 connected to Element [_segment_3, 7, 0], Element [_segment_3, 8, 0],
+_point_1 6 connected to Element [_segment_3, 9, 0], Element [_segment_3, 11, 0],
+_point_1 7 connected to Element [_segment_3, 9, 0], Element [_segment_3, 10, 0], Element [_segment_3, 12, 0],
+_point_1 8 connected to Element [_segment_3, 12, 0], Element [_segment_3, 13, 0],
+
+SubelementToElement1
+_quadrangle_8 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 9, 0], Element [_segment_3, 10, 0], Element [_segment_3, 11, 0],
+_quadrangle_8 1 connected to Element [_segment_3, 3, 0], Element [_segment_3, 10, 0], Element [_segment_3, 12, 0], Element [_segment_3, 13, 0],
+SubelementToElement1
+_triangle_6 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 2, 0],
+_triangle_6 1 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0],
+_triangle_6 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 5, 0], Element [_segment_3, 6, 0],
+_triangle_6 3 connected to Element [_segment_3, 4, 0], Element [_segment_3, 7, 0], Element [_segment_3, 8, 0],
+SubelementToElement2
+_segment_3 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_3 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_3 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_3 3 connected to Element [_point_1, 1, 0], Element [_point_1, 3, 0],
+_segment_3 4 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_3 5 connected to Element [_point_1, 1, 0], Element [_point_1, 4, 0],
+_segment_3 6 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_3 7 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_3 8 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_3 9 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_3 10 connected to Element [_point_1, 1, 0], Element [_point_1, 7, 0],
+_segment_3 11 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_3 12 connected to Element [_point_1, 7, 0], Element [_point_1, 8, 0],
+_segment_3 13 connected to Element [_point_1, 3, 0], Element [_point_1, 8, 0],
+[ OK ] TestBuildFacetFixture/10.Buildfacets (1 ms)
+[----------] 1 test from TestBuildFacetFixture/10 (1 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/11, where TypeParam = std::tuple<akantu::_element_type_hexahedron_8, akantu::_element_type_pentahedron_6>
+[ RUN ] TestBuildFacetFixture/11.Buildfacets
+ElementToSubelement1
+_triangle_3 0 connected to Element [_pentahedron_6, 0, 0], ElementNull,
+_triangle_3 1 connected to Element [_pentahedron_6, 0, 0], ElementNull,
+_triangle_3 2 connected to Element [_pentahedron_6, 1, 0], ElementNull,
+_triangle_3 3 connected to Element [_pentahedron_6, 1, 0], ElementNull,
+_triangle_3 4 connected to Element [_pentahedron_6, 2, 0], ElementNull,
+_triangle_3 5 connected to Element [_pentahedron_6, 2, 0], ElementNull,
+_triangle_3 6 connected to Element [_pentahedron_6, 3, 0], ElementNull,
+_triangle_3 7 connected to Element [_pentahedron_6, 3, 0], ElementNull,
+ElementToSubelement1
+_quadrangle_4 0 connected to Element [_pentahedron_6, 0, 0], Element [_pentahedron_6, 2, 0],
+_quadrangle_4 1 connected to Element [_pentahedron_6, 0, 0], ElementNull,
+_quadrangle_4 2 connected to Element [_pentahedron_6, 0, 0], Element [_hexahedron_8, 0, 0],
+_quadrangle_4 3 connected to Element [_pentahedron_6, 1, 0], Element [_pentahedron_6, 3, 0],
+_quadrangle_4 4 connected to Element [_pentahedron_6, 1, 0], Element [_pentahedron_6, 2, 0],
+_quadrangle_4 5 connected to Element [_pentahedron_6, 1, 0], Element [_hexahedron_8, 1, 0],
+_quadrangle_4 6 connected to Element [_pentahedron_6, 2, 0], ElementNull,
+_quadrangle_4 7 connected to Element [_pentahedron_6, 3, 0], ElementNull,
+_quadrangle_4 8 connected to Element [_pentahedron_6, 3, 0], ElementNull,
+_quadrangle_4 9 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 10 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 11 connected to Element [_hexahedron_8, 0, 0], Element [_hexahedron_8, 1, 0],
+_quadrangle_4 12 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 13 connected to Element [_hexahedron_8, 0, 0], ElementNull,
+_quadrangle_4 14 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+_quadrangle_4 15 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+_quadrangle_4 16 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+_quadrangle_4 17 connected to Element [_hexahedron_8, 1, 0], ElementNull,
+ElementToSubelement2
+_segment_2 0 connected to Element [_triangle_3, 0, 0], Element [_quadrangle_4, 1, 0],
+_segment_2 1 connected to Element [_triangle_3, 0, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 9, 0],
+_segment_2 2 connected to Element [_triangle_3, 0, 0], Element [_triangle_3, 4, 0], Element [_quadrangle_4, 0, 0],
+_segment_2 3 connected to Element [_triangle_3, 1, 0], Element [_triangle_3, 5, 0], Element [_quadrangle_4, 0, 0],
+_segment_2 4 connected to Element [_triangle_3, 1, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 13, 0],
+_segment_2 5 connected to Element [_triangle_3, 1, 0], Element [_quadrangle_4, 1, 0],
+_segment_2 6 connected to Element [_triangle_3, 2, 0], Element [_triangle_3, 4, 0], Element [_quadrangle_4, 4, 0],
+_segment_2 7 connected to Element [_triangle_3, 2, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 14, 0],
+_segment_2 8 connected to Element [_triangle_3, 2, 0], Element [_triangle_3, 6, 0], Element [_quadrangle_4, 3, 0],
+_segment_2 9 connected to Element [_triangle_3, 3, 0], Element [_triangle_3, 7, 0], Element [_quadrangle_4, 3, 0],
+_segment_2 10 connected to Element [_triangle_3, 3, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 17, 0],
+_segment_2 11 connected to Element [_triangle_3, 3, 0], Element [_triangle_3, 5, 0], Element [_quadrangle_4, 4, 0],
+_segment_2 12 connected to Element [_triangle_3, 4, 0], Element [_quadrangle_4, 6, 0],
+_segment_2 13 connected to Element [_triangle_3, 5, 0], Element [_quadrangle_4, 6, 0],
+_segment_2 14 connected to Element [_triangle_3, 6, 0], Element [_quadrangle_4, 7, 0],
+_segment_2 15 connected to Element [_triangle_3, 6, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 16 connected to Element [_triangle_3, 7, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 17 connected to Element [_triangle_3, 7, 0], Element [_quadrangle_4, 7, 0],
+_segment_2 18 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 11, 0],
+_segment_2 19 connected to Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 6, 0],
+_segment_2 20 connected to Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 10, 0],
+_segment_2 21 connected to Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 15, 0],
+_segment_2 22 connected to Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 6, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 23 connected to Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 8, 0],
+_segment_2 24 connected to Element [_quadrangle_4, 9, 0], Element [_quadrangle_4, 12, 0],
+_segment_2 25 connected to Element [_quadrangle_4, 9, 0], Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 14, 0],
+_segment_2 26 connected to Element [_quadrangle_4, 9, 0], Element [_quadrangle_4, 10, 0],
+_segment_2 27 connected to Element [_quadrangle_4, 10, 0], Element [_quadrangle_4, 13, 0],
+_segment_2 28 connected to Element [_quadrangle_4, 10, 0], Element [_quadrangle_4, 12, 0],
+_segment_2 29 connected to Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 12, 0], Element [_quadrangle_4, 16, 0],
+_segment_2 30 connected to Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 13, 0], Element [_quadrangle_4, 17, 0],
+_segment_2 31 connected to Element [_quadrangle_4, 12, 0], Element [_quadrangle_4, 13, 0],
+_segment_2 32 connected to Element [_quadrangle_4, 14, 0], Element [_quadrangle_4, 16, 0],
+_segment_2 33 connected to Element [_quadrangle_4, 14, 0], Element [_quadrangle_4, 15, 0],
+_segment_2 34 connected to Element [_quadrangle_4, 15, 0], Element [_quadrangle_4, 16, 0],
+_segment_2 35 connected to Element [_quadrangle_4, 15, 0], Element [_quadrangle_4, 17, 0],
+_segment_2 36 connected to Element [_quadrangle_4, 16, 0], Element [_quadrangle_4, 17, 0],
+ElementToSubelement3
+_point_1 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 2, 0], Element [_segment_2, 12, 0], Element [_segment_2, 19, 0],
+_point_1 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 20, 0], Element [_segment_2, 26, 0],
+_point_1 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 2, 0], Element [_segment_2, 6, 0], Element [_segment_2, 7, 0], Element [_segment_2, 18, 0], Element [_segment_2, 25, 0],
+_point_1 3 connected to Element [_segment_2, 3, 0], Element [_segment_2, 5, 0], Element [_segment_2, 13, 0], Element [_segment_2, 19, 0],
+_point_1 4 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 10, 0], Element [_segment_2, 11, 0], Element [_segment_2, 18, 0], Element [_segment_2, 30, 0],
+_point_1 5 connected to Element [_segment_2, 4, 0], Element [_segment_2, 5, 0], Element [_segment_2, 20, 0], Element [_segment_2, 27, 0],
+_point_1 6 connected to Element [_segment_2, 6, 0], Element [_segment_2, 8, 0], Element [_segment_2, 12, 0], Element [_segment_2, 15, 0], Element [_segment_2, 22, 0],
+_point_1 7 connected to Element [_segment_2, 7, 0], Element [_segment_2, 8, 0], Element [_segment_2, 14, 0], Element [_segment_2, 21, 0], Element [_segment_2, 33, 0],
+_point_1 8 connected to Element [_segment_2, 9, 0], Element [_segment_2, 11, 0], Element [_segment_2, 13, 0], Element [_segment_2, 16, 0], Element [_segment_2, 22, 0],
+_point_1 9 connected to Element [_segment_2, 9, 0], Element [_segment_2, 10, 0], Element [_segment_2, 17, 0], Element [_segment_2, 21, 0], Element [_segment_2, 35, 0],
+_point_1 10 connected to Element [_segment_2, 14, 0], Element [_segment_2, 15, 0], Element [_segment_2, 23, 0],
+_point_1 11 connected to Element [_segment_2, 16, 0], Element [_segment_2, 17, 0], Element [_segment_2, 23, 0],
+_point_1 12 connected to Element [_segment_2, 24, 0], Element [_segment_2, 26, 0], Element [_segment_2, 28, 0],
+_point_1 13 connected to Element [_segment_2, 24, 0], Element [_segment_2, 25, 0], Element [_segment_2, 29, 0], Element [_segment_2, 32, 0],
+_point_1 14 connected to Element [_segment_2, 27, 0], Element [_segment_2, 28, 0], Element [_segment_2, 31, 0],
+_point_1 15 connected to Element [_segment_2, 29, 0], Element [_segment_2, 30, 0], Element [_segment_2, 31, 0], Element [_segment_2, 36, 0],
+_point_1 16 connected to Element [_segment_2, 32, 0], Element [_segment_2, 33, 0], Element [_segment_2, 34, 0],
+_point_1 17 connected to Element [_segment_2, 34, 0], Element [_segment_2, 35, 0], Element [_segment_2, 36, 0],
+
+SubelementToElement1
+_hexahedron_8 0 connected to Element [_quadrangle_4, 2, 0], Element [_quadrangle_4, 9, 0], Element [_quadrangle_4, 10, 0], Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 12, 0], Element [_quadrangle_4, 13, 0],
+_hexahedron_8 1 connected to Element [_quadrangle_4, 5, 0], Element [_quadrangle_4, 11, 0], Element [_quadrangle_4, 14, 0], Element [_quadrangle_4, 15, 0], Element [_quadrangle_4, 16, 0], Element [_quadrangle_4, 17, 0],
+SubelementToElement1
+_pentahedron_6 0 connected to Element [_triangle_3, 0, 0], Element [_triangle_3, 1, 0], Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 1, 0], Element [_quadrangle_4, 2, 0],
+_pentahedron_6 1 connected to Element [_triangle_3, 2, 0], Element [_triangle_3, 3, 0], Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 5, 0],
+_pentahedron_6 2 connected to Element [_triangle_3, 4, 0], Element [_triangle_3, 5, 0], Element [_quadrangle_4, 0, 0], Element [_quadrangle_4, 4, 0], Element [_quadrangle_4, 6, 0],
+_pentahedron_6 3 connected to Element [_triangle_3, 6, 0], Element [_triangle_3, 7, 0], Element [_quadrangle_4, 3, 0], Element [_quadrangle_4, 7, 0], Element [_quadrangle_4, 8, 0],
+SubelementToElement2
+_triangle_3 0 connected to Element [_segment_2, 0, 0], Element [_segment_2, 1, 0], Element [_segment_2, 2, 0],
+_triangle_3 1 connected to Element [_segment_2, 3, 0], Element [_segment_2, 4, 0], Element [_segment_2, 5, 0],
+_triangle_3 2 connected to Element [_segment_2, 6, 0], Element [_segment_2, 7, 0], Element [_segment_2, 8, 0],
+_triangle_3 3 connected to Element [_segment_2, 9, 0], Element [_segment_2, 10, 0], Element [_segment_2, 11, 0],
+_triangle_3 4 connected to Element [_segment_2, 2, 0], Element [_segment_2, 6, 0], Element [_segment_2, 12, 0],
+_triangle_3 5 connected to Element [_segment_2, 3, 0], Element [_segment_2, 11, 0], Element [_segment_2, 13, 0],
+_triangle_3 6 connected to Element [_segment_2, 8, 0], Element [_segment_2, 14, 0], Element [_segment_2, 15, 0],
+_triangle_3 7 connected to Element [_segment_2, 9, 0], Element [_segment_2, 16, 0], Element [_segment_2, 17, 0],
+SubelementToElement2
+_quadrangle_4 0 connected to Element [_segment_2, 2, 0], Element [_segment_2, 3, 0], Element [_segment_2, 18, 0], Element [_segment_2, 19, 0],
+_quadrangle_4 1 connected to Element [_segment_2, 0, 0], Element [_segment_2, 5, 0], Element [_segment_2, 19, 0], Element [_segment_2, 20, 0],
+_quadrangle_4 2 connected to Element [_segment_2, 1, 0], Element [_segment_2, 4, 0], Element [_segment_2, 18, 0], Element [_segment_2, 20, 0],
+_quadrangle_4 3 connected to Element [_segment_2, 8, 0], Element [_segment_2, 9, 0], Element [_segment_2, 21, 0], Element [_segment_2, 22, 0],
+_quadrangle_4 4 connected to Element [_segment_2, 6, 0], Element [_segment_2, 11, 0], Element [_segment_2, 18, 0], Element [_segment_2, 22, 0],
+_quadrangle_4 5 connected to Element [_segment_2, 7, 0], Element [_segment_2, 10, 0], Element [_segment_2, 18, 0], Element [_segment_2, 21, 0],
+_quadrangle_4 6 connected to Element [_segment_2, 12, 0], Element [_segment_2, 13, 0], Element [_segment_2, 19, 0], Element [_segment_2, 22, 0],
+_quadrangle_4 7 connected to Element [_segment_2, 14, 0], Element [_segment_2, 17, 0], Element [_segment_2, 21, 0], Element [_segment_2, 23, 0],
+_quadrangle_4 8 connected to Element [_segment_2, 15, 0], Element [_segment_2, 16, 0], Element [_segment_2, 22, 0], Element [_segment_2, 23, 0],
+_quadrangle_4 9 connected to Element [_segment_2, 1, 0], Element [_segment_2, 24, 0], Element [_segment_2, 25, 0], Element [_segment_2, 26, 0],
+_quadrangle_4 10 connected to Element [_segment_2, 20, 0], Element [_segment_2, 26, 0], Element [_segment_2, 27, 0], Element [_segment_2, 28, 0],
+_quadrangle_4 11 connected to Element [_segment_2, 18, 0], Element [_segment_2, 25, 0], Element [_segment_2, 29, 0], Element [_segment_2, 30, 0],
+_quadrangle_4 12 connected to Element [_segment_2, 24, 0], Element [_segment_2, 28, 0], Element [_segment_2, 29, 0], Element [_segment_2, 31, 0],
+_quadrangle_4 13 connected to Element [_segment_2, 4, 0], Element [_segment_2, 27, 0], Element [_segment_2, 30, 0], Element [_segment_2, 31, 0],
+_quadrangle_4 14 connected to Element [_segment_2, 7, 0], Element [_segment_2, 25, 0], Element [_segment_2, 32, 0], Element [_segment_2, 33, 0],
+_quadrangle_4 15 connected to Element [_segment_2, 21, 0], Element [_segment_2, 33, 0], Element [_segment_2, 34, 0], Element [_segment_2, 35, 0],
+_quadrangle_4 16 connected to Element [_segment_2, 29, 0], Element [_segment_2, 32, 0], Element [_segment_2, 34, 0], Element [_segment_2, 36, 0],
+_quadrangle_4 17 connected to Element [_segment_2, 10, 0], Element [_segment_2, 30, 0], Element [_segment_2, 35, 0], Element [_segment_2, 36, 0],
+SubelementToElement3
+_segment_2 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_2 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_2 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_2 3 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_2 4 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_2 5 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_2 6 connected to Element [_point_1, 2, 0], Element [_point_1, 6, 0],
+_segment_2 7 connected to Element [_point_1, 2, 0], Element [_point_1, 7, 0],
+_segment_2 8 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_2 9 connected to Element [_point_1, 8, 0], Element [_point_1, 9, 0],
+_segment_2 10 connected to Element [_point_1, 4, 0], Element [_point_1, 9, 0],
+_segment_2 11 connected to Element [_point_1, 4, 0], Element [_point_1, 8, 0],
+_segment_2 12 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_2 13 connected to Element [_point_1, 3, 0], Element [_point_1, 8, 0],
+_segment_2 14 connected to Element [_point_1, 7, 0], Element [_point_1, 10, 0],
+_segment_2 15 connected to Element [_point_1, 6, 0], Element [_point_1, 10, 0],
+_segment_2 16 connected to Element [_point_1, 8, 0], Element [_point_1, 11, 0],
+_segment_2 17 connected to Element [_point_1, 9, 0], Element [_point_1, 11, 0],
+_segment_2 18 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_2 19 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_2 20 connected to Element [_point_1, 1, 0], Element [_point_1, 5, 0],
+_segment_2 21 connected to Element [_point_1, 7, 0], Element [_point_1, 9, 0],
+_segment_2 22 connected to Element [_point_1, 6, 0], Element [_point_1, 8, 0],
+_segment_2 23 connected to Element [_point_1, 10, 0], Element [_point_1, 11, 0],
+_segment_2 24 connected to Element [_point_1, 12, 0], Element [_point_1, 13, 0],
+_segment_2 25 connected to Element [_point_1, 2, 0], Element [_point_1, 13, 0],
+_segment_2 26 connected to Element [_point_1, 1, 0], Element [_point_1, 12, 0],
+_segment_2 27 connected to Element [_point_1, 5, 0], Element [_point_1, 14, 0],
+_segment_2 28 connected to Element [_point_1, 12, 0], Element [_point_1, 14, 0],
+_segment_2 29 connected to Element [_point_1, 13, 0], Element [_point_1, 15, 0],
+_segment_2 30 connected to Element [_point_1, 4, 0], Element [_point_1, 15, 0],
+_segment_2 31 connected to Element [_point_1, 14, 0], Element [_point_1, 15, 0],
+_segment_2 32 connected to Element [_point_1, 13, 0], Element [_point_1, 16, 0],
+_segment_2 33 connected to Element [_point_1, 7, 0], Element [_point_1, 16, 0],
+_segment_2 34 connected to Element [_point_1, 16, 0], Element [_point_1, 17, 0],
+_segment_2 35 connected to Element [_point_1, 9, 0], Element [_point_1, 17, 0],
+_segment_2 36 connected to Element [_point_1, 15, 0], Element [_point_1, 17, 0],
+[ OK ] TestBuildFacetFixture/11.Buildfacets (3 ms)
+[----------] 1 test from TestBuildFacetFixture/11 (3 ms total)
+
+[----------] 1 test from TestBuildFacetFixture/12, where TypeParam = std::tuple<akantu::_element_type_hexahedron_20, akantu::_element_type_pentahedron_15>
+[ RUN ] TestBuildFacetFixture/12.Buildfacets
+ElementToSubelement1
+_triangle_6 0 connected to Element [_pentahedron_15, 0, 0], ElementNull,
+_triangle_6 1 connected to Element [_pentahedron_15, 0, 0], ElementNull,
+_triangle_6 2 connected to Element [_pentahedron_15, 1, 0], ElementNull,
+_triangle_6 3 connected to Element [_pentahedron_15, 1, 0], ElementNull,
+_triangle_6 4 connected to Element [_pentahedron_15, 2, 0], ElementNull,
+_triangle_6 5 connected to Element [_pentahedron_15, 2, 0], ElementNull,
+_triangle_6 6 connected to Element [_pentahedron_15, 3, 0], ElementNull,
+_triangle_6 7 connected to Element [_pentahedron_15, 3, 0], ElementNull,
+ElementToSubelement1
+_quadrangle_8 0 connected to Element [_pentahedron_15, 0, 0], Element [_pentahedron_15, 2, 0],
+_quadrangle_8 1 connected to Element [_pentahedron_15, 0, 0], ElementNull,
+_quadrangle_8 2 connected to Element [_pentahedron_15, 0, 0], Element [_hexahedron_20, 0, 0],
+_quadrangle_8 3 connected to Element [_pentahedron_15, 1, 0], Element [_pentahedron_15, 3, 0],
+_quadrangle_8 4 connected to Element [_pentahedron_15, 1, 0], Element [_pentahedron_15, 2, 0],
+_quadrangle_8 5 connected to Element [_pentahedron_15, 1, 0], Element [_hexahedron_20, 1, 0],
+_quadrangle_8 6 connected to Element [_pentahedron_15, 2, 0], ElementNull,
+_quadrangle_8 7 connected to Element [_pentahedron_15, 3, 0], ElementNull,
+_quadrangle_8 8 connected to Element [_pentahedron_15, 3, 0], ElementNull,
+_quadrangle_8 9 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 10 connected to Element [_hexahedron_20, 0, 0], Element [_hexahedron_20, 1, 0],
+_quadrangle_8 11 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 12 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 13 connected to Element [_hexahedron_20, 0, 0], ElementNull,
+_quadrangle_8 14 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+_quadrangle_8 15 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+_quadrangle_8 16 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+_quadrangle_8 17 connected to Element [_hexahedron_20, 1, 0], ElementNull,
+ElementToSubelement2
+_segment_3 0 connected to Element [_triangle_6, 0, 0], Element [_quadrangle_8, 1, 0],
+_segment_3 1 connected to Element [_triangle_6, 0, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 12, 0],
+_segment_3 2 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 4, 0], Element [_quadrangle_8, 0, 0],
+_segment_3 3 connected to Element [_triangle_6, 1, 0], Element [_triangle_6, 5, 0], Element [_quadrangle_8, 0, 0],
+_segment_3 4 connected to Element [_triangle_6, 1, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 13, 0],
+_segment_3 5 connected to Element [_triangle_6, 1, 0], Element [_quadrangle_8, 1, 0],
+_segment_3 6 connected to Element [_triangle_6, 2, 0], Element [_triangle_6, 4, 0], Element [_quadrangle_8, 4, 0],
+_segment_3 7 connected to Element [_triangle_6, 2, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 16, 0],
+_segment_3 8 connected to Element [_triangle_6, 2, 0], Element [_triangle_6, 6, 0], Element [_quadrangle_8, 3, 0],
+_segment_3 9 connected to Element [_triangle_6, 3, 0], Element [_triangle_6, 7, 0], Element [_quadrangle_8, 3, 0],
+_segment_3 10 connected to Element [_triangle_6, 3, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 17, 0],
+_segment_3 11 connected to Element [_triangle_6, 3, 0], Element [_triangle_6, 5, 0], Element [_quadrangle_8, 4, 0],
+_segment_3 12 connected to Element [_triangle_6, 4, 0], Element [_quadrangle_8, 6, 0],
+_segment_3 13 connected to Element [_triangle_6, 5, 0], Element [_quadrangle_8, 6, 0],
+_segment_3 14 connected to Element [_triangle_6, 6, 0], Element [_quadrangle_8, 7, 0],
+_segment_3 15 connected to Element [_triangle_6, 6, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 16 connected to Element [_triangle_6, 7, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 17 connected to Element [_triangle_6, 7, 0], Element [_quadrangle_8, 7, 0],
+_segment_3 18 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 10, 0],
+_segment_3 19 connected to Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 6, 0],
+_segment_3 20 connected to Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 9, 0],
+_segment_3 21 connected to Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 14, 0],
+_segment_3 22 connected to Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 6, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 23 connected to Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 8, 0],
+_segment_3 24 connected to Element [_quadrangle_8, 9, 0], Element [_quadrangle_8, 12, 0],
+_segment_3 25 connected to Element [_quadrangle_8, 9, 0], Element [_quadrangle_8, 13, 0],
+_segment_3 26 connected to Element [_quadrangle_8, 9, 0], Element [_quadrangle_8, 11, 0],
+_segment_3 27 connected to Element [_quadrangle_8, 10, 0], Element [_quadrangle_8, 12, 0], Element [_quadrangle_8, 16, 0],
+_segment_3 28 connected to Element [_quadrangle_8, 10, 0], Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 15, 0],
+_segment_3 29 connected to Element [_quadrangle_8, 10, 0], Element [_quadrangle_8, 13, 0], Element [_quadrangle_8, 17, 0],
+_segment_3 30 connected to Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 12, 0],
+_segment_3 31 connected to Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 13, 0],
+_segment_3 32 connected to Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 16, 0],
+_segment_3 33 connected to Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 15, 0],
+_segment_3 34 connected to Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 17, 0],
+_segment_3 35 connected to Element [_quadrangle_8, 15, 0], Element [_quadrangle_8, 16, 0],
+_segment_3 36 connected to Element [_quadrangle_8, 15, 0], Element [_quadrangle_8, 17, 0],
+ElementToSubelement3
+_point_1 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 2, 0], Element [_segment_3, 12, 0], Element [_segment_3, 19, 0],
+_point_1 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 20, 0], Element [_segment_3, 24, 0],
+_point_1 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 2, 0], Element [_segment_3, 6, 0], Element [_segment_3, 7, 0], Element [_segment_3, 18, 0], Element [_segment_3, 27, 0],
+_point_1 3 connected to Element [_segment_3, 3, 0], Element [_segment_3, 5, 0], Element [_segment_3, 13, 0], Element [_segment_3, 19, 0],
+_point_1 4 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 10, 0], Element [_segment_3, 11, 0], Element [_segment_3, 18, 0], Element [_segment_3, 29, 0],
+_point_1 5 connected to Element [_segment_3, 4, 0], Element [_segment_3, 5, 0], Element [_segment_3, 20, 0], Element [_segment_3, 25, 0],
+_point_1 6 connected to Element [_segment_3, 6, 0], Element [_segment_3, 8, 0], Element [_segment_3, 12, 0], Element [_segment_3, 15, 0], Element [_segment_3, 22, 0],
+_point_1 7 connected to Element [_segment_3, 7, 0], Element [_segment_3, 8, 0], Element [_segment_3, 14, 0], Element [_segment_3, 21, 0], Element [_segment_3, 32, 0],
+_point_1 8 connected to Element [_segment_3, 9, 0], Element [_segment_3, 11, 0], Element [_segment_3, 13, 0], Element [_segment_3, 16, 0], Element [_segment_3, 22, 0],
+_point_1 9 connected to Element [_segment_3, 9, 0], Element [_segment_3, 10, 0], Element [_segment_3, 17, 0], Element [_segment_3, 21, 0], Element [_segment_3, 34, 0],
+_point_1 10 connected to Element [_segment_3, 14, 0], Element [_segment_3, 15, 0], Element [_segment_3, 23, 0],
+_point_1 11 connected to Element [_segment_3, 16, 0], Element [_segment_3, 17, 0], Element [_segment_3, 23, 0],
+_point_1 12 connected to Element [_segment_3, 24, 0], Element [_segment_3, 26, 0], Element [_segment_3, 30, 0],
+_point_1 13 connected to Element [_segment_3, 25, 0], Element [_segment_3, 26, 0], Element [_segment_3, 31, 0],
+_point_1 14 connected to Element [_segment_3, 27, 0], Element [_segment_3, 28, 0], Element [_segment_3, 30, 0], Element [_segment_3, 35, 0],
+_point_1 15 connected to Element [_segment_3, 28, 0], Element [_segment_3, 29, 0], Element [_segment_3, 31, 0], Element [_segment_3, 36, 0],
+_point_1 16 connected to Element [_segment_3, 32, 0], Element [_segment_3, 33, 0], Element [_segment_3, 35, 0],
+_point_1 17 connected to Element [_segment_3, 33, 0], Element [_segment_3, 34, 0], Element [_segment_3, 36, 0],
+
+SubelementToElement1
+_hexahedron_20 0 connected to Element [_quadrangle_8, 2, 0], Element [_quadrangle_8, 9, 0], Element [_quadrangle_8, 10, 0], Element [_quadrangle_8, 11, 0], Element [_quadrangle_8, 12, 0], Element [_quadrangle_8, 13, 0],
+_hexahedron_20 1 connected to Element [_quadrangle_8, 5, 0], Element [_quadrangle_8, 10, 0], Element [_quadrangle_8, 14, 0], Element [_quadrangle_8, 15, 0], Element [_quadrangle_8, 16, 0], Element [_quadrangle_8, 17, 0],
+SubelementToElement1
+_pentahedron_15 0 connected to Element [_triangle_6, 0, 0], Element [_triangle_6, 1, 0], Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 1, 0], Element [_quadrangle_8, 2, 0],
+_pentahedron_15 1 connected to Element [_triangle_6, 2, 0], Element [_triangle_6, 3, 0], Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 5, 0],
+_pentahedron_15 2 connected to Element [_triangle_6, 4, 0], Element [_triangle_6, 5, 0], Element [_quadrangle_8, 0, 0], Element [_quadrangle_8, 4, 0], Element [_quadrangle_8, 6, 0],
+_pentahedron_15 3 connected to Element [_triangle_6, 6, 0], Element [_triangle_6, 7, 0], Element [_quadrangle_8, 3, 0], Element [_quadrangle_8, 7, 0], Element [_quadrangle_8, 8, 0],
+SubelementToElement2
+_triangle_6 0 connected to Element [_segment_3, 0, 0], Element [_segment_3, 1, 0], Element [_segment_3, 2, 0],
+_triangle_6 1 connected to Element [_segment_3, 3, 0], Element [_segment_3, 4, 0], Element [_segment_3, 5, 0],
+_triangle_6 2 connected to Element [_segment_3, 6, 0], Element [_segment_3, 7, 0], Element [_segment_3, 8, 0],
+_triangle_6 3 connected to Element [_segment_3, 9, 0], Element [_segment_3, 10, 0], Element [_segment_3, 11, 0],
+_triangle_6 4 connected to Element [_segment_3, 2, 0], Element [_segment_3, 6, 0], Element [_segment_3, 12, 0],
+_triangle_6 5 connected to Element [_segment_3, 3, 0], Element [_segment_3, 11, 0], Element [_segment_3, 13, 0],
+_triangle_6 6 connected to Element [_segment_3, 8, 0], Element [_segment_3, 14, 0], Element [_segment_3, 15, 0],
+_triangle_6 7 connected to Element [_segment_3, 9, 0], Element [_segment_3, 16, 0], Element [_segment_3, 17, 0],
+SubelementToElement2
+_quadrangle_8 0 connected to Element [_segment_3, 2, 0], Element [_segment_3, 3, 0], Element [_segment_3, 18, 0], Element [_segment_3, 19, 0],
+_quadrangle_8 1 connected to Element [_segment_3, 0, 0], Element [_segment_3, 5, 0], Element [_segment_3, 19, 0], Element [_segment_3, 20, 0],
+_quadrangle_8 2 connected to Element [_segment_3, 1, 0], Element [_segment_3, 4, 0], Element [_segment_3, 18, 0], Element [_segment_3, 20, 0],
+_quadrangle_8 3 connected to Element [_segment_3, 8, 0], Element [_segment_3, 9, 0], Element [_segment_3, 21, 0], Element [_segment_3, 22, 0],
+_quadrangle_8 4 connected to Element [_segment_3, 6, 0], Element [_segment_3, 11, 0], Element [_segment_3, 18, 0], Element [_segment_3, 22, 0],
+_quadrangle_8 5 connected to Element [_segment_3, 7, 0], Element [_segment_3, 10, 0], Element [_segment_3, 18, 0], Element [_segment_3, 21, 0],
+_quadrangle_8 6 connected to Element [_segment_3, 12, 0], Element [_segment_3, 13, 0], Element [_segment_3, 19, 0], Element [_segment_3, 22, 0],
+_quadrangle_8 7 connected to Element [_segment_3, 14, 0], Element [_segment_3, 17, 0], Element [_segment_3, 21, 0], Element [_segment_3, 23, 0],
+_quadrangle_8 8 connected to Element [_segment_3, 15, 0], Element [_segment_3, 16, 0], Element [_segment_3, 22, 0], Element [_segment_3, 23, 0],
+_quadrangle_8 9 connected to Element [_segment_3, 20, 0], Element [_segment_3, 24, 0], Element [_segment_3, 25, 0], Element [_segment_3, 26, 0],
+_quadrangle_8 10 connected to Element [_segment_3, 18, 0], Element [_segment_3, 27, 0], Element [_segment_3, 28, 0], Element [_segment_3, 29, 0],
+_quadrangle_8 11 connected to Element [_segment_3, 26, 0], Element [_segment_3, 28, 0], Element [_segment_3, 30, 0], Element [_segment_3, 31, 0],
+_quadrangle_8 12 connected to Element [_segment_3, 1, 0], Element [_segment_3, 24, 0], Element [_segment_3, 27, 0], Element [_segment_3, 30, 0],
+_quadrangle_8 13 connected to Element [_segment_3, 4, 0], Element [_segment_3, 25, 0], Element [_segment_3, 29, 0], Element [_segment_3, 31, 0],
+_quadrangle_8 14 connected to Element [_segment_3, 21, 0], Element [_segment_3, 32, 0], Element [_segment_3, 33, 0], Element [_segment_3, 34, 0],
+_quadrangle_8 15 connected to Element [_segment_3, 28, 0], Element [_segment_3, 33, 0], Element [_segment_3, 35, 0], Element [_segment_3, 36, 0],
+_quadrangle_8 16 connected to Element [_segment_3, 7, 0], Element [_segment_3, 27, 0], Element [_segment_3, 32, 0], Element [_segment_3, 35, 0],
+_quadrangle_8 17 connected to Element [_segment_3, 10, 0], Element [_segment_3, 29, 0], Element [_segment_3, 34, 0], Element [_segment_3, 36, 0],
+SubelementToElement3
+_segment_3 0 connected to Element [_point_1, 0, 0], Element [_point_1, 1, 0],
+_segment_3 1 connected to Element [_point_1, 1, 0], Element [_point_1, 2, 0],
+_segment_3 2 connected to Element [_point_1, 0, 0], Element [_point_1, 2, 0],
+_segment_3 3 connected to Element [_point_1, 3, 0], Element [_point_1, 4, 0],
+_segment_3 4 connected to Element [_point_1, 4, 0], Element [_point_1, 5, 0],
+_segment_3 5 connected to Element [_point_1, 3, 0], Element [_point_1, 5, 0],
+_segment_3 6 connected to Element [_point_1, 2, 0], Element [_point_1, 6, 0],
+_segment_3 7 connected to Element [_point_1, 2, 0], Element [_point_1, 7, 0],
+_segment_3 8 connected to Element [_point_1, 6, 0], Element [_point_1, 7, 0],
+_segment_3 9 connected to Element [_point_1, 8, 0], Element [_point_1, 9, 0],
+_segment_3 10 connected to Element [_point_1, 4, 0], Element [_point_1, 9, 0],
+_segment_3 11 connected to Element [_point_1, 4, 0], Element [_point_1, 8, 0],
+_segment_3 12 connected to Element [_point_1, 0, 0], Element [_point_1, 6, 0],
+_segment_3 13 connected to Element [_point_1, 3, 0], Element [_point_1, 8, 0],
+_segment_3 14 connected to Element [_point_1, 7, 0], Element [_point_1, 10, 0],
+_segment_3 15 connected to Element [_point_1, 6, 0], Element [_point_1, 10, 0],
+_segment_3 16 connected to Element [_point_1, 8, 0], Element [_point_1, 11, 0],
+_segment_3 17 connected to Element [_point_1, 9, 0], Element [_point_1, 11, 0],
+_segment_3 18 connected to Element [_point_1, 2, 0], Element [_point_1, 4, 0],
+_segment_3 19 connected to Element [_point_1, 0, 0], Element [_point_1, 3, 0],
+_segment_3 20 connected to Element [_point_1, 1, 0], Element [_point_1, 5, 0],
+_segment_3 21 connected to Element [_point_1, 7, 0], Element [_point_1, 9, 0],
+_segment_3 22 connected to Element [_point_1, 6, 0], Element [_point_1, 8, 0],
+_segment_3 23 connected to Element [_point_1, 10, 0], Element [_point_1, 11, 0],
+_segment_3 24 connected to Element [_point_1, 1, 0], Element [_point_1, 12, 0],
+_segment_3 25 connected to Element [_point_1, 5, 0], Element [_point_1, 13, 0],
+_segment_3 26 connected to Element [_point_1, 12, 0], Element [_point_1, 13, 0],
+_segment_3 27 connected to Element [_point_1, 2, 0], Element [_point_1, 14, 0],
+_segment_3 28 connected to Element [_point_1, 14, 0], Element [_point_1, 15, 0],
+_segment_3 29 connected to Element [_point_1, 4, 0], Element [_point_1, 15, 0],
+_segment_3 30 connected to Element [_point_1, 12, 0], Element [_point_1, 14, 0],
+_segment_3 31 connected to Element [_point_1, 13, 0], Element [_point_1, 15, 0],
+_segment_3 32 connected to Element [_point_1, 7, 0], Element [_point_1, 16, 0],
+_segment_3 33 connected to Element [_point_1, 16, 0], Element [_point_1, 17, 0],
+_segment_3 34 connected to Element [_point_1, 9, 0], Element [_point_1, 17, 0],
+_segment_3 35 connected to Element [_point_1, 14, 0], Element [_point_1, 16, 0],
+_segment_3 36 connected to Element [_point_1, 15, 0], Element [_point_1, 17, 0],
+[ OK ] TestBuildFacetFixture/12.Buildfacets (4 ms)
+[----------] 1 test from TestBuildFacetFixture/12 (4 ms total)
+
+[----------] Global test environment tear-down
+[==========] 13 tests from 13 test suites ran. (44 ms total)
+[ PASSED ] 13 tests.
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.cc
deleted file mode 100644
index 1082cf689..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * @file test_buildfacets_hexahedron_20.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- * @author Marco Vocialta <marco.vocialta@epfl.ch>
- *
- * @date creation: Sun Oct 19 2014
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with hexahedrons
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 3;
- const ElementType type = _hexahedron_20;
-
- Mesh mesh(spatial_dimension);
- mesh.read("hexahedron_20.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- // debug::setDebugLevel(dblDump);
- // std::cout << mesh << std::endl;
- // std::cout << mesh_facets << std::endl;
-
- const ElementType type_facet = mesh.getFacetType(type);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
- const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel3 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_subfacet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subsubfacet);
-
- std::cout << "ElementToSubelement3" << std::endl;
- for (UInt i = 0; i < el_to_subel3.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel2(i).size(); ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subsubfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el3 =
- mesh_facets.getSubelementToElement(type);
- const Array<Element> & subel_to_el2 =
- mesh_facets.getSubelementToElement(type_facet);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_subfacet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement3" << std::endl;
- for (UInt i = 0; i < subel_to_el3.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < 6; ++j) {
- std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.verified
deleted file mode 100644
index dc5d0a345..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.verified
+++ /dev/null
@@ -1,135 +0,0 @@
-ElementToSubelement3
-_quadrangle_8 0 connected to _hexahedron_20 0, _hexahedron_20 3,
-_quadrangle_8 1 connected to _hexahedron_20 0, _hexahedron_20 1,
-_quadrangle_8 2 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 3 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 4 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 5 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 6 connected to _hexahedron_20 1, _not_defined 4294967295,
-_quadrangle_8 7 connected to _hexahedron_20 1, _hexahedron_20 2,
-_quadrangle_8 8 connected to _hexahedron_20 1, _not_defined 4294967295,
-_quadrangle_8 9 connected to _hexahedron_20 1, _not_defined 4294967295,
-_quadrangle_8 10 connected to _hexahedron_20 1, _not_defined 4294967295,
-_quadrangle_8 11 connected to _hexahedron_20 2, _not_defined 4294967295,
-_quadrangle_8 12 connected to _hexahedron_20 2, _not_defined 4294967295,
-_quadrangle_8 13 connected to _hexahedron_20 2, _not_defined 4294967295,
-_quadrangle_8 14 connected to _hexahedron_20 2, _hexahedron_20 3,
-_quadrangle_8 15 connected to _hexahedron_20 2, _not_defined 4294967295,
-_quadrangle_8 16 connected to _hexahedron_20 3, _not_defined 4294967295,
-_quadrangle_8 17 connected to _hexahedron_20 3, _not_defined 4294967295,
-_quadrangle_8 18 connected to _hexahedron_20 3, _not_defined 4294967295,
-_quadrangle_8 19 connected to _hexahedron_20 3, _not_defined 4294967295,
-ElementToSubelement2
-_segment_3 0 connected to _quadrangle_8 0, _quadrangle_8 4, _quadrangle_8 17,
-_segment_3 1 connected to _quadrangle_8 0, _quadrangle_8 1, _quadrangle_8 7, _quadrangle_8 14,
-_segment_3 2 connected to _quadrangle_8 0, _quadrangle_8 5, _quadrangle_8 16,
-_segment_3 3 connected to _quadrangle_8 0, _quadrangle_8 3, _quadrangle_8 19,
-_segment_3 4 connected to _quadrangle_8 1, _quadrangle_8 4, _quadrangle_8 8,
-_segment_3 5 connected to _quadrangle_8 1, _quadrangle_8 2, _quadrangle_8 9,
-_segment_3 6 connected to _quadrangle_8 1, _quadrangle_8 5, _quadrangle_8 6,
-_segment_3 7 connected to _quadrangle_8 2, _quadrangle_8 4,
-_segment_3 8 connected to _quadrangle_8 2, _quadrangle_8 3,
-_segment_3 9 connected to _quadrangle_8 2, _quadrangle_8 5,
-_segment_3 10 connected to _quadrangle_8 3, _quadrangle_8 4,
-_segment_3 11 connected to _quadrangle_8 3, _quadrangle_8 5,
-_segment_3 12 connected to _quadrangle_8 6, _quadrangle_8 7, _quadrangle_8 11,
-_segment_3 13 connected to _quadrangle_8 6, _quadrangle_8 10,
-_segment_3 14 connected to _quadrangle_8 6, _quadrangle_8 9,
-_segment_3 15 connected to _quadrangle_8 7, _quadrangle_8 8, _quadrangle_8 13,
-_segment_3 16 connected to _quadrangle_8 7, _quadrangle_8 10, _quadrangle_8 15,
-_segment_3 17 connected to _quadrangle_8 8, _quadrangle_8 9,
-_segment_3 18 connected to _quadrangle_8 8, _quadrangle_8 10,
-_segment_3 19 connected to _quadrangle_8 9, _quadrangle_8 10,
-_segment_3 20 connected to _quadrangle_8 11, _quadrangle_8 14, _quadrangle_8 16,
-_segment_3 21 connected to _quadrangle_8 11, _quadrangle_8 12,
-_segment_3 22 connected to _quadrangle_8 11, _quadrangle_8 15,
-_segment_3 23 connected to _quadrangle_8 12, _quadrangle_8 14, _quadrangle_8 18,
-_segment_3 24 connected to _quadrangle_8 12, _quadrangle_8 13,
-_segment_3 25 connected to _quadrangle_8 12, _quadrangle_8 15,
-_segment_3 26 connected to _quadrangle_8 13, _quadrangle_8 14, _quadrangle_8 17,
-_segment_3 27 connected to _quadrangle_8 13, _quadrangle_8 15,
-_segment_3 28 connected to _quadrangle_8 16, _quadrangle_8 19,
-_segment_3 29 connected to _quadrangle_8 16, _quadrangle_8 18,
-_segment_3 30 connected to _quadrangle_8 17, _quadrangle_8 18,
-_segment_3 31 connected to _quadrangle_8 17, _quadrangle_8 19,
-_segment_3 32 connected to _quadrangle_8 18, _quadrangle_8 19,
-ElementToSubelement1
-_point_1 0 connected to _segment_3 0, _segment_3 3, _segment_3 10, _segment_3 31,
-_point_1 1 connected to _segment_3 0, _segment_3 1, _segment_3 4, _segment_3 15, _segment_3 26,
-_point_1 2 connected to _segment_3 1, _segment_3 2, _segment_3 6, _segment_3 12, _segment_3 20,
-_point_1 3 connected to _segment_3 2, _segment_3 3, _segment_3 11, _segment_3 28,
-_point_1 4 connected to _segment_3 4, _segment_3 5, _segment_3 7, _segment_3 17,
-_point_1 5 connected to _segment_3 5, _segment_3 6, _segment_3 9, _segment_3 14,
-_point_1 6 connected to _segment_3 7, _segment_3 8, _segment_3 10,
-_point_1 7 connected to _segment_3 8, _segment_3 9, _segment_3 11,
-_point_1 8 connected to _segment_3 12, _segment_3 13, _segment_3 16, _segment_3 22,
-_point_1 9 connected to _segment_3 13, _segment_3 14, _segment_3 19,
-_point_1 10 connected to _segment_3 15, _segment_3 16, _segment_3 18, _segment_3 27,
-_point_1 11 connected to _segment_3 17, _segment_3 18, _segment_3 19,
-_point_1 12 connected to _segment_3 20, _segment_3 21, _segment_3 23, _segment_3 29,
-_point_1 13 connected to _segment_3 21, _segment_3 22, _segment_3 25,
-_point_1 14 connected to _segment_3 23, _segment_3 24, _segment_3 26, _segment_3 30,
-_point_1 15 connected to _segment_3 24, _segment_3 25, _segment_3 27,
-_point_1 16 connected to _segment_3 28, _segment_3 29, _segment_3 32,
-_point_1 17 connected to _segment_3 30, _segment_3 31, _segment_3 32,
-
-SubelementToElement3
-_hexahedron_20 0 connected to _quadrangle_8 0, _quadrangle_8 1, _quadrangle_8 2, _quadrangle_8 3, _quadrangle_8 4, _quadrangle_8 5,
-_hexahedron_20 1 connected to _quadrangle_8 1, _quadrangle_8 6, _quadrangle_8 7, _quadrangle_8 8, _quadrangle_8 9, _quadrangle_8 10,
-_hexahedron_20 2 connected to _quadrangle_8 7, _quadrangle_8 11, _quadrangle_8 12, _quadrangle_8 13, _quadrangle_8 14, _quadrangle_8 15,
-_hexahedron_20 3 connected to _quadrangle_8 0, _quadrangle_8 14, _quadrangle_8 16, _quadrangle_8 17, _quadrangle_8 18, _quadrangle_8 19,
-SubelementToElement2
-_quadrangle_8 0 connected to _segment_3 0, _segment_3 1, _segment_3 2, _segment_3 3,
-_quadrangle_8 1 connected to _segment_3 1, _segment_3 4, _segment_3 5, _segment_3 6,
-_quadrangle_8 2 connected to _segment_3 5, _segment_3 7, _segment_3 8, _segment_3 9,
-_quadrangle_8 3 connected to _segment_3 3, _segment_3 8, _segment_3 10, _segment_3 11,
-_quadrangle_8 4 connected to _segment_3 0, _segment_3 4, _segment_3 7, _segment_3 10,
-_quadrangle_8 5 connected to _segment_3 2, _segment_3 6, _segment_3 9, _segment_3 11,
-_quadrangle_8 6 connected to _segment_3 6, _segment_3 12, _segment_3 13, _segment_3 14,
-_quadrangle_8 7 connected to _segment_3 1, _segment_3 12, _segment_3 15, _segment_3 16,
-_quadrangle_8 8 connected to _segment_3 4, _segment_3 15, _segment_3 17, _segment_3 18,
-_quadrangle_8 9 connected to _segment_3 5, _segment_3 14, _segment_3 17, _segment_3 19,
-_quadrangle_8 10 connected to _segment_3 13, _segment_3 16, _segment_3 18, _segment_3 19,
-_quadrangle_8 11 connected to _segment_3 12, _segment_3 20, _segment_3 21, _segment_3 22,
-_quadrangle_8 12 connected to _segment_3 21, _segment_3 23, _segment_3 24, _segment_3 25,
-_quadrangle_8 13 connected to _segment_3 15, _segment_3 24, _segment_3 26, _segment_3 27,
-_quadrangle_8 14 connected to _segment_3 1, _segment_3 20, _segment_3 23, _segment_3 26,
-_quadrangle_8 15 connected to _segment_3 16, _segment_3 22, _segment_3 25, _segment_3 27,
-_quadrangle_8 16 connected to _segment_3 2, _segment_3 20, _segment_3 28, _segment_3 29,
-_quadrangle_8 17 connected to _segment_3 0, _segment_3 26, _segment_3 30, _segment_3 31,
-_quadrangle_8 18 connected to _segment_3 23, _segment_3 29, _segment_3 30, _segment_3 32,
-_quadrangle_8 19 connected to _segment_3 3, _segment_3 28, _segment_3 31, _segment_3 32,
-SubelementToElement1
-_segment_3 0 connected to _point_1 0, _point_1 1,
-_segment_3 1 connected to _point_1 1, _point_1 2,
-_segment_3 2 connected to _point_1 2, _point_1 3,
-_segment_3 3 connected to _point_1 0, _point_1 3,
-_segment_3 4 connected to _point_1 1, _point_1 4,
-_segment_3 5 connected to _point_1 4, _point_1 5,
-_segment_3 6 connected to _point_1 2, _point_1 5,
-_segment_3 7 connected to _point_1 4, _point_1 6,
-_segment_3 8 connected to _point_1 6, _point_1 7,
-_segment_3 9 connected to _point_1 5, _point_1 7,
-_segment_3 10 connected to _point_1 0, _point_1 6,
-_segment_3 11 connected to _point_1 3, _point_1 7,
-_segment_3 12 connected to _point_1 2, _point_1 8,
-_segment_3 13 connected to _point_1 8, _point_1 9,
-_segment_3 14 connected to _point_1 5, _point_1 9,
-_segment_3 15 connected to _point_1 1, _point_1 10,
-_segment_3 16 connected to _point_1 8, _point_1 10,
-_segment_3 17 connected to _point_1 4, _point_1 11,
-_segment_3 18 connected to _point_1 10, _point_1 11,
-_segment_3 19 connected to _point_1 9, _point_1 11,
-_segment_3 20 connected to _point_1 2, _point_1 12,
-_segment_3 21 connected to _point_1 12, _point_1 13,
-_segment_3 22 connected to _point_1 8, _point_1 13,
-_segment_3 23 connected to _point_1 12, _point_1 14,
-_segment_3 24 connected to _point_1 14, _point_1 15,
-_segment_3 25 connected to _point_1 13, _point_1 15,
-_segment_3 26 connected to _point_1 1, _point_1 14,
-_segment_3 27 connected to _point_1 10, _point_1 15,
-_segment_3 28 connected to _point_1 3, _point_1 16,
-_segment_3 29 connected to _point_1 12, _point_1 16,
-_segment_3 30 connected to _point_1 14, _point_1 17,
-_segment_3 31 connected to _point_1 0, _point_1 17,
-_segment_3 32 connected to _point_1 16, _point_1 17,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.cc
deleted file mode 100644
index 0d7dd4617..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * @file test_buildfacets_hexahedron_8.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- * @author Marco Vocialta <marco.vocialta@epfl.ch>
- *
- * @date creation: Tue May 08 2012
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with hexahedrons
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 3;
- const ElementType type = _hexahedron_8;
-
- Mesh mesh(spatial_dimension);
- mesh.read("hexahedron_8.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- // debug::setDebugLevel(dblDump);
- // std::cout << mesh << std::endl;
- // std::cout << mesh_facets << std::endl;
-
- const ElementType type_facet = mesh.getFacetType(type);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
- const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel3 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_subfacet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subsubfacet);
-
- std::cout << "ElementToSubelement3" << std::endl;
- for (UInt i = 0; i < el_to_subel3.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel2(i).size(); ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subsubfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el3 =
- mesh_facets.getSubelementToElement(type);
- const Array<Element> & subel_to_el2 =
- mesh_facets.getSubelementToElement(type_facet);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_subfacet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement3" << std::endl;
- for (UInt i = 0; i < subel_to_el3.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < 6; ++j) {
- std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.verified
deleted file mode 100644
index d60c11099..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.verified
+++ /dev/null
@@ -1,135 +0,0 @@
-ElementToSubelement3
-_quadrangle_4 0 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 1 connected to _hexahedron_8 0, _hexahedron_8 3,
-_quadrangle_4 2 connected to _hexahedron_8 0, _hexahedron_8 1,
-_quadrangle_4 3 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 4 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 5 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 6 connected to _hexahedron_8 1, _not_defined 4294967295,
-_quadrangle_4 7 connected to _hexahedron_8 1, _hexahedron_8 2,
-_quadrangle_4 8 connected to _hexahedron_8 1, _not_defined 4294967295,
-_quadrangle_4 9 connected to _hexahedron_8 1, _not_defined 4294967295,
-_quadrangle_4 10 connected to _hexahedron_8 1, _not_defined 4294967295,
-_quadrangle_4 11 connected to _hexahedron_8 2, _hexahedron_8 3,
-_quadrangle_4 12 connected to _hexahedron_8 2, _not_defined 4294967295,
-_quadrangle_4 13 connected to _hexahedron_8 2, _not_defined 4294967295,
-_quadrangle_4 14 connected to _hexahedron_8 2, _not_defined 4294967295,
-_quadrangle_4 15 connected to _hexahedron_8 2, _not_defined 4294967295,
-_quadrangle_4 16 connected to _hexahedron_8 3, _not_defined 4294967295,
-_quadrangle_4 17 connected to _hexahedron_8 3, _not_defined 4294967295,
-_quadrangle_4 18 connected to _hexahedron_8 3, _not_defined 4294967295,
-_quadrangle_4 19 connected to _hexahedron_8 3, _not_defined 4294967295,
-ElementToSubelement2
-_segment_2 0 connected to _quadrangle_4 0, _quadrangle_4 4,
-_segment_2 1 connected to _quadrangle_4 0, _quadrangle_4 3,
-_segment_2 2 connected to _quadrangle_4 0, _quadrangle_4 2, _quadrangle_4 8,
-_segment_2 3 connected to _quadrangle_4 0, _quadrangle_4 1, _quadrangle_4 17,
-_segment_2 4 connected to _quadrangle_4 1, _quadrangle_4 2, _quadrangle_4 7, _quadrangle_4 11,
-_segment_2 5 connected to _quadrangle_4 1, _quadrangle_4 5, _quadrangle_4 16,
-_segment_2 6 connected to _quadrangle_4 1, _quadrangle_4 4, _quadrangle_4 19,
-_segment_2 7 connected to _quadrangle_4 2, _quadrangle_4 3, _quadrangle_4 9,
-_segment_2 8 connected to _quadrangle_4 2, _quadrangle_4 5, _quadrangle_4 6,
-_segment_2 9 connected to _quadrangle_4 3, _quadrangle_4 4,
-_segment_2 10 connected to _quadrangle_4 3, _quadrangle_4 5,
-_segment_2 11 connected to _quadrangle_4 4, _quadrangle_4 5,
-_segment_2 12 connected to _quadrangle_4 6, _quadrangle_4 7, _quadrangle_4 12,
-_segment_2 13 connected to _quadrangle_4 6, _quadrangle_4 10,
-_segment_2 14 connected to _quadrangle_4 6, _quadrangle_4 9,
-_segment_2 15 connected to _quadrangle_4 7, _quadrangle_4 8, _quadrangle_4 14,
-_segment_2 16 connected to _quadrangle_4 7, _quadrangle_4 10, _quadrangle_4 15,
-_segment_2 17 connected to _quadrangle_4 8, _quadrangle_4 9,
-_segment_2 18 connected to _quadrangle_4 8, _quadrangle_4 10,
-_segment_2 19 connected to _quadrangle_4 9, _quadrangle_4 10,
-_segment_2 20 connected to _quadrangle_4 11, _quadrangle_4 14, _quadrangle_4 17,
-_segment_2 21 connected to _quadrangle_4 11, _quadrangle_4 13, _quadrangle_4 18,
-_segment_2 22 connected to _quadrangle_4 11, _quadrangle_4 12, _quadrangle_4 16,
-_segment_2 23 connected to _quadrangle_4 12, _quadrangle_4 13,
-_segment_2 24 connected to _quadrangle_4 12, _quadrangle_4 15,
-_segment_2 25 connected to _quadrangle_4 13, _quadrangle_4 14,
-_segment_2 26 connected to _quadrangle_4 13, _quadrangle_4 15,
-_segment_2 27 connected to _quadrangle_4 14, _quadrangle_4 15,
-_segment_2 28 connected to _quadrangle_4 16, _quadrangle_4 19,
-_segment_2 29 connected to _quadrangle_4 16, _quadrangle_4 18,
-_segment_2 30 connected to _quadrangle_4 17, _quadrangle_4 18,
-_segment_2 31 connected to _quadrangle_4 17, _quadrangle_4 19,
-_segment_2 32 connected to _quadrangle_4 18, _quadrangle_4 19,
-ElementToSubelement1
-_point_1 0 connected to _segment_2 0, _segment_2 3, _segment_2 6, _segment_2 31,
-_point_1 1 connected to _segment_2 0, _segment_2 1, _segment_2 9,
-_point_1 2 connected to _segment_2 1, _segment_2 2, _segment_2 7, _segment_2 17,
-_point_1 3 connected to _segment_2 2, _segment_2 3, _segment_2 4, _segment_2 15, _segment_2 20,
-_point_1 4 connected to _segment_2 4, _segment_2 5, _segment_2 8, _segment_2 12, _segment_2 22,
-_point_1 5 connected to _segment_2 5, _segment_2 6, _segment_2 11, _segment_2 28,
-_point_1 6 connected to _segment_2 7, _segment_2 8, _segment_2 10, _segment_2 14,
-_point_1 7 connected to _segment_2 9, _segment_2 10, _segment_2 11,
-_point_1 8 connected to _segment_2 12, _segment_2 13, _segment_2 16, _segment_2 24,
-_point_1 9 connected to _segment_2 13, _segment_2 14, _segment_2 19,
-_point_1 10 connected to _segment_2 15, _segment_2 16, _segment_2 18, _segment_2 27,
-_point_1 11 connected to _segment_2 17, _segment_2 18, _segment_2 19,
-_point_1 12 connected to _segment_2 20, _segment_2 21, _segment_2 25, _segment_2 30,
-_point_1 13 connected to _segment_2 21, _segment_2 22, _segment_2 23, _segment_2 29,
-_point_1 14 connected to _segment_2 23, _segment_2 24, _segment_2 26,
-_point_1 15 connected to _segment_2 25, _segment_2 26, _segment_2 27,
-_point_1 16 connected to _segment_2 28, _segment_2 29, _segment_2 32,
-_point_1 17 connected to _segment_2 30, _segment_2 31, _segment_2 32,
-
-SubelementToElement3
-_hexahedron_8 0 connected to _quadrangle_4 0, _quadrangle_4 1, _quadrangle_4 2, _quadrangle_4 3, _quadrangle_4 4, _quadrangle_4 5,
-_hexahedron_8 1 connected to _quadrangle_4 2, _quadrangle_4 6, _quadrangle_4 7, _quadrangle_4 8, _quadrangle_4 9, _quadrangle_4 10,
-_hexahedron_8 2 connected to _quadrangle_4 7, _quadrangle_4 11, _quadrangle_4 12, _quadrangle_4 13, _quadrangle_4 14, _quadrangle_4 15,
-_hexahedron_8 3 connected to _quadrangle_4 1, _quadrangle_4 11, _quadrangle_4 16, _quadrangle_4 17, _quadrangle_4 18, _quadrangle_4 19,
-SubelementToElement2
-_quadrangle_4 0 connected to _segment_2 0, _segment_2 1, _segment_2 2, _segment_2 3,
-_quadrangle_4 1 connected to _segment_2 3, _segment_2 4, _segment_2 5, _segment_2 6,
-_quadrangle_4 2 connected to _segment_2 2, _segment_2 4, _segment_2 7, _segment_2 8,
-_quadrangle_4 3 connected to _segment_2 1, _segment_2 7, _segment_2 9, _segment_2 10,
-_quadrangle_4 4 connected to _segment_2 0, _segment_2 6, _segment_2 9, _segment_2 11,
-_quadrangle_4 5 connected to _segment_2 5, _segment_2 8, _segment_2 10, _segment_2 11,
-_quadrangle_4 6 connected to _segment_2 8, _segment_2 12, _segment_2 13, _segment_2 14,
-_quadrangle_4 7 connected to _segment_2 4, _segment_2 12, _segment_2 15, _segment_2 16,
-_quadrangle_4 8 connected to _segment_2 2, _segment_2 15, _segment_2 17, _segment_2 18,
-_quadrangle_4 9 connected to _segment_2 7, _segment_2 14, _segment_2 17, _segment_2 19,
-_quadrangle_4 10 connected to _segment_2 13, _segment_2 16, _segment_2 18, _segment_2 19,
-_quadrangle_4 11 connected to _segment_2 4, _segment_2 20, _segment_2 21, _segment_2 22,
-_quadrangle_4 12 connected to _segment_2 12, _segment_2 22, _segment_2 23, _segment_2 24,
-_quadrangle_4 13 connected to _segment_2 21, _segment_2 23, _segment_2 25, _segment_2 26,
-_quadrangle_4 14 connected to _segment_2 15, _segment_2 20, _segment_2 25, _segment_2 27,
-_quadrangle_4 15 connected to _segment_2 16, _segment_2 24, _segment_2 26, _segment_2 27,
-_quadrangle_4 16 connected to _segment_2 5, _segment_2 22, _segment_2 28, _segment_2 29,
-_quadrangle_4 17 connected to _segment_2 3, _segment_2 20, _segment_2 30, _segment_2 31,
-_quadrangle_4 18 connected to _segment_2 21, _segment_2 29, _segment_2 30, _segment_2 32,
-_quadrangle_4 19 connected to _segment_2 6, _segment_2 28, _segment_2 31, _segment_2 32,
-SubelementToElement1
-_segment_2 0 connected to _point_1 0, _point_1 1,
-_segment_2 1 connected to _point_1 1, _point_1 2,
-_segment_2 2 connected to _point_1 2, _point_1 3,
-_segment_2 3 connected to _point_1 0, _point_1 3,
-_segment_2 4 connected to _point_1 3, _point_1 4,
-_segment_2 5 connected to _point_1 4, _point_1 5,
-_segment_2 6 connected to _point_1 0, _point_1 5,
-_segment_2 7 connected to _point_1 2, _point_1 6,
-_segment_2 8 connected to _point_1 4, _point_1 6,
-_segment_2 9 connected to _point_1 1, _point_1 7,
-_segment_2 10 connected to _point_1 6, _point_1 7,
-_segment_2 11 connected to _point_1 5, _point_1 7,
-_segment_2 12 connected to _point_1 4, _point_1 8,
-_segment_2 13 connected to _point_1 8, _point_1 9,
-_segment_2 14 connected to _point_1 6, _point_1 9,
-_segment_2 15 connected to _point_1 3, _point_1 10,
-_segment_2 16 connected to _point_1 8, _point_1 10,
-_segment_2 17 connected to _point_1 2, _point_1 11,
-_segment_2 18 connected to _point_1 10, _point_1 11,
-_segment_2 19 connected to _point_1 9, _point_1 11,
-_segment_2 20 connected to _point_1 3, _point_1 12,
-_segment_2 21 connected to _point_1 12, _point_1 13,
-_segment_2 22 connected to _point_1 4, _point_1 13,
-_segment_2 23 connected to _point_1 13, _point_1 14,
-_segment_2 24 connected to _point_1 8, _point_1 14,
-_segment_2 25 connected to _point_1 12, _point_1 15,
-_segment_2 26 connected to _point_1 14, _point_1 15,
-_segment_2 27 connected to _point_1 10, _point_1 15,
-_segment_2 28 connected to _point_1 5, _point_1 16,
-_segment_2 29 connected to _point_1 13, _point_1 16,
-_segment_2 30 connected to _point_1 12, _point_1 17,
-_segment_2 31 connected to _point_1 0, _point_1 17,
-_segment_2 32 connected to _point_1 16, _point_1 17,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.cc
deleted file mode 100644
index 0f96ad7ab..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * @file test_buildfacets_mixed2d_linear.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Fri Sep 18 2015
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with quadrangles
- * and triangles
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 2;
- const ElementType type1 = _quadrangle_4;
- const ElementType type2 = _triangle_3;
-
- Mesh mesh(spatial_dimension);
- mesh.read("mixed2d_linear.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet = mesh.getFacetType(type1);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el2_1 =
- mesh_facets.getSubelementToElement(type1);
- const Array<Element> & subel_to_el2_2 =
- mesh_facets.getSubelementToElement(type2);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2_1.size(); ++i) {
- std::cout << type1 << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2_1(i, j).type << " "
- << subel_to_el2_1(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt i = 0; i < subel_to_el2_2.size(); ++i) {
- std::cout << type2 << " " << i << " connected to ";
- for (UInt j = 0; j < 3; ++j) {
- std::cout << subel_to_el2_2(i, j).type << " "
- << subel_to_el2_2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.verified
deleted file mode 100644
index 4ad4ee085..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.verified
+++ /dev/null
@@ -1,48 +0,0 @@
-ElementToSubelement2
-_segment_2 0 connected to _triangle_3 0, _quadrangle_4 0,
-_segment_2 1 connected to _triangle_3 0, _triangle_3 2,
-_segment_2 2 connected to _triangle_3 0, _not_defined 4294967295,
-_segment_2 3 connected to _triangle_3 1, _quadrangle_4 1,
-_segment_2 4 connected to _triangle_3 1, _triangle_3 3,
-_segment_2 5 connected to _triangle_3 1, _triangle_3 2,
-_segment_2 6 connected to _triangle_3 2, _not_defined 4294967295,
-_segment_2 7 connected to _triangle_3 3, _not_defined 4294967295,
-_segment_2 8 connected to _triangle_3 3, _not_defined 4294967295,
-_segment_2 9 connected to _quadrangle_4 0, _not_defined 4294967295,
-_segment_2 10 connected to _quadrangle_4 0, _quadrangle_4 1,
-_segment_2 11 connected to _quadrangle_4 0, _not_defined 4294967295,
-_segment_2 12 connected to _quadrangle_4 1, _not_defined 4294967295,
-_segment_2 13 connected to _quadrangle_4 1, _not_defined 4294967295,
-ElementToSubelement1
-_point_1 0 connected to _segment_2 0, _segment_2 2, _segment_2 11,
-_point_1 1 connected to _segment_2 0, _segment_2 1, _segment_2 3, _segment_2 5, _segment_2 10,
-_point_1 2 connected to _segment_2 1, _segment_2 2, _segment_2 6,
-_point_1 3 connected to _segment_2 3, _segment_2 4, _segment_2 8, _segment_2 13,
-_point_1 4 connected to _segment_2 4, _segment_2 5, _segment_2 6, _segment_2 7,
-_point_1 5 connected to _segment_2 7, _segment_2 8,
-_point_1 6 connected to _segment_2 9, _segment_2 11,
-_point_1 7 connected to _segment_2 9, _segment_2 10, _segment_2 12,
-_point_1 8 connected to _segment_2 12, _segment_2 13,
-
-SubelementToElement2
-_quadrangle_4 0 connected to _segment_2 0, _segment_2 9, _segment_2 10, _segment_2 11,
-_quadrangle_4 1 connected to _segment_2 3, _segment_2 10, _segment_2 12, _segment_2 13,
-_triangle_3 0 connected to _segment_2 0, _segment_2 1, _segment_2 2,
-_triangle_3 1 connected to _segment_2 3, _segment_2 4, _segment_2 5,
-_triangle_3 2 connected to _segment_2 1, _segment_2 5, _segment_2 6,
-_triangle_3 3 connected to _segment_2 4, _segment_2 7, _segment_2 8,
-SubelementToElement1
-_segment_2 0 connected to _point_1 0, _point_1 1,
-_segment_2 1 connected to _point_1 1, _point_1 2,
-_segment_2 2 connected to _point_1 0, _point_1 2,
-_segment_2 3 connected to _point_1 1, _point_1 3,
-_segment_2 4 connected to _point_1 3, _point_1 4,
-_segment_2 5 connected to _point_1 1, _point_1 4,
-_segment_2 6 connected to _point_1 2, _point_1 4,
-_segment_2 7 connected to _point_1 4, _point_1 5,
-_segment_2 8 connected to _point_1 3, _point_1 5,
-_segment_2 9 connected to _point_1 6, _point_1 7,
-_segment_2 10 connected to _point_1 1, _point_1 7,
-_segment_2 11 connected to _point_1 0, _point_1 6,
-_segment_2 12 connected to _point_1 7, _point_1 8,
-_segment_2 13 connected to _point_1 3, _point_1 8,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.cc
deleted file mode 100644
index d9ef56d6f..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * @file test_buildfacets_mixed2d_quadratic.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Fri Sep 18 2015
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with quadrangles
- * and triangles
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 2;
- const ElementType type1 = _quadrangle_8;
- const ElementType type2 = _triangle_6;
-
- Mesh mesh(spatial_dimension);
- mesh.read("mixed2d_quadratic.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet = mesh.getFacetType(type1);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el2_1 =
- mesh_facets.getSubelementToElement(type1);
- const Array<Element> & subel_to_el2_2 =
- mesh_facets.getSubelementToElement(type2);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2_1.size(); ++i) {
- std::cout << type1 << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2_1(i, j).type << " "
- << subel_to_el2_1(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt i = 0; i < subel_to_el2_2.size(); ++i) {
- std::cout << type2 << " " << i << " connected to ";
- for (UInt j = 0; j < 3; ++j) {
- std::cout << subel_to_el2_2(i, j).type << " "
- << subel_to_el2_2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.verified
deleted file mode 100644
index 4380ea0ac..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.verified
+++ /dev/null
@@ -1,48 +0,0 @@
-ElementToSubelement2
-_segment_3 0 connected to _triangle_6 0, _quadrangle_8 0,
-_segment_3 1 connected to _triangle_6 0, _triangle_6 2,
-_segment_3 2 connected to _triangle_6 0, _not_defined 4294967295,
-_segment_3 3 connected to _triangle_6 1, _quadrangle_8 1,
-_segment_3 4 connected to _triangle_6 1, _triangle_6 3,
-_segment_3 5 connected to _triangle_6 1, _triangle_6 2,
-_segment_3 6 connected to _triangle_6 2, _not_defined 4294967295,
-_segment_3 7 connected to _triangle_6 3, _not_defined 4294967295,
-_segment_3 8 connected to _triangle_6 3, _not_defined 4294967295,
-_segment_3 9 connected to _quadrangle_8 0, _not_defined 4294967295,
-_segment_3 10 connected to _quadrangle_8 0, _quadrangle_8 1,
-_segment_3 11 connected to _quadrangle_8 0, _not_defined 4294967295,
-_segment_3 12 connected to _quadrangle_8 1, _not_defined 4294967295,
-_segment_3 13 connected to _quadrangle_8 1, _not_defined 4294967295,
-ElementToSubelement1
-_point_1 0 connected to _segment_3 0, _segment_3 2, _segment_3 11,
-_point_1 1 connected to _segment_3 0, _segment_3 1, _segment_3 3, _segment_3 5, _segment_3 10,
-_point_1 2 connected to _segment_3 1, _segment_3 2, _segment_3 6,
-_point_1 3 connected to _segment_3 3, _segment_3 4, _segment_3 8, _segment_3 13,
-_point_1 4 connected to _segment_3 4, _segment_3 5, _segment_3 6, _segment_3 7,
-_point_1 5 connected to _segment_3 7, _segment_3 8,
-_point_1 6 connected to _segment_3 9, _segment_3 11,
-_point_1 7 connected to _segment_3 9, _segment_3 10, _segment_3 12,
-_point_1 8 connected to _segment_3 12, _segment_3 13,
-
-SubelementToElement2
-_quadrangle_8 0 connected to _segment_3 0, _segment_3 9, _segment_3 10, _segment_3 11,
-_quadrangle_8 1 connected to _segment_3 3, _segment_3 10, _segment_3 12, _segment_3 13,
-_triangle_6 0 connected to _segment_3 0, _segment_3 1, _segment_3 2,
-_triangle_6 1 connected to _segment_3 3, _segment_3 4, _segment_3 5,
-_triangle_6 2 connected to _segment_3 1, _segment_3 5, _segment_3 6,
-_triangle_6 3 connected to _segment_3 4, _segment_3 7, _segment_3 8,
-SubelementToElement1
-_segment_3 0 connected to _point_1 0, _point_1 1,
-_segment_3 1 connected to _point_1 1, _point_1 2,
-_segment_3 2 connected to _point_1 0, _point_1 2,
-_segment_3 3 connected to _point_1 1, _point_1 3,
-_segment_3 4 connected to _point_1 3, _point_1 4,
-_segment_3 5 connected to _point_1 1, _point_1 4,
-_segment_3 6 connected to _point_1 2, _point_1 4,
-_segment_3 7 connected to _point_1 4, _point_1 5,
-_segment_3 8 connected to _point_1 3, _point_1 5,
-_segment_3 9 connected to _point_1 6, _point_1 7,
-_segment_3 10 connected to _point_1 1, _point_1 7,
-_segment_3 11 connected to _point_1 0, _point_1 6,
-_segment_3 12 connected to _point_1 7, _point_1 8,
-_segment_3 13 connected to _point_1 3, _point_1 8,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.cc
deleted file mode 100644
index ee2c04488..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * @file test_buildfacets_mixed3d_linear.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Sun Oct 19 2014
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with hexahedrons
- * and pentahedrons
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 3;
- const ElementType type1 = _hexahedron_8;
- const ElementType type2 = _pentahedron_6;
-
- Mesh mesh(spatial_dimension);
- mesh.read("mixed3d_linear.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet1 = mesh.getFacetType(type1);
- const ElementType type_facet2 = mesh.getFacetType(type2);
- const ElementType type_subfacet = mesh.getFacetType(type_facet1);
- const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel3_1 =
- mesh_facets.getElementToSubelement(type_facet1);
- const Array<std::vector<Element>> & el_to_subel3_2 =
- mesh_facets.getElementToSubelement(type_facet2);
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_subfacet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subsubfacet);
-
- std::cout << "ElementToSubelement3" << std::endl;
- for (UInt i = 0; i < el_to_subel3_1.size(); ++i) {
- std::cout << type_facet1 << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3_1(i)[j].type << " "
- << el_to_subel3_1(i)[j].element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt i = 0; i < el_to_subel3_2.size(); ++i) {
- std::cout << type_facet2 << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3_2(i)[j].type << " "
- << el_to_subel3_2(i)[j].element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel2(i).size(); ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subsubfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el3_1 =
- mesh_facets.getSubelementToElement(type1);
- const Array<Element> & subel_to_el3_2 =
- mesh_facets.getSubelementToElement(type2);
- const Array<Element> & subel_to_el2_1 =
- mesh_facets.getSubelementToElement(type_facet1);
- const Array<Element> & subel_to_el2_2 =
- mesh_facets.getSubelementToElement(type_facet2);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_subfacet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement3" << std::endl;
- for (UInt i = 0; i < subel_to_el3_1.size(); ++i) {
- std::cout << type1 << " " << i << " connected to ";
- for (UInt j = 0; j < 6; ++j) {
- std::cout << subel_to_el3_1(i, j).type << " "
- << subel_to_el3_1(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt i = 0; i < subel_to_el3_2.size(); ++i) {
- std::cout << type2 << " " << i << " connected to ";
- for (UInt j = 0; j < 5; ++j) {
- std::cout << subel_to_el3_2(i, j).type << " "
- << subel_to_el3_2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2_1.size(); ++i) {
- std::cout << type_facet1 << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2_1(i, j).type << " "
- << subel_to_el2_1(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt i = 0; i < subel_to_el2_2.size(); ++i) {
- std::cout << type_facet2 << " " << i << " connected to ";
- for (UInt j = 0; j < 3; ++j) {
- std::cout << subel_to_el2_2(i, j).type << " "
- << subel_to_el2_2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.verified
deleted file mode 100644
index af8630db1..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.verified
+++ /dev/null
@@ -1,157 +0,0 @@
-ElementToSubelement3
-_quadrangle_4 0 connected to _pentahedron_6 0, _pentahedron_6 2,
-_quadrangle_4 1 connected to _pentahedron_6 0, _not_defined 4294967295,
-_quadrangle_4 2 connected to _pentahedron_6 0, _hexahedron_8 0,
-_quadrangle_4 3 connected to _pentahedron_6 1, _pentahedron_6 3,
-_quadrangle_4 4 connected to _pentahedron_6 1, _pentahedron_6 2,
-_quadrangle_4 5 connected to _pentahedron_6 1, _hexahedron_8 1,
-_quadrangle_4 6 connected to _pentahedron_6 2, _not_defined 4294967295,
-_quadrangle_4 7 connected to _pentahedron_6 3, _not_defined 4294967295,
-_quadrangle_4 8 connected to _pentahedron_6 3, _not_defined 4294967295,
-_quadrangle_4 9 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 10 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 11 connected to _hexahedron_8 0, _hexahedron_8 1,
-_quadrangle_4 12 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 13 connected to _hexahedron_8 0, _not_defined 4294967295,
-_quadrangle_4 14 connected to _hexahedron_8 1, _not_defined 4294967295,
-_quadrangle_4 15 connected to _hexahedron_8 1, _not_defined 4294967295,
-_quadrangle_4 16 connected to _hexahedron_8 1, _not_defined 4294967295,
-_quadrangle_4 17 connected to _hexahedron_8 1, _not_defined 4294967295,
-_triangle_3 0 connected to _pentahedron_6 0, _not_defined 4294967295,
-_triangle_3 1 connected to _pentahedron_6 0, _not_defined 4294967295,
-_triangle_3 2 connected to _pentahedron_6 1, _not_defined 4294967295,
-_triangle_3 3 connected to _pentahedron_6 1, _not_defined 4294967295,
-_triangle_3 4 connected to _pentahedron_6 2, _not_defined 4294967295,
-_triangle_3 5 connected to _pentahedron_6 2, _not_defined 4294967295,
-_triangle_3 6 connected to _pentahedron_6 3, _not_defined 4294967295,
-_triangle_3 7 connected to _pentahedron_6 3, _not_defined 4294967295,
-ElementToSubelement2
-_segment_2 0 connected to _triangle_3 0, _quadrangle_4 1,
-_segment_2 1 connected to _triangle_3 0, _quadrangle_4 2, _quadrangle_4 9,
-_segment_2 2 connected to _triangle_3 0, _triangle_3 4, _quadrangle_4 0,
-_segment_2 3 connected to _triangle_3 1, _triangle_3 5, _quadrangle_4 0,
-_segment_2 4 connected to _triangle_3 1, _quadrangle_4 2, _quadrangle_4 13,
-_segment_2 5 connected to _triangle_3 1, _quadrangle_4 1,
-_segment_2 6 connected to _triangle_3 2, _triangle_3 4, _quadrangle_4 4,
-_segment_2 7 connected to _triangle_3 2, _quadrangle_4 5, _quadrangle_4 14,
-_segment_2 8 connected to _triangle_3 2, _triangle_3 6, _quadrangle_4 3,
-_segment_2 9 connected to _triangle_3 3, _triangle_3 7, _quadrangle_4 3,
-_segment_2 10 connected to _triangle_3 3, _quadrangle_4 5, _quadrangle_4 17,
-_segment_2 11 connected to _triangle_3 3, _triangle_3 5, _quadrangle_4 4,
-_segment_2 12 connected to _triangle_3 4, _quadrangle_4 6,
-_segment_2 13 connected to _triangle_3 5, _quadrangle_4 6,
-_segment_2 14 connected to _triangle_3 6, _quadrangle_4 7,
-_segment_2 15 connected to _triangle_3 6, _quadrangle_4 8,
-_segment_2 16 connected to _triangle_3 7, _quadrangle_4 8,
-_segment_2 17 connected to _triangle_3 7, _quadrangle_4 7,
-_segment_2 18 connected to _quadrangle_4 0, _quadrangle_4 2, _quadrangle_4 4, _quadrangle_4 5, _quadrangle_4 11,
-_segment_2 19 connected to _quadrangle_4 0, _quadrangle_4 1, _quadrangle_4 6,
-_segment_2 20 connected to _quadrangle_4 1, _quadrangle_4 2, _quadrangle_4 10,
-_segment_2 21 connected to _quadrangle_4 3, _quadrangle_4 5, _quadrangle_4 7, _quadrangle_4 15,
-_segment_2 22 connected to _quadrangle_4 3, _quadrangle_4 4, _quadrangle_4 6, _quadrangle_4 8,
-_segment_2 23 connected to _quadrangle_4 7, _quadrangle_4 8,
-_segment_2 24 connected to _quadrangle_4 9, _quadrangle_4 12,
-_segment_2 25 connected to _quadrangle_4 9, _quadrangle_4 11, _quadrangle_4 14,
-_segment_2 26 connected to _quadrangle_4 9, _quadrangle_4 10,
-_segment_2 27 connected to _quadrangle_4 10, _quadrangle_4 13,
-_segment_2 28 connected to _quadrangle_4 10, _quadrangle_4 12,
-_segment_2 29 connected to _quadrangle_4 11, _quadrangle_4 12, _quadrangle_4 16,
-_segment_2 30 connected to _quadrangle_4 11, _quadrangle_4 13, _quadrangle_4 17,
-_segment_2 31 connected to _quadrangle_4 12, _quadrangle_4 13,
-_segment_2 32 connected to _quadrangle_4 14, _quadrangle_4 16,
-_segment_2 33 connected to _quadrangle_4 14, _quadrangle_4 15,
-_segment_2 34 connected to _quadrangle_4 15, _quadrangle_4 16,
-_segment_2 35 connected to _quadrangle_4 15, _quadrangle_4 17,
-_segment_2 36 connected to _quadrangle_4 16, _quadrangle_4 17,
-ElementToSubelement1
-_point_1 0 connected to _segment_2 0, _segment_2 2, _segment_2 12, _segment_2 19,
-_point_1 1 connected to _segment_2 0, _segment_2 1, _segment_2 20, _segment_2 26,
-_point_1 2 connected to _segment_2 1, _segment_2 2, _segment_2 6, _segment_2 7, _segment_2 18, _segment_2 25,
-_point_1 3 connected to _segment_2 3, _segment_2 5, _segment_2 13, _segment_2 19,
-_point_1 4 connected to _segment_2 3, _segment_2 4, _segment_2 10, _segment_2 11, _segment_2 18, _segment_2 30,
-_point_1 5 connected to _segment_2 4, _segment_2 5, _segment_2 20, _segment_2 27,
-_point_1 6 connected to _segment_2 6, _segment_2 8, _segment_2 12, _segment_2 15, _segment_2 22,
-_point_1 7 connected to _segment_2 7, _segment_2 8, _segment_2 14, _segment_2 21, _segment_2 33,
-_point_1 8 connected to _segment_2 9, _segment_2 11, _segment_2 13, _segment_2 16, _segment_2 22,
-_point_1 9 connected to _segment_2 9, _segment_2 10, _segment_2 17, _segment_2 21, _segment_2 35,
-_point_1 10 connected to _segment_2 14, _segment_2 15, _segment_2 23,
-_point_1 11 connected to _segment_2 16, _segment_2 17, _segment_2 23,
-_point_1 12 connected to _segment_2 24, _segment_2 26, _segment_2 28,
-_point_1 13 connected to _segment_2 24, _segment_2 25, _segment_2 29, _segment_2 32,
-_point_1 14 connected to _segment_2 27, _segment_2 28, _segment_2 31,
-_point_1 15 connected to _segment_2 29, _segment_2 30, _segment_2 31, _segment_2 36,
-_point_1 16 connected to _segment_2 32, _segment_2 33, _segment_2 34,
-_point_1 17 connected to _segment_2 34, _segment_2 35, _segment_2 36,
-
-SubelementToElement3
-_hexahedron_8 0 connected to _quadrangle_4 2, _quadrangle_4 9, _quadrangle_4 10, _quadrangle_4 11, _quadrangle_4 12, _quadrangle_4 13,
-_hexahedron_8 1 connected to _quadrangle_4 5, _quadrangle_4 11, _quadrangle_4 14, _quadrangle_4 15, _quadrangle_4 16, _quadrangle_4 17,
-_pentahedron_6 0 connected to _triangle_3 0, _triangle_3 1, _quadrangle_4 0, _quadrangle_4 1, _quadrangle_4 2,
-_pentahedron_6 1 connected to _triangle_3 2, _triangle_3 3, _quadrangle_4 3, _quadrangle_4 4, _quadrangle_4 5,
-_pentahedron_6 2 connected to _triangle_3 4, _triangle_3 5, _quadrangle_4 0, _quadrangle_4 4, _quadrangle_4 6,
-_pentahedron_6 3 connected to _triangle_3 6, _triangle_3 7, _quadrangle_4 3, _quadrangle_4 7, _quadrangle_4 8,
-SubelementToElement2
-_quadrangle_4 0 connected to _segment_2 2, _segment_2 3, _segment_2 18, _segment_2 19,
-_quadrangle_4 1 connected to _segment_2 0, _segment_2 5, _segment_2 19, _segment_2 20,
-_quadrangle_4 2 connected to _segment_2 1, _segment_2 4, _segment_2 18, _segment_2 20,
-_quadrangle_4 3 connected to _segment_2 8, _segment_2 9, _segment_2 21, _segment_2 22,
-_quadrangle_4 4 connected to _segment_2 6, _segment_2 11, _segment_2 18, _segment_2 22,
-_quadrangle_4 5 connected to _segment_2 7, _segment_2 10, _segment_2 18, _segment_2 21,
-_quadrangle_4 6 connected to _segment_2 12, _segment_2 13, _segment_2 19, _segment_2 22,
-_quadrangle_4 7 connected to _segment_2 14, _segment_2 17, _segment_2 21, _segment_2 23,
-_quadrangle_4 8 connected to _segment_2 15, _segment_2 16, _segment_2 22, _segment_2 23,
-_quadrangle_4 9 connected to _segment_2 1, _segment_2 24, _segment_2 25, _segment_2 26,
-_quadrangle_4 10 connected to _segment_2 20, _segment_2 26, _segment_2 27, _segment_2 28,
-_quadrangle_4 11 connected to _segment_2 18, _segment_2 25, _segment_2 29, _segment_2 30,
-_quadrangle_4 12 connected to _segment_2 24, _segment_2 28, _segment_2 29, _segment_2 31,
-_quadrangle_4 13 connected to _segment_2 4, _segment_2 27, _segment_2 30, _segment_2 31,
-_quadrangle_4 14 connected to _segment_2 7, _segment_2 25, _segment_2 32, _segment_2 33,
-_quadrangle_4 15 connected to _segment_2 21, _segment_2 33, _segment_2 34, _segment_2 35,
-_quadrangle_4 16 connected to _segment_2 29, _segment_2 32, _segment_2 34, _segment_2 36,
-_quadrangle_4 17 connected to _segment_2 10, _segment_2 30, _segment_2 35, _segment_2 36,
-_triangle_3 0 connected to _segment_2 0, _segment_2 1, _segment_2 2,
-_triangle_3 1 connected to _segment_2 3, _segment_2 4, _segment_2 5,
-_triangle_3 2 connected to _segment_2 6, _segment_2 7, _segment_2 8,
-_triangle_3 3 connected to _segment_2 9, _segment_2 10, _segment_2 11,
-_triangle_3 4 connected to _segment_2 2, _segment_2 6, _segment_2 12,
-_triangle_3 5 connected to _segment_2 3, _segment_2 11, _segment_2 13,
-_triangle_3 6 connected to _segment_2 8, _segment_2 14, _segment_2 15,
-_triangle_3 7 connected to _segment_2 9, _segment_2 16, _segment_2 17,
-SubelementToElement1
-_segment_2 0 connected to _point_1 0, _point_1 1,
-_segment_2 1 connected to _point_1 1, _point_1 2,
-_segment_2 2 connected to _point_1 0, _point_1 2,
-_segment_2 3 connected to _point_1 3, _point_1 4,
-_segment_2 4 connected to _point_1 4, _point_1 5,
-_segment_2 5 connected to _point_1 3, _point_1 5,
-_segment_2 6 connected to _point_1 2, _point_1 6,
-_segment_2 7 connected to _point_1 2, _point_1 7,
-_segment_2 8 connected to _point_1 6, _point_1 7,
-_segment_2 9 connected to _point_1 8, _point_1 9,
-_segment_2 10 connected to _point_1 4, _point_1 9,
-_segment_2 11 connected to _point_1 4, _point_1 8,
-_segment_2 12 connected to _point_1 0, _point_1 6,
-_segment_2 13 connected to _point_1 3, _point_1 8,
-_segment_2 14 connected to _point_1 7, _point_1 10,
-_segment_2 15 connected to _point_1 6, _point_1 10,
-_segment_2 16 connected to _point_1 8, _point_1 11,
-_segment_2 17 connected to _point_1 9, _point_1 11,
-_segment_2 18 connected to _point_1 2, _point_1 4,
-_segment_2 19 connected to _point_1 0, _point_1 3,
-_segment_2 20 connected to _point_1 1, _point_1 5,
-_segment_2 21 connected to _point_1 7, _point_1 9,
-_segment_2 22 connected to _point_1 6, _point_1 8,
-_segment_2 23 connected to _point_1 10, _point_1 11,
-_segment_2 24 connected to _point_1 12, _point_1 13,
-_segment_2 25 connected to _point_1 2, _point_1 13,
-_segment_2 26 connected to _point_1 1, _point_1 12,
-_segment_2 27 connected to _point_1 5, _point_1 14,
-_segment_2 28 connected to _point_1 12, _point_1 14,
-_segment_2 29 connected to _point_1 13, _point_1 15,
-_segment_2 30 connected to _point_1 4, _point_1 15,
-_segment_2 31 connected to _point_1 14, _point_1 15,
-_segment_2 32 connected to _point_1 13, _point_1 16,
-_segment_2 33 connected to _point_1 7, _point_1 16,
-_segment_2 34 connected to _point_1 16, _point_1 17,
-_segment_2 35 connected to _point_1 9, _point_1 17,
-_segment_2 36 connected to _point_1 15, _point_1 17,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.cc
deleted file mode 100644
index e0b950663..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * @file test_buildfacets_mixed3d_quadratic.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Sun Oct 19 2014
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with hexahedrons
- * and pentahedrons
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 3;
- const ElementType type1 = _hexahedron_20;
- const ElementType type2 = _pentahedron_15;
-
- Mesh mesh(spatial_dimension);
- mesh.read("mixed3d_quadratic.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet1 = mesh.getFacetType(type1);
- const ElementType type_facet2 = mesh.getFacetType(type2);
- const ElementType type_subfacet = mesh.getFacetType(type_facet1);
- const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel3_1 =
- mesh_facets.getElementToSubelement(type_facet1);
- const Array<std::vector<Element>> & el_to_subel3_2 =
- mesh_facets.getElementToSubelement(type_facet2);
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_subfacet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subsubfacet);
-
- std::cout << "ElementToSubelement3" << std::endl;
- for (UInt i = 0; i < el_to_subel3_1.size(); ++i) {
- std::cout << type_facet1 << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3_1(i)[j].type << " "
- << el_to_subel3_1(i)[j].element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt i = 0; i < el_to_subel3_2.size(); ++i) {
- std::cout << type_facet2 << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3_2(i)[j].type << " "
- << el_to_subel3_2(i)[j].element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel2(i).size(); ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subsubfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el3_1 =
- mesh_facets.getSubelementToElement(type1);
- const Array<Element> & subel_to_el3_2 =
- mesh_facets.getSubelementToElement(type2);
- const Array<Element> & subel_to_el2_1 =
- mesh_facets.getSubelementToElement(type_facet1);
- const Array<Element> & subel_to_el2_2 =
- mesh_facets.getSubelementToElement(type_facet2);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_subfacet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement3" << std::endl;
- for (UInt i = 0; i < subel_to_el3_1.size(); ++i) {
- std::cout << type1 << " " << i << " connected to ";
- for (UInt j = 0; j < 6; ++j) {
- std::cout << subel_to_el3_1(i, j).type << " "
- << subel_to_el3_1(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt i = 0; i < subel_to_el3_2.size(); ++i) {
- std::cout << type2 << " " << i << " connected to ";
- for (UInt j = 0; j < 5; ++j) {
- std::cout << subel_to_el3_2(i, j).type << " "
- << subel_to_el3_2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2_1.size(); ++i) {
- std::cout << type_facet1 << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2_1(i, j).type << " "
- << subel_to_el2_1(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2_2.size(); ++i) {
- std::cout << type_facet2 << " " << i << " connected to ";
- for (UInt j = 0; j < 3; ++j) {
- std::cout << subel_to_el2_2(i, j).type << " "
- << subel_to_el2_2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.verified
deleted file mode 100644
index b2bf25403..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.verified
+++ /dev/null
@@ -1,158 +0,0 @@
-ElementToSubelement3
-_quadrangle_8 0 connected to _pentahedron_15 0, _pentahedron_15 2,
-_quadrangle_8 1 connected to _pentahedron_15 0, _not_defined 4294967295,
-_quadrangle_8 2 connected to _pentahedron_15 0, _hexahedron_20 0,
-_quadrangle_8 3 connected to _pentahedron_15 1, _pentahedron_15 3,
-_quadrangle_8 4 connected to _pentahedron_15 1, _pentahedron_15 2,
-_quadrangle_8 5 connected to _pentahedron_15 1, _hexahedron_20 1,
-_quadrangle_8 6 connected to _pentahedron_15 2, _not_defined 4294967295,
-_quadrangle_8 7 connected to _pentahedron_15 3, _not_defined 4294967295,
-_quadrangle_8 8 connected to _pentahedron_15 3, _not_defined 4294967295,
-_quadrangle_8 9 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 10 connected to _hexahedron_20 0, _hexahedron_20 1,
-_quadrangle_8 11 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 12 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 13 connected to _hexahedron_20 0, _not_defined 4294967295,
-_quadrangle_8 14 connected to _hexahedron_20 1, _not_defined 4294967295,
-_quadrangle_8 15 connected to _hexahedron_20 1, _not_defined 4294967295,
-_quadrangle_8 16 connected to _hexahedron_20 1, _not_defined 4294967295,
-_quadrangle_8 17 connected to _hexahedron_20 1, _not_defined 4294967295,
-_triangle_6 0 connected to _pentahedron_15 0, _not_defined 4294967295,
-_triangle_6 1 connected to _pentahedron_15 0, _not_defined 4294967295,
-_triangle_6 2 connected to _pentahedron_15 1, _not_defined 4294967295,
-_triangle_6 3 connected to _pentahedron_15 1, _not_defined 4294967295,
-_triangle_6 4 connected to _pentahedron_15 2, _not_defined 4294967295,
-_triangle_6 5 connected to _pentahedron_15 2, _not_defined 4294967295,
-_triangle_6 6 connected to _pentahedron_15 3, _not_defined 4294967295,
-_triangle_6 7 connected to _pentahedron_15 3, _not_defined 4294967295,
-ElementToSubelement2
-_segment_3 0 connected to _triangle_6 0, _quadrangle_8 1,
-_segment_3 1 connected to _triangle_6 0, _quadrangle_8 2, _quadrangle_8 12,
-_segment_3 2 connected to _triangle_6 0, _triangle_6 4, _quadrangle_8 0,
-_segment_3 3 connected to _triangle_6 1, _triangle_6 5, _quadrangle_8 0,
-_segment_3 4 connected to _triangle_6 1, _quadrangle_8 2, _quadrangle_8 13,
-_segment_3 5 connected to _triangle_6 1, _quadrangle_8 1,
-_segment_3 6 connected to _triangle_6 2, _triangle_6 4, _quadrangle_8 4,
-_segment_3 7 connected to _triangle_6 2, _quadrangle_8 5, _quadrangle_8 16,
-_segment_3 8 connected to _triangle_6 2, _triangle_6 6, _quadrangle_8 3,
-_segment_3 9 connected to _triangle_6 3, _triangle_6 7, _quadrangle_8 3,
-_segment_3 10 connected to _triangle_6 3, _quadrangle_8 5, _quadrangle_8 17,
-_segment_3 11 connected to _triangle_6 3, _triangle_6 5, _quadrangle_8 4,
-_segment_3 12 connected to _triangle_6 4, _quadrangle_8 6,
-_segment_3 13 connected to _triangle_6 5, _quadrangle_8 6,
-_segment_3 14 connected to _triangle_6 6, _quadrangle_8 7,
-_segment_3 15 connected to _triangle_6 6, _quadrangle_8 8,
-_segment_3 16 connected to _triangle_6 7, _quadrangle_8 8,
-_segment_3 17 connected to _triangle_6 7, _quadrangle_8 7,
-_segment_3 18 connected to _quadrangle_8 0, _quadrangle_8 2, _quadrangle_8 4, _quadrangle_8 5, _quadrangle_8 10,
-_segment_3 19 connected to _quadrangle_8 0, _quadrangle_8 1, _quadrangle_8 6,
-_segment_3 20 connected to _quadrangle_8 1, _quadrangle_8 2, _quadrangle_8 9,
-_segment_3 21 connected to _quadrangle_8 3, _quadrangle_8 5, _quadrangle_8 7, _quadrangle_8 14,
-_segment_3 22 connected to _quadrangle_8 3, _quadrangle_8 4, _quadrangle_8 6, _quadrangle_8 8,
-_segment_3 23 connected to _quadrangle_8 7, _quadrangle_8 8,
-_segment_3 24 connected to _quadrangle_8 9, _quadrangle_8 12,
-_segment_3 25 connected to _quadrangle_8 9, _quadrangle_8 13,
-_segment_3 26 connected to _quadrangle_8 9, _quadrangle_8 11,
-_segment_3 27 connected to _quadrangle_8 10, _quadrangle_8 12, _quadrangle_8 16,
-_segment_3 28 connected to _quadrangle_8 10, _quadrangle_8 11, _quadrangle_8 15,
-_segment_3 29 connected to _quadrangle_8 10, _quadrangle_8 13, _quadrangle_8 17,
-_segment_3 30 connected to _quadrangle_8 11, _quadrangle_8 12,
-_segment_3 31 connected to _quadrangle_8 11, _quadrangle_8 13,
-_segment_3 32 connected to _quadrangle_8 14, _quadrangle_8 16,
-_segment_3 33 connected to _quadrangle_8 14, _quadrangle_8 15,
-_segment_3 34 connected to _quadrangle_8 14, _quadrangle_8 17,
-_segment_3 35 connected to _quadrangle_8 15, _quadrangle_8 16,
-_segment_3 36 connected to _quadrangle_8 15, _quadrangle_8 17,
-ElementToSubelement1
-_point_1 0 connected to _segment_3 0, _segment_3 2, _segment_3 12, _segment_3 19,
-_point_1 1 connected to _segment_3 0, _segment_3 1, _segment_3 20, _segment_3 24,
-_point_1 2 connected to _segment_3 1, _segment_3 2, _segment_3 6, _segment_3 7, _segment_3 18, _segment_3 27,
-_point_1 3 connected to _segment_3 3, _segment_3 5, _segment_3 13, _segment_3 19,
-_point_1 4 connected to _segment_3 3, _segment_3 4, _segment_3 10, _segment_3 11, _segment_3 18, _segment_3 29,
-_point_1 5 connected to _segment_3 4, _segment_3 5, _segment_3 20, _segment_3 25,
-_point_1 6 connected to _segment_3 6, _segment_3 8, _segment_3 12, _segment_3 15, _segment_3 22,
-_point_1 7 connected to _segment_3 7, _segment_3 8, _segment_3 14, _segment_3 21, _segment_3 32,
-_point_1 8 connected to _segment_3 9, _segment_3 11, _segment_3 13, _segment_3 16, _segment_3 22,
-_point_1 9 connected to _segment_3 9, _segment_3 10, _segment_3 17, _segment_3 21, _segment_3 34,
-_point_1 10 connected to _segment_3 14, _segment_3 15, _segment_3 23,
-_point_1 11 connected to _segment_3 16, _segment_3 17, _segment_3 23,
-_point_1 12 connected to _segment_3 24, _segment_3 26, _segment_3 30,
-_point_1 13 connected to _segment_3 25, _segment_3 26, _segment_3 31,
-_point_1 14 connected to _segment_3 27, _segment_3 28, _segment_3 30, _segment_3 35,
-_point_1 15 connected to _segment_3 28, _segment_3 29, _segment_3 31, _segment_3 36,
-_point_1 16 connected to _segment_3 32, _segment_3 33, _segment_3 35,
-_point_1 17 connected to _segment_3 33, _segment_3 34, _segment_3 36,
-
-SubelementToElement3
-_hexahedron_20 0 connected to _quadrangle_8 2, _quadrangle_8 9, _quadrangle_8 10, _quadrangle_8 11, _quadrangle_8 12, _quadrangle_8 13,
-_hexahedron_20 1 connected to _quadrangle_8 5, _quadrangle_8 10, _quadrangle_8 14, _quadrangle_8 15, _quadrangle_8 16, _quadrangle_8 17,
-_pentahedron_15 0 connected to _triangle_6 0, _triangle_6 1, _quadrangle_8 0, _quadrangle_8 1, _quadrangle_8 2,
-_pentahedron_15 1 connected to _triangle_6 2, _triangle_6 3, _quadrangle_8 3, _quadrangle_8 4, _quadrangle_8 5,
-_pentahedron_15 2 connected to _triangle_6 4, _triangle_6 5, _quadrangle_8 0, _quadrangle_8 4, _quadrangle_8 6,
-_pentahedron_15 3 connected to _triangle_6 6, _triangle_6 7, _quadrangle_8 3, _quadrangle_8 7, _quadrangle_8 8,
-SubelementToElement2
-_quadrangle_8 0 connected to _segment_3 2, _segment_3 3, _segment_3 18, _segment_3 19,
-_quadrangle_8 1 connected to _segment_3 0, _segment_3 5, _segment_3 19, _segment_3 20,
-_quadrangle_8 2 connected to _segment_3 1, _segment_3 4, _segment_3 18, _segment_3 20,
-_quadrangle_8 3 connected to _segment_3 8, _segment_3 9, _segment_3 21, _segment_3 22,
-_quadrangle_8 4 connected to _segment_3 6, _segment_3 11, _segment_3 18, _segment_3 22,
-_quadrangle_8 5 connected to _segment_3 7, _segment_3 10, _segment_3 18, _segment_3 21,
-_quadrangle_8 6 connected to _segment_3 12, _segment_3 13, _segment_3 19, _segment_3 22,
-_quadrangle_8 7 connected to _segment_3 14, _segment_3 17, _segment_3 21, _segment_3 23,
-_quadrangle_8 8 connected to _segment_3 15, _segment_3 16, _segment_3 22, _segment_3 23,
-_quadrangle_8 9 connected to _segment_3 20, _segment_3 24, _segment_3 25, _segment_3 26,
-_quadrangle_8 10 connected to _segment_3 18, _segment_3 27, _segment_3 28, _segment_3 29,
-_quadrangle_8 11 connected to _segment_3 26, _segment_3 28, _segment_3 30, _segment_3 31,
-_quadrangle_8 12 connected to _segment_3 1, _segment_3 24, _segment_3 27, _segment_3 30,
-_quadrangle_8 13 connected to _segment_3 4, _segment_3 25, _segment_3 29, _segment_3 31,
-_quadrangle_8 14 connected to _segment_3 21, _segment_3 32, _segment_3 33, _segment_3 34,
-_quadrangle_8 15 connected to _segment_3 28, _segment_3 33, _segment_3 35, _segment_3 36,
-_quadrangle_8 16 connected to _segment_3 7, _segment_3 27, _segment_3 32, _segment_3 35,
-_quadrangle_8 17 connected to _segment_3 10, _segment_3 29, _segment_3 34, _segment_3 36,
-SubelementToElement2
-_triangle_6 0 connected to _segment_3 0, _segment_3 1, _segment_3 2,
-_triangle_6 1 connected to _segment_3 3, _segment_3 4, _segment_3 5,
-_triangle_6 2 connected to _segment_3 6, _segment_3 7, _segment_3 8,
-_triangle_6 3 connected to _segment_3 9, _segment_3 10, _segment_3 11,
-_triangle_6 4 connected to _segment_3 2, _segment_3 6, _segment_3 12,
-_triangle_6 5 connected to _segment_3 3, _segment_3 11, _segment_3 13,
-_triangle_6 6 connected to _segment_3 8, _segment_3 14, _segment_3 15,
-_triangle_6 7 connected to _segment_3 9, _segment_3 16, _segment_3 17,
-SubelementToElement1
-_segment_3 0 connected to _point_1 0, _point_1 1,
-_segment_3 1 connected to _point_1 1, _point_1 2,
-_segment_3 2 connected to _point_1 0, _point_1 2,
-_segment_3 3 connected to _point_1 3, _point_1 4,
-_segment_3 4 connected to _point_1 4, _point_1 5,
-_segment_3 5 connected to _point_1 3, _point_1 5,
-_segment_3 6 connected to _point_1 2, _point_1 6,
-_segment_3 7 connected to _point_1 2, _point_1 7,
-_segment_3 8 connected to _point_1 6, _point_1 7,
-_segment_3 9 connected to _point_1 8, _point_1 9,
-_segment_3 10 connected to _point_1 4, _point_1 9,
-_segment_3 11 connected to _point_1 4, _point_1 8,
-_segment_3 12 connected to _point_1 0, _point_1 6,
-_segment_3 13 connected to _point_1 3, _point_1 8,
-_segment_3 14 connected to _point_1 7, _point_1 10,
-_segment_3 15 connected to _point_1 6, _point_1 10,
-_segment_3 16 connected to _point_1 8, _point_1 11,
-_segment_3 17 connected to _point_1 9, _point_1 11,
-_segment_3 18 connected to _point_1 2, _point_1 4,
-_segment_3 19 connected to _point_1 0, _point_1 3,
-_segment_3 20 connected to _point_1 1, _point_1 5,
-_segment_3 21 connected to _point_1 7, _point_1 9,
-_segment_3 22 connected to _point_1 6, _point_1 8,
-_segment_3 23 connected to _point_1 10, _point_1 11,
-_segment_3 24 connected to _point_1 1, _point_1 12,
-_segment_3 25 connected to _point_1 5, _point_1 13,
-_segment_3 26 connected to _point_1 12, _point_1 13,
-_segment_3 27 connected to _point_1 2, _point_1 14,
-_segment_3 28 connected to _point_1 14, _point_1 15,
-_segment_3 29 connected to _point_1 4, _point_1 15,
-_segment_3 30 connected to _point_1 12, _point_1 14,
-_segment_3 31 connected to _point_1 13, _point_1 15,
-_segment_3 32 connected to _point_1 7, _point_1 16,
-_segment_3 33 connected to _point_1 16, _point_1 17,
-_segment_3 34 connected to _point_1 9, _point_1 17,
-_segment_3 35 connected to _point_1 14, _point_1 16,
-_segment_3 36 connected to _point_1 15, _point_1 17,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.cc
deleted file mode 100644
index 83027c537..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * @file test_buildfacets_pentahedron_15.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Sun Oct 19 2014
- * @date last modification: Tue Sep 08 2020
- *
- * @brief Test for cohesive elements
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 3;
- const ElementType type = _pentahedron_15;
-
- Mesh mesh(spatial_dimension);
- mesh.read("pentahedron_15.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- Vector<const ElementType> types_facet(mesh.getAllFacetTypes(type));
- const ElementType type_subfacet = mesh.getFacetType(types_facet(0));
- const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- for (UInt ft = 0; ft < types_facet.size(); ++ft) {
- ElementType type_facet = types_facet(ft);
- auto && el_to_subel3 = mesh_facets.getElementToSubelement(type_facet);
-
- std::cout << "ElementToSubelement3" << std::endl;
- for (UInt i = 0; i < el_to_subel3.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3(i)[j].type << " "
- << el_to_subel3(i)[j].element << ", ";
- }
- std::cout << " " << std::endl;
- }
- }
-
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_subfacet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subsubfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel2(i).size(); ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subsubfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el3 =
- mesh_facets.getSubelementToElement(type);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement3" << std::endl;
- for (UInt i = 0; i < subel_to_el3.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < subel_to_el3.getNbComponent(); ++j) {
- std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt ft = 0; ft < types_facet.size(); ++ft) {
- ElementType type_facet = types_facet(ft);
- auto && subel_to_el2 = mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < subel_to_el2.getNbComponent(); ++j) {
- std::cout << subel_to_el2(i, j).type << " "
- << subel_to_el2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
- }
-
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_subfacet);
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < subel_to_el1.getNbComponent(); ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.verified
deleted file mode 100644
index 779f7afa5..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.verified
+++ /dev/null
@@ -1,103 +0,0 @@
-ElementToSubelement3
-_triangle_6 0 connected to _pentahedron_15 0, _not_defined 4294967295,
-_triangle_6 1 connected to _pentahedron_15 0, _pentahedron_15 2,
-_triangle_6 2 connected to _pentahedron_15 1, _not_defined 4294967295,
-_triangle_6 3 connected to _pentahedron_15 1, _pentahedron_15 3,
-_triangle_6 4 connected to _pentahedron_15 2, _not_defined 4294967295,
-_triangle_6 5 connected to _pentahedron_15 3, _not_defined 4294967295,
-ElementToSubelement3
-_quadrangle_8 0 connected to _pentahedron_15 0, _pentahedron_15 1,
-_quadrangle_8 1 connected to _pentahedron_15 0, _not_defined 4294967295,
-_quadrangle_8 2 connected to _pentahedron_15 0, _not_defined 4294967295,
-_quadrangle_8 3 connected to _pentahedron_15 1, _not_defined 4294967295,
-_quadrangle_8 4 connected to _pentahedron_15 1, _not_defined 4294967295,
-_quadrangle_8 5 connected to _pentahedron_15 2, _pentahedron_15 3,
-_quadrangle_8 6 connected to _pentahedron_15 2, _not_defined 4294967295,
-_quadrangle_8 7 connected to _pentahedron_15 2, _not_defined 4294967295,
-_quadrangle_8 8 connected to _pentahedron_15 3, _not_defined 4294967295,
-_quadrangle_8 9 connected to _pentahedron_15 3, _not_defined 4294967295,
-ElementToSubelement2
-_segment_3 0 connected to _triangle_6 0, _quadrangle_8 1,
-_segment_3 1 connected to _triangle_6 0, _quadrangle_8 2,
-_segment_3 2 connected to _triangle_6 0, _triangle_6 2, _quadrangle_8 0,
-_segment_3 3 connected to _triangle_6 1, _triangle_6 3, _quadrangle_8 0, _quadrangle_8 5,
-_segment_3 4 connected to _triangle_6 1, _quadrangle_8 2, _quadrangle_8 7,
-_segment_3 5 connected to _triangle_6 1, _quadrangle_8 1, _quadrangle_8 6,
-_segment_3 6 connected to _triangle_6 2, _quadrangle_8 4,
-_segment_3 7 connected to _triangle_6 2, _quadrangle_8 3,
-_segment_3 8 connected to _triangle_6 3, _quadrangle_8 3, _quadrangle_8 8,
-_segment_3 9 connected to _triangle_6 3, _quadrangle_8 4, _quadrangle_8 9,
-_segment_3 10 connected to _triangle_6 4, _triangle_6 5, _quadrangle_8 5,
-_segment_3 11 connected to _triangle_6 4, _quadrangle_8 7,
-_segment_3 12 connected to _triangle_6 4, _quadrangle_8 6,
-_segment_3 13 connected to _triangle_6 5, _quadrangle_8 8,
-_segment_3 14 connected to _triangle_6 5, _quadrangle_8 9,
-_segment_3 15 connected to _quadrangle_8 0, _quadrangle_8 2, _quadrangle_8 3,
-_segment_3 16 connected to _quadrangle_8 0, _quadrangle_8 1, _quadrangle_8 4,
-_segment_3 17 connected to _quadrangle_8 1, _quadrangle_8 2,
-_segment_3 18 connected to _quadrangle_8 3, _quadrangle_8 4,
-_segment_3 19 connected to _quadrangle_8 5, _quadrangle_8 7, _quadrangle_8 8,
-_segment_3 20 connected to _quadrangle_8 5, _quadrangle_8 6, _quadrangle_8 9,
-_segment_3 21 connected to _quadrangle_8 6, _quadrangle_8 7,
-_segment_3 22 connected to _quadrangle_8 8, _quadrangle_8 9,
-ElementToSubelement1
-_point_1 0 connected to _segment_3 0, _segment_3 2, _segment_3 6, _segment_3 16,
-_point_1 1 connected to _segment_3 0, _segment_3 1, _segment_3 17,
-_point_1 2 connected to _segment_3 1, _segment_3 2, _segment_3 7, _segment_3 15,
-_point_1 3 connected to _segment_3 3, _segment_3 5, _segment_3 9, _segment_3 16, _segment_3 20,
-_point_1 4 connected to _segment_3 3, _segment_3 4, _segment_3 8, _segment_3 15, _segment_3 19,
-_point_1 5 connected to _segment_3 4, _segment_3 5, _segment_3 17, _segment_3 21,
-_point_1 6 connected to _segment_3 6, _segment_3 7, _segment_3 18,
-_point_1 7 connected to _segment_3 8, _segment_3 9, _segment_3 18, _segment_3 22,
-_point_1 8 connected to _segment_3 10, _segment_3 12, _segment_3 14, _segment_3 20,
-_point_1 9 connected to _segment_3 10, _segment_3 11, _segment_3 13, _segment_3 19,
-_point_1 10 connected to _segment_3 11, _segment_3 12, _segment_3 21,
-_point_1 11 connected to _segment_3 13, _segment_3 14, _segment_3 22,
-
-SubelementToElement3
-_pentahedron_15 0 connected to _triangle_6 0, _triangle_6 1, _quadrangle_8 0, _quadrangle_8 1, _quadrangle_8 2,
-_pentahedron_15 1 connected to _triangle_6 2, _triangle_6 3, _quadrangle_8 0, _quadrangle_8 3, _quadrangle_8 4,
-_pentahedron_15 2 connected to _triangle_6 1, _triangle_6 4, _quadrangle_8 5, _quadrangle_8 6, _quadrangle_8 7,
-_pentahedron_15 3 connected to _triangle_6 3, _triangle_6 5, _quadrangle_8 5, _quadrangle_8 8, _quadrangle_8 9,
-SubelementToElement2
-_triangle_6 0 connected to _segment_3 0, _segment_3 1, _segment_3 2,
-_triangle_6 1 connected to _segment_3 3, _segment_3 4, _segment_3 5,
-_triangle_6 2 connected to _segment_3 2, _segment_3 6, _segment_3 7,
-_triangle_6 3 connected to _segment_3 3, _segment_3 8, _segment_3 9,
-_triangle_6 4 connected to _segment_3 10, _segment_3 11, _segment_3 12,
-_triangle_6 5 connected to _segment_3 10, _segment_3 13, _segment_3 14,
-SubelementToElement2
-_quadrangle_8 0 connected to _segment_3 2, _segment_3 3, _segment_3 15, _segment_3 16,
-_quadrangle_8 1 connected to _segment_3 0, _segment_3 5, _segment_3 16, _segment_3 17,
-_quadrangle_8 2 connected to _segment_3 1, _segment_3 4, _segment_3 15, _segment_3 17,
-_quadrangle_8 3 connected to _segment_3 7, _segment_3 8, _segment_3 15, _segment_3 18,
-_quadrangle_8 4 connected to _segment_3 6, _segment_3 9, _segment_3 16, _segment_3 18,
-_quadrangle_8 5 connected to _segment_3 3, _segment_3 10, _segment_3 19, _segment_3 20,
-_quadrangle_8 6 connected to _segment_3 5, _segment_3 12, _segment_3 20, _segment_3 21,
-_quadrangle_8 7 connected to _segment_3 4, _segment_3 11, _segment_3 19, _segment_3 21,
-_quadrangle_8 8 connected to _segment_3 8, _segment_3 13, _segment_3 19, _segment_3 22,
-_quadrangle_8 9 connected to _segment_3 9, _segment_3 14, _segment_3 20, _segment_3 22,
-SubelementToElement1
-_segment_3 0 connected to _point_1 0, _point_1 1,
-_segment_3 1 connected to _point_1 1, _point_1 2,
-_segment_3 2 connected to _point_1 0, _point_1 2,
-_segment_3 3 connected to _point_1 3, _point_1 4,
-_segment_3 4 connected to _point_1 4, _point_1 5,
-_segment_3 5 connected to _point_1 3, _point_1 5,
-_segment_3 6 connected to _point_1 0, _point_1 6,
-_segment_3 7 connected to _point_1 2, _point_1 6,
-_segment_3 8 connected to _point_1 4, _point_1 7,
-_segment_3 9 connected to _point_1 3, _point_1 7,
-_segment_3 10 connected to _point_1 8, _point_1 9,
-_segment_3 11 connected to _point_1 9, _point_1 10,
-_segment_3 12 connected to _point_1 8, _point_1 10,
-_segment_3 13 connected to _point_1 9, _point_1 11,
-_segment_3 14 connected to _point_1 8, _point_1 11,
-_segment_3 15 connected to _point_1 2, _point_1 4,
-_segment_3 16 connected to _point_1 0, _point_1 3,
-_segment_3 17 connected to _point_1 1, _point_1 5,
-_segment_3 18 connected to _point_1 6, _point_1 7,
-_segment_3 19 connected to _point_1 4, _point_1 9,
-_segment_3 20 connected to _point_1 3, _point_1 8,
-_segment_3 21 connected to _point_1 5, _point_1 10,
-_segment_3 22 connected to _point_1 7, _point_1 11,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.cc
deleted file mode 100644
index 516ae6eab..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * @file test_buildfacets_pentahedron_6.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Sun Oct 19 2014
- * @date last modification: Tue Sep 08 2020
- *
- * @brief Test for cohesive elements
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 3;
- const ElementType type = _pentahedron_6;
-
- Mesh mesh(spatial_dimension);
- mesh.read("pentahedron_6.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- Vector<const ElementType> types_facet(mesh.getAllFacetTypes(type));
- const ElementType type_subfacet = mesh.getFacetType(types_facet(0));
- const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- for (UInt ft = 0; ft < types_facet.size(); ++ft) {
- ElementType type_facet = types_facet(ft);
- auto && el_to_subel3 = mesh_facets.getElementToSubelement(type_facet);
-
- std::cout << "ElementToSubelement3" << std::endl;
- for (UInt i = 0; i < el_to_subel3.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3(i)[j].type << " "
- << el_to_subel3(i)[j].element << ", ";
- }
- std::cout << " " << std::endl;
- }
- }
-
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_subfacet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subsubfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel2(i).size(); ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subsubfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- auto && subel_to_el3 = mesh_facets.getSubelementToElement(type);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement3" << std::endl;
- for (UInt i = 0; i < subel_to_el3.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < subel_to_el3.getNbComponent(); ++j) {
- std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- for (UInt ft = 0; ft < types_facet.size(); ++ft) {
- ElementType type_facet = types_facet(ft);
- auto && subel_to_el2 = mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < subel_to_el2.getNbComponent(); ++j) {
- std::cout << subel_to_el2(i, j).type << " "
- << subel_to_el2(i, j).element << ", ";
- }
- std::cout << " " << std::endl;
- }
- }
-
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_subfacet);
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < subel_to_el1.getNbComponent(); ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.verified
deleted file mode 100644
index 2c6f8fcef..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.verified
+++ /dev/null
@@ -1,103 +0,0 @@
-ElementToSubelement3
-_triangle_3 0 connected to _pentahedron_6 0, _not_defined 4294967295,
-_triangle_3 1 connected to _pentahedron_6 0, _pentahedron_6 2,
-_triangle_3 2 connected to _pentahedron_6 1, _not_defined 4294967295,
-_triangle_3 3 connected to _pentahedron_6 1, _pentahedron_6 3,
-_triangle_3 4 connected to _pentahedron_6 2, _not_defined 4294967295,
-_triangle_3 5 connected to _pentahedron_6 3, _not_defined 4294967295,
-ElementToSubelement3
-_quadrangle_4 0 connected to _pentahedron_6 0, _pentahedron_6 1,
-_quadrangle_4 1 connected to _pentahedron_6 0, _not_defined 4294967295,
-_quadrangle_4 2 connected to _pentahedron_6 0, _not_defined 4294967295,
-_quadrangle_4 3 connected to _pentahedron_6 1, _not_defined 4294967295,
-_quadrangle_4 4 connected to _pentahedron_6 1, _not_defined 4294967295,
-_quadrangle_4 5 connected to _pentahedron_6 2, _pentahedron_6 3,
-_quadrangle_4 6 connected to _pentahedron_6 2, _not_defined 4294967295,
-_quadrangle_4 7 connected to _pentahedron_6 2, _not_defined 4294967295,
-_quadrangle_4 8 connected to _pentahedron_6 3, _not_defined 4294967295,
-_quadrangle_4 9 connected to _pentahedron_6 3, _not_defined 4294967295,
-ElementToSubelement2
-_segment_2 0 connected to _triangle_3 0, _quadrangle_4 1,
-_segment_2 1 connected to _triangle_3 0, _quadrangle_4 2,
-_segment_2 2 connected to _triangle_3 0, _triangle_3 2, _quadrangle_4 0,
-_segment_2 3 connected to _triangle_3 1, _triangle_3 3, _quadrangle_4 0, _quadrangle_4 5,
-_segment_2 4 connected to _triangle_3 1, _quadrangle_4 2, _quadrangle_4 7,
-_segment_2 5 connected to _triangle_3 1, _quadrangle_4 1, _quadrangle_4 6,
-_segment_2 6 connected to _triangle_3 2, _quadrangle_4 4,
-_segment_2 7 connected to _triangle_3 2, _quadrangle_4 3,
-_segment_2 8 connected to _triangle_3 3, _quadrangle_4 3, _quadrangle_4 8,
-_segment_2 9 connected to _triangle_3 3, _quadrangle_4 4, _quadrangle_4 9,
-_segment_2 10 connected to _triangle_3 4, _triangle_3 5, _quadrangle_4 5,
-_segment_2 11 connected to _triangle_3 4, _quadrangle_4 7,
-_segment_2 12 connected to _triangle_3 4, _quadrangle_4 6,
-_segment_2 13 connected to _triangle_3 5, _quadrangle_4 8,
-_segment_2 14 connected to _triangle_3 5, _quadrangle_4 9,
-_segment_2 15 connected to _quadrangle_4 0, _quadrangle_4 2, _quadrangle_4 3,
-_segment_2 16 connected to _quadrangle_4 0, _quadrangle_4 1, _quadrangle_4 4,
-_segment_2 17 connected to _quadrangle_4 1, _quadrangle_4 2,
-_segment_2 18 connected to _quadrangle_4 3, _quadrangle_4 4,
-_segment_2 19 connected to _quadrangle_4 5, _quadrangle_4 7, _quadrangle_4 8,
-_segment_2 20 connected to _quadrangle_4 5, _quadrangle_4 6, _quadrangle_4 9,
-_segment_2 21 connected to _quadrangle_4 6, _quadrangle_4 7,
-_segment_2 22 connected to _quadrangle_4 8, _quadrangle_4 9,
-ElementToSubelement1
-_point_1 0 connected to _segment_2 0, _segment_2 2, _segment_2 6, _segment_2 16,
-_point_1 1 connected to _segment_2 0, _segment_2 1, _segment_2 17,
-_point_1 2 connected to _segment_2 1, _segment_2 2, _segment_2 7, _segment_2 15,
-_point_1 3 connected to _segment_2 3, _segment_2 5, _segment_2 9, _segment_2 16, _segment_2 20,
-_point_1 4 connected to _segment_2 3, _segment_2 4, _segment_2 8, _segment_2 15, _segment_2 19,
-_point_1 5 connected to _segment_2 4, _segment_2 5, _segment_2 17, _segment_2 21,
-_point_1 6 connected to _segment_2 6, _segment_2 7, _segment_2 18,
-_point_1 7 connected to _segment_2 8, _segment_2 9, _segment_2 18, _segment_2 22,
-_point_1 8 connected to _segment_2 10, _segment_2 12, _segment_2 14, _segment_2 20,
-_point_1 9 connected to _segment_2 10, _segment_2 11, _segment_2 13, _segment_2 19,
-_point_1 10 connected to _segment_2 11, _segment_2 12, _segment_2 21,
-_point_1 11 connected to _segment_2 13, _segment_2 14, _segment_2 22,
-
-SubelementToElement3
-_pentahedron_6 0 connected to _triangle_3 0, _triangle_3 1, _quadrangle_4 0, _quadrangle_4 1, _quadrangle_4 2,
-_pentahedron_6 1 connected to _triangle_3 2, _triangle_3 3, _quadrangle_4 0, _quadrangle_4 3, _quadrangle_4 4,
-_pentahedron_6 2 connected to _triangle_3 1, _triangle_3 4, _quadrangle_4 5, _quadrangle_4 6, _quadrangle_4 7,
-_pentahedron_6 3 connected to _triangle_3 3, _triangle_3 5, _quadrangle_4 5, _quadrangle_4 8, _quadrangle_4 9,
-SubelementToElement2
-_triangle_3 0 connected to _segment_2 0, _segment_2 1, _segment_2 2,
-_triangle_3 1 connected to _segment_2 3, _segment_2 4, _segment_2 5,
-_triangle_3 2 connected to _segment_2 2, _segment_2 6, _segment_2 7,
-_triangle_3 3 connected to _segment_2 3, _segment_2 8, _segment_2 9,
-_triangle_3 4 connected to _segment_2 10, _segment_2 11, _segment_2 12,
-_triangle_3 5 connected to _segment_2 10, _segment_2 13, _segment_2 14,
-SubelementToElement2
-_quadrangle_4 0 connected to _segment_2 2, _segment_2 3, _segment_2 15, _segment_2 16,
-_quadrangle_4 1 connected to _segment_2 0, _segment_2 5, _segment_2 16, _segment_2 17,
-_quadrangle_4 2 connected to _segment_2 1, _segment_2 4, _segment_2 15, _segment_2 17,
-_quadrangle_4 3 connected to _segment_2 7, _segment_2 8, _segment_2 15, _segment_2 18,
-_quadrangle_4 4 connected to _segment_2 6, _segment_2 9, _segment_2 16, _segment_2 18,
-_quadrangle_4 5 connected to _segment_2 3, _segment_2 10, _segment_2 19, _segment_2 20,
-_quadrangle_4 6 connected to _segment_2 5, _segment_2 12, _segment_2 20, _segment_2 21,
-_quadrangle_4 7 connected to _segment_2 4, _segment_2 11, _segment_2 19, _segment_2 21,
-_quadrangle_4 8 connected to _segment_2 8, _segment_2 13, _segment_2 19, _segment_2 22,
-_quadrangle_4 9 connected to _segment_2 9, _segment_2 14, _segment_2 20, _segment_2 22,
-SubelementToElement1
-_segment_2 0 connected to _point_1 0, _point_1 1,
-_segment_2 1 connected to _point_1 1, _point_1 2,
-_segment_2 2 connected to _point_1 0, _point_1 2,
-_segment_2 3 connected to _point_1 3, _point_1 4,
-_segment_2 4 connected to _point_1 4, _point_1 5,
-_segment_2 5 connected to _point_1 3, _point_1 5,
-_segment_2 6 connected to _point_1 0, _point_1 6,
-_segment_2 7 connected to _point_1 2, _point_1 6,
-_segment_2 8 connected to _point_1 4, _point_1 7,
-_segment_2 9 connected to _point_1 3, _point_1 7,
-_segment_2 10 connected to _point_1 8, _point_1 9,
-_segment_2 11 connected to _point_1 9, _point_1 10,
-_segment_2 12 connected to _point_1 8, _point_1 10,
-_segment_2 13 connected to _point_1 9, _point_1 11,
-_segment_2 14 connected to _point_1 8, _point_1 11,
-_segment_2 15 connected to _point_1 2, _point_1 4,
-_segment_2 16 connected to _point_1 0, _point_1 3,
-_segment_2 17 connected to _point_1 1, _point_1 5,
-_segment_2 18 connected to _point_1 6, _point_1 7,
-_segment_2 19 connected to _point_1 4, _point_1 9,
-_segment_2 20 connected to _point_1 3, _point_1 8,
-_segment_2 21 connected to _point_1 5, _point_1 10,
-_segment_2 22 connected to _point_1 7, _point_1 11,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.cc
deleted file mode 100644
index dac8d1620..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * @file test_buildfacets_quadrangle_4.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Fri Sep 18 2015
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with quadrangles
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 2;
- const ElementType type = _quadrangle_4;
-
- Mesh mesh(spatial_dimension);
- mesh.read("quadrangle_4.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet = mesh.getFacetType(type);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el2 =
- mesh_facets.getSubelementToElement(type);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.verified
deleted file mode 100644
index 0b9d1d061..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.verified
+++ /dev/null
@@ -1,42 +0,0 @@
-ElementToSubelement2
-_segment_2 0 connected to _quadrangle_4 0, _not_defined 4294967295,
-_segment_2 1 connected to _quadrangle_4 0, _quadrangle_4 2,
-_segment_2 2 connected to _quadrangle_4 0, _quadrangle_4 1,
-_segment_2 3 connected to _quadrangle_4 0, _not_defined 4294967295,
-_segment_2 4 connected to _quadrangle_4 1, _quadrangle_4 3,
-_segment_2 5 connected to _quadrangle_4 1, _not_defined 4294967295,
-_segment_2 6 connected to _quadrangle_4 1, _not_defined 4294967295,
-_segment_2 7 connected to _quadrangle_4 2, _not_defined 4294967295,
-_segment_2 8 connected to _quadrangle_4 2, _not_defined 4294967295,
-_segment_2 9 connected to _quadrangle_4 2, _quadrangle_4 3,
-_segment_2 10 connected to _quadrangle_4 3, _not_defined 4294967295,
-_segment_2 11 connected to _quadrangle_4 3, _not_defined 4294967295,
-ElementToSubelement1
-_point_1 0 connected to _segment_2 0, _segment_2 3,
-_point_1 1 connected to _segment_2 0, _segment_2 1, _segment_2 7,
-_point_1 2 connected to _segment_2 1, _segment_2 2, _segment_2 4, _segment_2 9,
-_point_1 3 connected to _segment_2 2, _segment_2 3, _segment_2 6,
-_point_1 4 connected to _segment_2 4, _segment_2 5, _segment_2 11,
-_point_1 5 connected to _segment_2 5, _segment_2 6,
-_point_1 6 connected to _segment_2 7, _segment_2 8,
-_point_1 7 connected to _segment_2 8, _segment_2 9, _segment_2 10,
-_point_1 8 connected to _segment_2 10, _segment_2 11,
-
-SubelementToElement2
-_quadrangle_4 0 connected to _segment_2 0, _segment_2 1, _segment_2 2, _segment_2 3,
-_quadrangle_4 1 connected to _segment_2 2, _segment_2 4, _segment_2 5, _segment_2 6,
-_quadrangle_4 2 connected to _segment_2 1, _segment_2 7, _segment_2 8, _segment_2 9,
-_quadrangle_4 3 connected to _segment_2 4, _segment_2 9, _segment_2 10, _segment_2 11,
-SubelementToElement1
-_segment_2 0 connected to _point_1 0, _point_1 1,
-_segment_2 1 connected to _point_1 1, _point_1 2,
-_segment_2 2 connected to _point_1 2, _point_1 3,
-_segment_2 3 connected to _point_1 0, _point_1 3,
-_segment_2 4 connected to _point_1 2, _point_1 4,
-_segment_2 5 connected to _point_1 4, _point_1 5,
-_segment_2 6 connected to _point_1 3, _point_1 5,
-_segment_2 7 connected to _point_1 1, _point_1 6,
-_segment_2 8 connected to _point_1 6, _point_1 7,
-_segment_2 9 connected to _point_1 2, _point_1 7,
-_segment_2 10 connected to _point_1 7, _point_1 8,
-_segment_2 11 connected to _point_1 4, _point_1 8,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.cc
deleted file mode 100644
index 5c0c45d76..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * @file test_buildfacets_quadrangle_8.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Fri Sep 18 2015
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with quadrangles
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 2;
- const ElementType type = _quadrangle_8;
-
- Mesh mesh(spatial_dimension);
- mesh.read("quadrangle_8.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet = mesh.getFacetType(type);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el2 =
- mesh_facets.getSubelementToElement(type);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.verified
deleted file mode 100644
index c2ab8a8b2..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.verified
+++ /dev/null
@@ -1,42 +0,0 @@
-ElementToSubelement2
-_segment_3 0 connected to _quadrangle_8 0, _not_defined 4294967295,
-_segment_3 1 connected to _quadrangle_8 0, _quadrangle_8 2,
-_segment_3 2 connected to _quadrangle_8 0, _quadrangle_8 1,
-_segment_3 3 connected to _quadrangle_8 0, _not_defined 4294967295,
-_segment_3 4 connected to _quadrangle_8 1, _quadrangle_8 3,
-_segment_3 5 connected to _quadrangle_8 1, _not_defined 4294967295,
-_segment_3 6 connected to _quadrangle_8 1, _not_defined 4294967295,
-_segment_3 7 connected to _quadrangle_8 2, _not_defined 4294967295,
-_segment_3 8 connected to _quadrangle_8 2, _not_defined 4294967295,
-_segment_3 9 connected to _quadrangle_8 2, _quadrangle_8 3,
-_segment_3 10 connected to _quadrangle_8 3, _not_defined 4294967295,
-_segment_3 11 connected to _quadrangle_8 3, _not_defined 4294967295,
-ElementToSubelement1
-_point_1 0 connected to _segment_3 0, _segment_3 3,
-_point_1 1 connected to _segment_3 0, _segment_3 1, _segment_3 7,
-_point_1 2 connected to _segment_3 1, _segment_3 2, _segment_3 4, _segment_3 9,
-_point_1 3 connected to _segment_3 2, _segment_3 3, _segment_3 6,
-_point_1 4 connected to _segment_3 4, _segment_3 5, _segment_3 11,
-_point_1 5 connected to _segment_3 5, _segment_3 6,
-_point_1 6 connected to _segment_3 7, _segment_3 8,
-_point_1 7 connected to _segment_3 8, _segment_3 9, _segment_3 10,
-_point_1 8 connected to _segment_3 10, _segment_3 11,
-
-SubelementToElement2
-_quadrangle_8 0 connected to _segment_3 0, _segment_3 1, _segment_3 2, _segment_3 3,
-_quadrangle_8 1 connected to _segment_3 2, _segment_3 4, _segment_3 5, _segment_3 6,
-_quadrangle_8 2 connected to _segment_3 1, _segment_3 7, _segment_3 8, _segment_3 9,
-_quadrangle_8 3 connected to _segment_3 4, _segment_3 9, _segment_3 10, _segment_3 11,
-SubelementToElement1
-_segment_3 0 connected to _point_1 0, _point_1 1,
-_segment_3 1 connected to _point_1 1, _point_1 2,
-_segment_3 2 connected to _point_1 2, _point_1 3,
-_segment_3 3 connected to _point_1 0, _point_1 3,
-_segment_3 4 connected to _point_1 2, _point_1 4,
-_segment_3 5 connected to _point_1 4, _point_1 5,
-_segment_3 6 connected to _point_1 3, _point_1 5,
-_segment_3 7 connected to _point_1 1, _point_1 6,
-_segment_3 8 connected to _point_1 6, _point_1 7,
-_segment_3 9 connected to _point_1 2, _point_1 7,
-_segment_3 10 connected to _point_1 7, _point_1 8,
-_segment_3 11 connected to _point_1 4, _point_1 8,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.cc
deleted file mode 100644
index 78397077d..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * @file test_buildfacets_tetrahedron_10.cc
- *
- * @author Marco Vocialta <marco.vocialta@epfl.ch>
- *
- * @date creation: Sun Oct 19 2014
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test for cohesive elements
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 3;
- const ElementType type = _tetrahedron_10;
-
- Mesh mesh(spatial_dimension);
- mesh.read("tetrahedron_10.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- // debug::setDebugLevel(dblDump);
- // std::cout << mesh << std::endl;
- // std::cout << mesh_facets << std::endl;
-
- const ElementType type_facet = mesh.getFacetType(type);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
- const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel3 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_subfacet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subsubfacet);
-
- std::cout << "ElementToSubelement3" << std::endl;
- for (UInt i = 0; i < el_to_subel3.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel2(i).size(); ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subsubfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el3 =
- mesh_facets.getSubelementToElement(type);
- const Array<Element> & subel_to_el2 =
- mesh_facets.getSubelementToElement(type_facet);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_subfacet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement3" << std::endl;
- for (UInt i = 0; i < subel_to_el3.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < 4; ++j) {
- std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 3; ++j) {
- std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.verified
deleted file mode 100644
index 4ab908f44..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.verified
+++ /dev/null
@@ -1,207 +0,0 @@
-ElementToSubelement3
-_triangle_6 0 connected to _tetrahedron_10 0, _tetrahedron_10 11,
-_triangle_6 1 connected to _tetrahedron_10 0, _tetrahedron_10 12,
-_triangle_6 2 connected to _tetrahedron_10 0, _tetrahedron_10 6,
-_triangle_6 3 connected to _tetrahedron_10 0, _not_defined 4294967295,
-_triangle_6 4 connected to _tetrahedron_10 1, _tetrahedron_10 11,
-_triangle_6 5 connected to _tetrahedron_10 1, _tetrahedron_10 15,
-_triangle_6 6 connected to _tetrahedron_10 1, _not_defined 4294967295,
-_triangle_6 7 connected to _tetrahedron_10 1, _tetrahedron_10 13,
-_triangle_6 8 connected to _tetrahedron_10 2, _not_defined 4294967295,
-_triangle_6 9 connected to _tetrahedron_10 2, _tetrahedron_10 12,
-_triangle_6 10 connected to _tetrahedron_10 2, _not_defined 4294967295,
-_triangle_6 11 connected to _tetrahedron_10 2, _tetrahedron_10 6,
-_triangle_6 12 connected to _tetrahedron_10 3, _tetrahedron_10 5,
-_triangle_6 13 connected to _tetrahedron_10 3, _not_defined 4294967295,
-_triangle_6 14 connected to _tetrahedron_10 3, _not_defined 4294967295,
-_triangle_6 15 connected to _tetrahedron_10 3, _tetrahedron_10 8,
-_triangle_6 16 connected to _tetrahedron_10 4, _tetrahedron_10 8,
-_triangle_6 17 connected to _tetrahedron_10 4, _not_defined 4294967295,
-_triangle_6 18 connected to _tetrahedron_10 4, _tetrahedron_10 6,
-_triangle_6 19 connected to _tetrahedron_10 4, _tetrahedron_10 5,
-_triangle_6 20 connected to _tetrahedron_10 5, _not_defined 4294967295,
-_triangle_6 21 connected to _tetrahedron_10 5, _not_defined 4294967295,
-_triangle_6 22 connected to _tetrahedron_10 6, _not_defined 4294967295,
-_triangle_6 23 connected to _tetrahedron_10 7, _tetrahedron_10 9,
-_triangle_6 24 connected to _tetrahedron_10 7, _tetrahedron_10 8,
-_triangle_6 25 connected to _tetrahedron_10 7, _not_defined 4294967295,
-_triangle_6 26 connected to _tetrahedron_10 7, _tetrahedron_10 13,
-_triangle_6 27 connected to _tetrahedron_10 8, _not_defined 4294967295,
-_triangle_6 28 connected to _tetrahedron_10 9, _not_defined 4294967295,
-_triangle_6 29 connected to _tetrahedron_10 9, _not_defined 4294967295,
-_triangle_6 30 connected to _tetrahedron_10 9, _tetrahedron_10 14,
-_triangle_6 31 connected to _tetrahedron_10 10, _tetrahedron_10 15,
-_triangle_6 32 connected to _tetrahedron_10 10, _tetrahedron_10 11,
-_triangle_6 33 connected to _tetrahedron_10 10, _not_defined 4294967295,
-_triangle_6 34 connected to _tetrahedron_10 10, _not_defined 4294967295,
-_triangle_6 35 connected to _tetrahedron_10 11, _not_defined 4294967295,
-_triangle_6 36 connected to _tetrahedron_10 12, _not_defined 4294967295,
-_triangle_6 37 connected to _tetrahedron_10 12, _not_defined 4294967295,
-_triangle_6 38 connected to _tetrahedron_10 13, _not_defined 4294967295,
-_triangle_6 39 connected to _tetrahedron_10 13, _tetrahedron_10 14,
-_triangle_6 40 connected to _tetrahedron_10 14, _not_defined 4294967295,
-_triangle_6 41 connected to _tetrahedron_10 14, _not_defined 4294967295,
-_triangle_6 42 connected to _tetrahedron_10 15, _not_defined 4294967295,
-_triangle_6 43 connected to _tetrahedron_10 15, _not_defined 4294967295,
-ElementToSubelement2
-_segment_3 0 connected to _triangle_6 0, _triangle_6 2, _triangle_6 4, _triangle_6 7, _triangle_6 16, _triangle_6 18, _triangle_6 24, _triangle_6 26,
-_segment_3 1 connected to _triangle_6 0, _triangle_6 1, _triangle_6 32, _triangle_6 34, _triangle_6 37,
-_segment_3 2 connected to _triangle_6 0, _triangle_6 3, _triangle_6 35,
-_segment_3 3 connected to _triangle_6 1, _triangle_6 2, _triangle_6 9, _triangle_6 11,
-_segment_3 4 connected to _triangle_6 1, _triangle_6 3, _triangle_6 36,
-_segment_3 5 connected to _triangle_6 2, _triangle_6 3, _triangle_6 22,
-_segment_3 6 connected to _triangle_6 4, _triangle_6 6, _triangle_6 35,
-_segment_3 7 connected to _triangle_6 4, _triangle_6 5, _triangle_6 31, _triangle_6 32,
-_segment_3 8 connected to _triangle_6 5, _triangle_6 6, _triangle_6 42,
-_segment_3 9 connected to _triangle_6 5, _triangle_6 7, _triangle_6 39, _triangle_6 40, _triangle_6 43,
-_segment_3 10 connected to _triangle_6 6, _triangle_6 7, _triangle_6 38,
-_segment_3 11 connected to _triangle_6 8, _triangle_6 10,
-_segment_3 12 connected to _triangle_6 8, _triangle_6 9, _triangle_6 37,
-_segment_3 13 connected to _triangle_6 8, _triangle_6 11, _triangle_6 18, _triangle_6 19, _triangle_6 20,
-_segment_3 14 connected to _triangle_6 9, _triangle_6 10, _triangle_6 36,
-_segment_3 15 connected to _triangle_6 10, _triangle_6 11, _triangle_6 22,
-_segment_3 16 connected to _triangle_6 12, _triangle_6 14, _triangle_6 20,
-_segment_3 17 connected to _triangle_6 12, _triangle_6 13, _triangle_6 21,
-_segment_3 18 connected to _triangle_6 12, _triangle_6 15, _triangle_6 16, _triangle_6 19,
-_segment_3 19 connected to _triangle_6 13, _triangle_6 14,
-_segment_3 20 connected to _triangle_6 13, _triangle_6 15, _triangle_6 27,
-_segment_3 21 connected to _triangle_6 14, _triangle_6 15, _triangle_6 23, _triangle_6 24, _triangle_6 29,
-_segment_3 22 connected to _triangle_6 16, _triangle_6 17, _triangle_6 27,
-_segment_3 23 connected to _triangle_6 17, _triangle_6 18, _triangle_6 22,
-_segment_3 24 connected to _triangle_6 17, _triangle_6 19, _triangle_6 21,
-_segment_3 25 connected to _triangle_6 20, _triangle_6 21,
-_segment_3 26 connected to _triangle_6 23, _triangle_6 25, _triangle_6 28,
-_segment_3 27 connected to _triangle_6 23, _triangle_6 26, _triangle_6 30, _triangle_6 39,
-_segment_3 28 connected to _triangle_6 24, _triangle_6 25, _triangle_6 27,
-_segment_3 29 connected to _triangle_6 25, _triangle_6 26, _triangle_6 38,
-_segment_3 30 connected to _triangle_6 28, _triangle_6 29,
-_segment_3 31 connected to _triangle_6 28, _triangle_6 30, _triangle_6 41,
-_segment_3 32 connected to _triangle_6 29, _triangle_6 30, _triangle_6 40,
-_segment_3 33 connected to _triangle_6 31, _triangle_6 33, _triangle_6 42,
-_segment_3 34 connected to _triangle_6 31, _triangle_6 34, _triangle_6 43,
-_segment_3 35 connected to _triangle_6 32, _triangle_6 33, _triangle_6 35,
-_segment_3 36 connected to _triangle_6 33, _triangle_6 34,
-_segment_3 37 connected to _triangle_6 36, _triangle_6 37,
-_segment_3 38 connected to _triangle_6 38, _triangle_6 39, _triangle_6 41,
-_segment_3 39 connected to _triangle_6 40, _triangle_6 41,
-_segment_3 40 connected to _triangle_6 42, _triangle_6 43,
-ElementToSubelement1
-_point_1 0 connected to _segment_3 0, _segment_3 2, _segment_3 5, _segment_3 6, _segment_3 10, _segment_3 22, _segment_3 23, _segment_3 28, _segment_3 29,
-_point_1 1 connected to _segment_3 0, _segment_3 1, _segment_3 3, _segment_3 7, _segment_3 9, _segment_3 12, _segment_3 13, _segment_3 16, _segment_3 18, _segment_3 21, _segment_3 27, _segment_3 32, _segment_3 34,
-_point_1 2 connected to _segment_3 1, _segment_3 2, _segment_3 4, _segment_3 35, _segment_3 36, _segment_3 37,
-_point_1 3 connected to _segment_3 3, _segment_3 4, _segment_3 5, _segment_3 14, _segment_3 15,
-_point_1 4 connected to _segment_3 6, _segment_3 7, _segment_3 8, _segment_3 33, _segment_3 35,
-_point_1 5 connected to _segment_3 8, _segment_3 9, _segment_3 10, _segment_3 38, _segment_3 39, _segment_3 40,
-_point_1 6 connected to _segment_3 11, _segment_3 13, _segment_3 15, _segment_3 23, _segment_3 24, _segment_3 25,
-_point_1 7 connected to _segment_3 11, _segment_3 12, _segment_3 14, _segment_3 37,
-_point_1 8 connected to _segment_3 16, _segment_3 17, _segment_3 19, _segment_3 25,
-_point_1 9 connected to _segment_3 17, _segment_3 18, _segment_3 20, _segment_3 22, _segment_3 24,
-_point_1 10 connected to _segment_3 19, _segment_3 20, _segment_3 21, _segment_3 26, _segment_3 28, _segment_3 30,
-_point_1 11 connected to _segment_3 26, _segment_3 27, _segment_3 29, _segment_3 31, _segment_3 38,
-_point_1 12 connected to _segment_3 30, _segment_3 31, _segment_3 32, _segment_3 39,
-_point_1 13 connected to _segment_3 33, _segment_3 34, _segment_3 36, _segment_3 40,
-
-SubelementToElement3
-_tetrahedron_10 0 connected to _triangle_6 0, _triangle_6 1, _triangle_6 2, _triangle_6 3,
-_tetrahedron_10 1 connected to _triangle_6 4, _triangle_6 5, _triangle_6 6, _triangle_6 7,
-_tetrahedron_10 2 connected to _triangle_6 8, _triangle_6 9, _triangle_6 10, _triangle_6 11,
-_tetrahedron_10 3 connected to _triangle_6 12, _triangle_6 13, _triangle_6 14, _triangle_6 15,
-_tetrahedron_10 4 connected to _triangle_6 16, _triangle_6 17, _triangle_6 18, _triangle_6 19,
-_tetrahedron_10 5 connected to _triangle_6 12, _triangle_6 19, _triangle_6 20, _triangle_6 21,
-_tetrahedron_10 6 connected to _triangle_6 2, _triangle_6 11, _triangle_6 18, _triangle_6 22,
-_tetrahedron_10 7 connected to _triangle_6 23, _triangle_6 24, _triangle_6 25, _triangle_6 26,
-_tetrahedron_10 8 connected to _triangle_6 15, _triangle_6 16, _triangle_6 24, _triangle_6 27,
-_tetrahedron_10 9 connected to _triangle_6 23, _triangle_6 28, _triangle_6 29, _triangle_6 30,
-_tetrahedron_10 10 connected to _triangle_6 31, _triangle_6 32, _triangle_6 33, _triangle_6 34,
-_tetrahedron_10 11 connected to _triangle_6 0, _triangle_6 4, _triangle_6 32, _triangle_6 35,
-_tetrahedron_10 12 connected to _triangle_6 1, _triangle_6 9, _triangle_6 36, _triangle_6 37,
-_tetrahedron_10 13 connected to _triangle_6 7, _triangle_6 26, _triangle_6 38, _triangle_6 39,
-_tetrahedron_10 14 connected to _triangle_6 30, _triangle_6 39, _triangle_6 40, _triangle_6 41,
-_tetrahedron_10 15 connected to _triangle_6 5, _triangle_6 31, _triangle_6 42, _triangle_6 43,
-SubelementToElement2
-_triangle_6 0 connected to _segment_3 0, _segment_3 1, _segment_3 2,
-_triangle_6 1 connected to _segment_3 1, _segment_3 3, _segment_3 4,
-_triangle_6 2 connected to _segment_3 0, _segment_3 3, _segment_3 5,
-_triangle_6 3 connected to _segment_3 2, _segment_3 4, _segment_3 5,
-_triangle_6 4 connected to _segment_3 0, _segment_3 6, _segment_3 7,
-_triangle_6 5 connected to _segment_3 7, _segment_3 8, _segment_3 9,
-_triangle_6 6 connected to _segment_3 6, _segment_3 8, _segment_3 10,
-_triangle_6 7 connected to _segment_3 0, _segment_3 9, _segment_3 10,
-_triangle_6 8 connected to _segment_3 11, _segment_3 12, _segment_3 13,
-_triangle_6 9 connected to _segment_3 3, _segment_3 12, _segment_3 14,
-_triangle_6 10 connected to _segment_3 11, _segment_3 14, _segment_3 15,
-_triangle_6 11 connected to _segment_3 3, _segment_3 13, _segment_3 15,
-_triangle_6 12 connected to _segment_3 16, _segment_3 17, _segment_3 18,
-_triangle_6 13 connected to _segment_3 17, _segment_3 19, _segment_3 20,
-_triangle_6 14 connected to _segment_3 16, _segment_3 19, _segment_3 21,
-_triangle_6 15 connected to _segment_3 18, _segment_3 20, _segment_3 21,
-_triangle_6 16 connected to _segment_3 0, _segment_3 18, _segment_3 22,
-_triangle_6 17 connected to _segment_3 22, _segment_3 23, _segment_3 24,
-_triangle_6 18 connected to _segment_3 0, _segment_3 13, _segment_3 23,
-_triangle_6 19 connected to _segment_3 13, _segment_3 18, _segment_3 24,
-_triangle_6 20 connected to _segment_3 13, _segment_3 16, _segment_3 25,
-_triangle_6 21 connected to _segment_3 17, _segment_3 24, _segment_3 25,
-_triangle_6 22 connected to _segment_3 5, _segment_3 15, _segment_3 23,
-_triangle_6 23 connected to _segment_3 21, _segment_3 26, _segment_3 27,
-_triangle_6 24 connected to _segment_3 0, _segment_3 21, _segment_3 28,
-_triangle_6 25 connected to _segment_3 26, _segment_3 28, _segment_3 29,
-_triangle_6 26 connected to _segment_3 0, _segment_3 27, _segment_3 29,
-_triangle_6 27 connected to _segment_3 20, _segment_3 22, _segment_3 28,
-_triangle_6 28 connected to _segment_3 26, _segment_3 30, _segment_3 31,
-_triangle_6 29 connected to _segment_3 21, _segment_3 30, _segment_3 32,
-_triangle_6 30 connected to _segment_3 27, _segment_3 31, _segment_3 32,
-_triangle_6 31 connected to _segment_3 7, _segment_3 33, _segment_3 34,
-_triangle_6 32 connected to _segment_3 1, _segment_3 7, _segment_3 35,
-_triangle_6 33 connected to _segment_3 33, _segment_3 35, _segment_3 36,
-_triangle_6 34 connected to _segment_3 1, _segment_3 34, _segment_3 36,
-_triangle_6 35 connected to _segment_3 2, _segment_3 6, _segment_3 35,
-_triangle_6 36 connected to _segment_3 4, _segment_3 14, _segment_3 37,
-_triangle_6 37 connected to _segment_3 1, _segment_3 12, _segment_3 37,
-_triangle_6 38 connected to _segment_3 10, _segment_3 29, _segment_3 38,
-_triangle_6 39 connected to _segment_3 9, _segment_3 27, _segment_3 38,
-_triangle_6 40 connected to _segment_3 9, _segment_3 32, _segment_3 39,
-_triangle_6 41 connected to _segment_3 31, _segment_3 38, _segment_3 39,
-_triangle_6 42 connected to _segment_3 8, _segment_3 33, _segment_3 40,
-_triangle_6 43 connected to _segment_3 9, _segment_3 34, _segment_3 40,
-SubelementToElement1
-_segment_3 0 connected to _point_1 0, _point_1 1,
-_segment_3 1 connected to _point_1 1, _point_1 2,
-_segment_3 2 connected to _point_1 0, _point_1 2,
-_segment_3 3 connected to _point_1 1, _point_1 3,
-_segment_3 4 connected to _point_1 2, _point_1 3,
-_segment_3 5 connected to _point_1 0, _point_1 3,
-_segment_3 6 connected to _point_1 0, _point_1 4,
-_segment_3 7 connected to _point_1 1, _point_1 4,
-_segment_3 8 connected to _point_1 4, _point_1 5,
-_segment_3 9 connected to _point_1 1, _point_1 5,
-_segment_3 10 connected to _point_1 0, _point_1 5,
-_segment_3 11 connected to _point_1 6, _point_1 7,
-_segment_3 12 connected to _point_1 1, _point_1 7,
-_segment_3 13 connected to _point_1 1, _point_1 6,
-_segment_3 14 connected to _point_1 3, _point_1 7,
-_segment_3 15 connected to _point_1 3, _point_1 6,
-_segment_3 16 connected to _point_1 1, _point_1 8,
-_segment_3 17 connected to _point_1 8, _point_1 9,
-_segment_3 18 connected to _point_1 1, _point_1 9,
-_segment_3 19 connected to _point_1 8, _point_1 10,
-_segment_3 20 connected to _point_1 9, _point_1 10,
-_segment_3 21 connected to _point_1 1, _point_1 10,
-_segment_3 22 connected to _point_1 0, _point_1 9,
-_segment_3 23 connected to _point_1 0, _point_1 6,
-_segment_3 24 connected to _point_1 6, _point_1 9,
-_segment_3 25 connected to _point_1 6, _point_1 8,
-_segment_3 26 connected to _point_1 10, _point_1 11,
-_segment_3 27 connected to _point_1 1, _point_1 11,
-_segment_3 28 connected to _point_1 0, _point_1 10,
-_segment_3 29 connected to _point_1 0, _point_1 11,
-_segment_3 30 connected to _point_1 10, _point_1 12,
-_segment_3 31 connected to _point_1 11, _point_1 12,
-_segment_3 32 connected to _point_1 1, _point_1 12,
-_segment_3 33 connected to _point_1 4, _point_1 13,
-_segment_3 34 connected to _point_1 1, _point_1 13,
-_segment_3 35 connected to _point_1 2, _point_1 4,
-_segment_3 36 connected to _point_1 2, _point_1 13,
-_segment_3 37 connected to _point_1 2, _point_1 7,
-_segment_3 38 connected to _point_1 5, _point_1 11,
-_segment_3 39 connected to _point_1 5, _point_1 12,
-_segment_3 40 connected to _point_1 5, _point_1 13,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.cc
deleted file mode 100644
index b006f2707..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * @file test_buildfacets_triangle_3.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Fri Sep 18 2015
- * @date last modification: Wed Nov 08 2017
- *
- * @brief Test to check the building of the facets. Mesh with triangles
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 2;
- const ElementType type = _triangle_3;
-
- Mesh mesh(spatial_dimension);
- mesh.read("triangle_3.msh");
- const auto & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet = mesh.getFacetType(type);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el2 =
- mesh_facets.getSubelementToElement(type);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < 3; ++j) {
- std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.verified
deleted file mode 100644
index 1d2923916..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.verified
+++ /dev/null
@@ -1,54 +0,0 @@
-ElementToSubelement2
-_segment_2 0 connected to _triangle_3 0, _not_defined 4294967295,
-_segment_2 1 connected to _triangle_3 0, _triangle_3 1,
-_segment_2 2 connected to _triangle_3 0, _not_defined 4294967295,
-_segment_2 3 connected to _triangle_3 1, _triangle_3 4,
-_segment_2 4 connected to _triangle_3 1, _triangle_3 2,
-_segment_2 5 connected to _triangle_3 2, _triangle_3 3,
-_segment_2 6 connected to _triangle_3 2, _not_defined 4294967295,
-_segment_2 7 connected to _triangle_3 3, _triangle_3 6,
-_segment_2 8 connected to _triangle_3 3, _not_defined 4294967295,
-_segment_2 9 connected to _triangle_3 4, _not_defined 4294967295,
-_segment_2 10 connected to _triangle_3 4, _triangle_3 5,
-_segment_2 11 connected to _triangle_3 5, _not_defined 4294967295,
-_segment_2 12 connected to _triangle_3 5, _triangle_3 6,
-_segment_2 13 connected to _triangle_3 6, _triangle_3 7,
-_segment_2 14 connected to _triangle_3 7, _not_defined 4294967295,
-_segment_2 15 connected to _triangle_3 7, _not_defined 4294967295,
-ElementToSubelement1
-_point_1 0 connected to _segment_2 0, _segment_2 2,
-_point_1 1 connected to _segment_2 0, _segment_2 1, _segment_2 3, _segment_2 9,
-_point_1 2 connected to _segment_2 1, _segment_2 2, _segment_2 4, _segment_2 6,
-_point_1 3 connected to _segment_2 3, _segment_2 4, _segment_2 5, _segment_2 7, _segment_2 10, _segment_2 12,
-_point_1 4 connected to _segment_2 5, _segment_2 6, _segment_2 8,
-_point_1 5 connected to _segment_2 7, _segment_2 8, _segment_2 13, _segment_2 15,
-_point_1 6 connected to _segment_2 9, _segment_2 10, _segment_2 11,
-_point_1 7 connected to _segment_2 11, _segment_2 12, _segment_2 13, _segment_2 14,
-_point_1 8 connected to _segment_2 14, _segment_2 15,
-
-SubelementToElement2
-_triangle_3 0 connected to _segment_2 0, _segment_2 1, _segment_2 2,
-_triangle_3 1 connected to _segment_2 1, _segment_2 3, _segment_2 4,
-_triangle_3 2 connected to _segment_2 4, _segment_2 5, _segment_2 6,
-_triangle_3 3 connected to _segment_2 5, _segment_2 7, _segment_2 8,
-_triangle_3 4 connected to _segment_2 3, _segment_2 9, _segment_2 10,
-_triangle_3 5 connected to _segment_2 10, _segment_2 11, _segment_2 12,
-_triangle_3 6 connected to _segment_2 7, _segment_2 12, _segment_2 13,
-_triangle_3 7 connected to _segment_2 13, _segment_2 14, _segment_2 15,
-SubelementToElement1
-_segment_2 0 connected to _point_1 0, _point_1 1,
-_segment_2 1 connected to _point_1 1, _point_1 2,
-_segment_2 2 connected to _point_1 0, _point_1 2,
-_segment_2 3 connected to _point_1 1, _point_1 3,
-_segment_2 4 connected to _point_1 2, _point_1 3,
-_segment_2 5 connected to _point_1 3, _point_1 4,
-_segment_2 6 connected to _point_1 2, _point_1 4,
-_segment_2 7 connected to _point_1 3, _point_1 5,
-_segment_2 8 connected to _point_1 4, _point_1 5,
-_segment_2 9 connected to _point_1 1, _point_1 6,
-_segment_2 10 connected to _point_1 3, _point_1 6,
-_segment_2 11 connected to _point_1 6, _point_1 7,
-_segment_2 12 connected to _point_1 3, _point_1 7,
-_segment_2 13 connected to _point_1 5, _point_1 7,
-_segment_2 14 connected to _point_1 7, _point_1 8,
-_segment_2 15 connected to _point_1 5, _point_1 8,
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.cc
deleted file mode 100644
index 67e66ec60..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * @file test_buildfacets_triangle_6.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Fri Sep 18 2015
- * @date last modification: Thu Nov 09 2017
- *
- * @brief Test to check the building of the facets. Mesh with triangles
- *
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
-#include <iostream>
-#include <limits>
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "mesh_utils.hh"
-/* -------------------------------------------------------------------------- */
-
-using namespace akantu;
-
-int main(int argc, char * argv[]) {
- initialize(argc, argv);
-
- const UInt spatial_dimension = 2;
- const ElementType type = _triangle_6;
-
- Mesh mesh(spatial_dimension);
- mesh.read("triangle_6.msh");
- Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
-
- const ElementType type_facet = mesh.getFacetType(type);
- const ElementType type_subfacet = mesh.getFacetType(type_facet);
-
- /* ------------------------------------------------------------------------ */
- /* Element to Subelement testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<std::vector<Element>> & el_to_subel2 =
- mesh_facets.getElementToSubelement(type_facet);
- const Array<std::vector<Element>> & el_to_subel1 =
- mesh_facets.getElementToSubelement(type_subfacet);
-
- std::cout << "ElementToSubelement2" << std::endl;
- for (UInt i = 0; i < el_to_subel2.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "ElementToSubelement1" << std::endl;
- for (UInt i = 0; i < el_to_subel1.size(); ++i) {
- std::cout << type_subfacet << " " << i << " connected to ";
- for (UInt j = 0; j < el_to_subel1(i).size(); ++j) {
- std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- /* ------------------------------------------------------------------------ */
- /* Subelement to Element testing */
- /* ------------------------------------------------------------------------ */
-
- const Array<Element> & subel_to_el2 =
- mesh_facets.getSubelementToElement(type);
- const Array<Element> & subel_to_el1 =
- mesh_facets.getSubelementToElement(type_facet);
-
- std::cout << " " << std::endl;
- std::cout << "SubelementToElement2" << std::endl;
- for (UInt i = 0; i < subel_to_el2.size(); ++i) {
- std::cout << type << " " << i << " connected to ";
- for (UInt j = 0; j < 3; ++j) {
- std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- std::cout << "SubelementToElement1" << std::endl;
- for (UInt i = 0; i < subel_to_el1.size(); ++i) {
- std::cout << type_facet << " " << i << " connected to ";
- for (UInt j = 0; j < 2; ++j) {
- std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element
- << ", ";
- }
- std::cout << " " << std::endl;
- }
-
- finalize();
-
- return EXIT_SUCCESS;
-}
diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.verified b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.verified
deleted file mode 100644
index 3afe9e109..000000000
--- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.verified
+++ /dev/null
@@ -1,54 +0,0 @@
-ElementToSubelement2
-_segment_3 0 connected to _triangle_6 0, _not_defined 4294967295,
-_segment_3 1 connected to _triangle_6 0, _triangle_6 1,
-_segment_3 2 connected to _triangle_6 0, _not_defined 4294967295,
-_segment_3 3 connected to _triangle_6 1, _triangle_6 4,
-_segment_3 4 connected to _triangle_6 1, _triangle_6 2,
-_segment_3 5 connected to _triangle_6 2, _triangle_6 3,
-_segment_3 6 connected to _triangle_6 2, _not_defined 4294967295,
-_segment_3 7 connected to _triangle_6 3, _triangle_6 6,
-_segment_3 8 connected to _triangle_6 3, _not_defined 4294967295,
-_segment_3 9 connected to _triangle_6 4, _not_defined 4294967295,
-_segment_3 10 connected to _triangle_6 4, _triangle_6 5,
-_segment_3 11 connected to _triangle_6 5, _not_defined 4294967295,
-_segment_3 12 connected to _triangle_6 5, _triangle_6 6,
-_segment_3 13 connected to _triangle_6 6, _triangle_6 7,
-_segment_3 14 connected to _triangle_6 7, _not_defined 4294967295,
-_segment_3 15 connected to _triangle_6 7, _not_defined 4294967295,
-ElementToSubelement1
-_point_1 0 connected to _segment_3 0, _segment_3 2,
-_point_1 1 connected to _segment_3 0, _segment_3 1, _segment_3 3, _segment_3 9,
-_point_1 2 connected to _segment_3 1, _segment_3 2, _segment_3 4, _segment_3 6,
-_point_1 3 connected to _segment_3 3, _segment_3 4, _segment_3 5, _segment_3 7, _segment_3 10, _segment_3 12,
-_point_1 4 connected to _segment_3 5, _segment_3 6, _segment_3 8,
-_point_1 5 connected to _segment_3 7, _segment_3 8, _segment_3 13, _segment_3 15,
-_point_1 6 connected to _segment_3 9, _segment_3 10, _segment_3 11,
-_point_1 7 connected to _segment_3 11, _segment_3 12, _segment_3 13, _segment_3 14,
-_point_1 8 connected to _segment_3 14, _segment_3 15,
-
-SubelementToElement2
-_triangle_6 0 connected to _segment_3 0, _segment_3 1, _segment_3 2,
-_triangle_6 1 connected to _segment_3 1, _segment_3 3, _segment_3 4,
-_triangle_6 2 connected to _segment_3 4, _segment_3 5, _segment_3 6,
-_triangle_6 3 connected to _segment_3 5, _segment_3 7, _segment_3 8,
-_triangle_6 4 connected to _segment_3 3, _segment_3 9, _segment_3 10,
-_triangle_6 5 connected to _segment_3 10, _segment_3 11, _segment_3 12,
-_triangle_6 6 connected to _segment_3 7, _segment_3 12, _segment_3 13,
-_triangle_6 7 connected to _segment_3 13, _segment_3 14, _segment_3 15,
-SubelementToElement1
-_segment_3 0 connected to _point_1 0, _point_1 1,
-_segment_3 1 connected to _point_1 1, _point_1 2,
-_segment_3 2 connected to _point_1 0, _point_1 2,
-_segment_3 3 connected to _point_1 1, _point_1 3,
-_segment_3 4 connected to _point_1 2, _point_1 3,
-_segment_3 5 connected to _point_1 3, _point_1 4,
-_segment_3 6 connected to _point_1 2, _point_1 4,
-_segment_3 7 connected to _point_1 3, _point_1 5,
-_segment_3 8 connected to _point_1 4, _point_1 5,
-_segment_3 9 connected to _point_1 1, _point_1 6,
-_segment_3 10 connected to _point_1 3, _point_1 6,
-_segment_3 11 connected to _point_1 6, _point_1 7,
-_segment_3 12 connected to _point_1 3, _point_1 7,
-_segment_3 13 connected to _point_1 5, _point_1 7,
-_segment_3 14 connected to _point_1 7, _point_1 8,
-_segment_3 15 connected to _point_1 5, _point_1 8,
diff --git a/test/test_mesh_utils/test_mesh_io/test_mesh_io_msh_physical_names.cc b/test/test_mesh_utils/test_mesh_io/test_mesh_io_msh_physical_names.cc
index ebea0cb68..1ae530732 100644
--- a/test/test_mesh_utils/test_mesh_io/test_mesh_io_msh_physical_names.cc
+++ b/test/test_mesh_utils/test_mesh_io/test_mesh_io_msh_physical_names.cc
@@ -1,61 +1,61 @@
/**
* @file test_mesh_io_msh_physical_names.cc
*
* @author Dana Christen <dana.christen@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Nov 02 2018
*
* @brief unit test for the MeshIOMSH physical names class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "aka_common.hh"
#include "mesh.hh"
#include <iostream>
#include <sstream>
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
UInt spatialDimension(3);
akantu::initialize(argc, argv);
Mesh mesh(spatialDimension);
mesh.read("./cube_physical_names.msh");
std::stringstream sstr;
for (auto type : mesh.elementTypes()) {
const Array<std::string> & name_vec =
mesh.getData<std::string>("physical_names", type);
- for (UInt i(0); i < name_vec.size(); i++) {
+ for (Int i(0); i < name_vec.size(); i++) {
std::cout << "Element " << i << " (of type " << type
<< ") has physical name " << name_vec(i) << "." << std::endl;
}
}
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc
index c9a2e57b2..a0f28c5d4 100644
--- a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc
+++ b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc
@@ -1,115 +1,114 @@
/**
* @file test_mesh_partitionate_mesh_data.cc
*
* @author Dana Christen <dana.christen@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Nov 02 2018
*
* @brief test of manual partitioner
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "mesh.hh"
#include "mesh_partition_mesh_data.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_elemental_field.hh"
#include "dumper_paraview.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
- UInt dim = 2;
+ Int dim = 2;
UInt nb_partitions = 8;
akantu::Mesh mesh(dim);
mesh.read("quad.msh");
- ElementTypeMapArray<UInt> partition;
+ ElementTypeMapArray<Int> partition;
UInt nb_component = 1;
GhostType gt = _not_ghost;
- for (auto & type : mesh.elementTypes(dim, gt)) {
- UInt nb_element = mesh.getNbElement(type, gt);
+ for (const auto & type : mesh.elementTypes(dim, gt)) {
+ Int nb_element = mesh.getNbElement(type, gt);
partition.alloc(nb_element, nb_component, type, gt);
- Array<UInt> & type_partition_reference = partition(type, gt);
- for (UInt i(0); i < nb_element; ++i) {
+ auto & type_partition_reference = partition(type, gt);
+ for (Int i(0); i < nb_element; ++i) {
Vector<Real> barycenter(dim);
Element element{type, i, gt};
mesh.getBarycenter(element, barycenter);
Real real_proc = barycenter[0] * nb_partitions;
if (std::abs(real_proc - round(real_proc)) <
10 * std::numeric_limits<Real>::epsilon()) {
type_partition_reference(i) = round(real_proc);
} else {
std::cout << "*";
type_partition_reference(i) = floor(real_proc);
}
std::cout << "Assigned proc " << type_partition_reference(i)
<< " to elem " << i << " (type " << type
<< ", barycenter x-coordinate " << barycenter[0] << ")"
<< std::endl;
}
}
- akantu::MeshPartitionMeshData * partitioner =
- new akantu::MeshPartitionMeshData(mesh, dim);
+ auto * partitioner = new akantu::MeshPartitionMeshData(mesh, dim);
partitioner->setPartitionMapping(partition);
partitioner->partitionate(nb_partitions);
- for (auto & type : mesh.elementTypes(dim, gt)) {
- UInt nb_element = mesh.getNbElement(type, gt);
- const Array<UInt> & type_partition_reference = partition(type, gt);
- const Array<UInt> & type_partition = partitioner->getPartitions()(type, gt);
- for (UInt i(0); i < nb_element; ++i) {
+ for (const auto & type : mesh.elementTypes(dim, gt)) {
+ auto nb_element = mesh.getNbElement(type, gt);
+ const auto & type_partition_reference = partition(type, gt);
+ const auto & type_partition = partitioner->getPartitions()(type, gt);
+ for (Int i(0); i < nb_element; ++i) {
if (not(type_partition(i) == type_partition_reference(i))) {
std::cout << "Incorrect partitioning" << std::endl;
return 1;
}
}
}
#ifdef DEBUG_TEST
DumperParaview dumper("test-mesh-data-partition");
dumpers::Field * field1 =
new dumpers::ElementalField<UInt>(partitioner->getPartitions(), dim);
- dumpers::Field * field2 = new dumpers::ElementalField<UInt>(partition, dim);
+ dumpers::Field * field2 = new dumpers::ElementalField<Int>(partition, dim);
dumper.registerMesh(mesh, dim);
dumper.registerField("partitions", field1);
dumper.registerField("partitions_ref", field2);
dumper.dump();
#endif
delete partitioner;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_scotch.cc b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_scotch.cc
index 82a95e473..c12c188d4 100644
--- a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_scotch.cc
+++ b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_scotch.cc
@@ -1,71 +1,71 @@
/**
* @file test_mesh_partitionate_scotch.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Sep 12 2010
* @date last modification: Fri Nov 02 2018
*
* @brief test of internal facet extraction
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "mesh.hh"
#include "mesh_partition_scotch.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_elemental_field.hh"
#include "dumper_iohelper_paraview.hh"
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
debug::setDebugLevel(akantu::dblDump);
int dim = 2;
Mesh mesh(dim);
mesh.read("triangle.msh");
MeshPartitionScotch partition(mesh, dim);
partition.partitionate(8);
DumperParaview dumper("test-scotch-partition");
- auto field = std::make_shared<dumpers::ElementalField<UInt>>(
+ auto field = std::make_shared<dumpers::ElementalField<Idx>>(
partition.getPartitions(), dim);
dumper.registerMesh(mesh, dim);
dumper.registerField("partitions", field);
dumper.dump();
partition.reorder();
mesh.write("triangle_reorder.msh");
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc b/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc
index 7eeb127d9..173eeefde 100644
--- a/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc
+++ b/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc
@@ -1,98 +1,98 @@
/**
* @file test_segment_nodetype.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Sep 18 2015
* @date last modification: Tue Feb 20 2018
*
* @brief Test to verify that the node type is correctly associated to
* the segments in parallel
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_synchronizer.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize(argc, argv);
- UInt spatial_dimension = 3;
+ Int spatial_dimension = 3;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
// partition the mesh
if (prank == 0) {
mesh.read("mesh.msh");
}
mesh.distribute();
// compute the node types for each segment
Mesh & mesh_facets = mesh.initMeshFacets();
MeshUtils::buildSegmentToNodeType(mesh, mesh_facets);
// verify that the number of segments per node type makes sense
std::map<Int, UInt> nb_facets_per_nodetype;
UInt nb_segments = 0;
for (auto ghost_type : ghost_types) {
const Array<Int> & segment_to_nodetype =
mesh_facets.getData<Int>("segment_to_nodetype", _segment_2, ghost_type);
// count the number of segments per node type
for (auto & stn : segment_to_nodetype) {
if (nb_facets_per_nodetype.find(stn) == nb_facets_per_nodetype.end())
nb_facets_per_nodetype[stn] = 1;
else
++nb_facets_per_nodetype[stn];
}
nb_segments += segment_to_nodetype.size();
}
// checking the solution
if (nb_segments != 24)
AKANTU_ERROR("The number of segments is wrong");
if (prank == 0) {
if (nb_facets_per_nodetype[-1] != 3 || nb_facets_per_nodetype[-2] != 9 ||
nb_facets_per_nodetype[-3] != 12)
AKANTU_ERROR("The segments of processor 0 have the wrong node type");
if (nb_facets_per_nodetype.size() > 3)
AKANTU_ERROR("Processor 0 cannot have any slave segment");
}
if (prank == psize - 1 &&
nb_facets_per_nodetype.find(-2) != nb_facets_per_nodetype.end())
AKANTU_ERROR("The last processor must not have any master facets");
finalize();
return 0;
}
diff --git a/test/test_model/patch_tests/data/CMakeLists.txt b/test/test_model/patch_tests/data/CMakeLists.txt
index 94dbf9a29..367aa76eb 100644
--- a/test/test_model/patch_tests/data/CMakeLists.txt
+++ b/test/test_model/patch_tests/data/CMakeLists.txt
@@ -1,75 +1,89 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Tue Jan 30 2018
# @date last modification: Tue Jan 30 2018
#
# @brief CMakeLists patch test data
#
#
# @section LICENSE
#
# Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
add_mesh(bar_segment_2 bar_segment.geo
DIM 1 ORDER 1 OUTPUT bar_segment_2.msh)
add_mesh(bar_segment_3 bar_segment.geo
DIM 1 ORDER 2 OUTPUT bar_segment_3.msh)
add_mesh(bar_triangle_3 bar_triangle.geo
DIM 2 ORDER 1 OUTPUT bar_triangle_3.msh)
add_mesh(bar_triangle_6 bar_triangle.geo
DIM 2 ORDER 2 OUTPUT bar_triangle_6.msh)
add_mesh(bar_quadrangle_4 bar_quadrangle.geo
DIM 2 ORDER 1 OUTPUT bar_quadrangle_4.msh)
add_mesh(bar_quadrangle_8 bar_quadrangle.geo
DIM 2 ORDER 2 OUTPUT bar_quadrangle_8.msh)
add_mesh(bar_tetrahedron_4 bar_tetrahedron.geo
DIM 3 ORDER 1 OUTPUT bar_tetrahedron_4.msh)
add_mesh(bar_tetrahedron_10 bar_tetrahedron.geo
DIM 3 ORDER 2 OUTPUT bar_tetrahedron_10.msh)
add_mesh(bar_hexahedron_8 bar_hexahedron.geo
DIM 3 ORDER 1 OUTPUT bar_hexahedron_8.msh)
add_mesh(bar_hexahedron_20 bar_hexahedron.geo
DIM 3 ORDER 2 OUTPUT bar_hexahedron_20.msh)
add_mesh(bar_pentahedron_6 bar_pentahedron.geo
DIM 3 ORDER 1 OUTPUT bar_pentahedron_6.msh)
add_mesh(bar_pentahedron_15 bar_pentahedron.geo
DIM 3 ORDER 2 OUTPUT bar_pentahedron_15.msh)
#===============================================================================
# Meshes
#===============================================================================
set(_patch_tests_meshes)
set(_patch_tests_bar_meshes)
package_get_variable(ET_ELEMENT_TYPES core _element_list)
+
+set(_element_list
+ _hexahedron_8
+ _hexahedron_20
+ _pentahedron_6
+ _pentahedron_15
+ _quadrangle_4
+ _quadrangle_8
+ _segment_2
+ _segment_3
+ _tetrahedron_4
+ _tetrahedron_10
+ _triangle_3
+ _triangle_6
+ )
+
foreach(_et ${_element_list})
- if(NOT _et STREQUAL _point_1)
- list(APPEND _patch_tests_meshes ${CMAKE_CURRENT_SOURCE_DIR}/${_et}.msh)
- list(APPEND _patch_tests_bar_meshes bar${_et})
- endif()
+ list(APPEND _patch_tests_meshes ${CMAKE_CURRENT_SOURCE_DIR}/${_et}.msh)
+ list(APPEND _patch_tests_bar_meshes bar${_et})
endforeach()
set(PATCH_TEST_MESHES ${_patch_tests_meshes}
CACHE INTERNAL "List of mesh files")
set(PATCH_TEST_BAR_MESHES ${_patch_tests_bar_meshes}
CACHE INTERNAL "List of bar mesh files")
diff --git a/test/test_model/patch_tests/patch_test_linear_anisotropic_explicit.cc b/test/test_model/patch_tests/patch_test_linear_anisotropic_explicit.cc
index 0c9760c92..636603f0a 100644
--- a/test/test_model/patch_tests/patch_test_linear_anisotropic_explicit.cc
+++ b/test/test_model/patch_tests/patch_test_linear_anisotropic_explicit.cc
@@ -1,138 +1,138 @@
/**
* @file patch_test_linear_anisotropic_explicit.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Till Junge <till.junge@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Tue May 14 2019
* @date last modification: Thu Oct 29 2020
*
* @brief patch test for elastic material in solid mechanics model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver.hh"
#include "patch_test_linear_solid_mechanics_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
// Stiffness tensor, rotated by hand
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestSMMLinear, AnisotropicExplicit) {
Real C[3][3][3][3] = {
{{{112.93753505, 1.85842452538e-10, -4.47654358027e-10},
{1.85847317471e-10, 54.2334345331, -3.69840984824},
{-4.4764768395e-10, -3.69840984824, 56.848605217}},
{{1.85847781609e-10, 25.429294233, -3.69840984816},
{25.429294233, 3.31613847493e-10, -8.38797920011e-11},
{-3.69840984816, -8.38804581349e-11, -1.97875715813e-10}},
{{-4.47654358027e-10, -3.69840984816, 28.044464917},
{-3.69840984816, 2.09374961813e-10, 9.4857455224e-12},
{28.044464917, 9.48308098714e-12, -2.1367885239e-10}}},
{{{1.85847781609e-10, 25.429294233, -3.69840984816},
{25.429294233, 3.31613847493e-10, -8.38793479119e-11},
{-3.69840984816, -8.38795699565e-11, -1.97876381947e-10}},
{{54.2334345331, 3.31617400207e-10, 2.09372075233e-10},
{3.3161562385e-10, 115.552705733, -3.15093728886e-10},
{2.09372075233e-10, -3.15090176173e-10, 54.2334345333}},
{{-3.69840984824, -8.38795699565e-11, 9.48219280872e-12},
{-8.38795699565e-11, -3.1509195253e-10, 25.4292942335},
{9.48441325477e-12, 25.4292942335, 3.69840984851}}},
{{{-4.47653469848e-10, -3.69840984816, 28.044464917},
{-3.69840984816, 2.09374073634e-10, 9.48752187924e-12},
{28.044464917, 9.48552347779e-12, -2.1367885239e-10}},
{{-3.69840984824, -8.3884899027e-11, 9.48219280872e-12},
{-8.3884899027e-11, -3.150972816e-10, 25.4292942335},
{9.48041645188e-12, 25.4292942335, 3.69840984851}},
{{56.848605217, -1.97875493768e-10, -2.13681516925e-10},
{-1.97877270125e-10, 54.2334345333, 3.69840984851},
{-2.13683293282e-10, 3.69840984851, 112.93753505}}}};
if (this->dim == 2) {
- for (UInt i = 0; i < this->dim; ++i) {
- for (UInt j = 0; j < this->dim; ++j) {
- for (UInt k = 0; k < this->dim; ++k) {
- for (UInt l = 0; l < this->dim; ++l) {
+ for (Int i = 0; i < this->dim; ++i) {
+ for (Int j = 0; j < this->dim; ++j) {
+ for (Int k = 0; k < this->dim; ++k) {
+ for (Int l = 0; l < this->dim; ++l) {
C[i][j][k][l] = 0;
}
}
}
}
C[0][0][0][0] = C[1][1][1][1] = 112.93753504999995;
C[0][0][1][1] = C[1][1][0][0] = 51.618263849999984;
C[0][1][0][1] = C[1][0][0][1] = C[0][1][1][0] = C[1][0][1][0] =
22.814123549999987;
}
if (this->dim == 1) {
C[0][0][0][0] = 105.092023;
}
this->initModel(_explicit_lumped_mass,
"material_anisotropic_" + std::to_string(this->dim) + ".dat");
const auto & coordinates = this->mesh->getNodes();
auto & displacement = this->model->getDisplacement();
// set the position of all nodes to the static solution
for (auto && tuple : zip(make_view(coordinates, this->dim),
make_view(displacement, this->dim))) {
this->setLinearDOF(std::get<1>(tuple), std::get<0>(tuple));
}
- for (UInt s = 0; s < 100; ++s) {
+ for (Int s = 0; s < 100; ++s) {
this->model->solveStep();
}
auto ekin = this->model->getEnergy("kinetic");
EXPECT_NEAR(0, ekin, 1e-16);
auto & mat = this->model->getMaterial(0);
this->checkDOFs(displacement);
this->checkGradient(mat.getGradU(this->type), displacement);
this->result_tolerance = 1e-11;
this->checkResults(
[&](const Matrix<Real> & pstrain) {
auto strain = (pstrain + pstrain.transpose()) / 2.;
- decltype(strain) stress(this->dim, this->dim);
+ Matrix<Real> stress(this->dim, this->dim);
- for (UInt i = 0; i < this->dim; ++i) {
- for (UInt j = 0; j < this->dim; ++j) {
+ for (Int i = 0; i < this->dim; ++i) {
+ for (Int j = 0; j < this->dim; ++j) {
stress(i, j) = 0;
- for (UInt k = 0; k < this->dim; ++k) {
- for (UInt l = 0; l < this->dim; ++l) {
+ for (Int k = 0; k < this->dim; ++k) {
+ for (Int l = 0; l < this->dim; ++l) {
stress(i, j) += C[i][j][k][l] * strain(k, l);
}
}
}
}
return stress;
},
mat.getStress(this->type), displacement);
}
diff --git a/test/test_model/patch_tests/patch_test_linear_anisotropic_implicit.cc b/test/test_model/patch_tests/patch_test_linear_anisotropic_implicit.cc
index e4134fe6c..275f83346 100644
--- a/test/test_model/patch_tests/patch_test_linear_anisotropic_implicit.cc
+++ b/test/test_model/patch_tests/patch_test_linear_anisotropic_implicit.cc
@@ -1,131 +1,131 @@
/**
* @file patch_test_linear_anisotropic_implicit.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Till Junge <till.junge@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Cyprien Wolff <cyprien.wolff@epfl.ch>
*
* @date creation: Tue May 14 2019
* @date last modification: Thu Oct 29 2020
*
* @brief patch test for elastic material in solid mechanics model
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver.hh"
#include "patch_test_linear_solid_mechanics_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
// Stiffness tensor, rotated by hand
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestSMMLinear, AnisotropicStatic) {
Real C[3][3][3][3] = {
{{{112.93753505, 1.85842452538e-10, -4.47654358027e-10},
{1.85847317471e-10, 54.2334345331, -3.69840984824},
{-4.4764768395e-10, -3.69840984824, 56.848605217}},
{{1.85847781609e-10, 25.429294233, -3.69840984816},
{25.429294233, 3.31613847493e-10, -8.38797920011e-11},
{-3.69840984816, -8.38804581349e-11, -1.97875715813e-10}},
{{-4.47654358027e-10, -3.69840984816, 28.044464917},
{-3.69840984816, 2.09374961813e-10, 9.4857455224e-12},
{28.044464917, 9.48308098714e-12, -2.1367885239e-10}}},
{{{1.85847781609e-10, 25.429294233, -3.69840984816},
{25.429294233, 3.31613847493e-10, -8.38793479119e-11},
{-3.69840984816, -8.38795699565e-11, -1.97876381947e-10}},
{{54.2334345331, 3.31617400207e-10, 2.09372075233e-10},
{3.3161562385e-10, 115.552705733, -3.15093728886e-10},
{2.09372075233e-10, -3.15090176173e-10, 54.2334345333}},
{{-3.69840984824, -8.38795699565e-11, 9.48219280872e-12},
{-8.38795699565e-11, -3.1509195253e-10, 25.4292942335},
{9.48441325477e-12, 25.4292942335, 3.69840984851}}},
{{{-4.47653469848e-10, -3.69840984816, 28.044464917},
{-3.69840984816, 2.09374073634e-10, 9.48752187924e-12},
{28.044464917, 9.48552347779e-12, -2.1367885239e-10}},
{{-3.69840984824, -8.3884899027e-11, 9.48219280872e-12},
{-8.3884899027e-11, -3.150972816e-10, 25.4292942335},
{9.48041645188e-12, 25.4292942335, 3.69840984851}},
{{56.848605217, -1.97875493768e-10, -2.13681516925e-10},
{-1.97877270125e-10, 54.2334345333, 3.69840984851},
{-2.13683293282e-10, 3.69840984851, 112.93753505}}}};
if (this->dim == 2) {
- for (UInt i = 0; i < this->dim; ++i) {
- for (UInt j = 0; j < this->dim; ++j) {
- for (UInt k = 0; k < this->dim; ++k) {
- for (UInt l = 0; l < this->dim; ++l) {
+ for (Int i = 0; i < this->dim; ++i) {
+ for (Int j = 0; j < this->dim; ++j) {
+ for (Int k = 0; k < this->dim; ++k) {
+ for (Int l = 0; l < this->dim; ++l) {
C[i][j][k][l] = 0;
}
}
}
}
C[0][0][0][0] = C[1][1][1][1] = 112.93753504999995;
C[0][0][1][1] = C[1][1][0][0] = 51.618263849999984;
C[0][1][0][1] = C[1][0][0][1] = C[0][1][1][0] = C[1][0][1][0] =
22.814123549999987;
}
if (this->dim == 1) {
C[0][0][0][0] = 105.092023;
}
this->initModel(_static,
"material_anisotropic_" + std::to_string(this->dim) + ".dat");
auto & solver = this->model->getNonLinearSolver();
solver.set("max_iterations", 2);
solver.set("threshold", 2e-4);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
this->model->solveStep();
auto & mat = this->model->getMaterial(0);
const auto & displacement = this->model->getDisplacement();
this->checkDOFs(displacement);
this->checkGradient(mat.getGradU(this->type), displacement);
this->result_tolerance = 1e-11;
this->checkResults(
[&](const Matrix<Real> & pstrain) {
auto strain = (pstrain + pstrain.transpose()) / 2.;
- decltype(strain) stress(this->dim, this->dim);
+ Matrix<Real> stress(this->dim, this->dim);
- for (UInt i = 0; i < this->dim; ++i) {
- for (UInt j = 0; j < this->dim; ++j) {
+ for (Int i = 0; i < this->dim; ++i) {
+ for (Int j = 0; j < this->dim; ++j) {
stress(i, j) = 0;
- for (UInt k = 0; k < this->dim; ++k) {
- for (UInt l = 0; l < this->dim; ++l) {
+ for (Int k = 0; k < this->dim; ++k) {
+ for (Int l = 0; l < this->dim; ++l) {
stress(i, j) += C[i][j][k][l] * strain(k, l);
}
}
}
}
return stress;
},
mat.getStress(this->type), displacement);
}
diff --git a/test/test_model/patch_tests/patch_test_linear_elastic_explicit.cc b/test/test_model/patch_tests/patch_test_linear_elastic_explicit.cc
index 9943fdbdf..6e666b8cc 100644
--- a/test/test_model/patch_tests/patch_test_linear_elastic_explicit.cc
+++ b/test/test_model/patch_tests/patch_test_linear_elastic_explicit.cc
@@ -1,100 +1,100 @@
/**
* @file patch_test_linear_elastic_explicit.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 30 2018
* @date last modification: Thu Oct 29 2020
*
* @brief patch test solid mechanics explicit
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "patch_test_linear_solid_mechanics_fixture.hh"
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestSMMLinear, Explicit) {
std::string filename = "material_check_stress_plane_stress.dat";
if (this->plane_strain)
filename = "material_check_stress_plane_strain.dat";
this->initModel(_explicit_lumped_mass, filename);
const auto & coordinates = this->mesh->getNodes();
auto & displacement = this->model->getDisplacement();
// set the position of all nodes to the static solution
for (auto && tuple : zip(make_view(coordinates, this->dim),
make_view(displacement, this->dim))) {
this->setLinearDOF(std::get<1>(tuple), std::get<0>(tuple));
}
- for (UInt s = 0; s < 100; ++s) {
+ for (Int s = 0; s < 100; ++s) {
this->model->solveStep();
}
auto ekin = this->model->getEnergy("kinetic");
EXPECT_NEAR(0, ekin, 1e-16);
this->checkAll();
#define debug 0
#if debug
this->model->setBaseName(std::to_string(this->type) + "_explicit");
this->model->addDumpField("stress");
this->model->addDumpField("grad_u");
this->model->addDumpFieldVector("internal_force");
this->model->addDumpFieldVector("external_force");
this->model->addDumpField("blocked_dofs");
this->model->addDumpFieldVector("displacement");
this->model->dump();
#endif
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestSMMLinear, ExplicitFiniteDeformation) {
std::string filename =
"material_check_stress_plane_stress_finite_deformation.dat";
if (this->plane_strain) {
filename = "material_check_stress_plane_strain_finite_deformation.dat";
} else {
SUCCEED();
return;
}
this->initModel(_explicit_lumped_mass, filename);
const auto & coordinates = this->mesh->getNodes();
auto & displacement = this->model->getDisplacement();
// set the position of all nodes to the static solution
for (auto && tuple : zip(make_view(coordinates, this->dim),
make_view(displacement, this->dim))) {
this->setLinearDOF(std::get<1>(tuple), std::get<0>(tuple));
}
- for (UInt s = 0; s < 100; ++s) {
+ for (Int s = 0; s < 100; ++s) {
this->model->solveStep();
}
auto ekin = this->model->getEnergy("kinetic");
EXPECT_NEAR(0, ekin, 1e-16);
this->checkAll();
}
diff --git a/test/test_model/patch_tests/patch_test_linear_elastic_implicit.cc b/test/test_model/patch_tests/patch_test_linear_elastic_implicit.cc
index 133f44e36..a98ae1ba8 100644
--- a/test/test_model/patch_tests/patch_test_linear_elastic_implicit.cc
+++ b/test/test_model/patch_tests/patch_test_linear_elastic_implicit.cc
@@ -1,168 +1,168 @@
/**
* @file patch_test_linear_elastic_implicit.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 30 2018
* @date last modification: Tue Mar 24 2020
*
* @brief Patch test for SolidMechanics implicit
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "patch_test_linear_solid_mechanics_fixture.hh"
/* -------------------------------------------------------------------------- */
#include "non_linear_solver.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
TYPED_TEST(TestPatchTestSMMLinear, Implicit) {
std::string filename = "material_check_stress_plane_stress.dat";
if (this->plane_strain)
filename = "material_check_stress_plane_strain.dat";
this->initModel(_implicit_dynamic, filename);
const auto & coordinates = this->mesh->getNodes();
auto & displacement = this->model->getDisplacement();
// set the position of all nodes to the static solution
for (auto && tuple : zip(make_view(coordinates, this->dim),
make_view(displacement, this->dim))) {
this->setLinearDOF(std::get<1>(tuple), std::get<0>(tuple));
}
- for (UInt s = 0; s < 100; ++s) {
+ for (Int s = 0; s < 100; ++s) {
this->model->solveStep();
}
auto ekin = this->model->getEnergy("kinetic");
EXPECT_NEAR(0, ekin, 1e-16);
this->checkAll();
#define debug 0
#if debug
this->model->setBaseName(std::to_string(this->type) + "_implicit");
this->model->addDumpField("stress");
this->model->addDumpField("grad_u");
this->model->addDumpFieldVector("internal_force");
this->model->addDumpFieldVector("external_force");
this->model->addDumpField("blocked_dofs");
this->model->addDumpFieldVector("displacement");
this->model->dump();
#endif
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestSMMLinear, Static) {
std::string filename = "material_check_stress_plane_stress.dat";
if (this->plane_strain)
filename = "material_check_stress_plane_strain.dat";
this->initModel(_static, filename);
auto & solver = this->model->getNonLinearSolver();
solver.set("max_iterations", 2);
solver.set("threshold", 2e-4);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
this->model->solveStep();
this->checkAll();
#define debug 0
#if debug
this->model->setBaseName(std::to_string(this->type) + "_static");
this->model->addDumpField("stress");
this->model->addDumpField("grad_u");
this->model->addDumpFieldVector("internal_force");
this->model->addDumpFieldVector("external_force");
this->model->addDumpField("blocked_dofs");
this->model->addDumpFieldVector("displacement");
this->model->dump();
#endif
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestSMMLinear, ImplicitFiniteDeformation) {
std::string filename =
"material_check_stress_plane_stress_finite_deformation.dat";
if (this->plane_strain)
filename = "material_check_stress_plane_strain_finite_deformation.dat";
else {
SUCCEED();
return;
}
this->initModel(_implicit_dynamic, filename);
const auto & coordinates = this->mesh->getNodes();
auto & displacement = this->model->getDisplacement();
// set the position of all nodes to the static solution
for (auto && tuple : zip(make_view(coordinates, this->dim),
make_view(displacement, this->dim))) {
this->setLinearDOF(std::get<1>(tuple), std::get<0>(tuple));
}
- for (UInt s = 0; s < 100; ++s) {
+ for (Int s = 0; s < 100; ++s) {
this->model->solveStep();
}
auto ekin = this->model->getEnergy("kinetic");
EXPECT_NEAR(0, ekin, 1e-16);
this->checkAll();
#define debug 0
#if debug
this->model->setBaseName(std::to_string(this->type) + "_implicit_finit_def");
this->model->addDumpField("stress");
this->model->addDumpField("grad_u");
this->model->addDumpFieldVector("internal_force");
this->model->addDumpFieldVector("external_force");
this->model->addDumpField("blocked_dofs");
this->model->addDumpFieldVector("displacement");
this->model->dump();
#endif
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestSMMLinear, StaticFiniteDeformation) {
std::string filename =
"material_check_stress_plane_stress_finite_deformation.dat";
if (this->plane_strain) {
filename = "material_check_stress_plane_strain_finite_deformation.dat";
} else {
SUCCEED();
return;
}
this->initModel(_static, filename);
auto & solver = this->model->getNonLinearSolver();
solver.set("max_iterations", 2);
solver.set("threshold", 2e-4);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
this->model->solveStep();
this->checkAll();
}
diff --git a/test/test_model/patch_tests/patch_test_linear_fixture.hh b/test/test_model/patch_tests/patch_test_linear_fixture.hh
index 048646c96..60d1f4edb 100644
--- a/test/test_model/patch_tests/patch_test_linear_fixture.hh
+++ b/test/test_model/patch_tests/patch_test_linear_fixture.hh
@@ -1,185 +1,183 @@
/**
* @file patch_test_linear_fixture.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 30 2018
* @date last modification: Sun Jun 02 2019
*
* @brief Fixture for linear patch tests
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "element_group.hh"
#include "mesh_utils.hh"
#include "model.hh"
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PATCH_TEST_LINEAR_FIXTURE_HH_
#define AKANTU_PATCH_TEST_LINEAR_FIXTURE_HH_
//#define DEBUG_TEST
using namespace akantu;
template <typename type_, typename M>
class TestPatchTestLinear : public ::testing::Test {
public:
static constexpr ElementType type = type_::value;
- static constexpr size_t dim = ElementClass<type>::getSpatialDimension();
+ static constexpr Int dim = ElementClass<type>::getSpatialDimension();
virtual void SetUp() {
mesh = std::make_unique<Mesh>(dim);
mesh->read(std::to_string(type) + ".msh");
MeshUtils::buildFacets(*mesh);
mesh->createBoundaryGroupFromGeometry();
model = std::make_unique<M>(*mesh);
}
virtual void TearDown() {
model.reset(nullptr);
mesh.reset(nullptr);
}
- virtual void initModel(const AnalysisMethod & method,
- const std::string & material_file) {
+ virtual void initModel(const AnalysisMethod &method,
+ const std::string &material_file) {
debug::setDebugLevel(dblError);
getStaticParser().parse(material_file);
this->model->initFull(_analysis_method = method);
this->applyBC();
if (method != _static)
this->model->setTimeStep(0.8 * this->model->getStableTimeStep());
}
virtual void applyBC() {
- auto & boundary = this->model->getBlockedDOFs();
+ auto &boundary = this->model->getBlockedDOFs();
- for (auto & eg : mesh->iterateElementGroups()) {
- for (const auto & node : eg.getNodeGroup()) {
- for (UInt s = 0; s < boundary.getNbComponent(); ++s) {
+ for (auto &eg : mesh->iterateElementGroups()) {
+ for (const auto &node : eg.getNodeGroup()) {
+ for (Int s = 0; s < boundary.getNbComponent(); ++s) {
boundary(node, s) = true;
}
}
}
}
- virtual void applyBConDOFs(const Array<Real> & dofs) {
- const auto & coordinates = this->mesh->getNodes();
- for (auto & eg : this->mesh->iterateElementGroups()) {
- for (const auto & node : eg.getNodeGroup()) {
+ virtual void applyBConDOFs(const Array<Real> &dofs) {
+ const auto &coordinates = this->mesh->getNodes();
+ for (auto &eg : this->mesh->iterateElementGroups()) {
+ for (const auto &node : eg.getNodeGroup()) {
this->setLinearDOF(dofs.begin(dofs.getNbComponent())[node],
coordinates.begin(this->dim)[node]);
}
}
}
- template <typename V> Matrix<Real> prescribed_gradient(const V & dof) {
+ template <typename V> Matrix<Real> prescribed_gradient(const V &dof) {
Matrix<Real> gradient(dof.getNbComponent(), dim);
- for (UInt i = 0; i < gradient.rows(); ++i) {
- for (UInt j = 0; j < gradient.cols(); ++j) {
+ for (Int i = 0; i < gradient.rows(); ++i) {
+ for (Int j = 0; j < gradient.cols(); ++j) {
gradient(i, j) = alpha(i, j + 1);
}
}
return gradient;
}
template <typename Gradient, typename DOFs>
- void checkGradient(const Gradient & gradient, const DOFs & dofs) {
+ void checkGradient(const Gradient &gradient, const DOFs &dofs) {
auto pgrad = prescribed_gradient(dofs);
- for (auto & grad :
+ for (auto &grad :
make_view(gradient, gradient.getNbComponent() / dim, dim)) {
auto diff = grad - pgrad;
- auto gradient_error =
- diff.template norm<L_inf>() / grad.template norm<L_inf>();
+ auto gradient_error = diff.template lpNorm<Eigen::Infinity>() /
+ grad.template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0, gradient_error, gradient_tolerance);
}
}
template <typename presult_func_t, typename Result, typename DOFs>
- void checkResults(presult_func_t && presult_func, const Result & results,
- const DOFs & dofs) {
- auto presult = presult_func(prescribed_gradient(dofs));
- for (auto & result :
- make_view(results, results.getNbComponent() / dim, dim)) {
+ void checkResults(presult_func_t &&presult_func, const Result &results,
+ const DOFs &dofs) {
+ Matrix<Real> presult = presult_func(prescribed_gradient(dofs));
+ for (auto &result : make_view(results, presult.rows(), presult.cols())) {
auto diff = result - presult;
- auto result_error =
- diff.template norm<L_inf>() / presult.template norm<L_inf>();
+ auto result_error = diff.template lpNorm<Eigen::Infinity>() /
+ presult.template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0, result_error, result_tolerance);
}
}
- template <typename V1, typename V2>
- void setLinearDOF(V1 && dof, V2 && coord) {
- for (UInt i = 0; i < dof.size(); ++i) {
+ template <typename V1, typename V2> void setLinearDOF(V1 &&dof, V2 &&coord) {
+ for (Int i = 0; i < dof.size(); ++i) {
dof(i) = this->alpha(i, 0);
- for (UInt j = 0; j < coord.size(); ++j) {
+ for (Int j = 0; j < coord.size(); ++j) {
dof(i) += this->alpha(i, j + 1) * coord(j);
}
}
}
- template <typename V> void checkDOFs(V && dofs) {
- const auto & coordinates = mesh->getNodes();
+ template <typename V> void checkDOFs(V &&dofs) {
+ const auto &coordinates = mesh->getNodes();
Vector<Real> ref_dof(dofs.getNbComponent());
- for (auto && tuple : zip(make_view(coordinates, dim),
- make_view(dofs, dofs.getNbComponent()))) {
+ for (auto &&tuple : zip(make_view(coordinates, dim),
+ make_view(dofs, dofs.getNbComponent()))) {
setLinearDOF(ref_dof, std::get<0>(tuple));
auto diff = std::get<1>(tuple) - ref_dof;
- auto dofs_error = diff.template norm<L_inf>();
+ auto dofs_error = diff.template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0, dofs_error, dofs_tolerance);
}
}
protected:
std::unique_ptr<Mesh> mesh;
std::unique_ptr<M> model;
Matrix<Real> alpha{{0.01, 0.02, 0.03, 0.04},
{0.05, 0.06, 0.07, 0.08},
{0.09, 0.10, 0.11, 0.12}};
Real gradient_tolerance{1e-13};
Real result_tolerance{1e-13};
Real dofs_tolerance{1e-15};
};
template <typename type_, typename M>
constexpr ElementType TestPatchTestLinear<type_, M>::type;
template <typename tuple_, typename M>
-constexpr size_t TestPatchTestLinear<tuple_, M>::dim;
+constexpr Int TestPatchTestLinear<tuple_, M>::dim;
#endif /* AKANTU_PATCH_TEST_LINEAR_FIXTURE_HH_ */
diff --git a/test/test_model/patch_tests/patch_test_linear_heat_transfer_explicit.cc b/test/test_model/patch_tests/patch_test_linear_heat_transfer_explicit.cc
index 5b51dd68f..c42c1e220 100644
--- a/test/test_model/patch_tests/patch_test_linear_heat_transfer_explicit.cc
+++ b/test/test_model/patch_tests/patch_test_linear_heat_transfer_explicit.cc
@@ -1,52 +1,52 @@
/**
* @file patch_test_linear_heat_transfer_explicit.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 30 2018
* @date last modification: Wed Jan 31 2018
*
* @brief HeatTransfer patch test
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "patch_test_linear_heat_transfer_fixture.hh"
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestHTMLinear, Explicit) {
this->initModel(_explicit_lumped_mass, "heat_transfer_input.dat");
const auto & coordinates = this->mesh->getNodes();
auto & temperature = this->model->getTemperature();
// set the position of all nodes to the static solution
for (auto && tuple :
zip(make_view(coordinates, this->dim), make_view(temperature, 1))) {
this->setLinearDOF(std::get<1>(tuple), std::get<0>(tuple));
}
- for (UInt s = 0; s < 100; ++s) {
+ for (Int s = 0; s < 100; ++s) {
this->model->solveStep();
}
this->checkAll();
}
diff --git a/test/test_model/patch_tests/patch_test_linear_heat_transfer_fixture.py b/test/test_model/patch_tests/patch_test_linear_heat_transfer_fixture.py
index 8bea9412d..dda2017c7 100644
--- a/test/test_model/patch_tests/patch_test_linear_heat_transfer_fixture.py
+++ b/test/test_model/patch_tests/patch_test_linear_heat_transfer_fixture.py
@@ -1,58 +1,58 @@
#!/usr/bin/env python3
-"""patch_test_linear_heat_transfer_fixture.py: heat transfer patch test in
-python"""
+"""ypatch_test_linear_heat_transfer_fixture.py: heat transfer patch test in
+python."""
__author__ = "Guillaume Anciaux"
__credits__ = [
"Guillaume Anciaux <guillaume.anciaux@epfl.ch>",
]
__copyright__ = "Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import patch_test_linear_fixture
import akantu
class TestPatchTestHTMLinear(patch_test_linear_fixture.TestPatchTestLinear):
model_type = akantu.HeatTransferModel
def applyBC(self):
super().applyBC()
temperature = self.model.getTemperature()
self.applyBConDOFs(temperature)
def checkAll(self):
temperature = self.model.getTemperature()
C = self.model.getMatrix("conductivity")
self.checkDOFs(temperature)
self.checkGradient(self.model.getTemperatureGradient(self.elem_type),
temperature)
self.prescribed_gradient(temperature)
self.checkResults(lambda grad_T: C.dot(grad_T.T),
self.model.getKgradT(self.elem_type),
temperature)
def initModel(self, method, material_file):
super().initModel(method, material_file)
if method != akantu._static:
self.model.setTimeStep(0.5 * self.model.getStableTimeStep())
def run_test_generic(self_, method):
self_.initModel(method, "heat_transfer_input.dat")
coordinates = self_.mesh.getNodes()
temperature = self_.model.getTemperature()
# set the position of all nodes to the static solution
self_.setLinearDOF(temperature, coordinates)
for s in range(0, 100):
self_.model.solveStep()
self_.checkAll()
diff --git a/test/test_model/patch_tests/patch_test_linear_heat_transfer_implicit.cc b/test/test_model/patch_tests/patch_test_linear_heat_transfer_implicit.cc
index 697b91eee..750bcada6 100644
--- a/test/test_model/patch_tests/patch_test_linear_heat_transfer_implicit.cc
+++ b/test/test_model/patch_tests/patch_test_linear_heat_transfer_implicit.cc
@@ -1,54 +1,54 @@
/**
* @file patch_test_linear_heat_transfer_implicit.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 30 2018
* @date last modification: Wed Feb 28 2018
*
* @brief HeatTransfer patch test
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "patch_test_linear_heat_transfer_fixture.hh"
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestPatchTestHTMLinear, Implicit) {
this->initModel(_implicit_dynamic, "heat_transfer_input.dat");
const auto & coordinates = this->mesh->getNodes();
auto & temperature = this->model->getTemperature();
// set the position of all nodes to the static solution
for (auto && tuple :
zip(make_view(coordinates, this->dim), make_view(temperature, 1))) {
this->setLinearDOF(std::get<1>(tuple), std::get<0>(tuple));
}
- for (UInt s = 0; s < 100; ++s) {
+ for (Int s = 0; s < 100; ++s) {
this->model->solveStep();
}
this->checkAll();
}
diff --git a/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh b/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh
index 676768afa..05681cbf8 100644
--- a/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh
+++ b/test/test_model/patch_tests/patch_test_linear_solid_mechanics_fixture.hh
@@ -1,156 +1,160 @@
/**
* @file patch_test_linear_solid_mechanics_fixture.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Jan 30 2018
* @date last modification: Wed Nov 18 2020
*
* @brief SolidMechanics patch tests fixture
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "patch_test_linear_fixture.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PATCH_TEST_LINEAR_SOLID_MECHANICS_FIXTURE_HH_
#define AKANTU_PATCH_TEST_LINEAR_SOLID_MECHANICS_FIXTURE_HH_
/* -------------------------------------------------------------------------- */
template <typename tuple_>
class TestPatchTestSMMLinear
: public TestPatchTestLinear<std::tuple_element_t<0, tuple_>,
SolidMechanicsModel> {
using parent =
TestPatchTestLinear<std::tuple_element_t<0, tuple_>, SolidMechanicsModel>;
public:
static constexpr bool plane_strain = std::tuple_element_t<1, tuple_>::value;
void applyBC() override {
parent::applyBC();
auto & displacement = this->model->getDisplacement();
this->applyBConDOFs(displacement);
}
void checkForces() {
auto & mat = this->model->getMaterial(0);
auto & internal_forces = this->model->getInternalForce();
auto & external_forces = this->model->getExternalForce();
auto dim = this->dim;
Matrix<Real> sigma =
make_view(mat.getStress(this->type), dim, dim).begin()[0];
external_forces.zero();
if (dim > 1) {
for (auto & eg : this->mesh->iterateElementGroups()) {
this->model->applyBC(BC::Neumann::FromHigherDim(sigma), eg.getName());
}
} else {
external_forces(0) = -sigma(0, 0);
external_forces(1) = sigma(0, 0);
}
Real force_norm_inf = -std::numeric_limits<Real>::max();
Vector<Real> total_force(dim);
total_force.zero();
for (auto && f : make_view(internal_forces, dim)) {
total_force += f;
- force_norm_inf = std::max(force_norm_inf, f.template norm<L_inf>());
+ force_norm_inf =
+ std::max(force_norm_inf, f.template lpNorm<Eigen::Infinity>());
}
- EXPECT_NEAR(0, total_force.template norm<L_inf>() / force_norm_inf, 1e-9);
+ EXPECT_NEAR(0,
+ total_force.template lpNorm<Eigen::Infinity>() / force_norm_inf,
+ 1e-9);
for (auto && tuple : zip(make_view(internal_forces, dim),
make_view(external_forces, dim))) {
auto && f_int = std::get<0>(tuple);
auto && f_ext = std::get<1>(tuple);
auto f = f_int + f_ext;
- EXPECT_NEAR(0, f.template norm<L_inf>() / force_norm_inf, 1e-9);
+ EXPECT_NEAR(0, f.template lpNorm<Eigen::Infinity>() / force_norm_inf,
+ 1e-9);
}
}
void checkAll() {
auto & displacement = this->model->getDisplacement();
auto & mat = this->model->getMaterial(0);
this->checkDOFs(displacement);
this->checkGradient(mat.getGradU(this->type), displacement);
this->checkResults(
[&](const Matrix<Real> & pstrain) {
Real nu = this->model->getMaterial(0).get("nu");
Real E = this->model->getMaterial(0).get("E");
- auto strain = (pstrain + pstrain.transpose()) / 2.;
+ Matrix<Real, parent::dim, parent::dim> strain =
+ (pstrain + pstrain.transpose()) / 2.;
auto trace = strain.trace();
auto lambda = nu * E / ((1 + nu) * (1 - 2 * nu));
auto mu = E / (2 * (1 + nu));
if (not this->plane_strain) {
lambda = nu * E / (1 - nu * nu);
}
- decltype(strain) stress(this->dim, this->dim);
+ Matrix<Real, parent::dim, parent::dim> stress;
- if (this->dim == 1) {
- stress(0, 0) = E * strain(0, 0);
+ if (parent::dim == 1) {
+ stress = E * strain;
} else {
- for (UInt i = 0; i < this->dim; ++i)
- for (UInt j = 0; j < this->dim; ++j)
- stress(i, j) =
- (i == j) * lambda * trace + 2 * mu * strain(i, j);
+ stress = Matrix<Real, parent::dim, parent::dim>::Identity() *
+ lambda * trace +
+ 2 * mu * strain;
}
return stress;
},
mat.getStress(this->type), displacement);
this->checkForces();
}
};
template <typename tuple_>
constexpr bool TestPatchTestSMMLinear<tuple_>::plane_strain;
template <typename T> struct invalid_plan_stress : std::true_type {};
template <typename type, typename bool_c>
struct invalid_plan_stress<std::tuple<type, bool_c>>
: aka::bool_constant<ElementClass<type::value>::getSpatialDimension() !=
2 and
not bool_c::value> {};
using true_false =
std::tuple<aka::bool_constant<true>, aka::bool_constant<false>>;
template <typename T> using valid_types = aka::negation<invalid_plan_stress<T>>;
using model_types = gtest_list_t<
tuple_filter_t<valid_types, cross_product_t<TestElementTypes, true_false>>>;
TYPED_TEST_SUITE(TestPatchTestSMMLinear, model_types, );
#endif /* AKANTU_PATCH_TEST_LINEAR_SOLID_MECHANICS_FIXTURE_HH_ */
diff --git a/test/test_model/patch_tests/test_lumped_mass.cc b/test/test_model/patch_tests/test_lumped_mass.cc
index f10ef3908..dfb753df6 100644
--- a/test/test_model/patch_tests/test_lumped_mass.cc
+++ b/test/test_model/patch_tests/test_lumped_mass.cc
@@ -1,103 +1,104 @@
/**
* @file test_lumped_mass.cc
*
* @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Dec 05 2017
* @date last modification: Wed Nov 18 2020
*
* @brief test the lumping of the mass matrix
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <tuple>
/* -------------------------------------------------------------------------- */
using namespace akantu;
template <typename tuple_>
class TestLumpedMassesFixture : public ::testing::Test {
public:
static constexpr ElementType type = tuple_::value;
static constexpr size_t dim = ElementClass<type>::getSpatialDimension();
void SetUp() override {
debug::setDebugLevel(dblError);
getStaticParser().parse("material_lumped.dat");
std::stringstream element_type;
element_type << type;
mesh = std::make_unique<Mesh>(dim);
mesh->read(element_type.str() + ".msh");
SCOPED_TRACE(element_type.str().c_str());
model = std::make_unique<SolidMechanicsModel>(*mesh);
model->initFull(_analysis_method = _explicit_lumped_mass);
}
void TearDown() override {
model.reset(nullptr);
mesh.reset(nullptr);
}
protected:
std::unique_ptr<Mesh> mesh;
std::unique_ptr<SolidMechanicsModel> model;
};
template <typename T> constexpr ElementType TestLumpedMassesFixture<T>::type;
template <typename T> constexpr size_t TestLumpedMassesFixture<T>::dim;
using mass_types = gtest_list_t<TestElementTypes>;
TYPED_TEST_SUITE(TestLumpedMassesFixture, mass_types, );
TYPED_TEST(TestLumpedMassesFixture, TestLumpedMass) {
this->model->assembleMassLumped();
auto rho = this->model->getMaterial(0).getRho();
auto & fem = this->model->getFEEngine();
auto nb_element = this->mesh->getNbElement(this->type);
auto nb_quadrature_points =
fem.getNbIntegrationPoints(this->type) * nb_element;
Array<Real> rho_on_quad(nb_quadrature_points, 1, rho, "rho_on_quad");
auto mass = fem.integrate(rho_on_quad, this->type);
const auto & masses = this->model->getMass();
- Vector<Real> sum(this->dim, 0.);
+ Vector<Real> sum(this->dim);
+ sum.zero();
for (auto & mass : make_view(masses, this->dim)) {
sum += mass;
}
- for (UInt s = 0; s < sum.size(); ++s)
+ for (Int s = 0; s < sum.size(); ++s)
EXPECT_NEAR(0., (mass - sum[s]) / mass, 2e-15);
}
diff --git a/test/test_model/test_common/test_dof_manager.cc b/test/test_model/test_common/test_dof_manager.cc
index f038faf45..733ea7788 100644
--- a/test/test_model/test_common/test_dof_manager.cc
+++ b/test/test_model/test_common/test_dof_manager.cc
@@ -1,302 +1,302 @@
/**
* @file test_dof_manager.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Feb 26 2019
* @date last modification: Wed Nov 18 2020
*
* @brief test the dof managers
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <dof_manager.hh>
#include <mesh_partition_scotch.hh>
#include <mesh_utils.hh>
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <numeric>
#include <string>
#include <type_traits>
/* -------------------------------------------------------------------------- */
namespace akantu {
enum DOFManagerType { _dmt_default, _dmt_petsc };
}
AKANTU_ENUM_HASH(DOFManagerType)
using namespace akantu;
// defined as struct to get there names in gtest outputs
struct dof_manager_default_
: public std::integral_constant<DOFManagerType, _dmt_default> {};
struct dof_manager_petsc_
: public std::integral_constant<DOFManagerType, _dmt_petsc> {};
using dof_manager_types = ::testing::Types<
#ifdef AKANTU_USE_PETSC
dof_manager_petsc_,
#endif
dof_manager_default_>;
namespace std {
std::string to_string(const DOFManagerType & type) {
std::unordered_map<DOFManagerType, std::string> map{
#ifdef AKANTU_USE_PETSC
{_dmt_petsc, "petsc"},
#endif
{_dmt_default, "default"},
};
return map.at(type);
}
} // namespace std
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
namespace akantu {
class DOFManagerTester {
public:
DOFManagerTester(std::unique_ptr<DOFManager> dof_manager)
: dof_manager(std::move(dof_manager)) {}
DOFManager & operator*() { return *dof_manager; }
DOFManager * operator->() { return dof_manager.get(); }
void getArrayPerDOFs(const ID & id, SolverVector & vector,
Array<Real> & array) {
dof_manager->getArrayPerDOFs(id, vector, array);
}
SolverVector & residual() { return *dof_manager->residual; }
private:
std::unique_ptr<DOFManager> dof_manager;
};
} // namespace akantu
template <class T> class DOFManagerFixture : public ::testing::Test {
public:
constexpr static DOFManagerType type = T::value;
- constexpr static UInt dim = 3;
+ constexpr static Int dim = 3;
void SetUp() override {
mesh = std::make_unique<Mesh>(this->dim);
auto & communicator = Communicator::getStaticCommunicator();
if (communicator.whoAmI() == 0) {
mesh->read("mesh.msh");
}
mesh->distribute();
nb_nodes = this->mesh->getNbNodes();
nb_total_nodes = this->mesh->getNbGlobalNodes();
auto && range_nodes = arange(nb_nodes);
nb_pure_local =
std::accumulate(range_nodes.begin(), range_nodes.end(), 0,
[&](auto && init, auto && val) {
return init + mesh->isLocalOrMasterNode(val);
});
}
void TearDown() override {
mesh.reset();
dof1.reset();
dof2.reset();
}
decltype(auto) alloc() {
std::unordered_map<DOFManagerType, std::string> types{
{_dmt_default, "default"}, {_dmt_petsc, "petsc"}};
return DOFManagerTester(DOFManagerFactory::getInstance().allocate(
types[T::value], *mesh, "dof_manager"));
}
decltype(auto) registerDOFs(DOFSupportType dst1, DOFSupportType dst2) {
auto dof_manager = DOFManagerTester(this->alloc());
auto n1 = dst1 == _dst_nodal ? nb_nodes : nb_pure_local;
this->dof1 = std::make_unique<Array<Real>>(n1, 3);
dof_manager->registerDOFs("dofs1", *this->dof1, dst1);
EXPECT_EQ(dof_manager.residual().size(), nb_total_nodes * 3);
auto n2 = dst2 == _dst_nodal ? nb_nodes : nb_pure_local;
this->dof2 = std::make_unique<Array<Real>>(n2, 5);
dof_manager->registerDOFs("dofs2", *this->dof2, dst2);
EXPECT_EQ(dof_manager.residual().size(), nb_total_nodes * 8);
return dof_manager;
}
protected:
Int nb_nodes{0}, nb_total_nodes{0}, nb_pure_local{0};
std::unique_ptr<Mesh> mesh;
std::unique_ptr<Array<Real>> dof1;
std::unique_ptr<Array<Real>> dof2;
};
template <class T> constexpr DOFManagerType DOFManagerFixture<T>::type;
-template <class T> constexpr UInt DOFManagerFixture<T>::dim;
+template <class T> constexpr Int DOFManagerFixture<T>::dim;
TYPED_TEST_SUITE(DOFManagerFixture, dof_manager_types, );
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, Construction) {
auto dof_manager = this->alloc();
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, DoubleConstruction) {
auto dof_manager = this->alloc();
dof_manager = this->alloc();
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, RegisterGenericDOF1) {
auto dof_manager = this->alloc();
Array<Real> dofs(this->nb_pure_local, 3);
dof_manager->registerDOFs("dofs1", dofs, _dst_generic);
EXPECT_GE(dof_manager.residual().size(), this->nb_total_nodes * 3);
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, RegisterNodalDOF1) {
auto dof_manager = this->alloc();
Array<Real> dofs(this->nb_nodes, 3);
dof_manager->registerDOFs("dofs1", dofs, _dst_nodal);
EXPECT_GE(dof_manager.residual().size(), this->nb_total_nodes * 3);
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, RegisterGenericDOF2) {
this->registerDOFs(_dst_generic, _dst_generic);
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, RegisterNodalDOF2) {
this->registerDOFs(_dst_nodal, _dst_nodal);
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, RegisterMixedDOF) {
auto dof_manager = this->registerDOFs(_dst_nodal, _dst_generic);
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, AssembleVector) {
auto dof_manager = this->registerDOFs(_dst_nodal, _dst_generic);
dof_manager.residual().zero();
for (auto && data :
enumerate(make_view(*this->dof1, this->dof1->getNbComponent()))) {
auto n = std::get<0>(data);
auto & l = std::get<1>(data);
l.set(1. * this->mesh->isLocalOrMasterNode(n));
}
this->dof2->set(2.);
dof_manager->assembleToResidual("dofs1", *this->dof1);
dof_manager->assembleToResidual("dofs2", *this->dof2);
this->dof1->set(0.);
this->dof2->set(0.);
dof_manager.getArrayPerDOFs("dofs1", dof_manager.residual(), *this->dof1);
for (auto && data :
enumerate(make_view(*this->dof1, this->dof1->getNbComponent()))) {
if (this->mesh->isLocalOrMasterNode(std::get<0>(data))) {
const auto & l = std::get<1>(data);
auto e = (l - Vector<Real>{1., 1., 1.}).norm();
ASSERT_EQ(e, 0.);
}
}
dof_manager.getArrayPerDOFs("dofs2", dof_manager.residual(), *this->dof2);
for (auto && l : make_view(*this->dof2, this->dof2->getNbComponent())) {
auto e = (l - Vector<Real>{2., 2., 2., 2., 2.}).norm();
ASSERT_EQ(e, 0.);
}
}
/* -------------------------------------------------------------------------- */
TYPED_TEST(DOFManagerFixture, AssembleMatrixNodal) {
auto dof_manager = this->registerDOFs(_dst_nodal, _dst_nodal);
auto && K = dof_manager->getNewMatrix("K", _symmetric);
K.zero();
auto && elemental_matrix = std::make_unique<Array<Real>>(
this->mesh->getNbElement(this->dim), 8 * 3 * 8 * 3);
for (auto && m : make_view(*elemental_matrix, 8 * 3, 8 * 3)) {
m.set(1.);
}
dof_manager->assembleElementalMatricesToMatrix(
"K", "dofs1", *elemental_matrix, _hexahedron_8);
elemental_matrix = std::make_unique<Array<Real>>(
this->mesh->getNbElement(this->dim), 8 * 5 * 8 * 5);
for (auto && m : make_view(*elemental_matrix, 8 * 5, 8 * 5)) {
m.set(1.);
}
dof_manager->assembleElementalMatricesToMatrix(
"K", "dofs2", *elemental_matrix, _hexahedron_8);
CSR<Element> node_to_elem;
MeshUtils::buildNode2Elements(*this->mesh, node_to_elem, this->dim);
dof_manager.residual().zero();
for (auto && data :
enumerate(zip(make_view(*this->dof1, this->dof1->getNbComponent()),
make_view(*this->dof2, this->dof2->getNbComponent())))) {
auto n = std::get<0>(data);
auto & l1 = std::get<0>(std::get<1>(data));
auto & l2 = std::get<1>(std::get<1>(data));
auto v = 1. * this->mesh->isLocalOrMasterNode(n);
l1.set(v);
l2.set(v);
}
dof_manager->assembleToResidual("dofs1", *this->dof1);
dof_manager->assembleToResidual("dofs2", *this->dof2);
for (auto && n : arange(this->nb_nodes)) {
if (not this->mesh->isLocalOrMasterNode(n)) {
}
}
}
diff --git a/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc b/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc
index a4ef18cc1..ff3b373a5 100644
--- a/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc
+++ b/test/test_model/test_common/test_model_solver/test_dof_manager_default.cc
@@ -1,133 +1,133 @@
/**
* @file test_dof_manager_default.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Feb 26 2016
* @date last modification: Wed Jan 30 2019
*
* @brief Test default dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager_default.hh"
#include "solver_callback.hh"
#include "sparse_matrix_aij.hh"
#include "time_step_solver.hh"
using namespace akantu;
/**
* =\o-----o-----o-> F
* | |
* |---- L ----|
*/
class MySolverCallback : public SolverCallback {
public:
- MySolverCallback(Real F, DOFManagerDefault & dof_manager, UInt nb_dofs = 3)
+ MySolverCallback(Real F, DOFManagerDefault & dof_manager, Int nb_dofs = 3)
: dof_manager(dof_manager), dispacement(nb_dofs, 1, "disp"),
blocked(nb_dofs, 1), forces(nb_dofs, 1), nb_dofs(nb_dofs) {
dof_manager.registerDOFs("disp", dispacement, _dst_generic);
dof_manager.registerBlockedDOFs("disp", blocked);
dispacement.set(0.);
forces.set(0.);
blocked.set(false);
forces(nb_dofs - 1, _x) = F;
blocked(0, _x) = true;
}
void assembleMatrix(const ID & matrix_id) override {
if (matrix_id != "K")
return;
auto & K = dynamic_cast<SparseMatrixAIJ &>(dof_manager.getMatrix("K"));
K.zero();
- for (UInt i = 1; i < nb_dofs - 1; ++i)
+ for (Int i = 1; i < nb_dofs - 1; ++i)
K.add(i, i, 2.);
- for (UInt i = 0; i < nb_dofs - 1; ++i)
+ for (Int i = 0; i < nb_dofs - 1; ++i)
K.add(i, i + 1, -1.);
K.add(0, 0, 1);
K.add(nb_dofs - 1, nb_dofs - 1, 1);
// K *= 1 / L_{el}
K *= nb_dofs - 1;
}
MatrixType getMatrixType(const ID & matrix_id) const override {
if (matrix_id == "K")
return _symmetric;
return _mt_not_defined;
}
void assembleLumpedMatrix(const ID &) override {}
void assembleResidual() override {
dof_manager.assembleToResidual("disp", forces);
}
void predictor() override {}
void corrector() override {}
DOFManagerDefault & dof_manager;
Array<Real> dispacement;
Array<bool> blocked;
Array<Real> forces;
- UInt nb_dofs;
+ Int nb_dofs;
};
int main(int argc, char * argv[]) {
initialize(argc, argv);
DOFManagerDefault dof_manager("test_dof_manager");
MySolverCallback callback(10., dof_manager, 11);
NonLinearSolver & nls =
dof_manager.getNewNonLinearSolver("my_nls", NonLinearSolverType::_linear);
TimeStepSolver & tss = dof_manager.getNewTimeStepSolver(
"my_tss", TimeStepSolverType::_static, nls, callback);
tss.setIntegrationScheme("disp", IntegrationSchemeType::_pseudo_time);
tss.solveStep(callback);
dof_manager.getMatrix("K").saveMatrix("K_dof_manager_default.mtx");
Array<Real>::const_scalar_iterator disp_it = callback.dispacement.begin();
Array<Real>::const_scalar_iterator force_it = callback.forces.begin();
Array<bool>::const_scalar_iterator blocked_it = callback.blocked.begin();
std::cout << std::setw(8) << "disp"
<< " " << std::setw(8) << "force"
<< " " << std::setw(8) << "blocked" << std::endl;
for (; disp_it != callback.dispacement.end();
++disp_it, ++force_it, ++blocked_it) {
std::cout << std::setw(8) << *disp_it << " " << std::setw(8) << *force_it
<< " " << std::setw(8) << std::boolalpha << *blocked_it
<< std::endl;
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_common/test_model_solver/test_model_solver.cc b/test/test_model/test_common/test_model_solver/test_model_solver.cc
index 67dec144c..38e0b1857 100644
--- a/test/test_model/test_common/test_model_solver/test_model_solver.cc
+++ b/test/test_model/test_common/test_model_solver/test_model_solver.cc
@@ -1,178 +1,178 @@
/**
* @file test_model_solver.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Apr 13 2016
* @date last modification: Tue Apr 23 2019
*
* @brief Test default dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_random_generator.hh"
#include "dof_manager.hh"
#include "dof_synchronizer.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
#include "model_solver.hh"
#include "non_linear_solver.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
#include "test_model_solver_my_model.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
/* -------------------------------------------------------------------------- */
using namespace akantu;
-static void genMesh(Mesh & mesh, UInt nb_nodes);
-static void printResults(MyModel & model, UInt nb_nodes);
+static void genMesh(Mesh & mesh, Int nb_nodes);
+static void printResults(MyModel & model, Int nb_nodes);
Real F = -10;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
UInt prank = Communicator::getStaticCommunicator().whoAmI();
std::cout << std::setprecision(7);
ID dof_manager_type = "default";
#if defined(DOF_MANAGER_TYPE)
dof_manager_type = DOF_MANAGER_TYPE;
#endif
UInt global_nb_nodes = 100;
Mesh mesh(1);
- RandomGenerator<UInt>::seed(1);
+ RandomGenerator<Idx>::seed(1);
if (prank == 0) {
genMesh(mesh, global_nb_nodes);
}
// std::cout << prank << RandGenerator<Real>::seed() << std::endl;
mesh.distribute();
MyModel model(F, mesh, false, dof_manager_type);
model.getNewSolver("static", TimeStepSolverType::_static,
NonLinearSolverType::_newton_raphson);
model.setIntegrationScheme("static", "disp",
IntegrationSchemeType::_pseudo_time);
NonLinearSolver & solver = model.getDOFManager().getNonLinearSolver("static");
solver.set("max_iterations", 2);
model.solveStep();
printResults(model, global_nb_nodes);
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
-void genMesh(Mesh & mesh, UInt nb_nodes) {
+void genMesh(Mesh & mesh, Int nb_nodes) {
MeshAccessor mesh_accessor(mesh);
- Array<Real> & nodes = mesh_accessor.getNodes();
- Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2);
+ auto & nodes = mesh_accessor.getNodes();
+ auto & conn = mesh_accessor.getConnectivity(_segment_2);
nodes.resize(nb_nodes);
mesh_accessor.setNbGlobalNodes(nb_nodes);
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
nodes(n, _x) = n * (1. / (nb_nodes - 1));
}
conn.resize(nb_nodes - 1);
- for (UInt n = 0; n < nb_nodes - 1; ++n) {
+ for (Int n = 0; n < nb_nodes - 1; ++n) {
conn(n, 0) = n;
conn(n, 1) = n + 1;
}
mesh_accessor.makeReady();
}
/* -------------------------------------------------------------------------- */
-void printResults(MyModel & model, UInt /*nb_nodes*/) {
+void printResults(MyModel & model, Int /*nb_nodes*/) {
// if (model.mesh.isDistributed()) {
// UInt prank = model.mesh.getCommunicator().whoAmI();
// auto & sync = dynamic_cast<DOFManagerDefault &>(model.getDOFManager())
// .getSynchronizer();
// if (prank == 0) {
// Array<Real> global_displacement(nb_nodes);
// Array<Real> global_forces(nb_nodes);
// Array<bool> global_blocked(nb_nodes);
// sync.gather(model.forces, global_forces);
// sync.gather(model.displacement, global_displacement);
// sync.gather(model.blocked, global_blocked);
// auto force_it = global_forces.begin();
// auto disp_it = global_displacement.begin();
// auto blocked_it = global_blocked.begin();
// std::cout << "node"
// << ", " << std::setw(8) << "disp"
// << ", " << std::setw(8) << "force"
// << ", " << std::setw(8) << "blocked" << std::endl;
// UInt node = 0;
// for (; disp_it != global_displacement.end();
// ++disp_it, ++force_it, ++blocked_it, ++node) {
// std::cout << node << ", " << std::setw(8) << *disp_it << ", "
// << std::setw(8) << *force_it << ", " << std::setw(8)
// << *blocked_it << std::endl;
// std::cout << std::flush;
// }
// } else {
// sync.gather(model.forces);
// sync.gather(model.displacement);
// sync.gather(model.blocked);
// }
// } else {
auto force_it = model.forces.begin();
auto disp_it = model.displacement.begin();
auto blocked_it = model.blocked.begin();
std::cout << "node"
<< ", " << std::setw(8) << "disp"
<< ", " << std::setw(8) << "force"
<< ", " << std::setw(8) << "blocked" << std::endl;
UInt node = 0;
for (; disp_it != model.displacement.end();
++disp_it, ++force_it, ++blocked_it, ++node) {
std::cout << node << ", " << std::setw(8) << *disp_it << ", "
<< std::setw(8) << *force_it << ", " << std::setw(8)
<< *blocked_it << std::endl;
std::cout << std::flush;
}
// }
}
diff --git a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc
index 8a5381e1f..341e0b6e9 100644
--- a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc
+++ b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.cc
@@ -1,247 +1,247 @@
/**
* @file test_model_solver_dynamic.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Apr 13 2016
* @date last modification: Wed Aug 14 2019
*
* @brief Test default dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "element_group.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
#include "non_linear_solver.hh"
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "dumper_element_partition.hh"
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
#include "test_model_solver_my_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
#ifndef EXPLICIT
#define EXPLICIT true
#endif
using namespace akantu;
class Sinusoidal : public BC::Dirichlet::DirichletFunctor {
public:
Sinusoidal(MyModel & model, Real amplitude, Real pulse_width, Real t)
: model(model), A(amplitude), k(2 * M_PI / pulse_width),
t(t), v{std::sqrt(model.E / model.rho)} {}
- void operator()(UInt n, Vector<bool> & /*flags*/, Vector<Real> & disp,
+ void operator()(Idx n, Vector<bool> & /*flags*/, Vector<Real> & disp,
const Vector<Real> & coord) const {
auto x = coord(_x);
model.velocity(n, _x) = k * v * A * sin(k * (x - v * t));
disp(_x) = A * cos(k * (x - v * t));
}
private:
MyModel & model;
Real A{1.};
Real k{2 * M_PI};
Real t{1.};
Real v{1.};
};
-static void genMesh(Mesh & mesh, UInt nb_nodes);
+static void genMesh(Mesh & mesh, Int nb_nodes);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
- UInt prank = Communicator::getStaticCommunicator().whoAmI();
- UInt global_nb_nodes = 201;
- UInt max_steps = 400;
+ Int prank = Communicator::getStaticCommunicator().whoAmI();
+ Int global_nb_nodes = 201;
+ Int max_steps = 400;
Real time_step = 0.001;
Mesh mesh(1);
Real F = -9.81;
bool _explicit = EXPLICIT;
const Real pulse_width = 0.2;
const Real A = 0.01;
ID dof_manager_type = "default";
#if defined(DOF_MANAGER_TYPE)
dof_manager_type = DOF_MANAGER_TYPE;
#endif
if (prank == 0)
genMesh(mesh, global_nb_nodes);
mesh.distribute();
// mesh.makePeriodic(_x);
MyModel model(F, mesh, _explicit, dof_manager_type);
model.forces.zero();
model.blocked.zero();
model.applyBC(Sinusoidal(model, A, pulse_width, 0.), "all");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "border");
if (!_explicit) {
model.getNewSolver("dynamic", TimeStepSolverType::_dynamic,
NonLinearSolverType::_newton_raphson);
model.setIntegrationScheme("dynamic", "disp",
IntegrationSchemeType::_trapezoidal_rule_2,
IntegrationScheme::_displacement);
} else {
model.getNewSolver("dynamic", TimeStepSolverType::_dynamic_lumped,
NonLinearSolverType::_lumped);
model.setIntegrationScheme("dynamic", "disp",
IntegrationSchemeType::_central_difference,
IntegrationScheme::_acceleration);
}
model.setTimeStep(time_step);
if (prank == 0) {
std::cout << std::scientific;
std::cout << std::setw(14) << "time"
<< "," << std::setw(14) << "wext"
<< "," << std::setw(14) << "epot"
<< "," << std::setw(14) << "ekin"
<< "," << std::setw(14) << "total"
<< "," << std::setw(14) << "max_disp"
<< "," << std::setw(14) << "min_disp" << std::endl;
}
Real wext = 0.;
model.getDOFManager().zeroResidual();
model.assembleResidual();
Real epot = 0; // model.getPotentialEnergy();
Real ekin = 0; // model.getKineticEnergy();
Real einit = ekin + epot;
Real etot = ekin + epot - wext - einit;
Real max_disp = 0., min_disp = 0.;
for (auto && disp : model.displacement) {
max_disp = std::max(max_disp, disp);
min_disp = std::min(min_disp, disp);
}
if (prank == 0) {
std::cout << std::setw(14) << 0. << "," << std::setw(14) << wext << ","
<< std::setw(14) << epot << "," << std::setw(14) << ekin << ","
<< std::setw(14) << etot << "," << std::setw(14) << max_disp
<< "," << std::setw(14) << min_disp << std::endl;
}
#if EXPLICIT == false
NonLinearSolver & solver =
model.getDOFManager().getNonLinearSolver("dynamic");
solver.set("max_iterations", 20);
#endif
auto && dumper = std::make_shared<DumperParaview>("dynamic", "./paraview");
mesh.registerExternalDumper(dumper, "dynamic", true);
mesh.addDumpMesh(mesh);
mesh.addDumpFieldExternalToDumper("dynamic", "displacement",
model.displacement);
mesh.addDumpFieldExternalToDumper("dynamic", "velocity", model.velocity);
mesh.addDumpFieldExternalToDumper("dynamic", "forces", model.forces);
mesh.addDumpFieldExternalToDumper("dynamic", "internal_forces",
model.internal_forces);
mesh.addDumpFieldExternalToDumper("dynamic", "acceleration",
model.acceleration);
mesh.dump();
- for (UInt i = 1; i < max_steps + 1; ++i) {
+ for (Int i = 1; i < max_steps + 1; ++i) {
model.applyBC(Sinusoidal(model, A, pulse_width, time_step * (i - 1)),
"border");
model.solveStep("dynamic");
mesh.dump();
epot = model.getPotentialEnergy();
ekin = model.getKineticEnergy();
wext += model.getExternalWorkIncrement();
etot = ekin + epot - wext - einit;
Real max_disp = 0., min_disp = 0.;
for (auto && disp : model.displacement) {
max_disp = std::max(max_disp, disp);
min_disp = std::min(min_disp, disp);
}
if (prank == 0) {
std::cout << std::setw(14) << time_step * i << "," << std::setw(14)
<< wext << "," << std::setw(14) << epot << "," << std::setw(14)
<< ekin << "," << std::setw(14) << etot << "," << std::setw(14)
<< max_disp << "," << std::setw(14) << min_disp << std::endl;
}
}
// output.close();
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
-void genMesh(Mesh & mesh, UInt nb_nodes) {
+void genMesh(Mesh & mesh, Int nb_nodes) {
MeshAccessor mesh_accessor(mesh);
- Array<Real> & nodes = mesh_accessor.getNodes();
- Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2);
+ auto & nodes = mesh_accessor.getNodes();
+ auto & conn = mesh_accessor.getConnectivity(_segment_2);
nodes.resize(nb_nodes);
auto & all = mesh.createNodeGroup("all_nodes");
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
nodes(n, _x) = n * (1. / (nb_nodes - 1));
all.add(n);
}
mesh.createElementGroupFromNodeGroup("all", "all_nodes");
conn.resize(nb_nodes - 1);
- for (UInt n = 0; n < nb_nodes - 1; ++n) {
+ for (Int n = 0; n < nb_nodes - 1; ++n) {
conn(n, 0) = n;
conn(n, 1) = n + 1;
}
- Array<UInt> & conn_points = mesh_accessor.getConnectivity(_point_1);
+ auto & conn_points = mesh_accessor.getConnectivity(_point_1);
conn_points.resize(2);
conn_points(0, 0) = 0;
conn_points(1, 0) = nb_nodes - 1;
auto & border = mesh.createElementGroup("border", 0);
border.add({_point_1, 0, _not_ghost}, true);
border.add({_point_1, 1, _not_ghost}, true);
mesh_accessor.makeReady();
}
diff --git a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.py b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.py
index 16fddb04a..66bf595b4 100644
--- a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.py
+++ b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic.py
@@ -1,56 +1,50 @@
#!/usr/bin/env python3
""" test_model_solver_dynamic.py: Test the model solver in python"""
__author__ = "Nicolas Richart"
__credits__ = [
"Nicolas Richart <nicolas.richart@epfl.ch>",
]
__copyright__ = "Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
# ------------------------------------------------------------------------------
import numpy as np
import python_fe as pfe
import matplotlib.pyplot as plt
import matplotlib.animation as animation
-# sim_u = np.genfromtxt("disp.csv", delimiter=",", names=True)
-
L = 1.
Ne = 200 # int(sim_u['node'][-1])
F = np.zeros(Ne + 1) # sim_u['force']
F[-1] = - 9.81
blocked = np.zeros(Ne + 1) # sim_u['blocked']
blocked[0] = 1
u = np.zeros(Ne + 1) # sim_u['disp']
trusses = pfe.TrussFE(Ne=Ne,
F={f: [np.where(F == f)] for f in np.unique(F)},
blocked=(np.where(blocked == 1),
u[blocked == 1]))
solver = pfe.DynamicSolver(trusses, delta_t=0.001)
-# for s in range(200):
-# solver.solveStep()
-
-
fig, ax = plt.subplots()
x = np.arange(Ne+1) * L / Ne # x-array
line, = ax.plot(x, trusses.u)
-def animate(i):
+def animate(*args):
+ """Animate in matplotlib the results of the steps."""
solver.solveStep()
line.set_ydata(trusses.u) # update the data
plt.ylim(np.min(trusses.u), np.max(trusses.u))
- return line,
+ return (line,)
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200),
interval=25, blit=True)
-
plt.show()
diff --git a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic_petsc.cc b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic_petsc.cc
index d54f37248..3c027e586 100644
--- a/test/test_model/test_common/test_model_solver/test_model_solver_dynamic_petsc.cc
+++ b/test/test_model/test_common/test_model_solver/test_model_solver_dynamic_petsc.cc
@@ -1,839 +1,839 @@
/**
* @file test_model_solver_dynamic_petsc.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Jan 06 2019
* @date last modification: Wed Mar 13 2019
*
* @brief Test default dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "element_group.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
#include "non_linear_solver.hh"
/* -------------------------------------------------------------------------- */
#include "boundary_condition_functor.hh"
#include "mpi_communicator_data.hh"
/* -------------------------------------------------------------------------- */
#include "dumpable_inline_impl.hh"
#include "dumper_element_partition.hh"
#include "dumper_iohelper_paraview.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
#include <petscmat.h>
#include <petscsnes.h>
#include <petscvec.h>
/* -------------------------------------------------------------------------- */
#ifndef EXPLICIT
#define EXPLICIT true
#endif
template <typename func>
void CHECK_ERR_CXX(func && func_, PetscErrorCode ierr) {
if (PetscUnlikely(ierr != 0)) {
const char * desc;
PetscErrorMessage(ierr, &desc, nullptr);
AKANTU_EXCEPTION("Error in PETSc call to \'" << func_ << "\': " << desc);
}
}
using namespace akantu;
static void genMesh(Mesh & mesh, UInt nb_nodes);
class MyModel {
public:
MyModel(Real F, Mesh & mesh, bool lumped)
: nb_dofs(mesh.getNbNodes()), nb_elements(mesh.getNbElement(_segment_2)),
lumped(lumped), E(1.), A(1.), rho(1.), mesh(mesh),
displacement(nb_dofs, 1, "disp"), velocity(nb_dofs, 1, "velo"),
acceleration(nb_dofs, 1, "accel"), blocked(nb_dofs, 1, "blocked"),
forces(nb_dofs, 1, "force_ext"),
internal_forces(nb_dofs, 1, "force_int"),
stresses(nb_elements, 1, "stress"), strains(nb_elements, 1, "strain"),
initial_lengths(nb_elements, 1, "L0") {
auto n_global = mesh.getNbGlobalNodes();
int n_local = 0;
std::vector<PetscInt> nodes_global_ids(nb_dofs);
for (auto && data : enumerate(nodes_global_ids)) {
auto n = std::get<0>(data);
n_local += mesh.isLocalOrMasterNode(n);
std::get<1>(data) = mesh.getNodeGlobalId(n);
}
mpi_comm = dynamic_cast<MPICommunicatorData &>(
mesh.getCommunicator().getCommunicatorData())
.getMPICommunicator();
MeshAccessor mesh_accessor(mesh);
ierr = ISLocalToGlobalMappingCreate(
mpi_comm, 1, mesh.getNbNodes(), nodes_global_ids.data(),
PETSC_COPY_VALUES, &petsc_local_to_global);
CHECK_ERR_CXX("ISLocalToGlobalMappingCreate", ierr);
auto setName = [](auto && Obj, auto && name) {
PetscObjectSetName(reinterpret_cast<PetscObject>(Obj), name);
};
ierr = VecCreate(mpi_comm, &rhs);
ierr = VecSetSizes(rhs, n_local, n_global);
ierr = VecSetFromOptions(rhs);
ierr = VecSetLocalToGlobalMapping(rhs, petsc_local_to_global);
setName(rhs, "rhs");
ierr = VecDuplicate(rhs, &x);
ierr = VecDuplicate(rhs, &x_save);
ierr = VecDuplicate(rhs, &dx);
ierr = VecDuplicate(rhs, &f_int);
ierr = VecDuplicate(rhs, &f_dirichlet);
setName(x, "x");
setName(x_save, "x save");
setName(dx, "dx");
setName(f_int, "f_int");
setName(f_dirichlet, "f_dirichlet");
ierr = MatCreate(mpi_comm, &M);
ierr = MatSetSizes(M, n_local, n_local, n_global, n_global);
ierr = MatSetFromOptions(M);
ierr = MatSetOption(M, MAT_SYMMETRIC, PETSC_TRUE);
ierr = MatSetOption(M, MAT_ROW_ORIENTED, PETSC_TRUE);
ierr = MatSetUp(M);
ierr = MatSetLocalToGlobalMapping(M, petsc_local_to_global,
petsc_local_to_global);
setName(M, "M");
assembleMass();
ierr = MatDuplicate(M, MAT_DO_NOT_COPY_VALUES, &K);
setName(K, "K");
ierr = MatDuplicate(M, MAT_DO_NOT_COPY_VALUES, &J);
setName(J, "J");
ierr = SNESCreate(mpi_comm, &snes);
ierr = SNESSetFromOptions(snes);
ierr = SNESSetFunction(snes, rhs, MyModel::FormFunction, this);
ierr = SNESSetJacobian(snes, J, J, MyModel::FormJacobian, this);
PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INDEX);
displacement.set(0.);
velocity.set(0.);
acceleration.set(0.);
forces.set(0.);
blocked.set(false);
blocked(0, 0) = true;
blocked(nb_dofs - 1, 0) = true;
displacement(0, 0) = 0;
displacement(nb_dofs - 1, 0) = 1;
for (auto && data :
zip(make_view(this->mesh.getConnectivity(_segment_2), 2),
make_view(this->initial_lengths))) {
const auto & conn = std::get<0>(data);
auto & L = std::get<1>(data);
auto p1 = this->mesh.getNodes()(conn(0), _x);
auto p2 = this->mesh.getNodes()(conn(1), _x);
L = std::abs(p2 - p1);
}
}
// static PetscErrorCode SNESMonitor(SNES snes,PetscInt its,PetscReal
// fnorm,void *ctx) {
// auto & _this = *reinterpret_cast<MyModel *>(ctx);
// //SNESMonitorDefault(snes, its, fnorm, PETSC_VIEWER_STDOUT_WORLD);
// }
static PetscErrorCode FormFunction(SNES /*snes*/, Vec /*dx*/, Vec /*f*/,
void * ctx) {
auto & _this = *reinterpret_cast<MyModel *>(ctx);
_this.assembleResidual();
return 0;
}
static PetscErrorCode FormJacobian(SNES /*snes*/, Vec /*dx*/, Mat /*J*/,
Mat /*P*/, void * ctx) {
auto & _this = *reinterpret_cast<MyModel *>(ctx);
_this.assembleJacobian();
return 0;
}
~MyModel() {
ierr = MatDestroy(&M);
ierr = MatDestroy(&K);
ierr = MatDestroy(&J);
ierr = VecDestroy(&rhs);
ierr = VecDestroy(&x);
ierr = VecDestroy(&dx);
ierr = VecDestroy(&x_save);
ierr = VecDestroy(&f_int);
PetscFinalize();
}
void solveStep() {
std::cout << "solveStep" << std::endl;
copy(x_save, displacement);
ierr = SNESSolve(snes, NULL, dx);
CHECK_ERR_CXX("SNESSolve", ierr);
setSolutionToDisplacement();
assembleResidual();
}
void applyBC() {
std::vector<PetscInt> rows;
for (auto && data : enumerate(blocked)) {
if (std::get<1>(data)) {
rows.push_back(std::get<0>(data));
}
}
copy(x, displacement);
ierr = MatZeroRowsColumnsLocal(J, rows.size(), rows.data(), 1., x,
f_dirichlet);
VecView(f_dirichlet, PETSC_VIEWER_STDOUT_WORLD);
CHECK_ERR_CXX("MatZeroRowsColumnsLocal", ierr);
}
void setSolutionToDisplacement() {
std::cout << "setSolutionToDisplacement" << std::endl;
ierr = VecWAXPY(x, 1, x_save, dx);
copy(displacement, x);
}
void assembleJacobian() {
std::cout << "assembleJacobian" << std::endl;
setSolutionToDisplacement();
assembleStiffness();
ierr = MatZeroEntries(J);
CHECK_ERR_CXX("MatZeroEntries", ierr);
ierr = MatAXPY(J, 1., K, SAME_NONZERO_PATTERN);
CHECK_ERR_CXX("MatAXPY", ierr);
MatView(J, PETSC_VIEWER_STDOUT_WORLD);
applyBC();
MatView(J, PETSC_VIEWER_STDOUT_WORLD);
}
void assembleMass() {
std::cout << "assembleMass" << std::endl;
ierr = MatZeroEntries(M);
CHECK_ERR_CXX("MatZeroEntries", ierr);
Array<Real> m_all_el(this->nb_elements, 4);
Matrix<Real> m(2, 2);
m(0, 0) = m(1, 1) = 2;
m(0, 1) = m(1, 0) = 1;
// under integrated
// m(0, 0) = m(1, 1) = 3./2.;
// m(0, 1) = m(1, 0) = 3./2.;
// lumping the mass matrix
// m(0, 0) += m(0, 1);
// m(1, 1) += m(1, 0);
// m(0, 1) = m(1, 0) = 0;
for (auto && data :
zip(make_view(this->mesh.getConnectivity(_segment_2), 2),
make_view(m_all_el, 2, 2))) {
const auto & conn = std::get<0>(data);
auto & m_el = std::get<1>(data);
UInt n1 = conn(0);
UInt n2 = conn(1);
Real p1 = this->mesh.getNodes()(n1, _x);
Real p2 = this->mesh.getNodes()(n2, _x);
Real L = std::abs(p2 - p1);
m_el = m;
m_el *= rho * A * L / 6.;
Vector<Int> conn_int(conn.size());
for (auto && data : zip(conn_int, conn)) {
std::get<0>(data) = std::get<1>(data);
}
- ierr = MatSetValuesLocal(M, conn_int.size(), conn_int.storage(),
- conn_int.size(), conn_int.storage(), m.storage(),
+ ierr = MatSetValuesLocal(M, conn_int.size(), conn_int.data(),
+ conn_int.size(), conn_int.data(), m.data(),
ADD_VALUES);
}
ierr = MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY);
ierr = MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY);
ierr = MatSetOption(M, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
PetscViewer viewer;
ierr = PetscViewerASCIIOpen(mpi_comm, "M.mtx", &viewer);
PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_MATRIXMARKET);
ierr = MatView(M, viewer);
PetscViewerPopFormat(viewer);
ierr = PetscViewerDestroy(&viewer);
// this->getDOFManager().assembleElementalMatricesToMatrix(
// "M", "disp", m_all_el, _segment_2);
is_mass_assembled = true;
}
// MatrixType getMatrixType(const ID &) { return _symmetric; }
// void assembleMatrix(const ID & matrix_id) {
// if (matrix_id == "K") {
// if (not is_stiffness_assembled)
// this->assembleStiffness();
// } else if (matrix_id == "M") {
// if (not is_mass_assembled)
// this->assembleMass();
// } else if (matrix_id == "C") {
// // pass, no damping matrix
// } else {
// AKANTU_EXCEPTION("This solver does not know what to do with a matrix "
// << matrix_id);
// }
// }
void assembleLumpedMatrix(const ID & matrix_id) {
std::cout << "assembleLumpedMatrix" << std::endl;
AKANTU_EXCEPTION("This solver does not know what to do with a matrix "
<< matrix_id);
}
void assembleStiffness() {
std::cout << "assembleStiffness" << std::endl;
// SparseMatrix & K = this->getDOFManager().getMatrix("K");
// K.zero();
ierr = MatZeroEntries(K);
CHECK_ERR_CXX("MatZeroEntries", ierr);
Matrix<Real> k(2, 2);
k(0, 0) = k(1, 1) = 1;
k(0, 1) = k(1, 0) = -1;
Array<Real> k_all_el(this->nb_elements, 4);
auto k_it = k_all_el.begin(2, 2);
auto cit = this->mesh.getConnectivity(_segment_2).begin(2);
auto cend = this->mesh.getConnectivity(_segment_2).end(2);
for (; cit != cend; ++cit, ++k_it) {
const auto & conn = *cit;
UInt n1 = conn(0);
UInt n2 = conn(1);
Real p1 = this->mesh.getNodes()(n1, _x);
Real p2 = this->mesh.getNodes()(n2, _x);
Real L = std::abs(p2 - p1);
auto & k_el = *k_it;
k_el = k;
k_el *= E * A / L;
Vector<Int> conn_int(conn.size());
for (auto && data : zip(conn_int, conn)) {
std::get<0>(data) = std::get<1>(data);
}
- ierr = MatSetValuesLocal(K, conn_int.size(), conn_int.storage(),
- conn_int.size(), conn_int.storage(),
- k_el.storage(), ADD_VALUES);
+ ierr = MatSetValuesLocal(K, conn_int.size(), conn_int.data(),
+ conn_int.size(), conn_int.data(), k_el.data(),
+ ADD_VALUES);
}
ierr = MatAssemblyBegin(K, MAT_FINAL_ASSEMBLY);
CHECK_ERR_CXX("MatAssemblyBegin", ierr);
ierr = MatAssemblyEnd(K, MAT_FINAL_ASSEMBLY);
CHECK_ERR_CXX("MatAssemblyEnd", ierr);
ierr = MatSetOption(K, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
CHECK_ERR_CXX("MatSetOption", ierr);
PetscViewer viewer;
ierr = PetscViewerASCIIOpen(mpi_comm, "K.mtx", &viewer);
CHECK_ERR_CXX("PetscViewerASCIIOpen", ierr);
PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_MATRIXMARKET);
ierr = MatView(K, viewer);
CHECK_ERR_CXX("MatView", ierr);
PetscViewerPopFormat(viewer);
ierr = PetscViewerDestroy(&viewer);
CHECK_ERR_CXX("PetscViewerDestroy", ierr);
// this->getDOFManager().assembleElementalMatricesToMatrix(
// "K", "disp", k_all_el, _segment_2);
is_stiffness_assembled = true;
}
void copy(Array<Real> & y, Vec x) {
std::cout << "copy <-" << std::endl;
const PetscScalar * x_local;
ierr = VecGetArrayRead(x, &x_local);
for (auto && data : zip(y, range(x_local + 0, x_local + y.size()))) {
std::get<0>(data) = std::get<1>(data);
}
ierr = VecRestoreArrayRead(x, &x_local);
// VecView(x, PETSC_VIEWER_STDOUT_WORLD);
- // std::cout << y.getID() << " " << Vector<Real>(y.storage(), y.size())
+ // std::cout << y.getID() << " " << Vector<Real>(y.data(), y.size())
// << std::endl;
}
void print(const Array<Real> & x) const {
- std::cout << x.getID() << " " << Vector<Real>(x.storage(), x.size())
+ std::cout << x.getID() << " " << VectorProxy<Real>(x.data(), x.size())
<< std::endl;
}
void copy(Vec x, const Array<Real> & y) {
std::cout << "copy ->" << std::endl;
PetscScalar * x_local;
ierr = VecGetArray(x, &x_local);
for (auto && data : zip(y, range(x_local + 0, x_local + y.size()))) {
std::get<1>(data) = std::get<0>(data);
}
ierr = VecRestoreArray(x, &x_local);
- // std::cout << y.getID() << " " << Vector<Real>(y.storage(), y.size())
+ // std::cout << y.getID() << " " << Vector<Real>(y.data(), y.size())
// << std::endl;
// VecView(x, PETSC_VIEWER_STDOUT_WORLD);
}
void assembleResidual() {
std::cout << "assembleResidual" << std::endl;
// this->getDOFManager().assembleToResidual("disp", forces);
setSolutionToDisplacement();
copy(rhs, forces);
// VecAXPY(rhs, -1., f_dirichlet);
print(displacement);
this->assembleResidual(_not_ghost);
// this->synchronize(SynchronizationTag::_user_1);
// this->getDOFManager().assembleToResidual("disp", internal_forces, -1.);
VecAXPY(rhs, 1., f_int);
for (auto && data : enumerate(blocked)) {
if (std::get<1>(data)) {
VecSetValueLocal(rhs, std::get<0>(data), 0., INSERT_VALUES);
}
}
VecAssemblyBegin(rhs);
VecAssemblyEnd(rhs);
VecView(rhs, PETSC_VIEWER_STDOUT_WORLD);
}
void assembleResidual(GhostType ghost_type) {
std::cout << "assembleResidual" << std::endl;
VecZeroEntries(f_int);
auto cit = this->mesh.getConnectivity(_segment_2, ghost_type).begin(2);
auto cend = this->mesh.getConnectivity(_segment_2, ghost_type).end(2);
auto strain_it = this->strains.begin();
auto stress_it = this->stresses.begin();
auto L_it = this->initial_lengths.begin();
for (; cit != cend; ++cit, ++strain_it, ++stress_it, ++L_it) {
const auto & conn = *cit;
UInt n1 = conn(0);
UInt n2 = conn(1);
Real u1 = this->displacement(n1, _x);
Real u2 = this->displacement(n2, _x);
*strain_it = (u2 - u1) / *L_it;
*stress_it = E * *strain_it;
Real f_n = A * *stress_it;
std::cout << n1 << "[" << u1 << "]"
<< " <-> " << n2 << "[" << u2 << "]"
<< " : " << f_n << std::endl;
ierr = VecSetValueLocal(f_int, n1, -f_n, ADD_VALUES);
ierr = VecSetValueLocal(f_int, n2, f_n, ADD_VALUES);
}
ierr = VecAssemblyBegin(f_int);
ierr = VecAssemblyEnd(f_int);
// this->getDOFManager().assembleElementalArrayLocalArray(
// forces_internal_el, internal_forces, _segment_2, ghost_type);
}
Real getPotentialEnergy() {
std::cout << "getPotentialEnergy" << std::endl;
copy(x, displacement);
Vec Ax;
ierr = VecDuplicate(x, &Ax);
ierr = MatMult(K, x, Ax);
PetscScalar res;
ierr = VecDot(x, Ax, &res);
return res / 2.;
}
Real getKineticEnergy() {
std::cout << "getKineticEnergy" << std::endl;
return 0;
}
// Real getExternalWorkIncrement() {
// Real res = 0;
// auto it = velocity.begin();
// auto end = velocity.end();
// auto if_it = internal_forces.begin();
// auto ef_it = forces.begin();
// auto b_it = blocked.begin();
- // for (UInt node = 0; it != end; ++it, ++if_it, ++ef_it, ++b_it, ++node) {
+ // for (Int node = 0; it != end; ++it, ++if_it, ++ef_it, ++b_it, ++node) {
// if (mesh.isLocalOrMasterNode(node))
// res += (*b_it ? -*if_it : *ef_it) * *it;
// }
// mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum);
// return res * this->getTimeStep();
// }
// void predictor() {}
// void corrector() {}
// /* ------------------------------------------------------------------------
// */ UInt getNbData(const Array<Element> & elements,
// const SynchronizationTag &) const {
// return elements.size() * sizeof(Real);
// }
// void packData(CommunicationBuffer & buffer, const Array<Element> &
// elements,
// const SynchronizationTag & tag) const {
// if (tag == SynchronizationTag::_user_1) {
// for (const auto & el : elements) {
// buffer << this->stresses(el.element);
// }
// }
// }
// void unpackData(CommunicationBuffer & buffer, const Array<Element> &
// elements,
// const SynchronizationTag & tag) {
// if (tag == SynchronizationTag::_user_1) {
// auto cit = this->mesh.getConnectivity(_segment_2, _ghost).begin(2);
// for (const auto & el : elements) {
// Real stress;
// buffer >> stress;
// Real f = A * stress;
// Vector<UInt> conn = cit[el.element];
// this->internal_forces(conn(0), _x) += -f;
// this->internal_forces(conn(1), _x) += f;
// }
// }
// }
Real getExternalWorkIncrement() {
std::cout << "getExternalWorkIncrement" << std::endl;
return 0.;
}
template <class Functor> void applyBC(Functor && func, const ID & group_id) {
auto & group = mesh.getElementGroup(group_id).getNodeGroup().getNodes();
auto blocked_dofs = make_view(blocked, 1).begin();
auto disps = make_view(displacement, 1).begin();
auto poss = make_view(mesh.getNodes(), 1).begin();
for (auto && node : group) {
- auto disp = Vector<Real>(disps[node]);
- auto pos = Vector<Real>(poss[node]);
- auto flags = Vector<bool>(blocked_dofs[node]);
+ auto disp = disps[node];
+ auto pos = poss[node];
+ auto flags = blocked_dofs[node];
func(node, flags, disp, pos);
}
}
const Mesh & getMesh() const { return mesh; }
UInt getSpatialDimension() const { return 1; }
auto & getBlockedDOFs() { return blocked; }
void setTimeStep(Real dt) {
std::cout << "setTimeStep" << std::endl;
this->dt = dt;
}
private:
PetscErrorCode ierr{0};
MPI_Comm mpi_comm;
ISLocalToGlobalMapping petsc_local_to_global;
UInt nb_dofs;
UInt nb_elements;
bool lumped;
bool is_stiffness_assembled{false};
bool is_mass_assembled{false};
bool is_lumped_mass_assembled{false};
Mat K{nullptr}, J{nullptr}, M{nullptr};
Vec rhs{nullptr}, x{nullptr}, x_save{nullptr}, dx{nullptr}, f_int{nullptr},
f_dirichlet{nullptr};
SNES snes;
Real dt{0};
Array<Real> save_displacement;
public:
Real E, A, rho;
Mesh & mesh;
Array<Real> displacement;
Array<Real> velocity;
Array<Real> acceleration;
Array<bool> blocked;
Array<Real> forces;
Array<Real> internal_forces;
Array<Real> stresses;
Array<Real> strains;
Array<Real> initial_lengths;
};
/* -------------------------------------------------------------------------- */
class Sinusoidal : public BC::Dirichlet::DirichletFunctor {
public:
Sinusoidal(MyModel & model, Real amplitude, Real pulse_width, Real t)
: model(model), A(amplitude), k(2 * M_PI / pulse_width),
t(t), v{std::sqrt(model.E / model.rho)} {}
void operator()(UInt n, Vector<bool> & /*flags*/, Vector<Real> & disp,
const Vector<Real> & coord) const {
auto x = coord(_x);
model.velocity(n, _x) = k * v * A * sin(k * (x - v * t));
disp(_x) = A * cos(k * (x - v * t));
}
private:
MyModel & model;
Real A{1.};
Real k{2 * M_PI};
Real t{1.};
Real v{1.};
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
PetscInitialize(&argc, &argv, nullptr, nullptr);
UInt prank = Communicator::getStaticCommunicator().whoAmI();
UInt global_nb_nodes = 3;
UInt max_steps = 400;
Real time_step = 0.001;
Mesh mesh(1);
Real F = -9.81;
bool _explicit = EXPLICIT;
// const Real pulse_width = 0.2;
const Real A = 0.01;
if (prank == 0)
genMesh(mesh, global_nb_nodes);
mesh.distribute();
// mesh.makePeriodic(_x);
MyModel model(F, mesh, _explicit);
// model.forces.zero();
// model.blocked.zero();
// model.applyBC(Sinusoidal(model, A, pulse_width, 0.), "all");
// model.applyBC(BC::Dirichlet::FlagOnly(_x), "border");
// if (!_explicit) {
// model.getNewSolver("dynamic", TimeStepSolverType::_dynamic,
// NonLinearSolverType::_newton_raphson);
// model.setIntegrationScheme("dynamic", "disp",
// IntegrationSchemeType::_trapezoidal_rule_2,
// IntegrationScheme::_displacement);
// } else {
// model.getNewSolver("dynamic", TimeStepSolverType::_dynamic_lumped,
// NonLinearSolverType::_lumped);
// model.setIntegrationScheme("dynamic", "disp",
// IntegrationSchemeType::_central_difference,
// IntegrationScheme::_acceleration);
// }
model.setTimeStep(time_step);
if (prank == 0) {
std::cout << std::scientific;
std::cout << std::setw(14) << "time"
<< "," << std::setw(14) << "wext"
<< "," << std::setw(14) << "epot"
<< "," << std::setw(14) << "ekin"
<< "," << std::setw(14) << "total"
<< "," << std::setw(14) << "max_disp"
<< "," << std::setw(14) << "min_disp" << std::endl;
}
Real wext = 0.;
// model.getDOFManager().clearResidual();
// model.assembleResidual();
Real epot = 0; // model.getPotentialEnergy();
Real ekin = 0; // model.getKineticEnergy();
Real einit = ekin + epot;
Real etot = ekin + epot - wext - einit;
Real max_disp = 0., min_disp = 0.;
for (auto && disp : model.displacement) {
max_disp = std::max(max_disp, disp);
min_disp = std::min(min_disp, disp);
}
if (prank == 0) {
std::cout << std::setw(14) << 0. << "," << std::setw(14) << wext << ","
<< std::setw(14) << epot << "," << std::setw(14) << ekin << ","
<< std::setw(14) << etot << "," << std::setw(14) << max_disp
<< "," << std::setw(14) << min_disp << std::endl;
}
// #if EXPLICIT == false
// NonLinearSolver & solver =
// model.getDOFManager().getNonLinearSolver("dynamic");
// solver.set("max_iterations", 20);
// #endif
auto * dumper = new DumperParaview("dynamic", "./paraview");
mesh.registerExternalDumper(*dumper, "dynamic", true);
mesh.addDumpMesh(mesh);
mesh.addDumpFieldExternalToDumper("dynamic", "displacement",
model.displacement);
mesh.addDumpFieldExternalToDumper("dynamic", "velocity", model.velocity);
mesh.addDumpFieldExternalToDumper("dynamic", "forces", model.forces);
mesh.addDumpFieldExternalToDumper("dynamic", "acceleration",
model.acceleration);
mesh.dump();
max_steps = 1;
- for (UInt i = 1; i < max_steps + 1; ++i) {
+ for (Int i = 1; i < max_steps + 1; ++i) {
// model.applyBC(Sinusoidal(model, A, pulse_width, time_step * (i - 1)),
// "border");
model.solveStep();
mesh.dump();
epot = model.getPotentialEnergy();
ekin = model.getKineticEnergy();
wext += model.getExternalWorkIncrement();
etot = ekin + epot - wext - einit;
Real max_disp = 0., min_disp = 0.;
for (auto && disp : model.displacement) {
max_disp = std::max(max_disp, disp);
min_disp = std::min(min_disp, disp);
}
if (prank == 0) {
std::cout << std::setw(14) << time_step * i << "," << std::setw(14)
<< wext << "," << std::setw(14) << epot << "," << std::setw(14)
<< ekin << "," << std::setw(14) << etot << "," << std::setw(14)
<< max_disp << "," << std::setw(14) << min_disp << std::endl;
}
}
// output.close();
// finalize();
// PetscFinalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void genMesh(Mesh & mesh, UInt nb_nodes) {
MeshAccessor mesh_accessor(mesh);
Array<Real> & nodes = mesh_accessor.getNodes();
Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2);
nodes.resize(nb_nodes);
// auto & all = mesh.createNodeGroup("all_nodes");
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
nodes(n, _x) = n * (1. / (nb_nodes - 1));
// all.add(n);
}
// mesh.createElementGroupFromNodeGroup("all", "all_nodes");
conn.resize(nb_nodes - 1);
- for (UInt n = 0; n < nb_nodes - 1; ++n) {
+ for (Int n = 0; n < nb_nodes - 1; ++n) {
conn(n, 0) = n;
conn(n, 1) = n + 1;
}
// Array<UInt> & conn_points = mesh_accessor.getConnectivity(_point_1);
// conn_points.resize(2);
// conn_points(0, 0) = 0;
// conn_points(1, 0) = nb_nodes - 1;
// auto & border = mesh.createElementGroup("border", 0);
// border.add({_point_1, 0, _not_ghost}, true);
// border.add({_point_1, 1, _not_ghost}, true);
mesh_accessor.makeReady();
}
diff --git a/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh b/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh
index 09848ab42..2e42c078c 100644
--- a/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh
+++ b/test/test_model/test_common/test_model_solver/test_model_solver_my_model.hh
@@ -1,453 +1,456 @@
/**
* @file test_model_solver_my_model.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Apr 13 2016
* @date last modification: Fri Jun 26 2020
*
* @brief Test default dof manager
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "boundary_condition.hh"
#include "communicator.hh"
#include "data_accessor.hh"
#include "dof_manager_default.hh"
#include "element_synchronizer.hh"
#include "mesh.hh"
#include "model_solver.hh"
#include "periodic_node_synchronizer.hh"
#include "solver_vector_default.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
#ifndef AKANTU_TEST_MODEL_SOLVER_MY_MODEL_HH_
#define AKANTU_TEST_MODEL_SOLVER_MY_MODEL_HH_
/**
* =\o-----o-----o-> F
* | |
* |---- L ----|
*/
class MyModel : public ModelSolver,
public BoundaryCondition<MyModel>,
public DataAccessor<Element> {
public:
MyModel(Real F, Mesh & mesh, bool lumped,
const ID & dof_manager_type = "default")
: ModelSolver(mesh, ModelType::_model, "model_solver"),
nb_dofs(mesh.getNbNodes()), nb_elements(mesh.getNbElement(_segment_2)),
lumped(lumped), E(1.), A(1.), rho(1.), mesh(mesh),
displacement(nb_dofs, 1, "disp"), velocity(nb_dofs, 1, "velo"),
acceleration(nb_dofs, 1, "accel"), blocked(nb_dofs, 1, "blocked"),
forces(nb_dofs, 1, "force_ext"),
internal_forces(nb_dofs, 1, "force_int"),
stresses(nb_elements, 1, "stress"), strains(nb_elements, 1, "strain"),
initial_lengths(nb_elements, 1, "L0") {
this->initDOFManager(dof_manager_type);
this->initBC(*this, displacement, forces);
this->getDOFManager().registerDOFs("disp", displacement, _dst_nodal);
this->getDOFManager().registerDOFsDerivative("disp", 1, velocity);
this->getDOFManager().registerDOFsDerivative("disp", 2, acceleration);
this->getDOFManager().registerBlockedDOFs("disp", blocked);
displacement.set(0.);
velocity.set(0.);
acceleration.set(0.);
forces.set(0.);
blocked.set(false);
- UInt global_nb_nodes = mesh.getNbGlobalNodes();
+ Int global_nb_nodes = mesh.getNbGlobalNodes();
for (auto && n : arange(nb_dofs)) {
auto global_id = mesh.getNodeGlobalId(n);
if (global_id == (global_nb_nodes - 1))
forces(n, _x) = F;
if (global_id == 0)
blocked(n, _x) = true;
}
auto cit = this->mesh.getConnectivity(_segment_2).begin(2);
auto cend = this->mesh.getConnectivity(_segment_2).end(2);
auto L_it = this->initial_lengths.begin();
for (; cit != cend; ++cit, ++L_it) {
- const Vector<UInt> & conn = *cit;
- UInt n1 = conn(0);
- UInt n2 = conn(1);
- Real p1 = this->mesh.getNodes()(n1, _x);
- Real p2 = this->mesh.getNodes()(n2, _x);
+ auto && conn = *cit;
+ auto n1 = conn(0);
+ auto n2 = conn(1);
+ auto p1 = this->mesh.getNodes()(n1, _x);
+ auto p2 = this->mesh.getNodes()(n2, _x);
*L_it = std::abs(p2 - p1);
}
this->registerDataAccessor(*this);
this->registerSynchronizer(
const_cast<ElementSynchronizer &>(this->mesh.getElementSynchronizer()),
SynchronizationTag::_user_1);
}
void assembleLumpedMass() {
auto & M = this->getDOFManager().getLumpedMatrix("M");
M.zero();
this->assembleLumpedMass(_not_ghost);
if (this->mesh.getNbElement(_segment_2, _ghost) > 0)
this->assembleLumpedMass(_ghost);
is_lumped_mass_assembled = true;
}
void assembleLumpedMass(GhostType ghost_type) {
Array<Real> M(nb_dofs, 1, 0.);
Array<Real> m_all_el(this->mesh.getNbElement(_segment_2, ghost_type), 2);
for (auto && data :
zip(make_view(this->mesh.getConnectivity(_segment_2), 2),
make_view(m_all_el, 2))) {
const auto & conn = std::get<0>(data);
auto & m_el = std::get<1>(data);
- UInt n1 = conn(0);
- UInt n2 = conn(1);
+ Int n1 = conn(0);
+ Int n2 = conn(1);
Real p1 = this->mesh.getNodes()(n1, _x);
Real p2 = this->mesh.getNodes()(n2, _x);
Real L = std::abs(p2 - p1);
Real M_n = rho * A * L / 2;
m_el(0) = m_el(1) = M_n;
}
this->getDOFManager().assembleElementalArrayLocalArray(
m_all_el, M, _segment_2, ghost_type);
this->getDOFManager().assembleToLumpedMatrix("disp", M, "M");
}
void assembleMass() {
SparseMatrix & M = this->getDOFManager().getMatrix("M");
M.zero();
Array<Real> m_all_el(this->nb_elements, 4);
Matrix<Real> m(2, 2);
m(0, 0) = m(1, 1) = 2;
m(0, 1) = m(1, 0) = 1;
// under integrated
// m(0, 0) = m(1, 1) = 3./2.;
// m(0, 1) = m(1, 0) = 3./2.;
// lumping the mass matrix
// m(0, 0) += m(0, 1);
// m(1, 1) += m(1, 0);
// m(0, 1) = m(1, 0) = 0;
for (auto && data :
zip(make_view(this->mesh.getConnectivity(_segment_2), 2),
make_view(m_all_el, 2, 2))) {
const auto & conn = std::get<0>(data);
auto & m_el = std::get<1>(data);
- UInt n1 = conn(0);
- UInt n2 = conn(1);
+ Int n1 = conn(0);
+ Int n2 = conn(1);
Real p1 = this->mesh.getNodes()(n1, _x);
Real p2 = this->mesh.getNodes()(n2, _x);
Real L = std::abs(p2 - p1);
m_el = m;
m_el *= rho * A * L / 6.;
}
this->getDOFManager().assembleElementalMatricesToMatrix(
"M", "disp", m_all_el, _segment_2);
is_mass_assembled = true;
}
- MatrixType getMatrixType(const ID &) const override { return _symmetric; }
+ MatrixType getMatrixType(const ID & id) const override {
+ if (id == "C") {
+ return _mt_not_defined;
+ }
+ return _symmetric;
+ }
void assembleMatrix(const ID & matrix_id) override {
if (matrix_id == "K") {
if (not is_stiffness_assembled)
this->assembleStiffness();
} else if (matrix_id == "M") {
if (not is_mass_assembled)
this->assembleMass();
} else if (matrix_id == "C") {
// pass, no damping matrix
} else {
AKANTU_EXCEPTION("This solver does not know what to do with a matrix "
<< matrix_id);
}
}
void assembleLumpedMatrix(const ID & matrix_id) override {
if (matrix_id == "M") {
if (not is_lumped_mass_assembled)
this->assembleLumpedMass();
} else {
AKANTU_EXCEPTION("This solver does not know what to do with a matrix "
<< matrix_id);
}
}
void assembleStiffness() {
SparseMatrix & K = this->getDOFManager().getMatrix("K");
K.zero();
Matrix<Real> k(2, 2);
k(0, 0) = k(1, 1) = 1;
k(0, 1) = k(1, 0) = -1;
Array<Real> k_all_el(this->nb_elements, 4);
auto k_it = k_all_el.begin(2, 2);
auto cit = this->mesh.getConnectivity(_segment_2).begin(2);
auto cend = this->mesh.getConnectivity(_segment_2).end(2);
for (; cit != cend; ++cit, ++k_it) {
const auto & conn = *cit;
- UInt n1 = conn(0);
- UInt n2 = conn(1);
+ auto n1 = conn(0);
+ auto n2 = conn(1);
- Real p1 = this->mesh.getNodes()(n1, _x);
- Real p2 = this->mesh.getNodes()(n2, _x);
+ auto p1 = this->mesh.getNodes()(n1, _x);
+ auto p2 = this->mesh.getNodes()(n2, _x);
- Real L = std::abs(p2 - p1);
+ auto L = std::abs(p2 - p1);
auto & k_el = *k_it;
k_el = k;
k_el *= E * A / L;
}
this->getDOFManager().assembleElementalMatricesToMatrix(
"K", "disp", k_all_el, _segment_2);
is_stiffness_assembled = true;
}
void assembleResidual() override {
this->getDOFManager().assembleToResidual("disp", forces);
internal_forces.zero();
this->assembleResidualInternal(_not_ghost);
this->synchronize(SynchronizationTag::_user_1);
this->getDOFManager().assembleToResidual("disp", internal_forces, -1.);
}
void assembleResidualInternal(GhostType ghost_type) {
Array<Real> forces_internal_el(
this->mesh.getNbElement(_segment_2, ghost_type), 2);
+ const auto & connectivity =
+ this->mesh.getConnectivity(_segment_2, ghost_type);
+ for (auto && data :
+ zip(make_view<2>(connectivity), strains, stresses, initial_lengths,
+ make_view<2>(forces_internal_el))) {
+ const auto & conn = std::get<0>(data);
+ auto n1 = conn(0);
+ auto n2 = conn(1);
- auto cit = this->mesh.getConnectivity(_segment_2, ghost_type).begin(2);
- auto cend = this->mesh.getConnectivity(_segment_2, ghost_type).end(2);
-
- auto f_it = forces_internal_el.begin(2);
-
- auto strain_it = this->strains.begin();
- auto stress_it = this->stresses.begin();
- auto L_it = this->initial_lengths.begin();
+ auto u1 = this->displacement(n1, _x);
+ auto u2 = this->displacement(n2, _x);
- for (; cit != cend; ++cit, ++f_it, ++strain_it, ++stress_it, ++L_it) {
- const auto & conn = *cit;
- UInt n1 = conn(0);
- UInt n2 = conn(1);
+ auto & strain = std::get<1>(data);
+ auto & stress = std::get<2>(data);
+ const auto & L = std::get<3>(data);
- Real u1 = this->displacement(n1, _x);
- Real u2 = this->displacement(n2, _x);
+ strain = (u2 - u1) / L;
+ stress = E * strain;
- *strain_it = (u2 - u1) / *L_it;
- *stress_it = E * *strain_it;
- Real f_n = A * *stress_it;
- Vector<Real> & f = *f_it;
+ auto f_n = A * stress;
+ auto & f = std::get<4>(data);
f(0) = -f_n;
f(1) = f_n;
}
this->getDOFManager().assembleElementalArrayLocalArray(
forces_internal_el, internal_forces, _segment_2, ghost_type);
}
Real getPotentialEnergy() {
Real res = 0;
if (not lumped) {
res = this->mulVectMatVect(this->displacement, "K", this->displacement);
} else {
- auto strain_it = this->strains.begin();
- auto stress_it = this->stresses.begin();
- auto strain_end = this->strains.end();
- auto L_it = this->initial_lengths.begin();
+ for (auto && data : zip(strains, stresses, initial_lengths)) {
+ auto & strain = std::get<0>(data);
+ auto & stress = std::get<1>(data);
+ const auto & L = std::get<2>(data);
- for (; strain_it != strain_end; ++strain_it, ++stress_it, ++L_it) {
- res += *strain_it * *stress_it * A * *L_it;
+ res += strain * stress * A * L;
}
mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum);
}
return res / 2.;
}
Real getKineticEnergy() {
Real res = 0;
if (not lumped) {
res = this->mulVectMatVect(this->velocity, "M", this->velocity);
} else {
Array<Real> & m = dynamic_cast<SolverVectorDefault &>(
this->getDOFManager().getLumpedMatrix("M"));
auto it = velocity.begin();
auto end = velocity.end();
auto m_it = m.begin();
- for (UInt node = 0; it != end; ++it, ++m_it, ++node) {
+ for (Int node = 0; it != end; ++it, ++m_it, ++node) {
if (mesh.isLocalOrMasterNode(node))
res += *m_it * *it * *it;
}
mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum);
}
return res / 2.;
}
Real getExternalWorkIncrement() {
Real res = 0;
auto it = velocity.begin();
auto end = velocity.end();
auto if_it = internal_forces.begin();
auto ef_it = forces.begin();
auto b_it = blocked.begin();
- for (UInt node = 0; it != end; ++it, ++if_it, ++ef_it, ++b_it, ++node) {
+ for (Int node = 0; it != end; ++it, ++if_it, ++ef_it, ++b_it, ++node) {
if (mesh.isLocalOrMasterNode(node))
res += (*b_it ? -*if_it : *ef_it) * *it;
}
mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum);
return res * this->getTimeStep();
}
Real mulVectMatVect(const Array<Real> & x, const ID & A_id,
const Array<Real> & y) {
Array<Real> Ay(nb_dofs);
this->getDOFManager().assembleMatMulVectToArray("disp", A_id, y, Ay);
Real res = 0.;
for (auto && data : zip(arange(nb_dofs), make_view(Ay), make_view(x))) {
res += std::get<2>(data) * std::get<1>(data) *
mesh.isLocalOrMasterNode(std::get<0>(data));
}
mesh.getCommunicator().allReduce(res, SynchronizerOperation::_sum);
return res;
}
/* ------------------------------------------------------------------------ */
- UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag &) const override {
+ Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag &) const override {
return elements.size() * sizeof(Real);
}
void packData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) const override {
if (tag == SynchronizationTag::_user_1) {
for (const auto & el : elements) {
buffer << this->stresses(el.element);
}
}
}
void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements,
const SynchronizationTag & tag) override {
if (tag == SynchronizationTag::_user_1) {
auto cit = this->mesh.getConnectivity(_segment_2, _ghost).begin(2);
for (const auto & el : elements) {
Real stress;
buffer >> stress;
Real f = A * stress;
- Vector<UInt> conn = cit[el.element];
+ auto && conn = cit[el.element];
this->internal_forces(conn(0), _x) += -f;
this->internal_forces(conn(1), _x) += f;
}
}
}
const Mesh & getMesh() const { return mesh; }
- UInt getSpatialDimension() const { return 1; }
+ Int getSpatialDimension() const { return 1; }
auto & getBlockedDOFs() { return blocked; }
private:
- UInt nb_dofs;
- UInt nb_elements;
+ Int nb_dofs;
+ Int nb_elements;
bool lumped;
bool is_stiffness_assembled{false};
bool is_mass_assembled{false};
bool is_lumped_mass_assembled{false};
public:
Real E, A, rho;
Mesh & mesh;
Array<Real> displacement;
Array<Real> velocity;
Array<Real> acceleration;
Array<bool> blocked;
Array<Real> forces;
Array<Real> internal_forces;
Array<Real> stresses;
Array<Real> strains;
Array<Real> initial_lengths;
};
#endif /* AKANTU_TEST_MODEL_SOLVER_MY_MODEL_HH_ */
} // namespace akantu
diff --git a/test/test_model/test_common/test_non_local_toolbox/my_model.hh b/test/test_model/test_common/test_non_local_toolbox/my_model.hh
index 9c0fa5e3e..ac9ad5deb 100644
--- a/test/test_model/test_common/test_non_local_toolbox/my_model.hh
+++ b/test/test_model/test_common/test_non_local_toolbox/my_model.hh
@@ -1,126 +1,127 @@
/**
* @file my_model.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Sep 11 2017
* @date last modification: Fri Jun 26 2020
*
* @brief A dummy model for tests purposes
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "integrator_gauss.hh"
#include "model.hh"
#include "non_local_manager.hh"
#include "non_local_manager_callback.hh"
#include "non_local_neighborhood_base.hh"
#include "shape_lagrange.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class MyModel : public Model, public NonLocalManagerCallback {
using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
public:
- MyModel(Mesh & mesh, UInt spatial_dimension)
+ MyModel(Mesh &mesh, Int spatial_dimension)
: Model(mesh, ModelType::_model, spatial_dimension),
manager(*this, *this) {
registerFEEngineObject<MyFEEngineType>("FEEngine", mesh, spatial_dimension);
manager.registerNeighborhood("test_region", "test_region");
getFEEngine().initShapeFunctions();
manager.initialize();
}
void initModel() override {}
MatrixType getMatrixType(const ID &) const override {
return _mt_not_defined;
}
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & /*method*/) override {
return std::make_tuple("test", TimeStepSolverType::_static);
}
void assembleMatrix(const ID &) override {}
void assembleLumpedMatrix(const ID &) override {}
void assembleResidual() override {}
- void onNodesAdded(const Array<UInt> &, const NewNodesEvent &) override {}
+ void onNodesAdded(const Array<Idx> &, const NewNodesEvent &) override {}
- void onNodesRemoved(const Array<UInt> &, const Array<UInt> &,
+ void onNodesRemoved(const Array<Idx> &, const Array<Idx> &,
const RemovedNodesEvent &) override {}
void onElementsAdded(const Array<Element> &,
const NewElementsEvent &) override {}
void onElementsRemoved(const Array<Element> &,
- const ElementTypeMapArray<UInt> &,
+ const ElementTypeMapArray<Idx> &,
const RemovedElementsEvent &) override {}
void onElementsChanged(const Array<Element> &, const Array<Element> &,
- const ElementTypeMapArray<UInt> &,
+ const ElementTypeMapArray<Idx> &,
const ChangedElementsEvent &) override {}
void insertIntegrationPointsInNeighborhoods(GhostType ghost_type) override {
ElementTypeMapArray<Real> quadrature_points_coordinates(
"quadrature_points_coordinates_tmp_nl", this->id);
quadrature_points_coordinates.initialize(this->getFEEngine(),
_nb_component = spatial_dimension,
_ghost_type = ghost_type);
IntegrationPoint q;
q.ghost_type = ghost_type;
q.global_num = 0;
- auto & neighborhood = manager.getNeighborhood("test_region");
+ auto &neighborhood = manager.getNeighborhood("test_region");
- for (auto & type : quadrature_points_coordinates.elementTypes(
+ for (const auto &type : quadrature_points_coordinates.elementTypes(
spatial_dimension, ghost_type)) {
q.type = type;
- auto & quads = quadrature_points_coordinates(type, ghost_type);
+
+ auto &quads = quadrature_points_coordinates(type, ghost_type);
this->getFEEngine().computeIntegrationPointsCoordinates(quads, type,
ghost_type);
auto quad_it = quads.begin(quads.getNbComponent());
auto quad_end = quads.end(quads.getNbComponent());
q.num_point = 0;
for (; quad_it != quad_end; ++quad_it) {
neighborhood.insertIntegrationPoint(q, *quad_it);
++q.num_point;
++q.global_num;
}
}
}
void computeNonLocalStresses(GhostType) override {}
void updateLocalInternal(ElementTypeMapReal &, GhostType,
ElementKind) override {}
void updateNonLocalInternal(ElementTypeMapReal &, GhostType,
ElementKind) override {}
- const auto & getNonLocalManager() const { return manager; }
+ const auto &getNonLocalManager() const { return manager; }
private:
NonLocalManager manager;
};
diff --git a/test/test_model/test_common/test_non_local_toolbox/plot_neighborhoods.py b/test/test_model/test_common/test_non_local_toolbox/plot_neighborhoods.py
index 09d59617a..1d2ad915f 100644
--- a/test/test_model/test_common/test_non_local_toolbox/plot_neighborhoods.py
+++ b/test/test_model/test_common/test_non_local_toolbox/plot_neighborhoods.py
@@ -1,109 +1,112 @@
#!/usr/bin/env python
-
-""" plot_neighborhoods.py: plot the neighborhoods in non local manager"""
+"""plot_neighborhoods.py: plot the neighborhoods in non local manager."""
__author__ = "Aurelia Isabel Cuba Ramos"
__credits__ = [
"Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>",
]
__copyright__ = "Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale" \
" de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \
" en Mécanique des Solides)"
__license__ = "LGPLv3"
import sys
from matplotlib import rc
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.backends.backend_pdf import PdfPages
# ------------------------------------------------------------------------------
-def readFile(filename):
+def read_file(filename):
+ """Read a reference file."""
quad_x_coords = list()
quad_y_coords = list()
with open(filename) as fh:
for line in fh:
if line.strip().startswith("#"):
line = fh.next()
x, y = [float(s) for s in line[1:-3].split(", ")]
quad_x_coords.append(float(x))
quad_y_coords.append(float(y))
return quad_x_coords, quad_y_coords
# ------------------------------------------------------------------------------
-def readNeighborhoods(filename):
+def read_neighborhoods(filename):
+ """Read a neighborhood file or verification."""
neighborhoods = dict()
with open(filename) as fh:
first_line = fh.readline()
key = int(first_line[0:-1].split(" ")[-1])
current_list = list()
for line in fh:
if line.strip().startswith("#"):
neighborhoods[key] = current_list
key = int(line[0:-1].split(" ")[-1])
current_list = list()
else:
coord = [float(s) for s in line[1:-3].split(", ")]
current_list.append(coord)
neighborhoods[key] = current_list
return neighborhoods
# ------------------------------------------------------------------------------
-def plotNeighborhood(quad_x_coords, quad_y_coords, neighborhood, r):
+def plot_neighborhood(quad_x_coords, quad_y_coords, neighborhood, r):
+ """Plot a neighborhood."""
ax = plt.subplot(111)
plt.axis([-1, 1, -1, 1])
# plot all quads
ax.plot(quad_x_coords, quad_y_coords, label='free',
linestyle='None', marker="+", markeredgewidth=0.2, markersize=4)
# plot center of neighborhood and circle
x = neighborhood[0][0]
y = neighborhood[0][1]
ax.plot(x, y, label='free', marker="+", markeredgewidth=0.2,
markersize=4, color='r')
circ = plt.Circle((x, y), radius=r, color='g', fill=False)
ax.add_patch(circ)
formatter = ticker.ScalarFormatter()
formatter.set_powerlimits((-2, 2))
ax.xaxis.set_major_formatter(formatter)
# plot all the neighbors
for i in range(1, len(neighborhood)):
ax.plot(neighborhood[i][0], neighborhood[i][1], label='free',
linestyle='None', marker="x", markeredgewidth=0.2,
markersize=4, color='y')
ax.grid(b=True, which='major', color='0.75',
linestyle='-', linewidth=0.5)
ax.grid(b=True, which='minor', color='0.75',
linestyle='-', linewidth=0.5)
# ------------------------------------------------------------------------------
def main():
+ """Run the main function."""
non_local_radius = 0.5
rc('text', usetex=True)
rc('font', family='serif', size=8, serif='Times')
neighborhood_file = sys.argv[1]
- quad_x_coords, quad_y_coords = readFile(neighborhood_file)
+ quad_x_coords, quad_y_coords = read_file(neighborhood_file)
nb_quads = len(quad_x_coords)
- neighborhoods = readNeighborhoods(neighborhood_file)
+ neighborhoods = read_neighborhoods(neighborhood_file)
with PdfPages('resulting_neighborhoods.pdf') as pdf:
for i in range(nb_quads):
plt.figure(1, figsize=(7/2.54, 7/2.54))
- plotNeighborhood(quad_x_coords, quad_y_coords,
- neighborhoods[i], non_local_radius)
+ plot_neighborhood(quad_x_coords, quad_y_coords,
+ neighborhoods[i], non_local_radius)
pdf.savefig()
plt.close()
if __name__ == "__main__":
main()
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_build_neighborhood_parallel.cc b/test/test_model/test_common/test_non_local_toolbox/test_build_neighborhood_parallel.cc
index 15ab6531e..0bfb5e942 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_build_neighborhood_parallel.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_build_neighborhood_parallel.cc
@@ -1,190 +1,190 @@
/**
* @file test_build_neighborhood_parallel.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Wed Jan 30 2019
*
* @brief test in parallel for the class NonLocalNeighborhood
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_iohelper_paraview.hh"
#include "non_local_neighborhood_base.hh"
#include "solid_mechanics_model.hh"
#include "test_material.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material_parallel_test.dat", argc, argv);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
// some configuration variables
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
// mesh creation and read
Mesh mesh(spatial_dimension);
if (prank == 0) {
mesh.read("parallel_test.msh");
}
mesh.distribute();
/// model creation
SolidMechanicsModel model(mesh);
/// dump the ghost elements before the non-local part is intialized
DumperParaview dumper_ghost("ghost_elements");
dumper_ghost.registerMesh(mesh, spatial_dimension, _ghost);
if (psize > 1) {
dumper_ghost.dump();
}
/// creation of material selector
auto && mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
/// dump material index in paraview
model.addDumpField("partitions");
model.dump();
/// model initialization changed to use our material
model.initFull();
/// dump the ghost elements after ghosts for non-local have been added
if (psize > 1)
dumper_ghost.dump();
model.addDumpField("grad_u");
model.addDumpField("grad_u non local");
model.addDumpField("material_index");
/// apply constant strain field everywhere in the plate
Matrix<Real> applied_strain(spatial_dimension, spatial_dimension);
applied_strain.zero();
- for (UInt i = 0; i < spatial_dimension; ++i)
+ for (Int i = 0; i < spatial_dimension; ++i)
applied_strain(i, i) = 2.;
ElementType element_type = _triangle_3;
GhostType ghost_type = _not_ghost;
/// apply constant grad_u field in all elements
- for (UInt m = 0; m < model.getNbMaterials(); ++m) {
+ for (Int m = 0; m < model.getNbMaterials(); ++m) {
auto & mat = model.getMaterial(m);
auto & grad_u = const_cast<Array<Real> &>(
mat.getInternal<Real>("grad_u")(element_type, ghost_type));
auto grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension);
auto grad_u_end = grad_u.end(spatial_dimension, spatial_dimension);
for (; grad_u_it != grad_u_end; ++grad_u_it)
(*grad_u_it) = -1. * applied_strain;
}
/// double the strain in the center: find the closed gauss point to the center
/// compute the quadrature points
ElementTypeMapReal quad_coords("quad_coords");
quad_coords.initialize(mesh, _nb_component = spatial_dimension,
_spatial_dimension = spatial_dimension,
_with_nb_element = true);
model.getFEEngine().computeIntegrationPointsCoordinates(quad_coords);
- Vector<Real> center(spatial_dimension, 0.);
+ Vector<Real> center(spatial_dimension);
+ center.zero();
Real min_distance = 2;
IntegrationPoint q_min;
for (auto type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_regular)) {
- UInt nb_elements = mesh.getNbElement(type, _not_ghost);
- UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(type);
- Array<Real> & coords = quad_coords(type, _not_ghost);
+ auto nb_elements = mesh.getNbElement(type, _not_ghost);
+ auto nb_quads = model.getFEEngine().getNbIntegrationPoints(type);
+ auto & coords = quad_coords(type, _not_ghost);
auto coord_it = coords.begin(spatial_dimension);
- for (UInt e = 0; e < nb_elements; ++e) {
- for (UInt q = 0; q < nb_quads; ++q, ++coord_it) {
- Real dist = center.distance(*coord_it);
+ for (Int e = 0; e < nb_elements; ++e) {
+ for (Int q = 0; q < nb_quads; ++q, ++coord_it) {
+ auto dist = center.distance(*coord_it);
if (dist < min_distance) {
min_distance = dist;
q_min.element = e;
q_min.num_point = q;
q_min.global_num = nb_elements * nb_quads + q;
q_min.type = type;
}
}
}
}
- Real global_min = min_distance;
+ auto global_min = min_distance;
comm.allReduce(global_min, SynchronizerOperation::_min);
if (Math::are_float_equal(global_min, min_distance)) {
- UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost)
+ auto mat_index = model.getMaterialByElement(q_min.type, _not_ghost)
.begin()[q_min.element];
- Material & mat = model.getMaterial(mat_index);
- UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(q_min.type);
- UInt local_el_index =
+ auto & mat = model.getMaterial(mat_index);
+ auto nb_quads = model.getFEEngine().getNbIntegrationPoints(q_min.type);
+ auto local_el_index =
model.getMaterialLocalNumbering(q_min.type, _not_ghost)
.begin()[q_min.element];
- UInt local_num = (local_el_index * nb_quads) + q_min.num_point;
- Array<Real> & grad_u = const_cast<Array<Real> &>(
+ auto local_num = (local_el_index * nb_quads) + q_min.num_point;
+ auto & grad_u = const_cast<Array<Real> &>(
mat.getInternal<Real>("grad_u")(q_min.type, _not_ghost));
- Array<Real>::iterator<Matrix<Real>> grad_u_it =
- grad_u.begin(spatial_dimension, spatial_dimension);
+ auto grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension);
grad_u_it += local_num;
- Matrix<Real> & g_u = *grad_u_it;
+ auto & g_u = *grad_u_it;
g_u += applied_strain;
}
/// compute the non-local strains
model.assembleInternalForces();
model.dump();
/// damage the element with higher grad_u completely, so that it is
/// not taken into account for the averaging
if (Math::are_float_equal(global_min, min_distance)) {
UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost)
.begin()[q_min.element];
Material & mat = model.getMaterial(mat_index);
UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(q_min.type);
UInt local_el_index =
model.getMaterialLocalNumbering(q_min.type, _not_ghost)
.begin()[q_min.element];
UInt local_num = (local_el_index * nb_quads) + q_min.num_point;
Array<Real> & damage = const_cast<Array<Real> &>(
mat.getInternal<Real>("damage")(q_min.type, _not_ghost));
- Real * dam_ptr = damage.storage();
+ Real * dam_ptr = damage.data();
dam_ptr += local_num;
*dam_ptr = 0.9;
}
/// compute the non-local strains
model.assembleInternalForces();
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_material.cc b/test/test_model/test_common/test_non_local_toolbox/test_material.cc
index 9aba193e4..4b20e7925 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_material.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_material.cc
@@ -1,57 +1,63 @@
/**
* @file test_material.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Wed Jan 30 2019
*
* @brief Implementation of test material for the non-local neighborhood base
* test
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_material.hh"
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
TestMaterial<dim>::TestMaterial(SolidMechanicsModel & model, const ID & id)
: Parent(model, id), grad_u_nl("grad_u non local", *this) {
this->is_non_local = true;
this->grad_u_nl.initialize(dim * dim);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void TestMaterial<dim>::registerNonLocalVariables() {
+template <Int dim> void TestMaterial<dim>::registerNonLocalVariables() {
this->model.getNonLocalManager().registerNonLocalVariable(
this->gradu.getName(), grad_u_nl.getName(), dim * dim);
this->model.getNonLocalManager()
.getNeighborhood(this->getNeighborhoodName())
.registerNonLocalVariable(grad_u_nl.getName());
}
/* -------------------------------------------------------------------------- */
// Instantiate the material for the 3 dimensions
-INSTANTIATE_MATERIAL(test_material, TestMaterial);
+template class TestMaterial<1>;
+template class TestMaterial<2>;
+template class TestMaterial<3>;
+
+static bool material_is_allocated_test_material =
+ instantiateMaterial<TestMaterial>("test_material");
+
/* -------------------------------------------------------------------------- */
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_material.hh b/test/test_model/test_common/test_non_local_toolbox/test_material.hh
index 9d76af8c0..375d44879 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_material.hh
+++ b/test/test_model/test_common/test_non_local_toolbox/test_material.hh
@@ -1,73 +1,73 @@
/**
* @file test_material.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Jan 30 2019
*
* @brief test material for the non-local neighborhood base test
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage.hh"
#include "material_damage_non_local.hh"
#ifndef TEST_MATERIAL_HH_
#define TEST_MATERIAL_HH_
using namespace akantu;
-template <UInt dim>
+template <Int dim>
class TestMaterial
: public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> {
/* ------------------------------------------------------------------------ */
/* Constructor/Destructor */
/* ------------------------------------------------------------------------ */
public:
using Parent =
MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>;
TestMaterial(SolidMechanicsModel & model, const ID & id);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void registerNonLocalVariables() override final;
void computeNonLocalStress(ElementType, GhostType) override final{};
void computeNonLocalStresses(GhostType) override final{};
protected:
ID getNeighborhoodName() override { return "test_region"; }
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
private:
InternalField<Real> grad_u_nl;
};
#endif /* TEST_MATERIAL_HH_ */
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_material_damage.cc b/test/test_model/test_common/test_non_local_toolbox/test_material_damage.cc
index 611e420d4..605b4a6ca 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_material_damage.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_material_damage.cc
@@ -1,59 +1,65 @@
/**
* @file test_material_damage.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Wed Jan 30 2019
*
* @brief Implementation of test material damage
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_material_damage.hh"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
TestMaterialDamage<dim>::TestMaterialDamage(SolidMechanicsModel & model,
const ID & id)
: Parent(model, id), grad_u_nl("grad_u non local", *this) {
this->is_non_local = true;
this->grad_u_nl.initialize(dim * dim);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void TestMaterialDamage<dim>::registerNonLocalVariables() {
+template <Int dim> void TestMaterialDamage<dim>::registerNonLocalVariables() {
this->model.getNonLocalManager().registerNonLocalVariable(
this->gradu.getName(), grad_u_nl.getName(), dim * dim);
this->model.getNonLocalManager()
.getNeighborhood(this->getNeighborhoodName())
.registerNonLocalVariable(grad_u_nl.getName());
}
/* -------------------------------------------------------------------------- */
// Instantiate the material for the 3 dimensions
-INSTANTIATE_MATERIAL(test_material, TestMaterialDamage);
+template class TestMaterialDamage<1>;
+template class TestMaterialDamage<2>;
+template class TestMaterialDamage<3>;
+
+static bool material_is_allocated_test_material =
+ instantiateMaterial<TestMaterialDamage>("test_material");
+
/* -------------------------------------------------------------------------- */
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_material_damage.hh b/test/test_model/test_common/test_non_local_toolbox/test_material_damage.hh
index b08564b0a..fd7a4a037 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_material_damage.hh
+++ b/test/test_model/test_common/test_non_local_toolbox/test_material_damage.hh
@@ -1,75 +1,75 @@
/**
* @file test_material_damage.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Jan 30 2019
*
* @brief test material damage for the non-local remove damage test
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_damage.hh"
#include "material_damage_non_local.hh"
/* -------------------------------------------------------------------------- */
#ifndef TEST_MATERIAL_DAMAGE_HH_
#define TEST_MATERIAL_DAMAGE_HH_
using namespace akantu;
-template <UInt dim>
+template <Int dim>
class TestMaterialDamage
: public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> {
using Parent =
MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>;
/* ------------------------------------------------------------------------ */
/* Constructor/Destructor */
/* ------------------------------------------------------------------------ */
public:
TestMaterialDamage(SolidMechanicsModel & model, const ID & id);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void registerNonLocalVariables() override final;
void computeNonLocalStress(ElementType, GhostType) override final{};
void insertQuadsInNeighborhoods(GhostType ghost_type);
protected:
// ID getNeighborhoodName() override { return "test_region"; }
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
private:
InternalField<Real> grad_u_nl;
};
#endif /* TEST_MATERIAL_DAMAGE_HH_ */
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_non_local_averaging.cc b/test/test_model/test_common/test_non_local_toolbox/test_non_local_averaging.cc
index 323134218..f37b64e5b 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_non_local_averaging.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_non_local_averaging.cc
@@ -1,112 +1,114 @@
/**
* @file test_non_local_averaging.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Sun Jun 16 2019
*
* @brief test for non-local averaging of strain
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "dumper_paraview.hh"
-#include "non_local_manager.hh"
-#include "non_local_neighborhood.hh"
+//#include "dumper_paraview.hh"
+//#include "non_local_manager.hh"
+//#include "non_local_neighborhood.hh"
#include "solid_mechanics_model.hh"
-#include "test_material.hh"
+//#include "test_material.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material_avg.dat", argc, argv);
// some configuration variables
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
ElementType element_type = _quadrangle_4;
GhostType ghost_type = _not_ghost;
// mesh creation and read
Mesh mesh(spatial_dimension);
mesh.read("plate.msh");
/// model creation
SolidMechanicsModel model(mesh);
/// creation of material selector
auto && mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
/// model initialization changed to use our material
model.initFull();
/// dump material index in paraview
model.addDumpField("material_index");
model.addDumpField("grad_u");
model.addDumpField("grad_u non local");
model.dump();
/// apply constant strain field everywhere in the plate
Matrix<Real> applied_strain(spatial_dimension, spatial_dimension);
applied_strain.zero();
- for (UInt i = 0; i < spatial_dimension; ++i)
+
+ for (Int i = 0; i < spatial_dimension; ++i) {
applied_strain(i, i) = 2.;
+ }
/// apply constant grad_u field in all elements
for (auto & mat : model.getMaterials()) {
auto & grad_us =
mat.getInternal<Real>("eigen_grad_u")(element_type, ghost_type);
for (auto & grad_u :
make_view(grad_us, spatial_dimension, spatial_dimension)) {
grad_u = -1. * applied_strain;
}
}
/// compute the non-local strains
model.assembleInternalForces();
model.dump();
/// verify the result: non-local averaging over constant field must
/// yield same constant field
Real test_result = 0.;
- Matrix<Real> difference(spatial_dimension, spatial_dimension, 0.);
+ Matrix<Real> difference(spatial_dimension, spatial_dimension);
for (auto & mat : model.getMaterials()) {
auto & grad_us_nl =
mat.getInternal<Real>("grad_u non local")(element_type, ghost_type);
for (auto & grad_u_nl :
make_view(grad_us_nl, spatial_dimension, spatial_dimension)) {
difference = grad_u_nl - applied_strain;
- test_result += difference.norm<L_2>();
+ test_result += difference.norm();
}
}
if (test_result > 10.e-13) {
AKANTU_EXCEPTION("the total norm is: " << test_result);
}
return 0;
}
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.cc b/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.cc
index 80c52dc20..a98e75671 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.cc
@@ -1,82 +1,84 @@
/**
* @file test_non_local_neighborhood_base.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Wed Jan 30 2019
*
* @brief test for the class NonLocalNeighborhoodBase
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "my_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material.dat", argc, argv);
// some configuration variables
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
// mesh creation and read
Mesh mesh(spatial_dimension);
mesh.read("plate.msh");
/// model creation
MyModel model(mesh, spatial_dimension);
const auto & manager = model.getNonLocalManager();
const auto & neighborhood = manager.getNeighborhood("test_region");
/// save the pair of quadrature points and the coords of all neighbors
std::string output_1 = "quadrature_pairs";
std::string output_2 = "neighborhoods";
neighborhood.savePairs(output_1);
neighborhood.saveNeighborCoords(output_2);
/// print results to screen for validation
std::ifstream quad_pairs;
quad_pairs.open("quadrature_pairs.0");
std::string current_line;
- while (getline(quad_pairs, current_line))
+ while (getline(quad_pairs, current_line)) {
std::cout << current_line << std::endl;
+ }
quad_pairs.close();
std::ifstream neighborhoods;
neighborhoods.open("neighborhoods.0");
- while (getline(neighborhoods, current_line))
+ while (getline(neighborhoods, current_line)) {
std::cout << current_line << std::endl;
+ }
neighborhoods.close();
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.verified b/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.verified
index 202338309..5d155b848 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.verified
+++ b/test/test_model/test_common/test_non_local_toolbox/test_non_local_neighborhood_base.verified
@@ -1,1110 +1,1110 @@
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 0(0)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 0(0)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 0(0)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 0(0)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 0(0)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 0(0)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 0(0)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 14(14)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 14(14)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 14(14)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 14(14)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 14(14)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 14(14)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 2(2)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 1(1)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 17(17)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 16(16)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 4(4)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 3(3)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 6(6)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 5(5)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 8(8)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 7(7)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 18(18)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 19(19)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 20(20)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 21(21)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 23(23)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 22(22)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 10(10)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 9(9)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 12(12)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 11(11)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 14(14)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 13(13)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 24(24)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 25(25)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 26(26)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 27(27)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 29(29)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 28(28)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 15(15)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 30(30)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 31(31)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 32(32)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 49(49)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 33(33)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 49(49)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 34(34)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 48(48)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 35(35)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 36(36)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 37(37)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 38(38)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 39(39)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 40(40)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 41(41)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 42(42)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 43(43)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 44(44)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 45(45)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 63(63)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 46(46)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 47(47)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 63(63)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 63(63)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 49(49)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 49(49)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 49(49)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 50(50)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 49(49)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 49(49)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 52(52)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 51(51)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 54(54)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 53(53)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 56(56)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 55(55)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 58(58)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 57(57)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 60(60)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 59(59)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 63(63)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 62(62)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 61(61)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 63(63)]
-IntegrationPoint [Element [_quadrangle_4, 0, 0], 63(63)] IntegrationPoint [Element [_quadrangle_4, 0, 0], 63(63)]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 0: 0] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 0: 0]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 0: 0] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 0: 0] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 0: 0] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 0: 0] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 0: 0] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 14: 14]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 14: 14]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 14: 14] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 14: 14]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 14: 14] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 14: 14] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 2: 2]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 1: 1] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 17: 17] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 16: 16]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 4: 4]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 3: 3] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 6: 6]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 5: 5] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 8: 8]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 7: 7] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 18: 18] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 19: 19] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 20: 20] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 21: 21] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 23: 23] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 22: 22]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 10: 10]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 9: 9] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 12: 12]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 11: 11] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 14: 14]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 13: 13] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 24: 24] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 25: 25] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 26: 26] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 27: 27] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 29: 29] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 28: 28]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 15: 15] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 30: 30] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 31: 31] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 32: 32] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 49: 49]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 33: 33] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 49: 49]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 34: 34] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 48: 48]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 35: 35] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 36: 36] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 37: 37] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 38: 38] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 39: 39] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 40: 40] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 41: 41] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 42: 42] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 43: 43] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 44: 44] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 45: 45] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 63: 63]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 46: 46] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 47: 47] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 63: 63]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 63: 63]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 49: 49] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 49: 49]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 49: 49] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 50: 50]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 49: 49] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 49: 49] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 52: 52]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 51: 51] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 54: 54]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 53: 53] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 56: 56]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 55: 55] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 58: 58]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 57: 57] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 60: 60]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 59: 59] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 63: 63]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 62: 62]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 61: 61] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 63: 63]
+IntegrationPoint[ Element [_quadrangle_4, -1, 0], 63: 63] IntegrationPoint[ Element [_quadrangle_4, -1, 0], 63: 63]
#neighbors for quad 0
-[-0.894338, -0.894338]
-[-0.605662, -0.894338]
-[-0.394338, -0.894338]
-[-0.894338, -0.605662]
-[-0.894338, -0.394338]
-[-0.605662, -0.605662]
+[[-0.894338], [-0.894338]]
+[[-0.605662], [-0.894338]]
+[[-0.394338], [-0.894338]]
+[[-0.894338], [-0.605662]]
+[[-0.894338], [-0.394338]]
+[[-0.605662], [-0.605662]]
#neighbors for quad 2
-[-0.894338, -0.605662]
-[-0.894338, -0.894338]
-[-0.894338, -0.394338]
-[-0.894338, -0.105662]
-[-0.605662, -0.605662]
-[-0.605662, -0.394338]
-[-0.394338, -0.605662]
-[-0.605662, -0.894338]
+[[-0.894338], [-0.605662]]
+[[-0.894338], [-0.894338]]
+[[-0.894338], [-0.394338]]
+[[-0.894338], [-0.105662]]
+[[-0.605662], [-0.605662]]
+[[-0.605662], [-0.394338]]
+[[-0.394338], [-0.605662]]
+[[-0.605662], [-0.894338]]
#neighbors for quad 4
-[-0.894338, -0.394338]
-[-0.894338, -0.894338]
-[-0.894338, -0.605662]
-[-0.894338, -0.105662]
-[-0.605662, -0.394338]
-[-0.605662, -0.105662]
-[-0.394338, -0.394338]
-[-0.894338, 0.105662]
-[-0.605662, -0.605662]
+[[-0.894338], [-0.394338]]
+[[-0.894338], [-0.894338]]
+[[-0.894338], [-0.605662]]
+[[-0.894338], [-0.105662]]
+[[-0.605662], [-0.394338]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.394338]]
+[[-0.894338], [0.105662]]
+[[-0.605662], [-0.605662]]
#neighbors for quad 6
-[-0.894338, -0.105662]
-[-0.894338, -0.605662]
-[-0.894338, -0.394338]
-[-0.605662, -0.105662]
-[-0.394338, -0.105662]
-[-0.894338, 0.105662]
-[-0.894338, 0.394338]
-[-0.605662, 0.105662]
-[-0.605662, -0.394338]
+[[-0.894338], [-0.105662]]
+[[-0.894338], [-0.605662]]
+[[-0.894338], [-0.394338]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.105662]]
+[[-0.894338], [0.105662]]
+[[-0.894338], [0.394338]]
+[[-0.605662], [0.105662]]
+[[-0.605662], [-0.394338]]
#neighbors for quad 8
-[-0.894338, 0.105662]
-[-0.894338, -0.394338]
-[-0.894338, -0.105662]
-[-0.894338, 0.394338]
-[-0.894338, 0.605662]
-[-0.605662, 0.105662]
-[-0.605662, 0.394338]
-[-0.394338, 0.105662]
-[-0.605662, -0.105662]
+[[-0.894338], [0.105662]]
+[[-0.894338], [-0.394338]]
+[[-0.894338], [-0.105662]]
+[[-0.894338], [0.394338]]
+[[-0.894338], [0.605662]]
+[[-0.605662], [0.105662]]
+[[-0.605662], [0.394338]]
+[[-0.394338], [0.105662]]
+[[-0.605662], [-0.105662]]
#neighbors for quad 10
-[-0.894338, 0.394338]
-[-0.894338, -0.105662]
-[-0.894338, 0.105662]
-[-0.894338, 0.605662]
-[-0.605662, 0.394338]
-[-0.605662, 0.605662]
-[-0.394338, 0.394338]
-[-0.894338, 0.894338]
-[-0.605662, 0.105662]
+[[-0.894338], [0.394338]]
+[[-0.894338], [-0.105662]]
+[[-0.894338], [0.105662]]
+[[-0.894338], [0.605662]]
+[[-0.605662], [0.394338]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.394338]]
+[[-0.894338], [0.894338]]
+[[-0.605662], [0.105662]]
#neighbors for quad 12
-[-0.894338, 0.605662]
-[-0.894338, 0.105662]
-[-0.894338, 0.394338]
-[-0.605662, 0.605662]
-[-0.394338, 0.605662]
-[-0.894338, 0.894338]
-[-0.605662, 0.894338]
-[-0.605662, 0.394338]
+[[-0.894338], [0.605662]]
+[[-0.894338], [0.105662]]
+[[-0.894338], [0.394338]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.605662]]
+[[-0.894338], [0.894338]]
+[[-0.605662], [0.894338]]
+[[-0.605662], [0.394338]]
#neighbors for quad 14
-[-0.894338, 0.894338]
-[-0.894338, 0.394338]
-[-0.894338, 0.605662]
-[-0.605662, 0.894338]
-[-0.394338, 0.894338]
-[-0.605662, 0.605662]
+[[-0.894338], [0.894338]]
+[[-0.894338], [0.394338]]
+[[-0.894338], [0.605662]]
+[[-0.605662], [0.894338]]
+[[-0.394338], [0.894338]]
+[[-0.605662], [0.605662]]
#neighbors for quad 1
-[-0.605662, -0.894338]
-[-0.894338, -0.894338]
-[-0.394338, -0.894338]
-[-0.105662, -0.894338]
-[-0.894338, -0.605662]
-[-0.605662, -0.605662]
-[-0.605662, -0.394338]
-[-0.394338, -0.605662]
+[[-0.605662], [-0.894338]]
+[[-0.894338], [-0.894338]]
+[[-0.394338], [-0.894338]]
+[[-0.105662], [-0.894338]]
+[[-0.894338], [-0.605662]]
+[[-0.605662], [-0.605662]]
+[[-0.605662], [-0.394338]]
+[[-0.394338], [-0.605662]]
#neighbors for quad 16
-[-0.394338, -0.894338]
-[-0.894338, -0.894338]
-[-0.605662, -0.894338]
-[-0.105662, -0.894338]
-[0.105662, -0.894338]
-[-0.394338, -0.605662]
-[-0.105662, -0.605662]
-[-0.394338, -0.394338]
-[-0.605662, -0.605662]
+[[-0.394338], [-0.894338]]
+[[-0.894338], [-0.894338]]
+[[-0.605662], [-0.894338]]
+[[-0.105662], [-0.894338]]
+[[0.105662], [-0.894338]]
+[[-0.394338], [-0.605662]]
+[[-0.105662], [-0.605662]]
+[[-0.394338], [-0.394338]]
+[[-0.605662], [-0.605662]]
#neighbors for quad 17
-[-0.105662, -0.894338]
-[-0.605662, -0.894338]
-[-0.394338, -0.894338]
-[0.105662, -0.894338]
-[0.394338, -0.894338]
-[-0.394338, -0.605662]
-[-0.105662, -0.605662]
-[-0.105662, -0.394338]
-[0.105662, -0.605662]
+[[-0.105662], [-0.894338]]
+[[-0.605662], [-0.894338]]
+[[-0.394338], [-0.894338]]
+[[0.105662], [-0.894338]]
+[[0.394338], [-0.894338]]
+[[-0.394338], [-0.605662]]
+[[-0.105662], [-0.605662]]
+[[-0.105662], [-0.394338]]
+[[0.105662], [-0.605662]]
#neighbors for quad 3
-[-0.605662, -0.605662]
-[-0.894338, -0.894338]
-[-0.894338, -0.605662]
-[-0.605662, -0.894338]
-[-0.394338, -0.894338]
-[-0.894338, -0.394338]
-[-0.605662, -0.394338]
-[-0.605662, -0.105662]
-[-0.394338, -0.605662]
-[-0.105662, -0.605662]
-[-0.394338, -0.394338]
+[[-0.605662], [-0.605662]]
+[[-0.894338], [-0.894338]]
+[[-0.894338], [-0.605662]]
+[[-0.605662], [-0.894338]]
+[[-0.394338], [-0.894338]]
+[[-0.894338], [-0.394338]]
+[[-0.605662], [-0.394338]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.605662]]
+[[-0.105662], [-0.605662]]
+[[-0.394338], [-0.394338]]
#neighbors for quad 5
-[-0.605662, -0.394338]
-[-0.894338, -0.605662]
-[-0.894338, -0.394338]
-[-0.605662, -0.894338]
-[-0.605662, -0.605662]
-[-0.894338, -0.105662]
-[-0.605662, -0.105662]
-[-0.394338, -0.605662]
-[-0.394338, -0.394338]
-[-0.105662, -0.394338]
-[-0.394338, -0.105662]
-[-0.605662, 0.105662]
+[[-0.605662], [-0.394338]]
+[[-0.894338], [-0.605662]]
+[[-0.894338], [-0.394338]]
+[[-0.605662], [-0.894338]]
+[[-0.605662], [-0.605662]]
+[[-0.894338], [-0.105662]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.605662]]
+[[-0.394338], [-0.394338]]
+[[-0.105662], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.605662], [0.105662]]
#neighbors for quad 7
-[-0.605662, -0.105662]
-[-0.894338, -0.394338]
-[-0.894338, -0.105662]
-[-0.605662, -0.605662]
-[-0.605662, -0.394338]
-[-0.394338, -0.394338]
-[-0.394338, -0.105662]
-[-0.105662, -0.105662]
-[-0.894338, 0.105662]
-[-0.605662, 0.105662]
-[-0.605662, 0.394338]
-[-0.394338, 0.105662]
+[[-0.605662], [-0.105662]]
+[[-0.894338], [-0.394338]]
+[[-0.894338], [-0.105662]]
+[[-0.605662], [-0.605662]]
+[[-0.605662], [-0.394338]]
+[[-0.394338], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.105662], [-0.105662]]
+[[-0.894338], [0.105662]]
+[[-0.605662], [0.105662]]
+[[-0.605662], [0.394338]]
+[[-0.394338], [0.105662]]
#neighbors for quad 18
-[-0.394338, -0.605662]
-[-0.894338, -0.605662]
-[-0.605662, -0.894338]
-[-0.394338, -0.894338]
-[-0.105662, -0.894338]
-[-0.605662, -0.605662]
-[-0.605662, -0.394338]
-[-0.105662, -0.605662]
-[-0.394338, -0.394338]
-[-0.105662, -0.394338]
-[-0.394338, -0.105662]
-[0.105662, -0.605662]
+[[-0.394338], [-0.605662]]
+[[-0.894338], [-0.605662]]
+[[-0.605662], [-0.894338]]
+[[-0.394338], [-0.894338]]
+[[-0.105662], [-0.894338]]
+[[-0.605662], [-0.605662]]
+[[-0.605662], [-0.394338]]
+[[-0.105662], [-0.605662]]
+[[-0.394338], [-0.394338]]
+[[-0.105662], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[0.105662], [-0.605662]]
#neighbors for quad 19
-[-0.105662, -0.605662]
-[-0.394338, -0.894338]
-[-0.105662, -0.894338]
-[-0.605662, -0.605662]
-[-0.394338, -0.605662]
-[0.105662, -0.894338]
-[-0.394338, -0.394338]
-[-0.105662, -0.394338]
-[-0.105662, -0.105662]
-[0.105662, -0.605662]
-[0.394338, -0.605662]
-[0.105662, -0.394338]
+[[-0.105662], [-0.605662]]
+[[-0.394338], [-0.894338]]
+[[-0.105662], [-0.894338]]
+[[-0.605662], [-0.605662]]
+[[-0.394338], [-0.605662]]
+[[0.105662], [-0.894338]]
+[[-0.394338], [-0.394338]]
+[[-0.105662], [-0.394338]]
+[[-0.105662], [-0.105662]]
+[[0.105662], [-0.605662]]
+[[0.394338], [-0.605662]]
+[[0.105662], [-0.394338]]
#neighbors for quad 20
-[-0.394338, -0.394338]
-[-0.894338, -0.394338]
-[-0.394338, -0.894338]
-[-0.605662, -0.605662]
-[-0.605662, -0.394338]
-[-0.605662, -0.105662]
-[-0.394338, -0.605662]
-[-0.105662, -0.605662]
-[-0.105662, -0.394338]
-[-0.394338, -0.105662]
-[-0.105662, -0.105662]
-[0.105662, -0.394338]
-[-0.394338, 0.105662]
+[[-0.394338], [-0.394338]]
+[[-0.894338], [-0.394338]]
+[[-0.394338], [-0.894338]]
+[[-0.605662], [-0.605662]]
+[[-0.605662], [-0.394338]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.605662]]
+[[-0.105662], [-0.605662]]
+[[-0.105662], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.105662], [-0.105662]]
+[[0.105662], [-0.394338]]
+[[-0.394338], [0.105662]]
#neighbors for quad 21
-[-0.105662, -0.394338]
-[-0.105662, -0.894338]
-[-0.605662, -0.394338]
-[-0.394338, -0.605662]
-[-0.105662, -0.605662]
-[-0.394338, -0.394338]
-[-0.394338, -0.105662]
-[-0.105662, -0.105662]
-[0.105662, -0.605662]
-[0.105662, -0.394338]
-[0.394338, -0.394338]
-[0.105662, -0.105662]
-[-0.105662, 0.105662]
+[[-0.105662], [-0.394338]]
+[[-0.105662], [-0.894338]]
+[[-0.605662], [-0.394338]]
+[[-0.394338], [-0.605662]]
+[[-0.105662], [-0.605662]]
+[[-0.394338], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.105662], [-0.105662]]
+[[0.105662], [-0.605662]]
+[[0.105662], [-0.394338]]
+[[0.394338], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[-0.105662], [0.105662]]
#neighbors for quad 22
-[-0.394338, -0.105662]
-[-0.894338, -0.105662]
-[-0.605662, -0.394338]
-[-0.605662, -0.105662]
-[-0.394338, -0.605662]
-[-0.394338, -0.394338]
-[-0.105662, -0.394338]
-[-0.105662, -0.105662]
-[0.105662, -0.105662]
-[-0.394338, 0.105662]
-[-0.105662, 0.105662]
-[-0.394338, 0.394338]
-[-0.605662, 0.105662]
+[[-0.394338], [-0.105662]]
+[[-0.894338], [-0.105662]]
+[[-0.605662], [-0.394338]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.605662]]
+[[-0.394338], [-0.394338]]
+[[-0.105662], [-0.394338]]
+[[-0.105662], [-0.105662]]
+[[0.105662], [-0.105662]]
+[[-0.394338], [0.105662]]
+[[-0.105662], [0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.605662], [0.105662]]
#neighbors for quad 23
-[-0.105662, -0.105662]
-[-0.605662, -0.105662]
-[-0.105662, -0.605662]
-[-0.394338, -0.394338]
-[-0.105662, -0.394338]
-[-0.394338, -0.105662]
-[0.105662, -0.394338]
-[0.105662, -0.105662]
-[0.394338, -0.105662]
-[-0.394338, 0.105662]
-[-0.105662, 0.105662]
-[-0.105662, 0.394338]
-[0.105662, 0.105662]
+[[-0.105662], [-0.105662]]
+[[-0.605662], [-0.105662]]
+[[-0.105662], [-0.605662]]
+[[-0.394338], [-0.394338]]
+[[-0.105662], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[0.105662], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.394338], [-0.105662]]
+[[-0.394338], [0.105662]]
+[[-0.105662], [0.105662]]
+[[-0.105662], [0.394338]]
+[[0.105662], [0.105662]]
#neighbors for quad 9
-[-0.605662, 0.105662]
-[-0.894338, -0.105662]
-[-0.894338, 0.105662]
-[-0.605662, -0.394338]
-[-0.605662, -0.105662]
-[-0.394338, -0.105662]
-[-0.894338, 0.394338]
-[-0.605662, 0.394338]
-[-0.605662, 0.605662]
-[-0.394338, 0.105662]
-[-0.105662, 0.105662]
-[-0.394338, 0.394338]
+[[-0.605662], [0.105662]]
+[[-0.894338], [-0.105662]]
+[[-0.894338], [0.105662]]
+[[-0.605662], [-0.394338]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.105662]]
+[[-0.894338], [0.394338]]
+[[-0.605662], [0.394338]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.105662]]
+[[-0.105662], [0.105662]]
+[[-0.394338], [0.394338]]
#neighbors for quad 11
-[-0.605662, 0.394338]
-[-0.894338, 0.105662]
-[-0.894338, 0.394338]
-[-0.605662, -0.105662]
-[-0.605662, 0.105662]
-[-0.894338, 0.605662]
-[-0.605662, 0.605662]
-[-0.394338, 0.105662]
-[-0.394338, 0.394338]
-[-0.105662, 0.394338]
-[-0.394338, 0.605662]
-[-0.605662, 0.894338]
+[[-0.605662], [0.394338]]
+[[-0.894338], [0.105662]]
+[[-0.894338], [0.394338]]
+[[-0.605662], [-0.105662]]
+[[-0.605662], [0.105662]]
+[[-0.894338], [0.605662]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.105662], [0.394338]]
+[[-0.394338], [0.605662]]
+[[-0.605662], [0.894338]]
#neighbors for quad 13
-[-0.605662, 0.605662]
-[-0.894338, 0.394338]
-[-0.894338, 0.605662]
-[-0.605662, 0.105662]
-[-0.605662, 0.394338]
-[-0.394338, 0.394338]
-[-0.394338, 0.605662]
-[-0.105662, 0.605662]
-[-0.894338, 0.894338]
-[-0.605662, 0.894338]
-[-0.394338, 0.894338]
+[[-0.605662], [0.605662]]
+[[-0.894338], [0.394338]]
+[[-0.894338], [0.605662]]
+[[-0.605662], [0.105662]]
+[[-0.605662], [0.394338]]
+[[-0.394338], [0.394338]]
+[[-0.394338], [0.605662]]
+[[-0.105662], [0.605662]]
+[[-0.894338], [0.894338]]
+[[-0.605662], [0.894338]]
+[[-0.394338], [0.894338]]
#neighbors for quad 24
-[-0.394338, 0.105662]
-[-0.894338, 0.105662]
-[-0.605662, -0.105662]
-[-0.394338, -0.394338]
-[-0.394338, -0.105662]
-[-0.105662, -0.105662]
-[-0.605662, 0.105662]
-[-0.605662, 0.394338]
-[-0.105662, 0.105662]
-[-0.394338, 0.394338]
-[-0.105662, 0.394338]
-[-0.394338, 0.605662]
-[0.105662, 0.105662]
+[[-0.394338], [0.105662]]
+[[-0.894338], [0.105662]]
+[[-0.605662], [-0.105662]]
+[[-0.394338], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.105662], [-0.105662]]
+[[-0.605662], [0.105662]]
+[[-0.605662], [0.394338]]
+[[-0.105662], [0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.105662], [0.394338]]
+[[-0.394338], [0.605662]]
+[[0.105662], [0.105662]]
#neighbors for quad 25
-[-0.105662, 0.105662]
-[-0.105662, -0.394338]
-[-0.394338, -0.105662]
-[-0.105662, -0.105662]
-[-0.605662, 0.105662]
-[-0.394338, 0.105662]
-[0.105662, -0.105662]
-[-0.394338, 0.394338]
-[-0.105662, 0.394338]
-[-0.105662, 0.605662]
-[0.105662, 0.105662]
-[0.394338, 0.105662]
-[0.105662, 0.394338]
+[[-0.105662], [0.105662]]
+[[-0.105662], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.105662], [-0.105662]]
+[[-0.605662], [0.105662]]
+[[-0.394338], [0.105662]]
+[[0.105662], [-0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.105662], [0.394338]]
+[[-0.105662], [0.605662]]
+[[0.105662], [0.105662]]
+[[0.394338], [0.105662]]
+[[0.105662], [0.394338]]
#neighbors for quad 26
-[-0.394338, 0.394338]
-[-0.894338, 0.394338]
-[-0.394338, -0.105662]
-[-0.605662, 0.105662]
-[-0.605662, 0.394338]
-[-0.605662, 0.605662]
-[-0.394338, 0.105662]
-[-0.105662, 0.105662]
-[-0.105662, 0.394338]
-[-0.394338, 0.605662]
-[-0.105662, 0.605662]
-[0.105662, 0.394338]
-[-0.394338, 0.894338]
+[[-0.394338], [0.394338]]
+[[-0.894338], [0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.605662], [0.105662]]
+[[-0.605662], [0.394338]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.105662]]
+[[-0.105662], [0.105662]]
+[[-0.105662], [0.394338]]
+[[-0.394338], [0.605662]]
+[[-0.105662], [0.605662]]
+[[0.105662], [0.394338]]
+[[-0.394338], [0.894338]]
#neighbors for quad 27
-[-0.105662, 0.394338]
-[-0.105662, -0.105662]
-[-0.605662, 0.394338]
-[-0.394338, 0.105662]
-[-0.105662, 0.105662]
-[-0.394338, 0.394338]
-[-0.394338, 0.605662]
-[-0.105662, 0.605662]
-[0.105662, 0.105662]
-[0.105662, 0.394338]
-[0.394338, 0.394338]
-[0.105662, 0.605662]
-[-0.105662, 0.894338]
+[[-0.105662], [0.394338]]
+[[-0.105662], [-0.105662]]
+[[-0.605662], [0.394338]]
+[[-0.394338], [0.105662]]
+[[-0.105662], [0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.394338], [0.605662]]
+[[-0.105662], [0.605662]]
+[[0.105662], [0.105662]]
+[[0.105662], [0.394338]]
+[[0.394338], [0.394338]]
+[[0.105662], [0.605662]]
+[[-0.105662], [0.894338]]
#neighbors for quad 28
-[-0.394338, 0.605662]
-[-0.894338, 0.605662]
-[-0.605662, 0.394338]
-[-0.605662, 0.605662]
-[-0.394338, 0.105662]
-[-0.394338, 0.394338]
-[-0.105662, 0.394338]
-[-0.105662, 0.605662]
-[0.105662, 0.605662]
-[-0.394338, 0.894338]
-[-0.105662, 0.894338]
-[-0.605662, 0.894338]
+[[-0.394338], [0.605662]]
+[[-0.894338], [0.605662]]
+[[-0.605662], [0.394338]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.105662], [0.394338]]
+[[-0.105662], [0.605662]]
+[[0.105662], [0.605662]]
+[[-0.394338], [0.894338]]
+[[-0.105662], [0.894338]]
+[[-0.605662], [0.894338]]
#neighbors for quad 29
-[-0.105662, 0.605662]
-[-0.605662, 0.605662]
-[-0.105662, 0.105662]
-[-0.394338, 0.394338]
-[-0.105662, 0.394338]
-[-0.394338, 0.605662]
-[0.105662, 0.394338]
-[0.105662, 0.605662]
-[0.394338, 0.605662]
-[-0.394338, 0.894338]
-[-0.105662, 0.894338]
-[0.105662, 0.894338]
+[[-0.105662], [0.605662]]
+[[-0.605662], [0.605662]]
+[[-0.105662], [0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.105662], [0.394338]]
+[[-0.394338], [0.605662]]
+[[0.105662], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.394338], [0.605662]]
+[[-0.394338], [0.894338]]
+[[-0.105662], [0.894338]]
+[[0.105662], [0.894338]]
#neighbors for quad 15
-[-0.605662, 0.894338]
-[-0.894338, 0.605662]
-[-0.894338, 0.894338]
-[-0.605662, 0.394338]
-[-0.605662, 0.605662]
-[-0.394338, 0.605662]
-[-0.394338, 0.894338]
-[-0.105662, 0.894338]
+[[-0.605662], [0.894338]]
+[[-0.894338], [0.605662]]
+[[-0.894338], [0.894338]]
+[[-0.605662], [0.394338]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.605662]]
+[[-0.394338], [0.894338]]
+[[-0.105662], [0.894338]]
#neighbors for quad 30
-[-0.394338, 0.894338]
-[-0.894338, 0.894338]
-[-0.605662, 0.605662]
-[-0.394338, 0.394338]
-[-0.394338, 0.605662]
-[-0.105662, 0.605662]
-[-0.605662, 0.894338]
-[-0.105662, 0.894338]
-[0.105662, 0.894338]
+[[-0.394338], [0.894338]]
+[[-0.894338], [0.894338]]
+[[-0.605662], [0.605662]]
+[[-0.394338], [0.394338]]
+[[-0.394338], [0.605662]]
+[[-0.105662], [0.605662]]
+[[-0.605662], [0.894338]]
+[[-0.105662], [0.894338]]
+[[0.105662], [0.894338]]
#neighbors for quad 31
-[-0.105662, 0.894338]
-[-0.105662, 0.394338]
-[-0.394338, 0.605662]
-[-0.105662, 0.605662]
-[-0.605662, 0.894338]
-[-0.394338, 0.894338]
-[0.105662, 0.605662]
-[0.105662, 0.894338]
-[0.394338, 0.894338]
+[[-0.105662], [0.894338]]
+[[-0.105662], [0.394338]]
+[[-0.394338], [0.605662]]
+[[-0.105662], [0.605662]]
+[[-0.605662], [0.894338]]
+[[-0.394338], [0.894338]]
+[[0.105662], [0.605662]]
+[[0.105662], [0.894338]]
+[[0.394338], [0.894338]]
#neighbors for quad 32
-[0.105662, -0.894338]
-[-0.394338, -0.894338]
-[-0.105662, -0.894338]
-[-0.105662, -0.605662]
-[0.394338, -0.894338]
-[0.605662, -0.894338]
-[0.105662, -0.605662]
-[0.394338, -0.605662]
-[0.105662, -0.394338]
+[[0.105662], [-0.894338]]
+[[-0.394338], [-0.894338]]
+[[-0.105662], [-0.894338]]
+[[-0.105662], [-0.605662]]
+[[0.394338], [-0.894338]]
+[[0.605662], [-0.894338]]
+[[0.105662], [-0.605662]]
+[[0.394338], [-0.605662]]
+[[0.105662], [-0.394338]]
#neighbors for quad 33
-[0.394338, -0.894338]
-[-0.105662, -0.894338]
-[0.105662, -0.894338]
-[0.605662, -0.894338]
-[0.894338, -0.894338]
-[0.105662, -0.605662]
-[0.394338, -0.605662]
-[0.394338, -0.394338]
-[0.605662, -0.605662]
+[[0.394338], [-0.894338]]
+[[-0.105662], [-0.894338]]
+[[0.105662], [-0.894338]]
+[[0.605662], [-0.894338]]
+[[0.894338], [-0.894338]]
+[[0.105662], [-0.605662]]
+[[0.394338], [-0.605662]]
+[[0.394338], [-0.394338]]
+[[0.605662], [-0.605662]]
#neighbors for quad 48
-[0.605662, -0.894338]
-[0.105662, -0.894338]
-[0.394338, -0.894338]
-[0.894338, -0.894338]
-[0.605662, -0.605662]
-[0.605662, -0.394338]
-[0.894338, -0.605662]
-[0.394338, -0.605662]
+[[0.605662], [-0.894338]]
+[[0.105662], [-0.894338]]
+[[0.394338], [-0.894338]]
+[[0.894338], [-0.894338]]
+[[0.605662], [-0.605662]]
+[[0.605662], [-0.394338]]
+[[0.894338], [-0.605662]]
+[[0.394338], [-0.605662]]
#neighbors for quad 34
-[0.105662, -0.605662]
-[-0.105662, -0.894338]
-[-0.394338, -0.605662]
-[-0.105662, -0.605662]
-[-0.105662, -0.394338]
-[0.105662, -0.894338]
-[0.394338, -0.894338]
-[0.394338, -0.605662]
-[0.105662, -0.394338]
-[0.394338, -0.394338]
-[0.105662, -0.105662]
-[0.605662, -0.605662]
+[[0.105662], [-0.605662]]
+[[-0.105662], [-0.894338]]
+[[-0.394338], [-0.605662]]
+[[-0.105662], [-0.605662]]
+[[-0.105662], [-0.394338]]
+[[0.105662], [-0.894338]]
+[[0.394338], [-0.894338]]
+[[0.394338], [-0.605662]]
+[[0.105662], [-0.394338]]
+[[0.394338], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.605662], [-0.605662]]
#neighbors for quad 35
-[0.394338, -0.605662]
-[-0.105662, -0.605662]
-[0.105662, -0.894338]
-[0.394338, -0.894338]
-[0.105662, -0.605662]
-[0.605662, -0.894338]
-[0.105662, -0.394338]
-[0.394338, -0.394338]
-[0.394338, -0.105662]
-[0.605662, -0.605662]
-[0.605662, -0.394338]
-[0.894338, -0.605662]
+[[0.394338], [-0.605662]]
+[[-0.105662], [-0.605662]]
+[[0.105662], [-0.894338]]
+[[0.394338], [-0.894338]]
+[[0.105662], [-0.605662]]
+[[0.605662], [-0.894338]]
+[[0.105662], [-0.394338]]
+[[0.394338], [-0.394338]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.605662]]
+[[0.605662], [-0.394338]]
+[[0.894338], [-0.605662]]
#neighbors for quad 36
-[0.105662, -0.394338]
-[-0.105662, -0.605662]
-[-0.394338, -0.394338]
-[-0.105662, -0.394338]
-[-0.105662, -0.105662]
-[0.105662, -0.894338]
-[0.105662, -0.605662]
-[0.394338, -0.605662]
-[0.394338, -0.394338]
-[0.105662, -0.105662]
-[0.394338, -0.105662]
-[0.605662, -0.394338]
-[0.105662, 0.105662]
+[[0.105662], [-0.394338]]
+[[-0.105662], [-0.605662]]
+[[-0.394338], [-0.394338]]
+[[-0.105662], [-0.394338]]
+[[-0.105662], [-0.105662]]
+[[0.105662], [-0.894338]]
+[[0.105662], [-0.605662]]
+[[0.394338], [-0.605662]]
+[[0.394338], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.394338]]
+[[0.105662], [0.105662]]
#neighbors for quad 37
-[0.394338, -0.394338]
-[-0.105662, -0.394338]
-[0.394338, -0.894338]
-[0.105662, -0.605662]
-[0.394338, -0.605662]
-[0.105662, -0.394338]
-[0.105662, -0.105662]
-[0.394338, -0.105662]
-[0.605662, -0.605662]
-[0.605662, -0.394338]
-[0.605662, -0.105662]
-[0.894338, -0.394338]
-[0.394338, 0.105662]
+[[0.394338], [-0.394338]]
+[[-0.105662], [-0.394338]]
+[[0.394338], [-0.894338]]
+[[0.105662], [-0.605662]]
+[[0.394338], [-0.605662]]
+[[0.105662], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.605662]]
+[[0.605662], [-0.394338]]
+[[0.605662], [-0.105662]]
+[[0.894338], [-0.394338]]
+[[0.394338], [0.105662]]
#neighbors for quad 38
-[0.105662, -0.105662]
-[-0.105662, -0.394338]
-[-0.394338, -0.105662]
-[-0.105662, -0.105662]
-[-0.105662, 0.105662]
-[0.105662, -0.605662]
-[0.105662, -0.394338]
-[0.394338, -0.394338]
-[0.394338, -0.105662]
-[0.605662, -0.105662]
-[0.105662, 0.105662]
-[0.394338, 0.105662]
-[0.105662, 0.394338]
+[[0.105662], [-0.105662]]
+[[-0.105662], [-0.394338]]
+[[-0.394338], [-0.105662]]
+[[-0.105662], [-0.105662]]
+[[-0.105662], [0.105662]]
+[[0.105662], [-0.605662]]
+[[0.105662], [-0.394338]]
+[[0.394338], [-0.394338]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.105662]]
+[[0.105662], [0.105662]]
+[[0.394338], [0.105662]]
+[[0.105662], [0.394338]]
#neighbors for quad 39
-[0.394338, -0.105662]
-[-0.105662, -0.105662]
-[0.394338, -0.605662]
-[0.105662, -0.394338]
-[0.394338, -0.394338]
-[0.105662, -0.105662]
-[0.605662, -0.394338]
-[0.605662, -0.105662]
-[0.894338, -0.105662]
-[0.105662, 0.105662]
-[0.394338, 0.105662]
-[0.394338, 0.394338]
-[0.605662, 0.105662]
+[[0.394338], [-0.105662]]
+[[-0.105662], [-0.105662]]
+[[0.394338], [-0.605662]]
+[[0.105662], [-0.394338]]
+[[0.394338], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.605662], [-0.394338]]
+[[0.605662], [-0.105662]]
+[[0.894338], [-0.105662]]
+[[0.105662], [0.105662]]
+[[0.394338], [0.105662]]
+[[0.394338], [0.394338]]
+[[0.605662], [0.105662]]
#neighbors for quad 50
-[0.605662, -0.605662]
-[0.394338, -0.894338]
-[0.605662, -0.894338]
-[0.105662, -0.605662]
-[0.394338, -0.605662]
-[0.394338, -0.394338]
-[0.605662, -0.394338]
-[0.605662, -0.105662]
-[0.894338, -0.605662]
-[0.894338, -0.394338]
-[0.894338, -0.894338]
+[[0.605662], [-0.605662]]
+[[0.394338], [-0.894338]]
+[[0.605662], [-0.894338]]
+[[0.105662], [-0.605662]]
+[[0.394338], [-0.605662]]
+[[0.394338], [-0.394338]]
+[[0.605662], [-0.394338]]
+[[0.605662], [-0.105662]]
+[[0.894338], [-0.605662]]
+[[0.894338], [-0.394338]]
+[[0.894338], [-0.894338]]
#neighbors for quad 52
-[0.605662, -0.394338]
-[0.605662, -0.894338]
-[0.394338, -0.605662]
-[0.105662, -0.394338]
-[0.394338, -0.394338]
-[0.394338, -0.105662]
-[0.605662, -0.605662]
-[0.605662, -0.105662]
-[0.894338, -0.394338]
-[0.894338, -0.105662]
-[0.605662, 0.105662]
-[0.894338, -0.605662]
+[[0.605662], [-0.394338]]
+[[0.605662], [-0.894338]]
+[[0.394338], [-0.605662]]
+[[0.105662], [-0.394338]]
+[[0.394338], [-0.394338]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.605662]]
+[[0.605662], [-0.105662]]
+[[0.894338], [-0.394338]]
+[[0.894338], [-0.105662]]
+[[0.605662], [0.105662]]
+[[0.894338], [-0.605662]]
#neighbors for quad 54
-[0.605662, -0.105662]
-[0.394338, -0.394338]
-[0.105662, -0.105662]
-[0.394338, -0.105662]
-[0.605662, -0.605662]
-[0.605662, -0.394338]
-[0.894338, -0.105662]
-[0.605662, 0.105662]
-[0.605662, 0.394338]
-[0.894338, 0.105662]
-[0.394338, 0.105662]
-[0.894338, -0.394338]
+[[0.605662], [-0.105662]]
+[[0.394338], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.605662]]
+[[0.605662], [-0.394338]]
+[[0.894338], [-0.105662]]
+[[0.605662], [0.105662]]
+[[0.605662], [0.394338]]
+[[0.894338], [0.105662]]
+[[0.394338], [0.105662]]
+[[0.894338], [-0.394338]]
#neighbors for quad 40
-[0.105662, 0.105662]
-[-0.105662, -0.105662]
-[-0.394338, 0.105662]
-[-0.105662, 0.105662]
-[-0.105662, 0.394338]
-[0.105662, -0.394338]
-[0.105662, -0.105662]
-[0.394338, -0.105662]
-[0.394338, 0.105662]
-[0.105662, 0.394338]
-[0.394338, 0.394338]
-[0.105662, 0.605662]
-[0.605662, 0.105662]
+[[0.105662], [0.105662]]
+[[-0.105662], [-0.105662]]
+[[-0.394338], [0.105662]]
+[[-0.105662], [0.105662]]
+[[-0.105662], [0.394338]]
+[[0.105662], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.394338], [-0.105662]]
+[[0.394338], [0.105662]]
+[[0.105662], [0.394338]]
+[[0.394338], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.605662], [0.105662]]
#neighbors for quad 41
-[0.394338, 0.105662]
-[-0.105662, 0.105662]
-[0.394338, -0.394338]
-[0.105662, -0.105662]
-[0.394338, -0.105662]
-[0.105662, 0.105662]
-[0.605662, -0.105662]
-[0.105662, 0.394338]
-[0.394338, 0.394338]
-[0.394338, 0.605662]
-[0.605662, 0.105662]
-[0.605662, 0.394338]
-[0.894338, 0.105662]
+[[0.394338], [0.105662]]
+[[-0.105662], [0.105662]]
+[[0.394338], [-0.394338]]
+[[0.105662], [-0.105662]]
+[[0.394338], [-0.105662]]
+[[0.105662], [0.105662]]
+[[0.605662], [-0.105662]]
+[[0.105662], [0.394338]]
+[[0.394338], [0.394338]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.105662]]
+[[0.605662], [0.394338]]
+[[0.894338], [0.105662]]
#neighbors for quad 42
-[0.105662, 0.394338]
-[-0.105662, 0.105662]
-[-0.394338, 0.394338]
-[-0.105662, 0.394338]
-[-0.105662, 0.605662]
-[0.105662, -0.105662]
-[0.105662, 0.105662]
-[0.394338, 0.105662]
-[0.394338, 0.394338]
-[0.105662, 0.605662]
-[0.394338, 0.605662]
-[0.605662, 0.394338]
-[0.105662, 0.894338]
+[[0.105662], [0.394338]]
+[[-0.105662], [0.105662]]
+[[-0.394338], [0.394338]]
+[[-0.105662], [0.394338]]
+[[-0.105662], [0.605662]]
+[[0.105662], [-0.105662]]
+[[0.105662], [0.105662]]
+[[0.394338], [0.105662]]
+[[0.394338], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.394338]]
+[[0.105662], [0.894338]]
#neighbors for quad 43
-[0.394338, 0.394338]
-[-0.105662, 0.394338]
-[0.394338, -0.105662]
-[0.105662, 0.105662]
-[0.394338, 0.105662]
-[0.105662, 0.394338]
-[0.105662, 0.605662]
-[0.394338, 0.605662]
-[0.605662, 0.105662]
-[0.605662, 0.394338]
-[0.605662, 0.605662]
-[0.894338, 0.394338]
-[0.394338, 0.894338]
+[[0.394338], [0.394338]]
+[[-0.105662], [0.394338]]
+[[0.394338], [-0.105662]]
+[[0.105662], [0.105662]]
+[[0.394338], [0.105662]]
+[[0.105662], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.105662]]
+[[0.605662], [0.394338]]
+[[0.605662], [0.605662]]
+[[0.894338], [0.394338]]
+[[0.394338], [0.894338]]
#neighbors for quad 44
-[0.105662, 0.605662]
-[-0.105662, 0.394338]
-[-0.394338, 0.605662]
-[-0.105662, 0.605662]
-[-0.105662, 0.894338]
-[0.105662, 0.105662]
-[0.105662, 0.394338]
-[0.394338, 0.394338]
-[0.394338, 0.605662]
-[0.605662, 0.605662]
-[0.105662, 0.894338]
-[0.394338, 0.894338]
+[[0.105662], [0.605662]]
+[[-0.105662], [0.394338]]
+[[-0.394338], [0.605662]]
+[[-0.105662], [0.605662]]
+[[-0.105662], [0.894338]]
+[[0.105662], [0.105662]]
+[[0.105662], [0.394338]]
+[[0.394338], [0.394338]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.605662]]
+[[0.105662], [0.894338]]
+[[0.394338], [0.894338]]
#neighbors for quad 45
-[0.394338, 0.605662]
-[-0.105662, 0.605662]
-[0.394338, 0.105662]
-[0.105662, 0.394338]
-[0.394338, 0.394338]
-[0.105662, 0.605662]
-[0.605662, 0.394338]
-[0.605662, 0.605662]
-[0.894338, 0.605662]
-[0.105662, 0.894338]
-[0.394338, 0.894338]
-[0.605662, 0.894338]
+[[0.394338], [0.605662]]
+[[-0.105662], [0.605662]]
+[[0.394338], [0.105662]]
+[[0.105662], [0.394338]]
+[[0.394338], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.605662], [0.394338]]
+[[0.605662], [0.605662]]
+[[0.894338], [0.605662]]
+[[0.105662], [0.894338]]
+[[0.394338], [0.894338]]
+[[0.605662], [0.894338]]
#neighbors for quad 56
-[0.605662, 0.105662]
-[0.394338, -0.105662]
-[0.605662, -0.394338]
-[0.605662, -0.105662]
-[0.105662, 0.105662]
-[0.394338, 0.105662]
-[0.394338, 0.394338]
-[0.605662, 0.394338]
-[0.605662, 0.605662]
-[0.894338, 0.105662]
-[0.894338, 0.394338]
-[0.894338, -0.105662]
+[[0.605662], [0.105662]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.394338]]
+[[0.605662], [-0.105662]]
+[[0.105662], [0.105662]]
+[[0.394338], [0.105662]]
+[[0.394338], [0.394338]]
+[[0.605662], [0.394338]]
+[[0.605662], [0.605662]]
+[[0.894338], [0.105662]]
+[[0.894338], [0.394338]]
+[[0.894338], [-0.105662]]
#neighbors for quad 58
-[0.605662, 0.394338]
-[0.605662, -0.105662]
-[0.394338, 0.105662]
-[0.105662, 0.394338]
-[0.394338, 0.394338]
-[0.394338, 0.605662]
-[0.605662, 0.105662]
-[0.605662, 0.605662]
-[0.894338, 0.394338]
-[0.894338, 0.605662]
-[0.605662, 0.894338]
-[0.894338, 0.105662]
+[[0.605662], [0.394338]]
+[[0.605662], [-0.105662]]
+[[0.394338], [0.105662]]
+[[0.105662], [0.394338]]
+[[0.394338], [0.394338]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.105662]]
+[[0.605662], [0.605662]]
+[[0.894338], [0.394338]]
+[[0.894338], [0.605662]]
+[[0.605662], [0.894338]]
+[[0.894338], [0.105662]]
#neighbors for quad 60
-[0.605662, 0.605662]
-[0.394338, 0.394338]
-[0.105662, 0.605662]
-[0.394338, 0.605662]
-[0.605662, 0.105662]
-[0.605662, 0.394338]
-[0.894338, 0.605662]
-[0.605662, 0.894338]
-[0.894338, 0.894338]
-[0.394338, 0.894338]
-[0.894338, 0.394338]
+[[0.605662], [0.605662]]
+[[0.394338], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.105662]]
+[[0.605662], [0.394338]]
+[[0.894338], [0.605662]]
+[[0.605662], [0.894338]]
+[[0.894338], [0.894338]]
+[[0.394338], [0.894338]]
+[[0.894338], [0.394338]]
#neighbors for quad 46
-[0.105662, 0.894338]
-[-0.105662, 0.605662]
-[-0.394338, 0.894338]
-[-0.105662, 0.894338]
-[0.105662, 0.394338]
-[0.105662, 0.605662]
-[0.394338, 0.605662]
-[0.394338, 0.894338]
-[0.605662, 0.894338]
+[[0.105662], [0.894338]]
+[[-0.105662], [0.605662]]
+[[-0.394338], [0.894338]]
+[[-0.105662], [0.894338]]
+[[0.105662], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.394338], [0.605662]]
+[[0.394338], [0.894338]]
+[[0.605662], [0.894338]]
#neighbors for quad 47
-[0.394338, 0.894338]
-[-0.105662, 0.894338]
-[0.394338, 0.394338]
-[0.105662, 0.605662]
-[0.394338, 0.605662]
-[0.105662, 0.894338]
-[0.605662, 0.605662]
-[0.605662, 0.894338]
-[0.894338, 0.894338]
+[[0.394338], [0.894338]]
+[[-0.105662], [0.894338]]
+[[0.394338], [0.394338]]
+[[0.105662], [0.605662]]
+[[0.394338], [0.605662]]
+[[0.105662], [0.894338]]
+[[0.605662], [0.605662]]
+[[0.605662], [0.894338]]
+[[0.894338], [0.894338]]
#neighbors for quad 62
-[0.605662, 0.894338]
-[0.394338, 0.605662]
-[0.605662, 0.394338]
-[0.605662, 0.605662]
-[0.105662, 0.894338]
-[0.394338, 0.894338]
-[0.894338, 0.894338]
-[0.894338, 0.605662]
+[[0.605662], [0.894338]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.394338]]
+[[0.605662], [0.605662]]
+[[0.105662], [0.894338]]
+[[0.394338], [0.894338]]
+[[0.894338], [0.894338]]
+[[0.894338], [0.605662]]
#neighbors for quad 49
-[0.894338, -0.894338]
-[0.394338, -0.894338]
-[0.605662, -0.894338]
-[0.605662, -0.605662]
-[0.894338, -0.605662]
-[0.894338, -0.394338]
+[[0.894338], [-0.894338]]
+[[0.394338], [-0.894338]]
+[[0.605662], [-0.894338]]
+[[0.605662], [-0.605662]]
+[[0.894338], [-0.605662]]
+[[0.894338], [-0.394338]]
#neighbors for quad 51
-[0.894338, -0.605662]
-[0.605662, -0.894338]
-[0.394338, -0.605662]
-[0.605662, -0.605662]
-[0.894338, -0.894338]
-[0.605662, -0.394338]
-[0.894338, -0.394338]
-[0.894338, -0.105662]
+[[0.894338], [-0.605662]]
+[[0.605662], [-0.894338]]
+[[0.394338], [-0.605662]]
+[[0.605662], [-0.605662]]
+[[0.894338], [-0.894338]]
+[[0.605662], [-0.394338]]
+[[0.894338], [-0.394338]]
+[[0.894338], [-0.105662]]
#neighbors for quad 53
-[0.894338, -0.394338]
-[0.394338, -0.394338]
-[0.605662, -0.605662]
-[0.605662, -0.394338]
-[0.894338, -0.894338]
-[0.894338, -0.605662]
-[0.605662, -0.105662]
-[0.894338, -0.105662]
-[0.894338, 0.105662]
+[[0.894338], [-0.394338]]
+[[0.394338], [-0.394338]]
+[[0.605662], [-0.605662]]
+[[0.605662], [-0.394338]]
+[[0.894338], [-0.894338]]
+[[0.894338], [-0.605662]]
+[[0.605662], [-0.105662]]
+[[0.894338], [-0.105662]]
+[[0.894338], [0.105662]]
#neighbors for quad 55
-[0.894338, -0.105662]
-[0.394338, -0.105662]
-[0.605662, -0.394338]
-[0.605662, -0.105662]
-[0.894338, -0.605662]
-[0.894338, -0.394338]
-[0.605662, 0.105662]
-[0.894338, 0.105662]
-[0.894338, 0.394338]
+[[0.894338], [-0.105662]]
+[[0.394338], [-0.105662]]
+[[0.605662], [-0.394338]]
+[[0.605662], [-0.105662]]
+[[0.894338], [-0.605662]]
+[[0.894338], [-0.394338]]
+[[0.605662], [0.105662]]
+[[0.894338], [0.105662]]
+[[0.894338], [0.394338]]
#neighbors for quad 57
-[0.894338, 0.105662]
-[0.605662, -0.105662]
-[0.394338, 0.105662]
-[0.605662, 0.105662]
-[0.894338, -0.394338]
-[0.894338, -0.105662]
-[0.605662, 0.394338]
-[0.894338, 0.394338]
-[0.894338, 0.605662]
+[[0.894338], [0.105662]]
+[[0.605662], [-0.105662]]
+[[0.394338], [0.105662]]
+[[0.605662], [0.105662]]
+[[0.894338], [-0.394338]]
+[[0.894338], [-0.105662]]
+[[0.605662], [0.394338]]
+[[0.894338], [0.394338]]
+[[0.894338], [0.605662]]
#neighbors for quad 59
-[0.894338, 0.394338]
-[0.394338, 0.394338]
-[0.605662, 0.105662]
-[0.605662, 0.394338]
-[0.894338, -0.105662]
-[0.894338, 0.105662]
-[0.605662, 0.605662]
-[0.894338, 0.605662]
-[0.894338, 0.894338]
+[[0.894338], [0.394338]]
+[[0.394338], [0.394338]]
+[[0.605662], [0.105662]]
+[[0.605662], [0.394338]]
+[[0.894338], [-0.105662]]
+[[0.894338], [0.105662]]
+[[0.605662], [0.605662]]
+[[0.894338], [0.605662]]
+[[0.894338], [0.894338]]
#neighbors for quad 61
-[0.894338, 0.605662]
-[0.394338, 0.605662]
-[0.605662, 0.394338]
-[0.605662, 0.605662]
-[0.894338, 0.105662]
-[0.894338, 0.394338]
-[0.605662, 0.894338]
-[0.894338, 0.894338]
+[[0.894338], [0.605662]]
+[[0.394338], [0.605662]]
+[[0.605662], [0.394338]]
+[[0.605662], [0.605662]]
+[[0.894338], [0.105662]]
+[[0.894338], [0.394338]]
+[[0.605662], [0.894338]]
+[[0.894338], [0.894338]]
#neighbors for quad 63
-[0.894338, 0.894338]
-[0.605662, 0.605662]
-[0.394338, 0.894338]
-[0.605662, 0.894338]
-[0.894338, 0.394338]
-[0.894338, 0.605662]
+[[0.894338], [0.894338]]
+[[0.605662], [0.605662]]
+[[0.394338], [0.894338]]
+[[0.605662], [0.894338]]
+[[0.894338], [0.394338]]
+[[0.894338], [0.605662]]
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_pair_computation.cc b/test/test_model/test_common/test_non_local_toolbox/test_pair_computation.cc
index d9a481f8c..ca827c3be 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_pair_computation.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_pair_computation.cc
@@ -1,229 +1,221 @@
/**
* @file test_pair_computation.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 25 2015
* @date last modification: Fri Jul 10 2020
*
* @brief test the weight computation with and without grid
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "dumper_paraview.hh"
#include "non_local_manager.hh"
#include "non_local_neighborhood.hh"
#include "solid_mechanics_model.hh"
#include "test_material_damage.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
-typedef std::vector<std::pair<IntegrationPoint, IntegrationPoint>> PairList;
+using PairList = std::vector<std::pair<IntegrationPoint, IntegrationPoint>>;
/* -------------------------------------------------------------------------- */
void computePairs(SolidMechanicsModel & model, PairList * pair_list);
int main(int argc, char * argv[]) {
akantu::initialize("material_remove_damage.dat", argc, argv);
// some configuration variables
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
// mesh creation and read
Mesh mesh(spatial_dimension);
if (prank == 0) {
mesh.read("pair_test.msh");
}
mesh.distribute();
/// model creation
SolidMechanicsModel model(mesh);
/// creation of material selector
auto && mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
/// model initialization changed to use our material
model.initFull();
/// dump material index in paraview
model.addDumpField("material_index");
model.dump();
/// compute the pairs by looping over all the quadrature points
std::array<PairList, 2> pair_list;
computePairs(model, pair_list.data());
const auto & pairs_mat_1_not_ghost =
model.getNonLocalManager().getNeighborhood("mat_1").getPairLists(
_not_ghost);
const auto & pairs_mat_1_ghost =
model.getNonLocalManager().getNeighborhood("mat_1").getPairLists(_ghost);
const auto & pairs_mat_2_not_ghost =
model.getNonLocalManager().getNeighborhood("mat_2").getPairLists(
_not_ghost);
const auto & pairs_mat_2_ghost =
model.getNonLocalManager().getNeighborhood("mat_2").getPairLists(_ghost);
/// compare the number of pairs
- UInt nb_not_ghost_pairs_grid =
+ auto nb_not_ghost_pairs_grid =
pairs_mat_1_not_ghost.size() + pairs_mat_2_not_ghost.size();
- UInt nb_ghost_pairs_grid =
+ auto nb_ghost_pairs_grid =
pairs_mat_1_ghost.size() + pairs_mat_2_ghost.size();
- UInt nb_not_ghost_pairs_no_grid = pair_list[0].size();
- UInt nb_ghost_pairs_no_grid = pair_list[1].size();
+ auto nb_not_ghost_pairs_no_grid = pair_list[0].size();
+ auto nb_ghost_pairs_no_grid = pair_list[1].size();
if ((nb_not_ghost_pairs_grid != nb_not_ghost_pairs_no_grid) ||
(nb_ghost_pairs_grid != nb_ghost_pairs_no_grid)) {
std::cout << "The number of pairs is not correct: TEST FAILED!!!"
<< std::endl;
- finalize();
return EXIT_FAILURE;
}
for (UInt i = 0; i < pairs_mat_1_not_ghost.size(); ++i) {
- PairList::const_iterator it = std::find(
- pair_list[0].begin(), pair_list[0].end(), (pairs_mat_1_not_ghost)[i]);
+ auto it = std::find(pair_list[0].begin(), pair_list[0].end(),
+ (pairs_mat_1_not_ghost)[i]);
if (it == pair_list[0].end()) {
std::cout << "The pairs are not correct" << std::endl;
- finalize();
return EXIT_FAILURE;
}
}
for (UInt i = 0; i < pairs_mat_2_not_ghost.size(); ++i) {
- PairList::const_iterator it = std::find(
- pair_list[0].begin(), pair_list[0].end(), (pairs_mat_2_not_ghost)[i]);
+ auto it = std::find(pair_list[0].begin(), pair_list[0].end(),
+ (pairs_mat_2_not_ghost)[i]);
if (it == pair_list[0].end()) {
std::cout << "The pairs are not correct" << std::endl;
- finalize();
return EXIT_FAILURE;
}
}
for (UInt i = 0; i < pairs_mat_1_ghost.size(); ++i) {
- PairList::const_iterator it = std::find(
- pair_list[1].begin(), pair_list[1].end(), (pairs_mat_1_ghost)[i]);
+ auto it = std::find(pair_list[1].begin(), pair_list[1].end(),
+ (pairs_mat_1_ghost)[i]);
if (it == pair_list[1].end()) {
std::cout << "The pairs are not correct" << std::endl;
- finalize();
return EXIT_FAILURE;
}
}
for (UInt i = 0; i < pairs_mat_2_ghost.size(); ++i) {
- PairList::const_iterator it = std::find(
- pair_list[1].begin(), pair_list[1].end(), (pairs_mat_2_ghost)[i]);
+ auto it = std::find(pair_list[1].begin(), pair_list[1].end(),
+ (pairs_mat_2_ghost)[i]);
if (it == pair_list[1].end()) {
std::cout << "The pairs are not correct" << std::endl;
- finalize();
return EXIT_FAILURE;
}
}
- finalize();
-
return 0;
}
/* -------------------------------------------------------------------------- */
void computePairs(SolidMechanicsModel & model, PairList * pair_list) {
- ElementKind kind = _ek_regular;
- Mesh & mesh = model.getMesh();
- UInt spatial_dimension = model.getSpatialDimension();
+ auto kind = _ek_regular;
+ auto & mesh = model.getMesh();
+ auto spatial_dimension = model.getSpatialDimension();
/// compute the quadrature points
ElementTypeMapReal quad_coords("quad_coords");
quad_coords.initialize(mesh, _nb_component = spatial_dimension,
_spatial_dimension = spatial_dimension,
_with_nb_element = true);
model.getFEEngine().computeIntegrationPointsCoordinates(quad_coords);
/// loop in a n^2 way over all the quads to generate the pairs
Real neighborhood_radius = 0.5;
IntegrationPoint q1;
IntegrationPoint q2;
GhostType ghost_type_1 = _not_ghost;
q1.ghost_type = ghost_type_1;
Vector<Real> q1_coords(spatial_dimension);
Vector<Real> q2_coords(spatial_dimension);
for (auto type_1 : mesh.elementTypes(spatial_dimension, _not_ghost, kind)) {
q1.type = type_1;
- UInt nb_elements_1 = mesh.getNbElement(type_1, ghost_type_1);
- UInt nb_quads_1 = model.getFEEngine().getNbIntegrationPoints(type_1);
- Array<Real> & quad_coords_1 = quad_coords(q1.type, q1.ghost_type);
+ auto nb_elements_1 = mesh.getNbElement(type_1, ghost_type_1);
+ auto nb_quads_1 = model.getFEEngine().getNbIntegrationPoints(type_1);
+ auto & quad_coords_1 = quad_coords(q1.type, q1.ghost_type);
auto coord_it_1 = quad_coords_1.begin(spatial_dimension);
- for (UInt e_1 = 0; e_1 < nb_elements_1; ++e_1) {
+ for (Int e_1 = 0; e_1 < nb_elements_1; ++e_1) {
q1.element = e_1;
- UInt mat_index_1 = model.getMaterialByElement(q1.type, q1.ghost_type)
+ auto mat_index_1 = model.getMaterialByElement(q1.type, q1.ghost_type)
.begin()[q1.element];
- for (UInt q_1 = 0; q_1 < nb_quads_1; ++q_1) {
+ for (Int q_1 = 0; q_1 < nb_quads_1; ++q_1) {
q1.global_num = nb_quads_1 * e_1 + q_1;
q1.num_point = q_1;
q1_coords = coord_it_1[q1.global_num];
/// loop over all other quads and create pairs for this given quad
for (auto ghost_type_2 : ghost_types) {
q2.ghost_type = ghost_type_2;
for (auto type_2 :
mesh.elementTypes(spatial_dimension, ghost_type_2, kind)) {
q2.type = type_2;
- UInt nb_elements_2 = mesh.getNbElement(type_2, ghost_type_2);
- UInt nb_quads_2 =
+ auto nb_elements_2 = mesh.getNbElement(type_2, ghost_type_2);
+ auto nb_quads_2 =
model.getFEEngine().getNbIntegrationPoints(type_2);
- Array<Real> & quad_coords_2 = quad_coords(q2.type, q2.ghost_type);
+ auto & quad_coords_2 = quad_coords(q2.type, q2.ghost_type);
auto coord_it_2 = quad_coords_2.begin(spatial_dimension);
- for (UInt e_2 = 0; e_2 < nb_elements_2; ++e_2) {
+ for (Int e_2 = 0; e_2 < nb_elements_2; ++e_2) {
q2.element = e_2;
- UInt mat_index_2 =
+ auto mat_index_2 =
model.getMaterialByElement(q2.type, q2.ghost_type)
.begin()[q2.element];
- for (UInt q_2 = 0; q_2 < nb_quads_2; ++q_2) {
+ for (Int q_2 = 0; q_2 < nb_quads_2; ++q_2) {
q2.global_num = nb_quads_2 * e_2 + q_2;
q2.num_point = q_2;
q2_coords = coord_it_2[q2.global_num];
- Real distance = q1_coords.distance(q2_coords);
+ auto distance = q1_coords.distance(q2_coords);
if (mat_index_1 != mat_index_2)
continue;
else if (distance <=
neighborhood_radius + Math::getTolerance() &&
(q2.ghost_type == _ghost ||
(q2.ghost_type == _not_ghost &&
q1.global_num <=
q2.global_num))) { // storing only half lists
pair_list[q2.ghost_type].push_back(std::make_pair(q1, q2));
}
}
}
}
}
}
}
}
}
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_remove_damage_weight_function.cc b/test/test_model/test_common/test_non_local_toolbox/test_remove_damage_weight_function.cc
index 6f114cb0c..9cc4b49b8 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_remove_damage_weight_function.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_remove_damage_weight_function.cc
@@ -1,192 +1,187 @@
/**
* @file test_remove_damage_weight_function.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Oct 07 2015
* @date last modification: Wed Nov 27 2019
*
* @brief Test the damage weight funcion for non local computations
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "dumper_paraview.hh"
#include "non_local_manager.hh"
#include "non_local_neighborhood.hh"
#include "solid_mechanics_model.hh"
#include "test_material.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material_remove_damage.dat", argc, argv);
// some configuration variables
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
ElementType element_type = _quadrangle_4;
GhostType ghost_type = _not_ghost;
// mesh creation and read
Mesh mesh(spatial_dimension);
mesh.read("plate.msh");
/// model creation
SolidMechanicsModel model(mesh);
/// creation of material selector
auto && mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
/// model initialization changed to use our material
model.initFull();
/// dump material index in paraview
model.addDumpField("material_index");
model.addDumpField("grad_u");
model.addDumpField("grad_u non local");
model.addDumpField("damage");
model.dump();
/// apply constant strain field in all elements except element 3 and 15
- Matrix<Real> applied_strain(spatial_dimension, spatial_dimension);
- applied_strain.zero();
- for (UInt i = 0; i < spatial_dimension; ++i)
- applied_strain(i, i) = 2.;
+ Matrix<Real> applied_strain =
+ 2. * Matrix<Real>::Identity(spatial_dimension, spatial_dimension);
/// apply different strain in element 3 and 15
- Matrix<Real> modified_strain(spatial_dimension, spatial_dimension);
- modified_strain.zero();
- for (UInt i = 0; i < spatial_dimension; ++i)
- modified_strain(i, i) = 1.;
+ Matrix<Real> modified_strain =
+ Matrix<Real>::Identity(spatial_dimension, spatial_dimension);
/// apply constant grad_u field in all elements
- for (UInt m = 0; m < model.getNbMaterials(); ++m) {
- Material & mat = model.getMaterial(m);
- Array<Real> & grad_u = const_cast<Array<Real> &>(
- mat.getInternal<Real>("eigen_grad_u")(element_type, ghost_type));
+ for (Int m = 0; m < model.getNbMaterials(); ++m) {
+ auto & mat = model.getMaterial(m);
+ auto & grad_u =
+ mat.getInternal<Real>("eigen_grad_u")(element_type, ghost_type);
auto grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension);
auto grad_u_end = grad_u.end(spatial_dimension, spatial_dimension);
- UInt element_counter = 0;
+ Int element_counter = 0;
for (; grad_u_it != grad_u_end; ++grad_u_it, ++element_counter)
if (element_counter == 12 || element_counter == 13 ||
element_counter == 14 || element_counter == 15)
(*grad_u_it) = -1. * modified_strain;
else
(*grad_u_it) = -1. * applied_strain;
}
/// compute the non-local strains
model.assembleInternalForces();
model.dump();
/// save the weights in a file
auto & neighborhood_1 = model.getNonLocalManager().getNeighborhood("mat_1");
auto & neighborhood_2 = model.getNonLocalManager().getNeighborhood("mat_2");
neighborhood_1.saveWeights("before_0");
neighborhood_2.saveWeights("before_1");
- for (UInt n = 0; n < 2; ++n) {
+ for (Int n = 0; n < 2; ++n) {
/// print results to screen for validation
std::stringstream sstr;
sstr << "before_" << n << ".0";
std::ifstream weights;
weights.open(sstr.str());
std::string current_line;
- while (getline(weights, current_line))
+ while (getline(weights, current_line)) {
std::cout << current_line << std::endl;
+ }
weights.close();
}
/// apply damage to not have the elements with lower strain impact the
/// averaging
- for (UInt m = 0; m < model.getNbMaterials(); ++m) {
+ for (Int m = 0; m < model.getNbMaterials(); ++m) {
auto & mat =
dynamic_cast<MaterialDamage<spatial_dimension> &>(model.getMaterial(m));
- auto & damage = const_cast<Array<Real> &>(
- mat.getInternal<Real>("damage")(element_type, ghost_type));
+ auto & damage = mat.getInternal<Real>("damage")(element_type, ghost_type);
auto dam_it = damage.begin();
auto dam_end = damage.end();
- UInt element_counter = 0;
- for (; dam_it != dam_end; ++dam_it, ++element_counter)
+ Int element_counter = 0;
+ for (; dam_it != dam_end; ++dam_it, ++element_counter) {
if (element_counter == 12 || element_counter == 13 ||
- element_counter == 14 || element_counter == 15)
+ element_counter == 14 || element_counter == 15) {
*dam_it = 0.9;
+ }
+ }
}
/// compute the non-local strains
model.assembleInternalForces();
neighborhood_1.saveWeights("after_0");
neighborhood_2.saveWeights("after_1");
- for (UInt n = 0; n < 2; ++n) {
+ for (Int n = 0; n < 2; ++n) {
/// print results to screen for validation
std::stringstream sstr;
sstr << "after_" << n << ".0";
std::ifstream weights;
weights.open(sstr.str());
std::string current_line;
- while (getline(weights, current_line))
+ while (getline(weights, current_line)) {
std::cout << current_line << std::endl;
+ }
weights.close();
}
model.dump();
/// verify the result: non-local averaging over constant field must
/// yield same constant field
Real test_result = 0.;
- Matrix<Real> difference(spatial_dimension, spatial_dimension, 0.);
+ Matrix<Real> difference(spatial_dimension, spatial_dimension);
Matrix<Real> difference_in_damaged_elements(spatial_dimension,
- spatial_dimension, 0.);
- for (UInt m = 0; m < model.getNbMaterials(); ++m) {
+ spatial_dimension);
+ for (Int m = 0; m < model.getNbMaterials(); ++m) {
difference_in_damaged_elements.zero();
auto & mat = model.getMaterial(m);
- auto & grad_u_nl = const_cast<Array<Real> &>(
- mat.getInternal<Real>("grad_u non local")(element_type, ghost_type));
+ auto & grad_u_nl =
+ mat.getInternal<Real>("grad_u non local")(element_type, ghost_type);
auto grad_u_nl_it = grad_u_nl.begin(spatial_dimension, spatial_dimension);
auto grad_u_nl_end = grad_u_nl.end(spatial_dimension, spatial_dimension);
UInt element_counter = 0;
for (; grad_u_nl_it != grad_u_nl_end; ++grad_u_nl_it, ++element_counter) {
if (element_counter == 12 || element_counter == 13 ||
- element_counter == 14 || element_counter == 15)
+ element_counter == 14 || element_counter == 15) {
difference_in_damaged_elements += (*grad_u_nl_it);
- else
+ } else {
difference = (*grad_u_nl_it) - applied_strain;
- test_result += difference.norm<L_2>();
+ }
+ test_result += difference.norm();
}
difference_in_damaged_elements *= (1 / 4.);
difference_in_damaged_elements -= (1.41142 * modified_strain);
- test_result += difference_in_damaged_elements.norm<L_2>();
+ test_result += difference_in_damaged_elements.norm();
}
if (test_result > 10.e-5) {
std::cout << "the total norm is: " << test_result << std::endl;
return EXIT_FAILURE;
}
-
- finalize();
-
- return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_common/test_non_local_toolbox/test_weight_computation.cc b/test/test_model/test_common/test_non_local_toolbox/test_weight_computation.cc
index 252b9ba96..9d2ec8c70 100644
--- a/test/test_model/test_common/test_non_local_toolbox/test_weight_computation.cc
+++ b/test/test_model/test_common/test_non_local_toolbox/test_weight_computation.cc
@@ -1,69 +1,69 @@
/**
* @file test_weight_computation.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sat Sep 26 2015
* @date last modification: Wed Jan 30 2019
*
* @brief test for the weight computation with base weight function
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "my_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material_weight_computation.dat", argc, argv);
// some configuration variables
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
// mesh creation and read
Mesh mesh(spatial_dimension);
mesh.read("plate.msh");
/// model creation
MyModel model(mesh, spatial_dimension);
/// save the weights in a file
const auto & neighborhood =
model.getNonLocalManager().getNeighborhood("test_region");
neighborhood.saveWeights("weights");
/// print results to screen for validation
std::ifstream weights;
weights.open("weights.0");
std::string current_line;
while (getline(weights, current_line))
std::cout << current_line << std::endl;
weights.close();
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_contact_mechanics_model/test_coupler/test_contact_coupling.cc b/test/test_model/test_contact_mechanics_model/test_coupler/test_contact_coupling.cc
index a49008ae8..2f1f9aac8 100644
--- a/test/test_model/test_contact_mechanics_model/test_coupler/test_contact_coupling.cc
+++ b/test/test_model/test_contact_mechanics_model/test_coupler/test_contact_coupling.cc
@@ -1,75 +1,75 @@
/**
* @file test_contact_coupling.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Thu May 16 2019
*
* @brief Test for contact mechanics model class
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_contact.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize("material.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("coupling.msh");
CouplerSolidContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModel();
auto & contact = coupler.getContactMechanicsModel();
solid.initFull(_analysis_method = _static);
contact.initFull(_analysis_method = _implicit_contact);
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "bot_body");
solid.applyBC(BC::Dirichlet::IncrementValue(0.001, _y), "bot_body");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "top");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "top");
coupler.initFull(_analysis_method = _implicit_contact);
coupler.setBaseName("coupling");
coupler.addDumpFieldVector("displacement");
coupler.addDumpField("blocked_dofs");
coupler.addDumpField("external_force");
coupler.addDumpField("internal_force");
coupler.addDumpField("grad_u");
coupler.addDumpField("stress");
coupler.solveStep();
contact.dump();
return 0;
}
diff --git a/test/test_model/test_contact_mechanics_model/test_coupler/test_coupled_stiffness.cc b/test/test_model/test_contact_mechanics_model/test_coupler/test_coupled_stiffness.cc
index a0ef09068..47b5c1394 100644
--- a/test/test_model/test_contact_mechanics_model/test_coupler/test_coupled_stiffness.cc
+++ b/test/test_model/test_contact_mechanics_model/test_coupler/test_coupled_stiffness.cc
@@ -1,140 +1,140 @@
/**
* @file test_coupled_stiffness.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri May 24 2019
* @date last modification: Wed Oct 02 2019
*
* @brief Test for contact mechanics model class
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "coupler_solid_contact.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "sparse_matrix.hh"
#include "surface_selector.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
Real max_displacement = 0.01;
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize("material_stiffness.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("flat_on_flat.msh");
CouplerSolidContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModel();
auto & contact = coupler.getContactMechanicsModel();
auto && selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names", solid);
solid.setMaterialSelector(selector);
solid.initFull(_analysis_method = _static);
contact.initFull(_analysis_method = _implicit_contact);
auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
contact.getContactDetector().setSurfaceSelector(surface_selector);
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "bottom");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "bottom");
solid.applyBC(BC::Dirichlet::IncrementValue(-max_displacement, _y), "top");
coupler.initFull(_analysis_method = _implicit_contact);
auto & solver = coupler.getNonLinearSolver();
solver.set("max_iterations", 1000);
solver.set("threshold", 1e-2);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
coupler.setBaseName("test-coupled-stiffness");
coupler.addDumpFieldVector("displacement");
coupler.addDumpFieldVector("normals");
coupler.addDumpFieldVector("contact_force");
coupler.addDumpFieldVector("external_force");
coupler.addDumpFieldVector("internal_force");
coupler.addDumpField("gaps");
coupler.addDumpField("blocked_dofs");
coupler.addDumpField("grad_u");
coupler.addDumpField("stress");
auto & before_assembly = const_cast<SparseMatrix &>(
coupler.getDOFManager().getNewMatrix("K", _symmetric));
solid.assembleStiffnessMatrix();
auto & solid_assembly =
const_cast<SparseMatrix &>(coupler.getDOFManager().getMatrix("K"));
solid_assembly.saveMatrix("solid_assembly.mtx");
auto & displacement = solid.getDisplacement();
contact.search(displacement);
contact.assembleStiffnessMatrix();
auto contact_map = contact.getContactMap();
auto nb_contacts = contact_map.size();
auto & contact_assembly =
const_cast<SparseMatrix &>(coupler.getDOFManager().getMatrix("K"));
contact_assembly.saveMatrix("contact_assembly.mtx");
solid.assembleInternalForces();
contact.assembleInternalForces();
coupler.dump();
Array<Real> & contact_force = contact.getInternalForce();
- for (UInt n : arange(contact_force.size())) {
+ for (Int n : arange(contact_force.size())) {
std::cerr << contact_force(n, 1) << std::endl;
}
if (solid_assembly.size() == contact_assembly.size() and nb_contacts > 0) {
std::cerr << "size of stiffness matrix of solid = "
<< solid_assembly.size() << std::endl;
std::cerr << "size of stiffness matrix of coupled = "
<< contact_assembly.size() << std::endl;
std::cerr << "number of contacts = " << nb_contacts << std::endl;
for (auto & pair : contact_map) {
std::cerr << "Node " << pair.first << " in contact with "
<< pair.second.master << " of gap " << pair.second.gap
<< std::endl;
}
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_contact_mechanics_model/test_explicit_dynamic.cc b/test/test_model/test_contact_mechanics_model/test_explicit_dynamic.cc
index b8c6fb759..30780313e 100644
--- a/test/test_model/test_contact_mechanics_model/test_explicit_dynamic.cc
+++ b/test/test_model/test_contact_mechanics_model/test_explicit_dynamic.cc
@@ -1,167 +1,167 @@
/**
* @file test_explicit_dynamic.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Fri Dec 11 2020
* @date last modification: Sun Jun 06 2021
*
* @brief Test for dynamic explicit contact
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "coupler_solid_contact.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "surface_selector.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
template <typename T> std::vector<T> arrange(T start, T stop, T step = 1) {
std::vector<T> values;
for (T value = start; value <= stop; value += step)
values.push_back(value);
return values;
}
int main(int argc, char * argv[]) {
UInt max_steps = 2000;
Real max_displacement = 1e-2;
Real damping_ratio = 0.99;
std::string mesh_file = "flat_on_flat.msh";
std::string material_file = "material.dat";
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize(material_file, argc, argv);
Mesh mesh(spatial_dimension);
mesh.read(mesh_file);
CouplerSolidContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModel();
auto & contact = coupler.getContactMechanicsModel();
auto && material_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
solid);
solid.setMaterialSelector(material_selector);
coupler.initFull(_analysis_method = _explicit_lumped_mass);
auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
contact.getContactDetector().setSurfaceSelector(surface_selector);
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "upper");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "lower");
Real time_step = solid.getStableTimeStep();
time_step *= 0.05;
coupler.setTimeStep(time_step);
std::cout << "Stable time increment : " << time_step << " sec "
<< std::endl;
coupler.setBaseName("explicit-dynamic");
coupler.addDumpFieldVector("displacement");
coupler.addDumpFieldVector("normals");
coupler.addDumpFieldVector("contact_force");
coupler.addDumpFieldVector("external_force");
coupler.addDumpFieldVector("internal_force");
coupler.addDumpField("gaps");
coupler.addDumpField("areas");
coupler.addDumpField("blocked_dofs");
coupler.addDumpField("strain");
coupler.addDumpField("stress");
auto & velocity = solid.getVelocity();
auto & gaps = contact.getGaps();
auto xi = arrange<Real>(0, 1, 1. / max_steps);
std::vector<Real> displacements;
std::transform(xi.begin(), xi.end(), std::back_inserter(displacements),
[&](Real & p) -> Real {
return 0. + (max_displacement)*pow(p, 3) *
(10 - 15 * p + 6 * pow(p, 2));
});
- for (UInt s : arange(max_steps)) {
+ for (Int s : arange(max_steps)) {
solid.applyBC(BC::Dirichlet::FixedValue(-displacements[s], _y), "loading");
solid.applyBC(BC::Dirichlet::FixedValue(displacements[s], _y), "fixed");
coupler.solveStep();
for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) {
auto & gap = std::get<0>(tuple);
auto & vel = std::get<1>(tuple);
if (gap > 0) {
vel *= damping_ratio;
}
}
if (s % 100 == 0) {
coupler.dump();
}
}
coupler.dump();
const ElementType element_type = _quadrangle_4;
const Array<Real> & stress_vect =
solid.getMaterial("upper").getStress(element_type);
auto stress_it = stress_vect.begin(spatial_dimension, spatial_dimension);
auto stress_end = stress_vect.end(spatial_dimension, spatial_dimension);
Real stress_tolerance = 1e-2;
Matrix<Real> presc_stress{{0, 0}, {0, 7e5}};
for (; stress_it != stress_end; ++stress_it) {
const auto & stress = *stress_it;
Real stress_error =
(std::abs(stress(1, 1)) - presc_stress(1, 1)) / (presc_stress(1, 1));
// if error is more than 1%
if (std::abs(stress_error) > stress_tolerance) {
std::cerr << "stress error: " << stress_error << " > " << stress_tolerance
<< std::endl;
std::cerr << "stress: " << stress << std::endl
<< "prescribed stress: " << presc_stress << std::endl;
return EXIT_FAILURE;
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_contact_mechanics_model/test_explicit_friction.cc b/test/test_model/test_contact_mechanics_model/test_explicit_friction.cc
index a6fe45a51..32868c951 100644
--- a/test/test_model/test_contact_mechanics_model/test_explicit_friction.cc
+++ b/test/test_model/test_contact_mechanics_model/test_explicit_friction.cc
@@ -1,179 +1,179 @@
/**
* @file test_explicit_friction.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sun Jun 06 2021
* @date last modification: Sun Jun 06 2021
*
* @brief Test contact mechanics with friction
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
#include "coupler_solid_contact.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "surface_selector.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
template <typename T> std::vector<T> arrange(T start, T stop, T step = 1) {
std::vector<T> values;
for (T value = start; value <= stop; value += step)
values.push_back(value);
return values;
}
int main(int argc, char * argv[]) {
- UInt max_normal_steps = 2500;
- UInt max_shear_steps = 7500;
+ Int max_normal_steps = 2500;
+ Int max_shear_steps = 7500;
Real max_shear_displacement = 1e-1;
Real max_normal_displacement = 2e-2;
Real damping_ratio = 0.99;
std::string mesh_file = "sliding-block-2D.msh";
std::string material_file = "material-friction.dat";
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize(material_file, argc, argv);
Mesh mesh(spatial_dimension);
mesh.read(mesh_file);
CouplerSolidContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModel();
auto & contact = coupler.getContactMechanicsModel();
auto && material_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
solid);
solid.setMaterialSelector(material_selector);
coupler.initFull(_analysis_method = _explicit_lumped_mass);
auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
contact.getContactDetector().setSurfaceSelector(surface_selector);
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "lower");
solid.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "lower");
Real time_step = solid.getStableTimeStep();
time_step *= 0.05;
coupler.setTimeStep(time_step);
std::cout << "Stable time increment : " << time_step << " sec "
<< std::endl;
coupler.setBaseName("explicit-friction");
coupler.addDumpFieldVector("displacement");
coupler.addDumpFieldVector("normals");
coupler.addDumpFieldVector("contact_force");
coupler.addDumpFieldVector("tangential_force");
coupler.addDumpFieldVector("external_force");
coupler.addDumpFieldVector("internal_force");
coupler.addDumpField("gaps");
coupler.addDumpField("areas");
coupler.addDumpField("blocked_dofs");
coupler.addDumpField("strain");
coupler.addDumpField("stress");
coupler.addDumpField("contact_state");
auto & velocity = solid.getVelocity();
auto & gaps = contact.getGaps();
auto xi = arrange<Real>(0, 1, 1. / max_shear_steps);
std::vector<Real> shear_displacements;
std::transform(xi.begin(), xi.end(), std::back_inserter(shear_displacements),
[&](Real & p) -> Real {
return 0. + (max_shear_displacement)*pow(p, 3) *
(10 - 15 * p + 6 * pow(p, 2));
});
auto normal_xi = arrange<Real>(0, 1, 1. / max_normal_steps);
std::vector<Real> normal_displacements;
std::transform(normal_xi.begin(), normal_xi.end(),
std::back_inserter(normal_displacements),
[&](Real & p) -> Real {
return 0. + (max_normal_displacement)*pow(p, 3) *
(10 - 15 * p + 6 * pow(p, 2));
});
auto max_steps = max_normal_steps + max_shear_steps;
auto & contact_nodes = surface_selector->getSlaveList();
auto & tangential_traction = contact.getTangentialTractions();
- for (UInt s : arange(max_steps)) {
+ for (Int s : arange(max_steps)) {
if (s < max_normal_steps) {
solid.applyBC(BC::Dirichlet::FixedValue(-normal_displacements[s], _y),
"loading");
} else {
solid.applyBC(BC::Dirichlet::FixedValue(
shear_displacements[s - max_normal_steps], _x),
"loading");
}
coupler.solveStep();
for (auto && tuple : zip(gaps, make_view(velocity, spatial_dimension))) {
auto & gap = std::get<0>(tuple);
auto & vel = std::get<1>(tuple);
if (gap > 0) {
vel *= damping_ratio;
}
}
if (s % 100 == 0) {
coupler.dump();
}
auto sum = std::accumulate(tangential_traction.begin(),
tangential_traction.end(), 0.0);
auto num_tang_traction = std::abs(sum) / contact_nodes.size();
Real exp_tang_traction = 0.3 * 1.4e6;
Real error =
std::abs(num_tang_traction - exp_tang_traction) / exp_tang_traction;
if (error > 1e-3 and num_tang_traction > exp_tang_traction) {
std::cerr << error << "----" << num_tang_traction << std::endl;
return EXIT_FAILURE;
}
}
coupler.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_contact_mechanics_model/test_resolution/test_explicit_resolution.cc b/test/test_model/test_contact_mechanics_model/test_resolution/test_explicit_resolution.cc
index a92784701..49aba5796 100644
--- a/test/test_model/test_contact_mechanics_model/test_resolution/test_explicit_resolution.cc
+++ b/test/test_model/test_contact_mechanics_model/test_resolution/test_explicit_resolution.cc
@@ -1,52 +1,52 @@
/**
* @file test_explicit_resolution.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Thu Feb 21 2013
* @date last modification: Thu Jan 17 2019
*
* @brief Test for explicit contact resolution
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "contact_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
int main(int argc, char * argv[]) {
initialize("options.dat", argc, argv);
Mesh mesh(spatial_dimension);
// mesh.read("explicit_2d.msh");
ContactMechanicsModel model(mesh);
model.initFull(_analysis_method = _static);
std::cout << model;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_phase_field_model/test_multi_material.cc b/test/test_model/test_phase_field_model/test_multi_material.cc
index 91f30929c..92da08464 100644
--- a/test/test_model/test_phase_field_model/test_multi_material.cc
+++ b/test/test_model/test_phase_field_model/test_multi_material.cc
@@ -1,127 +1,127 @@
/**
* @file test_multi_material.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Wed Feb 24 2021
* @date last modification: Sun Feb 28 2021
*
* @brief test of the class PhaseFieldModel on the 2d square
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "coupler_solid_phasefield.hh"
#include "material.hh"
#include "material_phasefield.hh"
#include "non_linear_solver.hh"
#include "phase_field_model.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel &, Real &);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material_multiple.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("test_two_element.msh");
CouplerSolidPhaseField coupler(mesh);
auto & model = coupler.getSolidMechanicsModel();
auto & phase = coupler.getPhaseFieldModel();
auto && mat_selector =
std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
model);
model.setMaterialSelector(mat_selector);
model.initFull(_analysis_method = _explicit_lumped_mass);
Real time_step = model.getStableTimeStep();
time_step *= 0.8;
model.setTimeStep(time_step);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
model.setBaseName("multi_material");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("damage");
model.addDumpFieldVector("displacement");
model.addDumpField("blocked_dofs");
model.dump();
- UInt nbSteps = 1000;
+ Int nbSteps = 1000;
Real increment = 1e-4;
- for (UInt s = 0; s < nbSteps; ++s) {
+ for (Int s = 0; s < nbSteps; ++s) {
Real axial_strain = increment * s;
applyDisplacement(model, axial_strain);
coupler.solve();
model.dump();
}
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel & model, Real & increment) {
auto & displacement = model.getDisplacement();
auto & positions = model.getMesh().getNodes();
auto & blocked_dofs = model.getBlockedDOFs();
- for (UInt n = 0; n < model.getMesh().getNbNodes(); ++n) {
+ for (Int n = 0; n < model.getMesh().getNbNodes(); ++n) {
if (positions(n, 1) == -1) {
displacement(n, 1) = 0;
blocked_dofs(n, 1) = true;
displacement(n, 0) = 0;
blocked_dofs(n, 0) = true;
} else if (positions(n, 1) == 1) {
displacement(n, 0) = 0;
displacement(n, 1) = increment;
blocked_dofs(n, 0) = true;
blocked_dofs(n, 1) = true;
} else {
displacement(n, 0) = 0;
blocked_dofs(n, 0) = true;
}
}
}
diff --git a/test/test_model/test_phase_field_model/test_phase_field_anisotropic.cc b/test/test_model/test_phase_field_model/test_phase_field_anisotropic.cc
index f83dec4ec..4dd6cf12a 100644
--- a/test/test_model/test_phase_field_model/test_phase_field_anisotropic.cc
+++ b/test/test_model/test_phase_field_model/test_phase_field_anisotropic.cc
@@ -1,148 +1,148 @@
#include "aka_common.hh"
#include "coupler_solid_phasefield.hh"
#include "material.hh"
#include "material_phasefield.hh"
#include "non_linear_solver.hh"
#include "phase_field_model.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
const UInt spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel &, Real &);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
std::ofstream os("data.csv");
os << "#strain stress damage analytical_sigma analytical_damage" << std::endl;
initialize("material_coupling.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("test_one_element.msh");
CouplerSolidPhaseField coupler(mesh);
auto & model = coupler.getSolidMechanicsModel();
auto & phase = coupler.getPhaseFieldModel();
model.initFull(_analysis_method = _static);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
model.setBaseName("phase_solid");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
model.dump();
UInt nbSteps = 1500;
Real increment = 1e-4;
auto & stress = model.getMaterial(0).getArray<Real>("stress", _quadrangle_4);
auto & damage = model.getMaterial(0).getArray<Real>("damage", _quadrangle_4);
Real analytical_damage{0.};
Real analytical_sigma{0.};
auto & phasefield = phase.getPhaseField(0);
const Real E = phasefield.getParam("E");
const Real nu = phasefield.getParam("nu");
Real c22 = E * (1 - nu) / ((1 + nu) * (1 - 2 * nu));
const Real gc = phasefield.getParam("gc");
const Real l0 = phasefield.getParam("l0");
Real error_stress{0.};
Real error_damage{0.};
Real max_strain{0.};
for (UInt s = 0; s < nbSteps; ++s) {
Real axial_strain{0.};
if (s < 500) {
axial_strain = increment * s;
} else if (s < 1000) {
axial_strain = (1500 - 2 * double(s)) * increment;
} else {
axial_strain = (3 * double(s) - 3500) * increment;
}
applyDisplacement(model, axial_strain);
if (axial_strain > max_strain) {
max_strain = axial_strain;
}
coupler.solve("static", "static");
analytical_damage = max_strain * max_strain * c22 /
(gc / l0 + max_strain * max_strain * c22);
if (axial_strain < 0.) {
analytical_sigma = c22 * axial_strain;
} else {
analytical_sigma = c22 * axial_strain * (1 - analytical_damage) *
(1 - analytical_damage);
}
error_stress = std::abs(analytical_sigma - stress(0, 3)) / analytical_sigma;
error_damage = std::abs(analytical_damage - damage(0)) / analytical_damage;
if ((error_damage > 1e-8 or error_stress > 1e-8) and
std::abs(axial_strain) < 1e-13) {
std::cerr << std::left << std::setw(15)
<< "Error damage: " << error_damage << std::endl;
std::cerr << std::left << std::setw(15)
<< "Error stress: " << error_stress << std::endl;
return EXIT_FAILURE;
}
os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " "
<< analytical_sigma << " " << analytical_damage << " " << error_stress
<< " " << error_damage << std::endl;
model.dump();
}
os.close();
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel & model, Real & increment) {
auto & displacement = model.getDisplacement();
auto & positions = model.getMesh().getNodes();
auto & blocked_dofs = model.getBlockedDOFs();
- for (UInt n = 0; n < model.getMesh().getNbNodes(); ++n) {
+ for (Idx n = 0; n < model.getMesh().getNbNodes(); ++n) {
if (positions(n, 1) == -0.5) {
displacement(n, 0) = 0;
displacement(n, 1) = 0;
blocked_dofs(n, 0) = true;
blocked_dofs(n, 1) = true;
} else {
displacement(n, 0) = 0;
displacement(n, 1) = increment;
blocked_dofs(n, 0) = true;
blocked_dofs(n, 1) = true;
}
}
}
/* -------------------------------------------------------------------------- */
diff --git a/test/test_model/test_phase_field_model/test_phase_solid_coupling.cc b/test/test_model/test_phase_field_model/test_phase_solid_coupling.cc
index b8c162cbb..d422887cb 100644
--- a/test/test_model/test_phase_field_model/test_phase_solid_coupling.cc
+++ b/test/test_model/test_phase_field_model/test_phase_solid_coupling.cc
@@ -1,276 +1,277 @@
/**
* @file test_phase_solid_coupling.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sun Jan 06 2019
* @date last modification: Wed Mar 03 2021
*
* @brief test of the class PhaseFieldModel on the 2d square
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_phasefield.hh"
#include "non_linear_solver.hh"
#include "phase_field_model.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel &, Real &);
void computeStrainOnQuadPoints(SolidMechanicsModel &, PhaseFieldModel &,
- const GhostType &);
+ GhostType);
void computeDamageOnQuadPoints(SolidMechanicsModel &, PhaseFieldModel &,
- const GhostType &);
+ GhostType);
void gradUToEpsilon(const Matrix<Real> &, Matrix<Real> &);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
std::ofstream os("data.csv");
os << "#strain stress damage analytical_sigma analytical_damage" << std::endl;
initialize("material_coupling.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("test_one_element.msh");
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _static);
PhaseFieldModel phase(mesh);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
model.setBaseName("phase_solid");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
model.dump();
- UInt nbSteps = 1000;
+ Int nbSteps = 1000;
Real increment = 1e-4;
auto & stress = model.getMaterial(0).getArray<Real>("stress", _quadrangle_4);
auto & damage = model.getMaterial(0).getArray<Real>("damage", _quadrangle_4);
Real analytical_damage{0.};
Real analytical_sigma{0.};
auto & phasefield = phase.getPhaseField(0);
const Real E = phasefield.getParam("E");
const Real nu = phasefield.getParam("nu");
Real c22 = E * (1 - nu) / ((1 + nu) * (1 - 2 * nu));
const Real gc = phasefield.getParam("gc");
const Real l0 = phasefield.getParam("l0");
Real error_stress{0.};
Real error_damage{0.};
- for (UInt s = 0; s < nbSteps; ++s) {
+ for (Int s = 0; s < nbSteps; ++s) {
Real axial_strain = increment * s;
applyDisplacement(model, axial_strain);
model.solveStep();
computeStrainOnQuadPoints(model, phase, _not_ghost);
phase.solveStep();
computeDamageOnQuadPoints(model, phase, _not_ghost);
model.assembleInternalForces();
analytical_damage = axial_strain * axial_strain * c22 /
(gc / l0 + axial_strain * axial_strain * c22);
analytical_sigma =
c22 * axial_strain * (1 - analytical_damage) * (1 - analytical_damage);
error_stress = std::abs(analytical_sigma - stress(0, 3)) / analytical_sigma;
error_damage = std::abs(analytical_damage - damage(0)) / analytical_damage;
if (error_damage > 1e-8 or error_stress > 1e-8) {
std::cerr << std::left << std::setw(15)
<< "Error damage: " << error_damage << std::endl;
std::cerr << std::left << std::setw(15)
<< "Error stress: " << error_stress << std::endl;
return EXIT_FAILURE;
}
os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " "
<< analytical_sigma << " " << analytical_damage << " " << error_stress
<< " " << error_damage << std::endl;
model.dump();
}
os.close();
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel & model, Real & increment) {
auto & displacement = model.getDisplacement();
auto & positions = model.getMesh().getNodes();
auto & blocked_dofs = model.getBlockedDOFs();
- for (UInt n = 0; n < model.getMesh().getNbNodes(); ++n) {
+ for (Int n = 0; n < model.getMesh().getNbNodes(); ++n) {
if (positions(n, 1) == -0.5) {
displacement(n, 0) = 0;
displacement(n, 1) = 0;
blocked_dofs(n, 0) = true;
blocked_dofs(n, 1) = true;
} else {
displacement(n, 0) = 0;
displacement(n, 1) = increment;
blocked_dofs(n, 0) = true;
blocked_dofs(n, 1) = true;
}
}
}
/* -------------------------------------------------------------------------- */
void computeStrainOnQuadPoints(SolidMechanicsModel & solid,
- PhaseFieldModel & phase,
- const GhostType & ghost_type) {
+ PhaseFieldModel & phase, GhostType ghost_type) {
auto & mesh = solid.getMesh();
auto nb_materials = solid.getNbMaterials();
auto nb_phasefields = phase.getNbPhaseFields();
AKANTU_DEBUG_ASSERT(
nb_phasefields == nb_materials,
"The number of phasefields and materials should be equal");
for (auto index : arange(nb_materials)) {
auto & material = solid.getMaterial(index);
for (auto index2 : arange(nb_phasefields)) {
auto & phasefield = phase.getPhaseField(index2);
if (phasefield.getName() == material.getName()) {
auto & strain_on_qpoints = phasefield.getStrain();
auto & gradu_on_qpoints = material.getGradU();
- for (auto & type : mesh.elementTypes(spatial_dimension, ghost_type)) {
+ for (const auto & type :
+ mesh.elementTypes(spatial_dimension, ghost_type)) {
auto & strain_on_qpoints_vect = strain_on_qpoints(type, ghost_type);
auto & gradu_on_qpoints_vect = gradu_on_qpoints(type, ghost_type);
for (auto && values :
zip(make_view(strain_on_qpoints_vect, spatial_dimension,
spatial_dimension),
make_view(gradu_on_qpoints_vect, spatial_dimension,
spatial_dimension))) {
auto & strain = std::get<0>(values);
auto & grad_u = std::get<1>(values);
- gradUToEpsilon(grad_u, strain);
+ Material::gradUToEpsilon<spatial_dimension>(grad_u, strain);
}
}
break;
}
}
}
}
/* -------------------------------------------------------------------------- */
void computeDamageOnQuadPoints(SolidMechanicsModel & solid,
- PhaseFieldModel & phase,
- const GhostType & ghost_type) {
+ PhaseFieldModel & phase, GhostType ghost_type) {
auto & fem = phase.getFEEngine();
auto & mesh = phase.getMesh();
auto nb_materials = solid.getNbMaterials();
auto nb_phasefields = phase.getNbPhaseFields();
AKANTU_DEBUG_ASSERT(
nb_phasefields == nb_materials,
"The number of phasefields and materials should be equal");
for (auto index : arange(nb_materials)) {
auto & material = solid.getMaterial(index);
for (auto index2 : arange(nb_phasefields)) {
auto & phasefield = phase.getPhaseField(index2);
if (phasefield.getName() == material.getName()) {
switch (spatial_dimension) {
case 1: {
- auto & mat = static_cast<MaterialPhaseField<1> &>(material);
+ auto & mat = dynamic_cast<MaterialPhaseField<1> &>(material);
auto & solid_damage = mat.getDamage();
- for (auto & type : mesh.elementTypes(spatial_dimension, ghost_type)) {
+ for (const auto & type :
+ mesh.elementTypes(spatial_dimension, ghost_type)) {
auto & damage_on_qpoints_vect = solid_damage(type, ghost_type);
fem.interpolateOnIntegrationPoints(
phase.getDamage(), damage_on_qpoints_vect, 1, type, ghost_type);
}
break;
}
case 2: {
- auto & mat = static_cast<MaterialPhaseField<2> &>(material);
+ auto & mat = dynamic_cast<MaterialPhaseField<2> &>(material);
auto & solid_damage = mat.getDamage();
- for (auto & type : mesh.elementTypes(spatial_dimension, ghost_type)) {
+ for (const auto & type :
+ mesh.elementTypes(spatial_dimension, ghost_type)) {
auto & damage_on_qpoints_vect = solid_damage(type, ghost_type);
fem.interpolateOnIntegrationPoints(
phase.getDamage(), damage_on_qpoints_vect, 1, type, ghost_type);
}
break;
}
default:
break;
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon) {
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j)
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = 0; j < spatial_dimension; ++j)
epsilon(i, j) = 0.5 * (grad_u(i, j) + grad_u(j, i));
}
}
diff --git a/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc b/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc
index db920d581..076e67d32 100644
--- a/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc
+++ b/test/test_model/test_phase_field_model/test_phase_solid_explicit.cc
@@ -1,158 +1,158 @@
/**
* @file test_phase_solid_explicit.cc
*
* @author Mohit Pundir <mohit.pundir@epfl.ch>
*
* @date creation: Sun Feb 28 2021
* @date last modification: Fri Jun 25 2021
*
* @brief test of the class PhaseFieldModel on the 2d square
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_phasefield.hh"
#include "non_linear_solver.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel &, Real &);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
std::ofstream os("data-explicit.csv");
os << "#strain stress damage analytical_sigma analytical_damage error_stress "
"error_damage"
<< std::endl;
initialize("material_coupling.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("test_one_element.msh");
CouplerSolidPhaseField coupler(mesh);
auto & model = coupler.getSolidMechanicsModel();
auto & phase = coupler.getPhaseFieldModel();
model.initFull(_analysis_method = _explicit_lumped_mass);
Real time_factor = 0.8;
Real stable_time_step = model.getStableTimeStep() * time_factor;
model.setTimeStep(stable_time_step);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
model.setBaseName("phase_solid");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
model.dump();
- UInt nbSteps = 1000;
+ Int nbSteps = 1000;
Real increment = 1e-4;
auto & stress = model.getMaterial(0).getArray<Real>("stress", _quadrangle_4);
auto & damage = model.getMaterial(0).getArray<Real>("damage", _quadrangle_4);
Real analytical_damage{0.};
Real analytical_sigma{0.};
auto & phasefield = phase.getPhaseField(0);
const Real E = phasefield.getParam("E");
const Real nu = phasefield.getParam("nu");
Real c22 = E * (1 - nu) / ((1 + nu) * (1 - 2 * nu));
const Real gc = phasefield.getParam("gc");
const Real l0 = phasefield.getParam("l0");
Real error_stress{0.};
Real error_damage{0.};
- for (UInt s = 0; s < nbSteps; ++s) {
+ for (Int s = 0; s < nbSteps; ++s) {
Real axial_strain = increment * s;
applyDisplacement(model, axial_strain);
coupler.solve("explicit_lumped", "static");
analytical_damage = axial_strain * axial_strain * c22 /
(gc / l0 + axial_strain * axial_strain * c22);
analytical_sigma =
c22 * axial_strain * (1 - analytical_damage) * (1 - analytical_damage);
error_stress = std::abs(analytical_sigma - stress(0, 3)) / analytical_sigma;
error_damage = std::abs(analytical_damage - damage(0)) / analytical_damage;
if (error_damage > 1e-8 and error_stress > 1e-8) {
std::cerr << std::left << std::setw(15)
<< "Error damage: " << error_damage << std::endl;
std::cerr << std::left << std::setw(15)
<< "Error stress: " << error_stress << std::endl;
return EXIT_FAILURE;
}
os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " "
<< analytical_sigma << " " << analytical_damage << " " << error_stress
<< " " << error_damage << std::endl;
model.dump();
}
os.close();
finalize();
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel & model, Real & increment) {
auto & displacement = model.getDisplacement();
auto & positions = model.getMesh().getNodes();
auto & blocked_dofs = model.getBlockedDOFs();
- for (UInt n = 0; n < model.getMesh().getNbNodes(); ++n) {
+ for (Int n = 0; n < model.getMesh().getNbNodes(); ++n) {
if (positions(n, 1) == -0.5) {
displacement(n, 0) = 0;
displacement(n, 1) = 0;
blocked_dofs(n, 0) = true;
blocked_dofs(n, 1) = true;
} else {
displacement(n, 0) = 0;
displacement(n, 1) = increment;
blocked_dofs(n, 0) = true;
blocked_dofs(n, 1) = true;
}
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc
index 520e543c6..2d181d7e7 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc
@@ -1,104 +1,104 @@
/**
* @file test_cohesive_1d_element.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Jan 10 2018
*
* @brief Test for 1D cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
const UInt max_steps = 2000;
const Real strain_rate = 5;
- UInt spatial_dimension = 1;
+ Int spatial_dimension = 1;
Mesh mesh(spatial_dimension, "mesh");
mesh.read("bar.msh");
Math::setTolerance(1e-7);
SolidMechanicsModelCohesive model(mesh);
model.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = true);
auto time_step = model.getStableTimeStep() * 0.01;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
auto posx_max = mesh.getUpperBounds()(_x);
auto posx_min = mesh.getLowerBounds()(_x);
/// initial conditions
const auto & position = mesh.getNodes();
auto & velocity = model.getVelocity();
auto nb_nodes = mesh.getNbNodes();
- for (UInt n = 0; n < nb_nodes; ++n)
+ for (Int n = 0; n < nb_nodes; ++n)
velocity(n) = strain_rate * (position(n) - (posx_max + posx_min) / 2.);
/// boundary conditions
model.applyBC(BC::Dirichlet::FlagOnly(_x), "left");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "right");
auto disp_increment = strain_rate * (posx_max - posx_min) / 2. * time_step;
model.assembleInternalForces();
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.checkCohesiveStress();
model.solveStep();
auto nb_cohesive_elements = mesh.getNbElement(_cohesive_1d_2);
if (s % 10 == 0) {
std::cout << "passing step " << s << "/" << max_steps
<< ", number of cohesive elemets:" << nb_cohesive_elements
<< std::endl;
}
/// update external work and boundary conditions
model.applyBC(BC::Dirichlet::IncrementValue(-disp_increment, _x), "left");
model.applyBC(BC::Dirichlet::IncrementValue(disp_increment, _x), "right");
}
auto Ed = model.getEnergy("dissipated");
auto Edt = 100. * 3.;
std::cout << Ed << " " << Edt << std::endl;
if (std::abs(Ed - Edt) > 0.001 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
finalize();
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc
index 7c81a31e9..1739300f0 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc
@@ -1,183 +1,223 @@
/**
* @file test_cohesive_buildfragments.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu May 09 2019
*
* @brief Test for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+//#include "boost_graph_converter.hh"
#include "fragment_manager.hh"
#include "material_cohesive.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
+#include <algorithm>
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
+static const bool debug_ = true;
+
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
Math::setTolerance(1e-14);
- const UInt spatial_dimension = 2;
- const UInt max_steps = 200;
+ const Int spatial_dimension = 2;
+ const Int max_steps = 200;
Real strain_rate = 1.e5;
ElementType type = _quadrangle_4;
Real L = 0.03;
Real theoretical_mass = L * L / 20. * 2500;
ElementType type_facet = Mesh::getFacetType(type);
ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
Mesh mesh(spatial_dimension);
mesh.read("mesh.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = true);
Real time_step = model.getStableTimeStep() * 0.05;
model.setTimeStep(time_step);
// std::cout << "Time step: " << time_step << std::endl;
Real disp_increment = strain_rate * L / 2. * time_step;
model.assembleMassLumped();
- Array<Real> & velocity = model.getVelocity();
- const Array<Real> & position = mesh.getNodes();
- UInt nb_nodes = mesh.getNbNodes();
+ auto & velocity = model.getVelocity();
+ const auto & position = mesh.getNodes();
+ auto nb_nodes = mesh.getNbNodes();
+ // auto nb_elements = mesh.getNbElement(type);
+ // auto & mesh_facets = mesh.getMeshFacets();
/// initial conditions
- for (UInt n = 0; n < nb_nodes; ++n)
+ for (Int n = 0; n < nb_nodes; ++n) {
velocity(n, 0) = strain_rate * position(n, 0);
+ }
/// boundary conditions
model.applyBC(BC::Dirichlet::FixedValue(0, _x), "Left_side");
model.applyBC(BC::Dirichlet::FixedValue(0, _x), "Right_side");
- UInt cohesive_index = 1;
+ auto cohesive_index = 1;
- UInt nb_quad_per_facet =
+ auto nb_quad_per_facet =
model.getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
- MaterialCohesive & mat_cohesive =
+ auto & mat_cohesive =
dynamic_cast<MaterialCohesive &>(model.getMaterial(cohesive_index));
const Array<Real> & damage = mat_cohesive.getDamage(type_cohesive);
FragmentManager fragment_manager(model, false);
- const Array<Real> & fragment_mass = fragment_manager.getMass();
+
+ if (debug_) {
+ model.setBaseName("buildfragments");
+ model.addDumpFieldVector("displacement");
+ model.addDumpField("velocity");
+ model.addDumpField("acceleration");
+ model.addDumpField("internal_force");
+ model.addDumpField("stress");
+ model.addDumpField("grad_u");
+ model.addDumpFieldToDumper("cohesive elements", "damage");
+ model.dump();
+ }
+
+ Vector<Int> counts(4);
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.checkCohesiveStress();
model.solveStep();
+ // BoostGraphConverter converter(mesh);
+ // converter.toGraphviz("blip_" + std::to_string(s) + ".dot");
+
+ if (debug_) {
+ model.dump();
+ model.dump("cohesive elements");
+ }
/// apply boundary conditions
model.applyBC(BC::Dirichlet::IncrementValue(-disp_increment, _x),
"Left_side");
model.applyBC(BC::Dirichlet::IncrementValue(disp_increment, _x),
"Right_side");
+ // const auto & elements_to_facets = mesh_facets.getSubelementToElement();
+
+ // for (auto && el : element_range(nb_elements, type)) {
+ // auto && element_to_facets = elements_to_facets.get(el);
+ // counts.zero();
+ // for (auto && facet_data : enumerate(element_to_facets)) {
+ // const auto & connected_elements =
+ // mesh_facets.getElementToSubelement(std::get<1>(facet_data));
+ // counts[std::get<0>(facet_data)] = std::count_if(
+ // connected_elements.begin(), connected_elements.end(),
+ // [](auto && element) { return element == ElementNull; });
+ // }
+ // std::cout << el << " - " << counts << std::endl;
+ // }
+
if (s % 1 == 0) {
// model.dump();
std::cout << "passing step " << s << "/" << max_steps << std::endl;
fragment_manager.computeAllData();
/// check number of fragments
- UInt nb_fragment_num = fragment_manager.getNbFragment();
+ Int nb_fragment_num = fragment_manager.getNbFragment();
- UInt nb_cohesive_elements = mesh.getNbElement(type_cohesive);
+ auto nb_cohesive_elements = mesh.getNbElement(type_cohesive);
- UInt nb_fragment = 1;
- for (UInt el = 0; el < nb_cohesive_elements; ++el) {
- UInt q = 0;
+ Int nb_fragment = 1;
+ for (Int el = 0; el < nb_cohesive_elements; ++el) {
+ Int q = 0;
while (q < nb_quad_per_facet &&
Math::are_float_equal(damage(el * nb_quad_per_facet + q), 1))
++q;
if (q == nb_quad_per_facet) {
++nb_fragment;
}
}
if (nb_fragment != nb_fragment_num) {
- std::cout << "The number of fragments is wrong!" << std::endl;
- return EXIT_FAILURE;
+ AKANTU_EXCEPTION("The number of fragments is wrong! Got: "
+ << nb_fragment_num << " - expected: " << nb_fragment);
}
/// check mass computation
- Real total_mass = 0.;
- for (UInt frag = 0; frag < nb_fragment_num; ++frag) {
- total_mass += fragment_mass(frag);
- }
-
- if (!Math::are_float_equal(theoretical_mass, total_mass)) {
- std::cout << "The fragments' mass is wrong!" << std::endl;
- return EXIT_FAILURE;
+ const auto & fragment_mass = fragment_manager.getMass();
+ Vector<Real> zeros = Vector<Real>::Zero(spatial_dimension);
+ auto total_mass =
+ std::accumulate(fragment_mass.begin(spatial_dimension),
+ fragment_mass.end(spatial_dimension), zeros);
+
+ if (!Math::are_float_equal(theoretical_mass, total_mass(0))) {
+ AKANTU_EXCEPTION("The fragments' mass is wrong! Got: "
+ << total_mass(0)
+ << " - expected: " << theoretical_mass);
}
}
}
model.dump();
/// check velocities
- UInt nb_fragment = fragment_manager.getNbFragment();
- const Array<Real> & fragment_velocity = fragment_manager.getVelocity();
- const Array<Real> & fragment_center = fragment_manager.getCenterOfMass();
+ Int nb_fragment = fragment_manager.getNbFragment();
+ const auto & fragment_velocity = fragment_manager.getVelocity();
+ const auto & fragment_center = fragment_manager.getCenterOfMass();
Real fragment_length = L / nb_fragment;
Real initial_position = -L / 2. + fragment_length / 2.;
- for (UInt frag = 0; frag < nb_fragment; ++frag) {
+ for (Int frag = 0; frag < nb_fragment; ++frag) {
Real theoretical_center = initial_position + fragment_length * frag;
if (!Math::are_float_equal(fragment_center(frag, 0), theoretical_center)) {
- std::cout << "The fragments' center is wrong!" << std::endl;
- return EXIT_FAILURE;
+ AKANTU_EXCEPTION("The fragments' center is wrong!");
}
Real initial_vel = fragment_center(frag, 0) * strain_rate;
Math::setTolerance(100);
if (!Math::are_float_equal(fragment_velocity(frag), initial_vel)) {
- std::cout << "The fragments' velocity is wrong!" << std::endl;
- return EXIT_FAILURE;
+ AKANTU_EXCEPTION("The fragments' velocity is wrong!");
}
}
- finalize();
-
std::cout << "OK: test_cohesive_buildfragments was passed!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc
index bf4e24cdf..fbbd9ec4f 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc
@@ -1,136 +1,136 @@
/**
* @file test_cohesive_extrinsic.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Dec 14 2017
*
* @brief Test for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
debug::setDebugLevel(dblWarning);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const UInt max_steps = 1000;
Mesh mesh(spatial_dimension);
mesh.read("triangle.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
model.getElementInserter().setLimit(_y, -0.30, -0.20);
model.updateAutomaticInsertion();
mesh.setBaseName("test_cohesive_extrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("mass");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpFieldVector("external_force");
model.addDumpFieldVector("internal_force");
model.addDumpField("grad_u");
model.dump();
Real time_step = model.getStableTimeStep() * 0.05;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
Array<Real> & position = mesh.getNodes();
Array<Real> & velocity = model.getVelocity();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & displacement = model.getDisplacement();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
boundary(n, 1) = true;
if (position(n, 0) > 0.99 || position(n, 0) < -0.99)
boundary(n, 0) = true;
}
/// initial conditions
Real loading_rate = 0.5;
Real disp_update = loading_rate * time_step;
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
velocity(n, 1) = loading_rate * position(n, 1);
}
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
/// update displacement on extreme nodes
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
displacement(n, 1) += disp_update * position(n, 1);
}
model.checkCohesiveStress();
model.solveStep();
if (s % 100 == 0) {
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
model.dump();
}
Real Ed = model.getEnergy("dissipated");
Real Edt = 200 * std::sqrt(2);
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
finalize();
return EXIT_FAILURE;
}
finalize();
std::cout << "OK: test_cohesive_extrinsic was passed!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc
index 760f84709..a6e3eb4c0 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc
@@ -1,244 +1,244 @@
/**
* @file test_cohesive_extrinsic_fatigue.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Feb 20 2015
* @date last modification: Tue Feb 20 2018
*
* @brief Test for the linear fatigue cohesive law
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear_fatigue.hh"
#include "solid_mechanics_model_cohesive.hh"
#include <limits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
// the following class contains an implementation of the 1D linear
// fatigue cohesive law
class MaterialFatigue {
public:
MaterialFatigue(Real delta_f, Real sigma_c, Real delta_c)
: delta_f(delta_f), sigma_c(sigma_c), delta_c(delta_c), delta_prec(0),
traction(sigma_c), delta_max(0),
stiff_plus(std::numeric_limits<Real>::max()),
tolerance(Math::getTolerance()){};
Real computeTraction(Real delta) {
if (delta - delta_c > -tolerance)
traction = 0;
else if (delta_max < tolerance && delta < tolerance)
traction = sigma_c;
else {
Real delta_dot = delta - delta_prec;
if (delta_dot > -tolerance) {
stiff_plus *= 1 - delta_dot / delta_f;
traction += stiff_plus * delta_dot;
Real max_traction = sigma_c * (1 - delta / delta_c);
if (traction - max_traction > -tolerance || delta_max < tolerance) {
traction = max_traction;
stiff_plus = traction / delta;
}
} else {
Real stiff_minus = traction / delta_prec;
stiff_plus += (stiff_plus - stiff_minus) * delta_dot / delta_f;
traction += stiff_minus * delta_dot;
}
}
delta_prec = delta;
delta_max = std::max(delta, delta_max);
return traction;
}
private:
const Real delta_f;
const Real sigma_c;
const Real delta_c;
Real delta_prec;
Real traction;
Real delta_max;
Real stiff_plus;
const Real tolerance;
};
void imposeOpening(SolidMechanicsModelCohesive &, Real);
void arange(Array<Real> &, Real, Real, Real);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material_fatigue.dat", argc, argv);
Math::setTolerance(1e-13);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const ElementType type = _quadrangle_4;
Mesh mesh(spatial_dimension);
mesh.read("fatigue.msh");
// init stuff
const ElementType type_facet = Mesh::getFacetType(type);
const ElementType type_cohesive =
FEEngine::getCohesiveElementType(type_facet);
SolidMechanicsModelCohesive model(mesh);
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
MaterialCohesiveLinearFatigue<2> & numerical_material =
dynamic_cast<MaterialCohesiveLinearFatigue<2> &>(
model.getMaterial("cohesive"));
Real delta_f = numerical_material.getParam("delta_f");
Real delta_c = numerical_material.getParam("delta_c");
Real sigma_c = 1;
const Array<Real> & traction_array =
numerical_material.getTraction(type_cohesive);
MaterialFatigue theoretical_material(delta_f, sigma_c, delta_c);
// model.setBaseName("fatigue");
// model.addDumpFieldVector("displacement");
// model.addDumpField("stress");
// model.dump();
// stretch material
Real strain = 1;
Array<Real> & displacement = model.getDisplacement();
const Array<Real> & position = mesh.getNodes();
for (UInt n = 0; n < mesh.getNbNodes(); ++n)
displacement(n, 0) = position(n, 0) * strain;
model.assembleInternalForces();
// model.dump();
// insert cohesive elements
model.checkCohesiveStress();
// create the displacement sequence
Real increment = 0.01;
Array<Real> openings;
arange(openings, 0, 0.5, increment);
arange(openings, 0.5, 0.1, increment);
arange(openings, 0.1, 0.7, increment);
arange(openings, 0.7, 0.3, increment);
arange(openings, 0.3, 0.6, increment);
arange(openings, 0.6, 0.3, increment);
arange(openings, 0.3, 0.7, increment);
arange(openings, 0.7, 1.3, increment);
const Array<UInt> & switches = numerical_material.getSwitches(type_cohesive);
// std::ofstream edis("fatigue_edis.txt");
// impose openings
for (UInt i = 0; i < openings.size(); ++i) {
// compute numerical traction
imposeOpening(model, openings(i));
model.assembleInternalForces();
// model.dump();
Real numerical_traction = traction_array(0, 0);
// compute theoretical traction
Real theoretical_traction =
theoretical_material.computeTraction(openings(i));
// test traction
if (std::abs(numerical_traction - theoretical_traction) > 1e-13)
AKANTU_ERROR("The numerical traction "
<< numerical_traction << " and theoretical traction "
<< theoretical_traction << " are not coincident");
// edis << model.getEnergy("dissipated") << std::endl;
}
if (switches(0) != 7)
AKANTU_ERROR("The number of switches is wrong");
std::cout << "OK: the test_cohesive_extrinsic_fatigue passed." << std::endl;
return 0;
}
/* -------------------------------------------------------------------------- */
void imposeOpening(SolidMechanicsModelCohesive & model, Real opening) {
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Mesh & mesh = model.getFEEngine().getMesh();
Array<Real> & position = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
UInt nb_nodes = mesh.getNbNodes();
Array<bool> update(nb_nodes);
update.zero();
Mesh::type_iterator it = mesh.firstType(spatial_dimension);
Mesh::type_iterator end = mesh.lastType(spatial_dimension);
for (; it != end; ++it) {
ElementType type = *it;
UInt nb_element = mesh.getNbElement(type);
UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
const Array<UInt> & connectivity = mesh.getConnectivity(type);
Vector<Real> barycenter(spatial_dimension);
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
mesh.getBarycenter({type, el, _not_ghost}, barycenter);
if (barycenter(0) > 1) {
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
UInt node = connectivity(el, n);
if (!update(node)) {
displacement(node, 0) = opening + position(node, 0);
update(node) = true;
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void arange(Array<Real> & openings, Real begin, Real end, Real increment) {
if (begin < end) {
for (Real opening = begin; opening < end - increment / 2.;
opening += increment)
openings.push_back(opening);
} else {
for (Real opening = begin; opening > end + increment / 2.;
opening -= increment)
openings.push_back(opening);
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc
index 119b0faff..8dc457272 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc
@@ -1,129 +1,129 @@
/**
* @file test_cohesive_extrinsic_quadrangle.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Dec 14 2017
*
* @brief Test for extrinsic cohesive elements and quadrangles
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const UInt max_steps = 1000;
Mesh mesh(spatial_dimension);
mesh.read("quadrangle.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
model.getElementInserter().setLimit(_y, -0.05, 0.05);
model.updateAutomaticInsertion();
Real time_step = model.getStableTimeStep() * 0.05;
model.setTimeStep(time_step);
// std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
const Array<Real> & position = mesh.getNodes();
Array<Real> & velocity = model.getVelocity();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & displacement = model.getDisplacement();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
boundary(n, 1) = true;
if (position(n, 0) > 0.99 || position(n, 0) < -0.99)
boundary(n, 0) = true;
}
model.assembleInternalForces();
/// initial conditions
Real loading_rate = 0.2;
Real disp_update = loading_rate * time_step;
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
velocity(n, 1) = loading_rate * position(n, 1);
}
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
/// update displacement on extreme nodes
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
displacement(n, 1) += disp_update * position(n, 1);
}
model.checkCohesiveStress();
model.solveStep();
if (s % 1 == 0) {
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
}
mesh.write("mesh_final.msh");
Real Ed = model.getEnergy("dissipated");
Real Edt = 200;
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.99 || Ed > Edt * 1.01 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
return EXIT_FAILURE;
}
finalize();
std::cout << "OK: test_cohesive_extrinsic_quadrangle was passed!"
<< std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc
index 76dd30965..426efa6ad 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc
@@ -1,240 +1,240 @@
/**
* @file test_cohesive_extrinsic_tetrahedron.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Aug 22 2017
*
* @brief Test for serial extrinsic cohesive elements for tetrahedron
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
Real function(Real constant, Real x, Real y, Real z) {
return constant + 2. * x + 3. * y + 4 * z;
}
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
// const UInt max_steps = 1000;
// Real increment = 0.005;
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
Math::setTolerance(1.e-12);
ElementType type = _tetrahedron_10;
ElementType type_facet = Mesh::getFacetType(type);
ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
Mesh mesh(spatial_dimension);
mesh.read("tetrahedron.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
const MaterialCohesiveLinear<3> & mat_cohesive =
dynamic_cast<const MaterialCohesiveLinear<3> &>(model.getMaterial(1));
std::cout << mat_cohesive << std::endl;
std::cout << model.getMaterial(2) << std::endl;
const Real sigma_c = mat_cohesive.get("sigma_c");
const Real beta = mat_cohesive.get("beta");
std::cout << sigma_c << " " << beta << std::endl;
Array<Real> & position = mesh.getNodes();
/* ------------------------------------------------------------------------ */
/* Facet part */
/* ------------------------------------------------------------------------ */
/// compute quadrature points positions on facets
const Mesh & mesh_facets = model.getMeshFacets();
UInt nb_facet = mesh_facets.getNbElement(type_facet);
UInt nb_quad_per_facet =
model.getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
UInt nb_tot_quad = nb_quad_per_facet * nb_facet;
Array<Real> quad_facets(nb_tot_quad, spatial_dimension);
model.getFEEngine("FacetsFEEngine")
.interpolateOnIntegrationPoints(position, quad_facets, spatial_dimension,
type_facet);
/* ------------------------------------------------------------------------ */
/* End of facet part */
/* ------------------------------------------------------------------------ */
/// compute quadrature points position of the elements
UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type);
UInt nb_element = mesh.getNbElement(type);
UInt nb_tot_quad_el = nb_quad_per_element * nb_element;
Array<Real> quad_elements(nb_tot_quad_el, spatial_dimension);
model.getFEEngine().interpolateOnIntegrationPoints(position, quad_elements,
spatial_dimension, type);
/// assign some values to stresses
Array<Real> & stress =
const_cast<Array<Real> &>(model.getMaterial(0).getStress(type));
Array<Real>::iterator<Matrix<Real>> stress_it =
stress.begin(spatial_dimension, spatial_dimension);
for (UInt q = 0; q < nb_tot_quad_el; ++q, ++stress_it) {
/// compute values
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = i; j < spatial_dimension; ++j) {
UInt index = i * spatial_dimension + j;
(*stress_it)(i, j) =
index * function(sigma_c * 5, quad_elements(q, 0),
quad_elements(q, 1), quad_elements(q, 2));
}
}
/// fill symmetrical part
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = 0; j < i; ++j) {
(*stress_it)(i, j) = (*stress_it)(j, i);
}
}
}
/// compute stress on facet quads
Array<Real> stress_facets(nb_tot_quad, spatial_dimension * spatial_dimension);
Array<Real>::iterator<Matrix<Real>> stress_facets_it =
stress_facets.begin(spatial_dimension, spatial_dimension);
for (UInt q = 0; q < nb_tot_quad; ++q, ++stress_facets_it) {
/// compute values
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = i; j < spatial_dimension; ++j) {
UInt index = i * spatial_dimension + j;
(*stress_facets_it)(i, j) =
index * function(sigma_c * 5, quad_facets(q, 0), quad_facets(q, 1),
quad_facets(q, 2));
}
}
/// fill symmetrical part
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = 0; j < i; ++j) {
(*stress_facets_it)(i, j) = (*stress_facets_it)(j, i);
}
}
}
/// insert cohesive elements
model.checkCohesiveStress();
/// check insertion stress
const Array<Real> & normals = model.getFEEngine("FacetsFEEngine")
.getNormalsOnIntegrationPoints(type_facet);
const Array<Real> & tangents = model.getTangents(type_facet);
const Array<Real> & sigma_c_eff =
mat_cohesive.getInsertionTraction(type_cohesive);
Vector<Real> normal_stress(spatial_dimension);
const Array<std::vector<Element>> & coh_element_to_facet =
mesh_facets.getElementToSubelement(type_facet);
Array<Real>::iterator<Matrix<Real>> quad_facet_stress =
stress_facets.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_iterator<Vector<Real>> quad_normal =
normals.begin(spatial_dimension);
Array<Real>::const_iterator<Vector<Real>> quad_tangents =
tangents.begin(tangents.getNbComponent());
for (UInt f = 0; f < nb_facet; ++f) {
const Element & cohesive_element = coh_element_to_facet(f)[1];
for (UInt q = 0; q < nb_quad_per_facet;
++q, ++quad_facet_stress, ++quad_normal, ++quad_tangents) {
if (cohesive_element == ElementNull)
continue;
normal_stress.mul<false>(*quad_facet_stress, *quad_normal);
Real normal_contrib = normal_stress.dot(*quad_normal);
Real first_tangent_contrib = 0;
- for (UInt dim = 0; dim < spatial_dimension; ++dim)
+ for (Int dim = 0; dim < spatial_dimension; ++dim)
first_tangent_contrib += normal_stress(dim) * (*quad_tangents)(dim);
Real second_tangent_contrib = 0;
- for (UInt dim = 0; dim < spatial_dimension; ++dim)
+ for (Int dim = 0; dim < spatial_dimension; ++dim)
second_tangent_contrib +=
normal_stress(dim) * (*quad_tangents)(dim + spatial_dimension);
Real tangent_contrib =
std::sqrt(first_tangent_contrib * first_tangent_contrib +
second_tangent_contrib * second_tangent_contrib);
normal_contrib = std::max(0., normal_contrib);
Real effective_norm =
std::sqrt(normal_contrib * normal_contrib +
tangent_contrib * tangent_contrib / beta / beta);
if (effective_norm < sigma_c)
continue;
if (!Math::are_float_equal(
effective_norm,
sigma_c_eff(cohesive_element.element * nb_quad_per_facet + q))) {
std::cout << "Insertion tractions do not match" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
}
finalize();
std::cout << "OK: test_cohesive_extrinsic was passed!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc
index 01132d989..baabd6a60 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc
@@ -1,172 +1,172 @@
/**
* @file test_assembling_K_cohe_elements.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
*
* @date creation: Fri May 15 2015
* @date last modification: Tue Feb 20 2018
*
* @brief Test to check the correct matrix assembling for cohesive elements
* with degenerated nodes
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model_cohesive.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
debug::setDebugLevel(dblWarning);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Real increment = 0.004;
bool passed = true;
Real tol = 1.0e-13;
Mesh mesh(spatial_dimension);
mesh.read("quadrangle.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull(SolidMechanicsModelCohesiveOptions(_static, true));
/// CohesiveElementInserter
model.getElementInserter().setLimit(_y, -0.001, 0.001);
model.updateAutomaticInsertion();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & position = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
// SparseMatrix & K_test = model.getStiffnessMatrix();
Array<Real> K_verified(0, 3, "K_matrix_verified");
Array<Real> K_test(0, 3, "K_matrix_test");
/// load the verified stiffness matrix
Vector<Real> tmp(3);
UInt nb_lines;
std::ifstream infile("K_matrix_verified.dat");
std::string line;
if (!infile.good())
AKANTU_ERROR("Cannot open file K_matrix_verified.dat");
else {
- for (UInt i = 0; i < 2; ++i) {
+ for (Int i = 0; i < 2; ++i) {
getline(infile, line);
std::stringstream sstr_data(line);
if (i == 1) {
sstr_data >> tmp(0) >> tmp(1) >> tmp(2);
nb_lines = tmp(2);
}
}
- for (UInt i = 0; i < nb_lines; ++i) {
+ for (Int i = 0; i < nb_lines; ++i) {
getline(infile, line);
std::stringstream sstr_data(line);
sstr_data >> tmp(0) >> tmp(1) >> tmp(2);
K_verified.push_back(tmp);
}
}
infile.close();
/// impose boundary conditions
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (position(n, 1) < -0.99) {
boundary(n, 1) = true;
boundary(n, 0) = true;
}
if (position(n, 1) > 0.99 && position(n, 0) < -0.99)
boundary(n, 1) = true;
}
/// solve step
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (position(n, 1) > 0.99 && position(n, 0) < -0.99)
displacement(n, 1) += increment;
}
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 10);
solver.set("threshold", 1e-13);
model.solveStep();
model.getDOFManager().getMatrix("K").saveMatrix("K_matrix_test.dat");
/// load the stiffness matrix to be tested
std::ifstream infile2("K_matrix_test.dat");
if (!infile2.good())
AKANTU_ERROR("Cannot open file K_matrix_test.dat");
else {
- for (UInt i = 0; i < 2; ++i) {
+ for (Int i = 0; i < 2; ++i) {
getline(infile2, line);
std::stringstream sstr_data(line);
if (i == 1) {
sstr_data >> tmp(0) >> tmp(1) >> tmp(2);
nb_lines = tmp(2);
}
}
- for (UInt i = 0; i < nb_lines; ++i) {
+ for (Int i = 0; i < nb_lines; ++i) {
getline(infile2, line);
std::stringstream sstr_data(line);
sstr_data >> tmp(0) >> tmp(1) >> tmp(2);
K_test.push_back(tmp);
}
}
infile2.close();
- for (UInt i = 0; i < K_verified.size(); ++i) {
- for (UInt j = 0; j < K_test.size(); ++j) {
+ for (Int i = 0; i < K_verified.size(); ++i) {
+ for (Int j = 0; j < K_test.size(); ++j) {
if ((K_test(j, 0) == K_verified(i, 0)) &&
(K_test(j, 1) == K_verified(i, 1))) {
if (std::abs(K_verified(i, 2)) < tol) {
if (std::abs(K_test(j, 2)) > tol)
passed = false;
} else {
Real ratio = (std::abs(K_test(j, 2) - K_verified(i, 2))) /
(std::abs(K_verified(i, 2)));
if (ratio > tol)
passed = false;
}
}
}
}
finalize();
if (passed)
return EXIT_SUCCESS;
else
return EXIT_FAILURE;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_fixture.hh b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_fixture.hh
index 80363caf4..b2f357fe6 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_fixture.hh
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_fixture.hh
@@ -1,347 +1,352 @@
/**
* @file test_cohesive_fixture.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Jan 10 2018
* @date last modification: Wed Nov 18 2020
*
* @brief Coehsive element test fixture
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "solid_mechanics_model_cohesive.hh"
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TEST_COHESIVE_FIXTURE_HH_
#define AKANTU_TEST_COHESIVE_FIXTURE_HH_
using namespace akantu;
template <::akantu::AnalysisMethod t>
using analysis_method_t = std::integral_constant<::akantu::AnalysisMethod, t>;
class StrainIncrement : public BC::Functor {
public:
StrainIncrement(const Matrix<Real> & strain, BC::Axis dir)
: strain_inc(strain), dir(dir) {}
void operator()(UInt /*node*/, Vector<bool> & flags, Vector<Real> & primal,
const Vector<Real> & coord) const {
if (std::abs(coord(dir)) < 1e-8) {
return;
}
flags.set(true);
primal += strain_inc * coord;
}
static const BC::Functor::Type type = BC::Functor::_dirichlet;
private:
Matrix<Real> strain_inc;
BC::Axis dir;
};
template <typename param_> class TestSMMCFixture : public ::testing::Test {
public:
static constexpr ElementType cohesive_type =
std::tuple_element_t<0, param_>::value;
static constexpr ElementType type_1 = std::tuple_element_t<1, param_>::value;
static constexpr ElementType type_2 = std::tuple_element_t<2, param_>::value;
static constexpr size_t dim =
ElementClass<cohesive_type>::getSpatialDimension();
void SetUp() {
mesh = std::make_unique<Mesh>(this->dim);
if (Communicator::getStaticCommunicator().whoAmI() == 0) {
mesh->read(this->mesh_name);
}
mesh->distribute();
}
void TearDown() {
model.reset(nullptr);
mesh.reset(nullptr);
}
void createModel() {
model = std::make_unique<SolidMechanicsModelCohesive>(*mesh);
model->initFull(_analysis_method = this->analysis_method,
_is_extrinsic = this->is_extrinsic);
auto time_step = this->model->getStableTimeStep() * 0.01;
this->model->setTimeStep(time_step);
if (dim == 1) {
surface = 1;
group_size = 1;
return;
}
auto facet_type = mesh->getFacetType(this->cohesive_type);
auto & fe_engine = model->getFEEngineBoundary();
const auto & group = mesh->getElementGroup("insertion");
group_size = group.size(_ghost_type = _not_ghost);
const auto & elements = group.getElements(facet_type);
Array<Real> ones(fe_engine.getNbIntegrationPoints(facet_type) * group_size);
ones.set(1.);
surface = fe_engine.integrate(ones, facet_type, _not_ghost, elements);
mesh->getCommunicator().allReduce(surface, SynchronizerOperation::_sum);
mesh->getCommunicator().allReduce(group_size, SynchronizerOperation::_sum);
#define debug_ 0
#if debug_
+ auto size = mesh->getCommunicator().getNbProc();
+ this->model->setBaseName("solid_mechanics_model_cohesive_" +
+ std::to_string(size));
+ // this->model->addDumpField("partition");
this->model->addDumpFieldVector("displacement");
this->model->addDumpFieldVector("velocity");
this->model->addDumpFieldVector("internal_force");
this->model->addDumpFieldVector("external_force");
this->model->addDumpField("blocked_dofs");
this->model->addDumpField("stress");
this->model->addDumpField("strain");
this->model->assembleInternalForces();
- this->model->setBaseNameToDumper("cohesive elements", "cohesive_elements");
+ this->model->setBaseNameToDumper(
+ "cohesive elements", "cohesive_elements_" + std::to_string(size));
this->model->addDumpFieldVectorToDumper("cohesive elements",
"displacement");
this->model->addDumpFieldToDumper("cohesive elements", "damage");
this->model->addDumpFieldToDumper("cohesive elements", "tractions");
this->model->addDumpFieldToDumper("cohesive elements", "opening");
this->model->dump();
this->model->dump("cohesive elements");
#endif
}
void setInitialCondition(const Matrix<Real> & strain) {
for (auto && data :
zip(make_view(this->mesh->getNodes(), this->dim),
make_view(this->model->getDisplacement(), this->dim))) {
const auto & pos = std::get<0>(data);
auto & disp = std::get<1>(data);
disp = strain * pos;
}
}
bool checkDamaged() {
UInt nb_damaged = 0;
auto & damage =
model->getMaterial("insertion").getArray<Real>("damage", cohesive_type);
for (auto d : damage) {
if (d >= .99) {
++nb_damaged;
}
}
return (nb_damaged == group_size);
}
void steps(const Matrix<Real> & strain) {
StrainIncrement functor((1. / 300) * strain, this->dim == 1 ? _x : _y);
for (auto _ [[gnu::unused]] : arange(nb_steps)) {
this->model->applyBC(functor, "loading");
this->model->applyBC(functor, "fixed");
if (this->is_extrinsic) {
this->model->checkCohesiveStress();
}
this->model->solveStep();
#if debug_
this->model->dump();
this->model->dump("cohesive elements");
#endif
}
}
void checkInsertion() {
auto nb_cohesive_element = this->mesh->getNbElement(cohesive_type);
mesh->getCommunicator().allReduce(nb_cohesive_element,
SynchronizerOperation::_sum);
EXPECT_EQ(nb_cohesive_element, group_size);
}
void checkDissipated(Real expected_density) {
Real edis = this->model->getEnergy("dissipated");
EXPECT_NEAR(this->surface * expected_density, edis, 5e-1);
}
void testModeI() {
this->createModel();
auto & mat_el = this->model->getMaterial("body");
auto speed = mat_el.getPushWaveSpeed(Element());
auto direction = _y;
if (dim == 1) {
direction = _x;
}
auto length =
mesh->getUpperBounds()(direction) - mesh->getLowerBounds()(direction);
nb_steps = length / speed / model->getTimeStep();
SCOPED_TRACE(std::to_string(this->dim) + "D - " + std::to_string(type_1) +
":" + std::to_string(type_2));
auto & mat_co = this->model->getMaterial("insertion");
Real sigma_c = mat_co.get("sigma_c");
Real E = mat_el.get("E");
Real nu = mat_el.get("nu");
Matrix<Real> strain;
if (dim == 1) {
- strain = {{1.}};
+ strain = Matrix<Real>{{1.}};
} else if (dim == 2) {
- strain = {{-nu, 0.}, {0., 1. - nu}};
+ strain = Matrix<Real>{{-nu, 0.}, {0., 1. - nu}};
strain *= (1. + nu);
} else if (dim == 3) {
- strain = {{-nu, 0., 0.}, {0., 1., 0.}, {0., 0., -nu}};
+ strain = Matrix<Real>{{-nu, 0., 0.}, {0., 1., 0.}, {0., 0., -nu}};
}
strain *= sigma_c / E;
this->setInitialCondition((1 - 1e-5) * strain);
this->steps(2e-2 * strain);
}
void testModeII() {
this->createModel();
auto & mat_el = this->model->getMaterial("body");
Real speed;
try {
speed =
mat_el.getShearWaveSpeed(Element()); // the slowest speed if exists
} catch (...) {
speed = mat_el.getPushWaveSpeed(Element());
}
auto direction = _y;
if (dim == 1)
direction = _x;
auto length =
mesh->getUpperBounds()(direction) - mesh->getLowerBounds()(direction);
nb_steps = 2 * length / 2. / speed / model->getTimeStep();
SCOPED_TRACE(std::to_string(this->dim) + "D - " + std::to_string(type_1) +
":" + std::to_string(type_2));
if (this->dim > 1)
this->model->applyBC(BC::Dirichlet::FlagOnly(_y), "sides");
if (this->dim > 2)
this->model->applyBC(BC::Dirichlet::FlagOnly(_z), "sides");
auto & mat_co = this->model->getMaterial("insertion");
Real sigma_c = mat_co.get("sigma_c");
Real beta = mat_co.get("beta");
// Real G_c = mat_co.get("G_c");
Real E = mat_el.get("E");
Real nu = mat_el.get("nu");
Matrix<Real> strain;
if (dim == 1) {
- strain = {{1.}};
+ strain = Matrix<Real>{{1.}};
} else if (dim == 2) {
- strain = {{0., 1.}, {0., 0.}};
+ strain = Matrix<Real>{{0., 1.}, {0., 0.}};
strain *= (1. + nu);
} else if (dim == 3) {
- strain = {{0., 1., 0.}, {0., 0., 0.}, {0., 0., 0.}};
+ strain = Matrix<Real>{{0., 1., 0.}, {0., 0., 0.}, {0., 0., 0.}};
strain *= (1. + nu);
}
strain *= 2 * beta * beta * sigma_c / E;
// nb_steps *= 5;
this->setInitialCondition((1. - 1e-5) * strain);
this->steps(0.005 * strain);
}
protected:
std::unique_ptr<Mesh> mesh;
std::unique_ptr<SolidMechanicsModelCohesive> model;
std::string mesh_name{std::to_string(cohesive_type) + std::to_string(type_1) +
(type_1 == type_2 ? "" : std::to_string(type_2)) +
".msh"};
bool is_extrinsic;
AnalysisMethod analysis_method;
Real surface{0};
UInt nb_steps{1000};
UInt group_size{10000};
};
/* -------------------------------------------------------------------------- */
template <typename param_>
constexpr ElementType TestSMMCFixture<param_>::cohesive_type;
template <typename param_>
constexpr ElementType TestSMMCFixture<param_>::type_1;
template <typename param_>
constexpr ElementType TestSMMCFixture<param_>::type_2;
template <typename param_> constexpr size_t TestSMMCFixture<param_>::dim;
/* -------------------------------------------------------------------------- */
using IsExtrinsicTypes = std::tuple<std::true_type, std::false_type>;
using AnalysisMethodTypes =
std::tuple<analysis_method_t<_explicit_lumped_mass>>;
using coh_types = gtest_list_t<std::tuple<
std::tuple<_element_type_cohesive_1d_2, _element_type_segment_2,
_element_type_segment_2>,
std::tuple<_element_type_cohesive_2d_4, _element_type_triangle_3,
_element_type_triangle_3>,
std::tuple<_element_type_cohesive_2d_4, _element_type_quadrangle_4,
_element_type_quadrangle_4>,
std::tuple<_element_type_cohesive_2d_4, _element_type_triangle_3,
_element_type_quadrangle_4>,
std::tuple<_element_type_cohesive_2d_6, _element_type_triangle_6,
_element_type_triangle_6>,
std::tuple<_element_type_cohesive_2d_6, _element_type_quadrangle_8,
_element_type_quadrangle_8>,
std::tuple<_element_type_cohesive_2d_6, _element_type_triangle_6,
_element_type_quadrangle_8>,
std::tuple<_element_type_cohesive_3d_6, _element_type_tetrahedron_4,
_element_type_tetrahedron_4>,
std::tuple<_element_type_cohesive_3d_12, _element_type_tetrahedron_10,
_element_type_tetrahedron_10> /*,
std::tuple<_element_type_cohesive_3d_8, _element_type_hexahedron_8,
_element_type_hexahedron_8>,
std::tuple<_element_type_cohesive_3d_16, _element_type_hexahedron_20,
_element_type_hexahedron_20>*/>>;
TYPED_TEST_SUITE(TestSMMCFixture, coh_types, );
#endif /* AKANTU_TEST_COHESIVE_FIXTURE_HH_ */
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_cohesive_insertion_along_physical_surfaces.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_cohesive_insertion_along_physical_surfaces.cc
index 4b5b16f85..b137107f9 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_cohesive_insertion_along_physical_surfaces.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_cohesive_insertion_along_physical_surfaces.cc
@@ -1,95 +1,95 @@
/**
* @file test_cohesive_insertion_along_physical_surfaces.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Aug 07 2015
* @date last modification: Thu Oct 29 2020
*
* @brief Test intrinsic insertion of cohesive elements along physical surfaces
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_cohesive.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_io_msh.hh"
#include "mesh_utils.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("input_file.dat", argc, argv);
Math::setTolerance(1e-15);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
Mesh mesh(spatial_dimension);
mesh.read("3d_spherical_inclusion.msh");
SolidMechanicsModelCohesive model(mesh);
auto && material_selector =
std::make_shared<MeshDataMaterialCohesiveSelector>(model);
material_selector->setFallback(model.getMaterialSelector());
model.setMaterialSelector(material_selector);
model.initFull();
std::vector<std::string> surfaces_name = {"interface", "coh1", "coh2",
"coh3", "coh4", "coh5"};
- UInt nb_surf = surfaces_name.size();
+ Int nb_surf = surfaces_name.size();
- for (auto & type :
+ for (const auto & type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_cohesive)) {
- for (UInt i = 0; i < nb_surf; ++i) {
+ for (Int i = 0; i < nb_surf; ++i) {
- UInt expected_insertion = mesh.getElementGroup(surfaces_name[i])
+ auto expected_insertion = mesh.getElementGroup(surfaces_name[i])
.getElements(mesh.getFacetType(type))
.size();
- UInt inserted_elements =
+ auto inserted_elements =
model.getMaterial(surfaces_name[i]).getElementFilter()(type).size();
if (not(expected_insertion == inserted_elements)) {
std::cout << "!!! Mismatch in insertion of surface named "
<< surfaces_name[i] << " --> " << inserted_elements
<< " inserted elements out of " << expected_insertion
<< std::endl;
return 1;
}
}
}
return 0;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_group_update.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_group_update.cc
index daf419c65..38d7cf204 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_group_update.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_insertion/test_group_update.cc
@@ -1,65 +1,65 @@
#include <non_linear_solver.hh>
#include <solid_mechanics_model_cohesive.hh>
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("bar.msh");
// Create model
SolidMechanicsModelCohesive model(mesh);
model.initFull(_analysis_method = _static, _is_extrinsic = true);
// Configure solver
auto & solver = model.getNonLinearSolver("static");
solver.set("max_iterations", 100);
solver.set("threshold", 1e-10);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
model.initNewSolver(_explicit_lumped_mass);
// Dynamic insertion of cohesive elements
model.updateAutomaticInsertion();
auto dt_crit = model.getStableTimeStep(); // Critical time step
auto dt = dt_crit * 0.1; // Adopted time step
auto time_simulation = 6.0e-6; // Total time of simulation (s)
auto n_steps = int(time_simulation / dt); // Number of time steps
// Apply Dirichlet BC to block displacements at y direction on top and
// bottom
model.applyBC(BC::Dirichlet::FixedValue(0., _y), "YBlocked");
// Constant velocity boundary condition
// Applied strain rate(s - 1)
auto strain_rate = 1e5;
// Applied velocity at the boundary
auto vel =
strain_rate * (mesh.getUpperBounds()(_x) - mesh.getLowerBounds()(_x)) / 2;
model.applyBC(BC::Dirichlet::IncrementValue(-vel * dt, _x), "left");
model.applyBC(BC::Dirichlet::IncrementValue(vel * dt, _x), "right");
// VTK plot setup
model.setBaseName("bar");
model.addDumpFieldVector("displacement");
// VTK plot setup for Cohesive model
model.setBaseNameToDumper("cohesive elements", "cohesive");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
- for (auto n : arange(n_steps)) {
+ for (auto _ [[gnu::unused]] : arange(n_steps)) {
// Apply velocity at the extremities
model.applyBC(BC::Dirichlet::IncrementValue(-vel * dt, _x), "left");
model.applyBC(BC::Dirichlet::IncrementValue(vel * dt, _x), "right");
model.dump();
model.dump("cohesive elements");
// Run simulation
model.checkCohesiveStress();
model.solveStep("explicit_lumped");
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc
index 0392290d9..aa3079f6e 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc
@@ -1,180 +1,180 @@
/**
* @file test_cohesive_intrinsic.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Dec 18 2017
*
* @brief Test for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "mesh.hh"
#include "mesh_utils.hh"
#include "solid_mechanics_model_cohesive.hh"
#include "dumper_paraview.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
static void updateDisplacement(SolidMechanicsModelCohesive &, Array<UInt> &,
ElementType, Real);
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
debug::setDebugLevel(dblWarning);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const UInt max_steps = 350;
const ElementType type = _triangle_6;
Mesh mesh(spatial_dimension);
mesh.read("triangle.msh");
std::cout << mesh << std::endl;
SolidMechanicsModelCohesive model(mesh);
model.getElementInserter().setLimit(_x, -0.26, -0.24);
/// model initialization
model.initFull();
mesh.write("mesh_cohesive.msh");
Real time_step = model.getStableTimeStep() * 0.8;
model.setTimeStep(time_step);
// std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
Array<bool> & boundary = model.getBlockedDOFs();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
UInt nb_element = mesh.getNbElement(type);
/// boundary conditions
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int n = 0; n < nb_nodes; ++n) {
boundary(n, dim) = true;
}
}
model.assembleInternalForces();
model.setBaseName("intrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("internal_force");
model.addDumpField("stress");
model.addDumpField("strain");
model.addDumpField("external_force");
model.dump();
model.setBaseNameToDumper("cohesive elements", "cohesive_elements_triangle");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump("cohesive elements");
/// update displacement
Array<UInt> elements;
Vector<Real> bary(spatial_dimension);
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
mesh.getBarycenter({type, el, _not_ghost}, bary);
if (bary(0) > -0.25)
elements.push_back(el);
}
Real increment = 0.01;
updateDisplacement(model, elements, type, increment);
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
updateDisplacement(model, elements, type, increment);
if (s % 1 == 0) {
model.dump();
model.dump("cohesive elements");
std::cout << "passing step " << s << "/" << max_steps
<< ", Ed = " << model.getEnergy("dissipated") << std::endl;
}
}
Real Ed = model.getEnergy("dissipated");
Real Edt = 2 * sqrt(2);
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
return EXIT_FAILURE;
}
finalize();
std::cout << "OK: test_cohesive_intrinsic was passed!" << std::endl;
return EXIT_SUCCESS;
}
static void updateDisplacement(SolidMechanicsModelCohesive & model,
Array<UInt> & elements, ElementType type,
Real increment) {
Mesh & mesh = model.getFEEngine().getMesh();
UInt nb_element = elements.size();
UInt nb_nodes = mesh.getNbNodes();
UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
const Array<UInt> & connectivity = mesh.getConnectivity(type);
Array<Real> & displacement = model.getDisplacement();
Array<bool> update(nb_nodes);
update.zero();
- for (UInt el = 0; el < nb_element; ++el) {
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int el = 0; el < nb_element; ++el) {
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
UInt node = connectivity(elements(el), n);
if (!update(node)) {
displacement(node, 0) += increment;
// displacement(node, 1) += increment;
update(node) = true;
}
}
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc
index c5714ff55..03797df7f 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc
@@ -1,207 +1,207 @@
/**
* @file test_cohesive_intrinsic_quadrangle.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Dec 18 2017
*
* @brief Intrinsic cohesive elements' test for quadrangles
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
static void updateDisplacement(SolidMechanicsModelCohesive &, Array<UInt> &,
ElementType, Real);
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const UInt max_steps = 350;
const ElementType type = _quadrangle_4;
Mesh mesh(spatial_dimension);
mesh.read("quadrangle.msh");
// debug::setDebugLevel(dblDump);
// std::cout << mesh << std::endl;
// debug::setDebugLevel(dblWarning);
SolidMechanicsModelCohesive model(mesh);
model.getElementInserter().setLimit(_x, -0.01, 0.01);
/// model initialization
model.initFull();
Real time_step = model.getStableTimeStep() * 0.8;
model.setTimeStep(time_step);
model.assembleMassLumped();
Array<bool> & boundary = model.getBlockedDOFs();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
UInt nb_element = mesh.getNbElement(type);
/// boundary conditions
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int n = 0; n < nb_nodes; ++n) {
boundary(n, dim) = true;
}
}
model.assembleInternalForces();
model.setBaseName("intrinsic_quadrangle");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("internal_force");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("external_force");
model.setBaseNameToDumper("cohesive elements",
"cohesive_elements_quadrangle");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump();
model.dump("cohesive elements");
/// update displacement
Array<UInt> elements;
Vector<Real> bary(spatial_dimension);
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
mesh.getBarycenter({type, el, _not_ghost}, bary);
if (bary(_x) > 0.)
elements.push_back(el);
}
Real increment = 0.01;
updateDisplacement(model, elements, type, increment);
- // for (UInt n = 0; n < nb_nodes; ++n) {
+ // for (Int n = 0; n < nb_nodes; ++n) {
// if (position(n, 1) + displacement(n, 1) > 0) {
// if (position(n, 0) == 0) {
// displacement(n, 1) -= 0.25;
// }
// if (position(n, 0) == 1) {
// displacement(n, 1) += 0.25;
// }
// }
// }
// std::ofstream edis("edis.txt");
// std::ofstream erev("erev.txt");
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
updateDisplacement(model, elements, type, increment);
if (s % 1 == 0) {
model.dump();
model.dump("cohesive elements");
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
// // update displacement
- // for (UInt n = 0; n < nb_nodes; ++n) {
+ // for (Int n = 0; n < nb_nodes; ++n) {
// if (position(n, 1) + displacement(n, 1) > 0) {
// displacement(n, 0) -= 0.01;
// }
// }
// Real Ed = dynamic_cast<MaterialCohesive&>
// (model.getMaterial(1)).getDissipatedEnergy();
// Real Er = dynamic_cast<MaterialCohesive&>
// (model.getMaterial(1)).getReversibleEnergy();
// edis << s << " "
// << Ed << std::endl;
// erev << s << " "
// << Er << std::endl;
}
// edis.close();
// erev.close();
Real Ed = model.getEnergy("dissipated");
Real Edt = 1;
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.999 || Ed > Edt * 1.001) {
std::cout << "The dissipated energy is incorrect" << std::endl;
return EXIT_FAILURE;
}
finalize();
std::cout << "OK: test_cohesive_intrinsic_quadrangle was passed!"
<< std::endl;
return EXIT_SUCCESS;
}
static void updateDisplacement(SolidMechanicsModelCohesive & model,
Array<UInt> & elements, ElementType type,
Real increment) {
Mesh & mesh = model.getFEEngine().getMesh();
UInt nb_element = elements.size();
UInt nb_nodes = mesh.getNbNodes();
UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
const Array<UInt> & connectivity = mesh.getConnectivity(type);
Array<Real> & displacement = model.getDisplacement();
Array<bool> update(nb_nodes);
update.zero();
- for (UInt el = 0; el < nb_element; ++el) {
- for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+ for (Int el = 0; el < nb_element; ++el) {
+ for (Int n = 0; n < nb_nodes_per_element; ++n) {
UInt node = connectivity(elements(el), n);
if (!update(node)) {
displacement(node, 0) += increment;
// displacement(node, 1) += increment;
update(node) = true;
}
}
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc
index 6443d7691..7a4864887 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc
@@ -1,355 +1,354 @@
/**
* @file test_cohesive_intrinsic_tetrahedron.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Dec 18 2017
*
* @brief Test for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "material_cohesive.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class Checker {
public:
Checker(const SolidMechanicsModelCohesive & model,
const Array<UInt> & elements, ElementType type);
void check(const Vector<Real> & opening, const Matrix<Real> & rotation) {
checkTractions(opening, rotation);
checkEquilibrium();
computeEnergy(opening);
}
void updateDisplacement(const Vector<Real> & increment);
protected:
void checkTractions(const Vector<Real> & opening,
const Matrix<Real> & rotation);
void checkEquilibrium();
void checkResidual(const Matrix<Real> & rotation);
void computeEnergy(const Vector<Real> & opening);
private:
std::set<UInt> nodes_to_check;
const SolidMechanicsModelCohesive & model;
ElementType type;
// const Array<UInt> & elements;
const Material & mat_cohesive;
Real sigma_c;
const Real beta;
const Real G_c;
const Real delta_0;
const Real kappa;
Real delta_c;
- const UInt spatial_dimension;
+ const Int spatial_dimension;
const ElementType type_facet;
const ElementType type_cohesive;
const Array<Real> & traction;
const Array<Real> & damage;
const UInt nb_quad_per_el;
const UInt nb_element;
const Real beta2_kappa2;
const Real beta2_kappa;
Vector<Real> theoretical_traction;
Vector<Real> traction_old;
Vector<Real> opening_old;
Real Ed;
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material_tetrahedron.dat", argc, argv);
// debug::setDebugLevel(dblDump);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
const UInt max_steps = 60;
const Real increment_constant = 0.01;
Math::setTolerance(1.e-12);
const ElementType type = _tetrahedron_10;
Mesh mesh(spatial_dimension);
mesh.read("tetrahedron.msh");
SolidMechanicsModelCohesive model(mesh);
model.getElementInserter().setLimit(_x, -0.01, 0.01);
/// model initialization
model.initFull();
Array<bool> & boundary = model.getBlockedDOFs();
boundary.set(true);
UInt nb_element = mesh.getNbElement(type);
model.setBaseName("intrinsic_tetrahedron");
model.addDumpFieldVector("displacement");
model.addDumpField("internal_force");
model.dump();
model.setBaseNameToDumper("cohesive elements",
"cohesive_elements_tetrahedron");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump("cohesive elements");
/// find elements to displace
Array<UInt> elements;
Vector<Real> bary(spatial_dimension);
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
mesh.getBarycenter({type, el, _not_ghost}, bary);
if (bary(_x) > 0.01)
elements.push_back(el);
}
/// rotate mesh
Real angle = 1.;
// clang-format off
Matrix<Real> rotation{
{std::cos(angle), std::sin(angle) * -1., 0.},
{std::sin(angle), std::cos(angle), 0.},
{0., 0., 1.}};
// clang-format on
Vector<Real> increment_tmp{increment_constant, 2. * increment_constant,
3. * increment_constant};
Vector<Real> increment = rotation * increment_tmp;
auto & position = mesh.getNodes();
auto position_it = position.begin(spatial_dimension);
auto position_end = position.end(spatial_dimension);
for (; position_it != position_end; ++position_it) {
auto & pos = *position_it;
pos = rotation * pos;
}
model.dump();
model.dump("cohesive elements");
/// find nodes to check
Checker checker(model, elements, type);
checker.updateDisplacement(increment);
Real theoretical_Ed = 0;
Vector<Real> opening(spatial_dimension, 0.);
Vector<Real> opening_old(spatial_dimension, 0.);
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
model.dump();
model.dump("cohesive elements");
opening += increment_tmp;
checker.check(opening, rotation);
checker.updateDisplacement(increment);
}
model.dump();
model.dump("cohesive elements");
Real Ed = model.getEnergy("dissipated");
theoretical_Ed *= 4.;
std::cout << Ed << " " << theoretical_Ed << std::endl;
if (!Math::are_float_equal(Ed, theoretical_Ed) || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
finalize();
return EXIT_FAILURE;
}
finalize();
std::cout << "OK: test_cohesive_intrinsic_tetrahedron was passed!"
<< std::endl;
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void Checker::updateDisplacement(const Vector<Real> & increment) {
Mesh & mesh = model.getFEEngine().getMesh();
const auto & connectivity = mesh.getConnectivity(type);
auto & displacement = model.getDisplacement();
Array<bool> update(displacement.size());
update.zero();
auto conn_it = connectivity.begin(connectivity.getNbComponent());
auto conn_end = connectivity.begin(connectivity.getNbComponent());
for (; conn_it != conn_end; ++conn_it) {
const auto & conn = *conn_it;
- for (UInt n = 0; n < conn.size(); ++n) {
+ for (Int n = 0; n < conn.size(); ++n) {
UInt node = conn(n);
if (!update(node)) {
- Vector<Real> node_disp(displacement.storage() +
- node * spatial_dimension,
+ Vector<Real> node_disp(displacement.data() + node * spatial_dimension,
spatial_dimension);
node_disp += increment;
update(node) = true;
}
}
}
}
/* -------------------------------------------------------------------------- */
Checker::Checker(const SolidMechanicsModelCohesive & model,
const Array<UInt> & elements, ElementType type)
: model(model), type(std::move(type)), // elements(elements),
mat_cohesive(model.getMaterial(1)), sigma_c(mat_cohesive.get("sigma_c")),
beta(mat_cohesive.get("beta")), G_c(mat_cohesive.get("G_c")),
delta_0(mat_cohesive.get("delta_0")), kappa(mat_cohesive.get("kappa")),
spatial_dimension(model.getSpatialDimension()),
type_facet(Mesh::getFacetType(type)),
type_cohesive(FEEngine::getCohesiveElementType(type_facet)),
traction(mat_cohesive.getArray<Real>("tractions", type_cohesive)),
damage(mat_cohesive.getArray<Real>("damage", type_cohesive)),
nb_quad_per_el(model.getFEEngine("CohesiveFEEngine")
.getNbIntegrationPoints(type_cohesive)),
nb_element(model.getMesh().getNbElement(type_cohesive)),
beta2_kappa2(beta * beta / kappa / kappa),
beta2_kappa(beta * beta / kappa) {
const Mesh & mesh = model.getMesh();
const auto & connectivity = mesh.getConnectivity(type);
const auto & position = mesh.getNodes();
auto conn_it = connectivity.begin(connectivity.getNbComponent());
for (const auto & element : elements) {
Vector<UInt> conn_el(conn_it[element]);
- for (UInt n = 0; n < conn_el.size(); ++n) {
+ for (Int n = 0; n < conn_el.size(); ++n) {
UInt node = conn_el(n);
if (Math::are_float_equal(position(node, _x), 0.))
nodes_to_check.insert(node);
}
}
delta_c = 2 * G_c / sigma_c;
sigma_c *= delta_c / (delta_c - delta_0);
}
/* -------------------------------------------------------------------------- */
void Checker::checkTractions(const Vector<Real> & opening,
const Matrix<Real> & rotation) {
auto normal_opening = opening * Vector<Real>{1., 0., 0.};
auto tangential_opening = opening - normal_opening;
const Real normal_opening_norm = normal_opening.norm();
const Real tangential_opening_norm = tangential_opening.norm();
const Real delta =
std::max(std::sqrt(tangential_opening_norm * tangential_opening_norm *
beta2_kappa2 +
normal_opening_norm * normal_opening_norm),
0.);
Real theoretical_damage = std::min(delta / delta_c, 1.);
theoretical_traction = (tangential_opening * beta2_kappa + normal_opening) *
sigma_c / delta * (1. - theoretical_damage);
// adjust damage
theoretical_damage = std::max((delta - delta_0) / (delta_c - delta_0), 0.);
theoretical_damage = std::min(theoretical_damage, 1.);
Vector<Real> theoretical_traction_rotated = rotation * theoretical_traction;
std::for_each(
traction.begin(spatial_dimension), traction.end(spatial_dimension),
[&theoretical_traction_rotated](auto && traction) {
- Real diff =
- Vector<Real>(theoretical_traction_rotated - traction).norm<L_inf>();
+ Real diff = Vector<Real>(theoretical_traction_rotated - traction)
+ .lpNorm<Eigen::Infinity>();
if (diff > 1e-14)
throw std::domain_error("Tractions are incorrect");
});
std::for_each(damage.begin(), damage.end(),
[&theoretical_damage](auto && damage) {
if (not Math::are_float_equal(theoretical_damage, damage))
throw std::domain_error("Damage is incorrect");
});
}
/* -------------------------------------------------------------------------- */
void Checker::computeEnergy(const Vector<Real> & opening) {
/// compute energy
auto Do = opening - opening_old;
auto Dt = traction_old + theoretical_traction;
Ed += .5 * Do.dot(Dt);
opening_old = opening;
traction_old = theoretical_traction;
}
/* -------------------------------------------------------------------------- */
void Checker::checkEquilibrium() {
Vector<Real> residual_sum(spatial_dimension, 0.);
const auto & residual = model.getInternalForce();
auto res_it = residual.begin(spatial_dimension);
auto res_end = residual.end(spatial_dimension);
for (; res_it != res_end; ++res_it)
residual_sum += *res_it;
- if (!Math::are_float_equal(residual_sum.norm<L_inf>(), 0.))
+ if (!Math::are_float_equal(residual_sum.lpNorm<Eigen::Infinity>(), 0.))
throw std::domain_error("System is not in equilibrium!");
}
/* -------------------------------------------------------------------------- */
void Checker::checkResidual(const Matrix<Real> & rotation) {
Vector<Real> total_force(spatial_dimension, 0.);
const auto & residual = model.getInternalForce();
for (auto node : nodes_to_check) {
Vector<Real> res(residual.begin(spatial_dimension)[node]);
total_force += res;
}
Vector<Real> theoretical_total_force(spatial_dimension);
theoretical_total_force.mul<false>(rotation, theoretical_traction);
theoretical_total_force *= -1 * 2 * 2;
- for (UInt s = 0; s < spatial_dimension; ++s) {
+ for (Int s = 0; s < spatial_dimension; ++s) {
if (!Math::are_float_equal(total_force(s), theoretical_total_force(s))) {
std::cout << "Total force isn't correct!" << std::endl;
std::terminate();
}
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc
index c3f99da6d..bb51d8695 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc
@@ -1,127 +1,127 @@
/**
* @file test_cohesive_intrinsic_tetrahedron_fragmentation.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Dec 18 2017
*
* @brief Test for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
// debug::setDebugLevel(dblDump);
ElementType type = _tetrahedron_10;
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
const UInt max_steps = 100;
Mesh mesh(spatial_dimension);
mesh.read("tetrahedron_full.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull();
Real time_step = model.getStableTimeStep() * 0.8;
model.setTimeStep(time_step);
// std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
model.assembleInternalForces();
model.setBaseName("intrinsic_tetrahedron_fragmentation");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("internal_force");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.setBaseNameToDumper("cohesive elements",
"cohesive_elements_tetrahedron_fragmentation");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump();
model.dump("cohesive elements");
/// update displacement
UInt nb_element = mesh.getNbElement(type);
UInt nb_nodes = mesh.getNbNodes();
UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
Vector<Real> bary(spatial_dimension);
const Array<UInt> & connectivity = mesh.getConnectivity(type);
Array<Real> & displacement = model.getDisplacement();
Array<bool> update(nb_nodes);
for (UInt s = 0; s < max_steps; ++s) {
Real increment = s / 10.;
update.zero();
for (UInt el = 0; el < nb_element; ++el) {
mesh.getBarycenter({type, el, _not_ghost}, bary);
for (UInt n = 0; n < nb_nodes_per_element; ++n) {
UInt node = connectivity(el, n);
if (!update(node)) {
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
displacement(node, dim) = increment * bary(dim);
update(node) = true;
}
}
}
}
if (s % 10 == 0) {
model.dump();
model.dump("cohesive elements");
}
}
if (nb_nodes != nb_element * Mesh::getNbNodesPerElement(type)) {
std::cout << "Wrong number of nodes" << std::endl;
finalize();
return EXIT_FAILURE;
}
finalize();
std::cout << "OK: test_cohesive_intrinsic_tetrahedron was passed!"
<< std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc
index fac80b5c8..2d8731571 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc
@@ -1,175 +1,175 @@
/**
* @file test_cohesive_intrinsic_impl.cc
*
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Sun Dec 30 2018
*
* @brief Test for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
debug::setDebugLevel(dblError);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const ElementType type = _triangle_6;
Mesh mesh(spatial_dimension);
mesh.read("implicit.msh");
CohesiveElementInserter inserter(mesh);
inserter.setLimit(_y, 0.9, 1.1);
inserter.insertIntrinsicElements();
// mesh.write("implicit_cohesive.msh");
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initFull(SolidMechanicsModelCohesiveOptions(_static));
/// boundary conditions
Array<bool> & boundary = model.getBlockedDOFs();
UInt nb_nodes = mesh.getNbNodes();
Array<Real> & position = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
const ElementType type_facet = mesh.getFacetType(type);
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (std::abs(position(n, 1)) < Math::getTolerance()) {
boundary(n, 1) = true;
displacement(n, 1) = 0.0;
}
if ((std::abs(position(n, 0)) < Math::getTolerance()) &&
(position(n, 1) < 1.1)) {
boundary(n, 0) = true;
displacement(n, 0) = 0.0;
}
if ((std::abs(position(n, 0) - 1) < Math::getTolerance()) &&
(std::abs(position(n, 1) - 1) < Math::getTolerance())) {
boundary(n, 0) = true;
displacement(n, 0) = 0.0;
}
if (std::abs(position(n, 1) - 2) < Math::getTolerance()) {
boundary(n, 1) = true;
}
}
model.setBaseName("intrinsic_impl");
model.addDumpField("displacement");
// model.addDumpField("mass" );
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("force");
model.addDumpField("residual");
// model.addDumpField("damage" );
model.addDumpField("stress");
model.addDumpField("strain");
model.dump();
const MaterialCohesive & mat_coh =
dynamic_cast<const MaterialCohesive &>(model.getMaterial(1));
ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
const Array<Real> & opening = mat_coh.getOpening(type_cohesive);
// const Array<Real> & traction = mat_coh.getTraction(type_cohesive);
model.assembleInternalForces();
const Array<Real> & residual = model.getInternalForce();
UInt max_step = 1000;
Real increment = 3. / max_step;
Real error_tol = 10e-6;
std::ofstream fout;
fout.open("output");
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 100);
solver.set("threshold", 1e-5);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
/// Main loop
- for (UInt nstep = 0; nstep < max_step; ++nstep) {
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int nstep = 0; nstep < max_step; ++nstep) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (std::abs(position(n, 1) - 2) < Math::getTolerance()) {
displacement(n, 1) += increment;
}
}
model.solveStep();
// model.dump();
Real resid = 0;
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (std::abs(position(n, 1) - 2.) / 2. < Math::getTolerance()) {
resid += residual(n, 1);
}
}
Real analytical = exp(1) * std::abs(opening(0, 1)) *
exp(-std::abs(opening(0, 1)) / 0.5) / 0.5;
// the residual force is comparing with the theoretical value of the
// cohesive law
error_tol = std::abs((std::abs(resid) - analytical) / analytical);
fout << nstep << " " << -resid << " " << analytical << " " << error_tol
<< std::endl;
if (error_tol > 1e-3) {
std::cout << "Relative error: " << error_tol << std::endl;
std::cout << "Test failed!" << std::endl;
return EXIT_FAILURE;
}
}
model.dump();
fout.close();
finalize();
std::cout << "Test passed!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_linear_friction/test_cohesive_friction.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_linear_friction/test_cohesive_friction.cc
index 6950a86ca..491672436 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_linear_friction/test_cohesive_friction.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_linear_friction/test_cohesive_friction.cc
@@ -1,241 +1,241 @@
/**
* @file test_cohesive_friction.cc
*
* @author Mauro Corrado <mauro.corrado@epfl.ch>
*
* @date creation: Thu Jan 14 2016
* @date last modification: Sun Dec 30 2018
*
* @brief testing the correct behavior of the friction law included in
* the cohesive linear law, in implicit
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <time.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
Math::setTolerance(1.e-15);
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
const ElementType type = _cohesive_2d_4;
Mesh mesh(spatial_dimension);
mesh.read("mesh_cohesive_friction.msh");
// Create the model
SolidMechanicsModelCohesive model(mesh);
// Model initialization
model.initFull(SolidMechanicsModelCohesiveOptions(_static, true));
// CohesiveElementInserter inserter(mesh);
model.limitInsertion(_y, -0.001, 0.001);
model.updateAutomaticInsertion();
Real eps = 1e-10;
Array<Real> & pos = mesh.getNodes();
Array<Real> & disp = model.getDisplacement();
Array<bool> & boun = model.getBlockedDOFs();
const Array<Real> & residual = model.getInternalForce();
Array<Real> & cohe_opening = const_cast<Array<Real> &>(
model.getMaterial("interface").getInternal<Real>("opening")(type));
Array<Real> & friction_force = const_cast<Array<Real> &>(
model.getMaterial("interface").getInternal<Real>("friction_force")(type));
// Boundary conditions
- for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
+ for (Int i = 0; i < mesh.getNbNodes(); ++i) {
if (pos(i, 1) < -0.49 || pos(i, 1) > 0.49) {
boun(i, 0) = true;
boun(i, 1) = true;
}
}
bool passed = true;
Real tolerance = 1e-13;
Real error;
bool load_reduction = false;
Real tol_increase_factor = 1e5;
Real increment = 1.0e-4;
model.synchronizeBoundaries();
model.updateResidual();
/* -------------------------------------------- */
/* LOADING PHASE to introduce cohesive elements */
/* -------------------------------------------- */
- for (UInt nstep = 0; nstep < 100; ++nstep) {
+ for (Int nstep = 0; nstep < 100; ++nstep) {
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (pos(n, 1) > 0.49)
disp(n, 1) += increment;
}
model.solveStepCohesive<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
tolerance, error, 25, load_reduction, tol_increase_factor);
if (error > tolerance) {
AKANTU_ERROR("Convergence not reached in the mode I loading phase");
passed = false;
}
}
/* --------------------------------------------------------- */
/* UNLOADING PHASE to bring cohesive elements in compression */
/* --------------------------------------------------------- */
- for (UInt nstep = 0; nstep < 110; ++nstep) {
+ for (Int nstep = 0; nstep < 110; ++nstep) {
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (pos(n, 1) > 0.49)
disp(n, 1) -= increment;
}
model.solveStepCohesive<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
tolerance, error, 25, load_reduction, tol_increase_factor);
if (error > tolerance) {
AKANTU_ERROR("Convergence not reached in the mode I unloading phase");
passed = false;
}
}
/* -------------------------------------------------- */
/* SHEAR PHASE - displacement towards right */
/* -------------------------------------------------- */
increment *= 2;
- for (UInt nstep = 0; nstep < 30; ++nstep) {
+ for (Int nstep = 0; nstep < 30; ++nstep) {
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (pos(n, 1) > 0.49)
disp(n, 0) += increment;
}
model.solveStepCohesive<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
tolerance, error, 25, load_reduction, tol_increase_factor);
if (error > tolerance) {
AKANTU_ERROR("Convergence not reached in the shear loading phase");
passed = false;
}
}
/* ---------------------------------------------------*/
/* Check the horizontal component of the reaction */
/* ---------------------------------------------------*/
// Friction + mode II cohesive behavior
Real reac_X = 0.;
- for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
+ for (Int i = 0; i < mesh.getNbNodes(); ++i) {
if (pos(i, 1) > 0.49)
reac_X += residual(i, 0);
}
if (std::abs(reac_X - (-13.987451183762181)) > eps)
passed = false;
// Only friction
Real friction = friction_force(0, 0) + friction_force(1, 0);
if (std::abs(friction - (-12.517967866999832)) > eps)
passed = false;
/* -------------------------------------------------- */
/* SHEAR PHASE - displacement back to zero */
/* -------------------------------------------------- */
- for (UInt nstep = 0; nstep < 30; ++nstep) {
+ for (Int nstep = 0; nstep < 30; ++nstep) {
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (pos(n, 1) > 0.49)
disp(n, 0) -= increment;
}
model.solveStepCohesive<_scm_newton_raphson_tangent,
SolveConvergenceCriteria::_increment>(
tolerance, error, 25, load_reduction, tol_increase_factor);
if (error > tolerance) {
AKANTU_ERROR("Convergence not reached in the shear unloading phase");
passed = false;
}
}
/* ------------------------------------------------------- */
/* Check the horizontal component of the reaction and */
/* the residual relative sliding in the cohesive elements */
/* ------------------------------------------------------- */
// Friction + mode II cohesive behavior
reac_X = 0.;
- for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
+ for (Int i = 0; i < mesh.getNbNodes(); ++i) {
if (pos(i, 1) > 0.49)
reac_X += residual(i, 0);
}
if (std::abs(reac_X - 12.400313187122208) > eps)
passed = false;
// Only friction
friction = 0.;
friction = friction_force(0, 0) + friction_force(1, 0);
if (std::abs(friction - 12.523300983293165) > eps)
passed = false;
// Residual sliding
Real sliding[2];
sliding[0] = cohe_opening(0, 0);
sliding[1] = cohe_opening(1, 0);
if (std::abs(sliding[0] - (-0.00044246686809147357)) > eps)
passed = false;
if (passed)
return EXIT_SUCCESS;
else
return EXIT_FAILURE;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh b/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh
index 8647dca80..37e8932d2 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_fixture.hh
@@ -1,314 +1,314 @@
/**
* @file test_material_cohesive_fixture.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Feb 21 2018
* @date last modification: Sun Dec 30 2018
*
* @brief Test the traction separations laws for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
//#define debug_
/* -------------------------------------------------------------------------- */
-template <template <UInt> class Mat, typename dim_>
+template <template <Int> class Mat, typename dim_>
class TestMaterialCohesiveFixture : public ::testing::Test {
public:
- static constexpr UInt dim = dim_::value;
+ static constexpr Int dim = dim_::value;
using Material = Mat<dim>;
void SetUp() override {
mesh = std::make_unique<Mesh>(dim);
model = std::make_unique<SolidMechanicsModelCohesive>(*mesh);
material = std::make_unique<Material>(*model);
material->SetUps();
openings = std::make_unique<Array<Real>>(0, dim);
tractions = std::make_unique<Array<Real>>(0, dim);
reset();
gen.seed(::testing::GTEST_FLAG(random_seed));
normal = getRandomNormal();
tangents = getRandomTangents();
}
void TearDown() override {
material.reset(nullptr);
model.reset(nullptr);
mesh.reset(nullptr);
openings.reset(nullptr);
tractions.reset(nullptr);
}
void reset() {
openings->resize(1);
tractions->resize(1);
openings->zero();
tractions->zero();
}
/* ------------------------------------------------------------------------ */
void addOpening(const Vector<Real> & direction, Real start, Real stop,
UInt nb_steps) {
for (auto s : arange(nb_steps)) {
auto opening =
direction * (start + (stop - start) / Real(nb_steps) * Real(s + 1));
openings->push_back(opening);
}
tractions->resize(openings->size());
}
/* ------------------------------------------------------------------------ */
Vector<Real> getRandomVector() {
std::uniform_real_distribution<Real> dis;
Vector<Real> vector(dim);
for (auto s : arange(dim))
vector(s) = dis(gen);
return vector;
}
Vector<Real> getRandomNormal() {
auto normal = getRandomVector();
normal.normalize();
#if defined(debug_)
normal.set(0.);
normal(0) = 1.;
#endif
return normal;
}
Matrix<Real> getRandomTangents() {
auto dim = normal.size();
Matrix<Real> tangent(dim, dim - 1);
if (dim == 2) {
- Math::normal2(normal.storage(), tangent(0).storage());
+ tangent(0) = Math::normal(normal);
}
if (dim == 3) {
auto v = getRandomVector();
- tangent(0) = (v - v.dot(normal) * normal).normalize();
- Math::normal3(normal.storage(), tangent(0).storage(),
- tangent(1).storage());
+ tangent(0) = (v - v.dot(normal) * normal).normalized();
+ tangent(1) = Math::normal(tangent(0), normal);
}
#if defined(debug_)
if (dim == 2)
tangent(0) = Vector<Real>{0., 1};
if (dim == 3)
tangent = Matrix<Real>{{0., 0.}, {1., 0.}, {0., 1.}};
#endif
return tangent;
}
/* ------------------------------------------------------------------------ */
void output_csv() {
const ::testing::TestInfo * const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
std::ofstream cout(std::string(test_info->name()) + ".csv");
auto print_vect_name = [&](auto name) {
for (auto s : arange(dim)) {
if (s != 0) {
cout << ", ";
}
cout << name << "_" << s;
}
};
auto print_vect = [&](const auto & vect) {
cout << vect.dot(normal);
if (dim > 1)
cout << ", " << vect.dot(tangents(0));
if (dim > 2)
cout << ", " << vect.dot(tangents(1));
};
cout << "delta, ";
print_vect_name("opening");
cout << ", ";
print_vect_name("traction");
cout << std::endl;
for (auto && data : zip(make_view(*this->openings, this->dim),
make_view(*this->tractions, this->dim))) {
const auto & opening = std::get<0>(data);
auto & traction = std::get<1>(data);
cout << this->material->delta(opening, normal) << ", ";
print_vect(opening);
cout << ", ";
print_vect(traction);
cout << std::endl;
}
}
/* ------------------------------------------------------------------------ */
Real dissipated() {
- Vector<Real> prev_opening(dim, 0.);
- Vector<Real> prev_traction(dim, 0.);
+ Vector<Real> prev_opening = Vector<Real>::Zero(dim);
+ Vector<Real> prev_traction = Vector<Real>::Zero(dim);
Real etot = 0.;
Real erev = 0.;
for (auto && data : zip(make_view(*this->openings, this->dim),
make_view(*this->tractions, this->dim))) {
const auto & opening = std::get<0>(data);
const auto & traction = std::get<1>(data);
etot += (opening - prev_opening).dot(traction + prev_traction) / 2.;
erev = traction.dot(opening) / 2.;
prev_opening = opening;
prev_traction = traction;
}
return etot - erev;
}
/* ------------------------------------------------------------------------ */
void checkModeI(Real max_opening, Real expected_dissipated) {
this->material->insertion_stress_ = this->material->sigma_c_ * normal;
addOpening(normal, 0., max_opening, 100);
this->material->computeTractions(*openings, normal, *tractions);
for (auto && data : zip(make_view(*this->openings, this->dim),
make_view(*this->tractions, this->dim))) {
const auto & opening = std::get<0>(data);
auto & traction = std::get<1>(data);
auto T = traction.dot(normal);
EXPECT_NEAR(0, (traction - T * normal).norm(), 1e-9);
auto T_expected =
this->material->tractionModeI(opening, normal).dot(normal);
EXPECT_NEAR(T_expected, T, 1e-9);
}
EXPECT_NEAR(expected_dissipated, dissipated(), 1e-5);
this->output_csv();
}
/* ------------------------------------------------------------------------ */
void checkModeII(Real max_opening) {
if (this->dim == 1) {
SUCCEED();
return;
}
std::uniform_real_distribution<Real> dis;
- auto direction = Vector<Real>(tangents(0));
+ Vector<Real> direction = tangents(0);
auto alpha = dis(gen) + 0.1;
auto beta = dis(gen) + 0.2;
#ifndef debug_
- direction = alpha * Vector<Real>(tangents(0));
- if (dim > 2)
- direction += beta * Vector<Real>(tangents(1));
+ direction = alpha * tangents(0);
+ if (dim > 2) {
+ direction += beta * tangents(1);
+ }
- direction = direction.normalize();
+ direction = direction.normalized();
#endif
beta = this->material->get("beta");
this->material->insertion_stress_ =
beta * this->material->sigma_c_ * direction;
addOpening(direction, 0., max_opening, 100);
this->material->computeTractions(*openings, normal, *tractions);
for (auto && data : zip(make_view(*this->openings, this->dim),
make_view(*this->tractions, this->dim))) {
const auto & opening = std::get<0>(data);
const auto & traction = std::get<1>(data);
// In ModeII normal traction should be 0
ASSERT_NEAR(0, traction.dot(normal), 1e-9);
// Normal opening is null
ASSERT_NEAR(0, opening.dot(normal), 1e-16);
auto T = traction.dot(direction);
auto T_expected =
this->material->tractionModeII(opening, normal).dot(direction);
EXPECT_NEAR(T_expected, T, 1e-9);
}
// EXPECT_NEAR(expected_dissipated, dissipated(), 1e-5);
this->output_csv();
}
protected:
Vector<Real> normal;
Matrix<Real> tangents;
std::unique_ptr<Mesh> mesh;
std::unique_ptr<SolidMechanicsModelCohesive> model;
std::unique_ptr<Material> material;
std::unique_ptr<Array<Real>> openings;
std::unique_ptr<Array<Real>> tractions;
std::mt19937 gen;
};
-template <template <UInt> class Mat, UInt dim>
+template <template <Int> class Mat, Int dim>
struct TestMaterialCohesive : public Mat<dim> {
TestMaterialCohesive(SolidMechanicsModel & model)
- : Mat<dim>(model, "test"), insertion_stress_(dim, 0.) {}
+ : Mat<dim>(model, "test"), insertion_stress_(Vector<Real>(dim)) {}
virtual void SetUp() {}
virtual void resetInternal() {}
void SetUps() {
this->initMaterial();
this->SetUp();
this->updateInternalParameters();
this->resetInternals();
}
void resetInternals() { this->resetInternal(); }
virtual void computeTractions(Array<Real> & /*openings*/,
const Vector<Real> & /*normal*/,
Array<Real> & /*tractions*/) {}
Vector<Real> insertion_stress_;
Real sigma_c_{0};
bool is_extrinsic{true};
};
-template <template <UInt> class Mat, typename dim_>
-constexpr UInt TestMaterialCohesiveFixture<Mat, dim_>::dim;
+template <template <Int> class Mat, typename dim_>
+constexpr Int TestMaterialCohesiveFixture<Mat, dim_>::dim;
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_linear.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_linear.cc
index a0769b005..9ea5bb71b 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_linear.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_materials/test_material_cohesive_linear.cc
@@ -1,195 +1,197 @@
/**
* @file test_material_cohesive_linear.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Feb 21 2018
* @date last modification: Wed Nov 18 2020
*
* @brief Test material cohesive linear
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_material_cohesive_fixture.hh"
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
struct TestMaterialCohesiveLinear
: public TestMaterialCohesive<MaterialCohesiveLinear, dim> {
TestMaterialCohesiveLinear(SolidMechanicsModel & model)
: TestMaterialCohesive<MaterialCohesiveLinear, dim>(model) {}
void SetUp() override {
this->is_extrinsic = true;
this->beta = 2.;
this->kappa = 2;
this->G_c = 10.;
this->sigma_c_ = 1e6;
this->penalty = 1e11;
this->delta_c_ = 2. * this->G_c / this->sigma_c_;
}
void resetInternal() override {
- normal_opening = Vector<Real>(dim, 0.);
- tangential_opening = Vector<Real>(dim, 0.);
- contact_traction = Vector<Real>(dim, 0.);
- contact_opening = Vector<Real>(dim, 0.);
+ // normal_opening_ = Vector<Real>::Zero(dim);
+ // tangential_opening_ = Vector<Real>::Zero(dim);
+ contact_traction_ = Vector<Real>::Zero(dim);
+ contact_opening_ = Vector<Real>::Zero(dim);
}
void computeTractions(Array<Real> & openings, const Vector<Real> & normal,
Array<Real> & tractions) override {
- for (auto && data :
+ for (auto && [opening, traction] :
zip(make_view(openings, dim), make_view(tractions, dim))) {
- auto & opening = std::get<0>(data);
- auto & traction = std::get<1>(data);
- this->computeTractionOnQuad(
- traction, opening, normal, delta_max, this->delta_c_,
- this->insertion_stress_, this->sigma_c_, normal_opening,
- tangential_opening, normal_opening_norm, tangential_opening_norm,
- damage, penetration, contact_traction, contact_opening);
+ auto && args = tuple::make_named_tuple(
+ "normal"_n = normal, "opening"_n = opening, "traction"_n = traction,
+ "contact_opening"_n = contact_opening_,
+ "contact_traction"_n = contact_traction_, "delta_max"_n = delta_max_,
+ "sigma_c"_n = this->sigma_c_, "damage"_n = damage_,
+ "delta_c"_n = this->delta_c_,
+ "insertion_stress"_n = this->insertion_stress_);
- opening += contact_opening;
- traction += contact_traction;
+ this->computeTractionOnQuad(args);
+
+ opening += contact_opening_;
+ traction += contact_traction_;
}
}
Real delta(const Vector<Real> & opening, const Vector<Real> & normal) {
auto beta = this->beta;
auto kappa = this->kappa;
auto normal_opening = opening.dot(normal) * normal;
auto tangential_opening = opening - normal_opening;
return std::sqrt(std::pow(normal_opening.norm(), 2) +
std::pow(tangential_opening.norm() * beta / kappa, 2));
}
Vector<Real> traction(const Vector<Real> & opening,
const Vector<Real> & normal) {
auto delta_c = this->delta_c_;
auto sigma_c = this->sigma_c_;
auto beta = this->beta;
auto kappa = this->kappa;
auto normal_opening = opening.dot(normal) * normal;
auto tangential_opening = opening - normal_opening;
auto delta_ = this->delta(opening, normal);
if (delta_ < 1e-16) {
return this->insertion_stress_;
}
if (opening.dot(normal) / delta_c < -Math::getTolerance()) {
ADD_FAILURE() << "This is contact";
- return Vector<Real>(dim, 0.);
+ return Vector<Real>::Zero(dim);
}
auto T = sigma_c * (delta_c - delta_) / delta_c / delta_ *
(normal_opening + tangential_opening * beta * beta / kappa);
return T;
}
Vector<Real> tractionModeI(const Vector<Real> & opening,
const Vector<Real> & normal) {
return traction(opening, normal);
}
Vector<Real> tractionModeII(const Vector<Real> & opening,
const Vector<Real> & normal) {
return traction(opening, normal);
}
public:
- Real delta_c_{0};
+ Real delta_c_{0.};
- Real delta_max{0.};
- Real normal_opening_norm{0};
- Real tangential_opening_norm{0};
- Real damage{0};
- bool penetration{false};
+ Real delta_max_{0.};
+ // Real normal_opening_norm_{0.};
+ // Real tangential_opening_norm{0.};
+ Real damage_{0.};
+ bool penetration_{false};
Real etot{0.};
Real edis{0.};
- Vector<Real> normal_opening;
- Vector<Real> tangential_opening;
+ Vector<Real> normal_opening_;
+ Vector<Real> tangential_opening_;
- Vector<Real> contact_traction;
- Vector<Real> contact_opening;
+ Vector<Real> contact_traction_;
+ Vector<Real> contact_opening_;
};
template <typename dim_>
using TestMaterialCohesiveLinearFixture =
TestMaterialCohesiveFixture<TestMaterialCohesiveLinear, dim_>;
using coh_types = gtest_list_t<TestAllDimensions>;
TYPED_TEST_SUITE(TestMaterialCohesiveLinearFixture, coh_types, );
TYPED_TEST(TestMaterialCohesiveLinearFixture, ModeI) {
this->checkModeI(this->material->delta_c_, this->material->get("G_c"));
Real G_c = this->material->get("G_c");
EXPECT_NEAR(G_c, this->dissipated(), 1e-6);
}
TYPED_TEST(TestMaterialCohesiveLinearFixture, ModeII) {
this->checkModeII(this->material->delta_c_);
if (this->dim != 1) {
Real G_c = this->material->get("G_c");
Real beta = this->material->get("beta");
Real dis = beta * G_c;
EXPECT_NEAR(dis, this->dissipated(), 1e-6);
}
}
TYPED_TEST(TestMaterialCohesiveLinearFixture, Cycles) {
auto delta_c = this->material->delta_c_;
auto sigma_c = this->material->sigma_c_;
this->material->insertion_stress_ = this->normal * sigma_c;
this->addOpening(this->normal, 0, 0.1 * delta_c, 100);
this->addOpening(this->normal, 0.1 * delta_c, 0., 100);
this->addOpening(this->normal, 0., 0.5 * delta_c, 100);
this->addOpening(this->normal, 0.5 * delta_c, -1.e-5, 100);
this->addOpening(this->normal, -1.e-5, 0.9 * delta_c, 100);
this->addOpening(this->normal, 0.9 * delta_c, 0., 100);
this->addOpening(this->normal, 0., delta_c, 100);
this->material->computeTractions(*this->openings, this->normal,
*this->tractions);
Real G_c = this->material->get("G_c");
EXPECT_NEAR(G_c, this->dissipated(), 2e-3); // due to contact dissipation at 0
this->output_csv();
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc
index 8ffbbb4d5..781a415c3 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc
@@ -1,214 +1,214 @@
/**
* @file test_cohesive_facet_stress_synchronizer.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 08 2017
*
* @brief Test for facet stress synchronizer
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
Real function(Real constant, Real x, Real y, Real z) {
return constant + 2. * x + 3. * y + 4 * z;
}
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
ElementType type = _tetrahedron_10;
ElementType type_facet = Mesh::getFacetType(type);
Math::setTolerance(1.e-11);
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
// Read the mesh
mesh.read("tetrahedron.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
SolidMechanicsModelCohesive model(mesh);
model.initParallel(partition, NULL, true);
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
Array<Real> & position = mesh.getNodes();
/* ------------------------------------------------------------------------ */
/* Facet part */
/* ------------------------------------------------------------------------ */
/// compute quadrature points positions on facets
const Mesh & mesh_facets = model.getMeshFacets();
UInt nb_facet = mesh_facets.getNbElement(type_facet);
UInt nb_quad_per_facet =
model.getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
UInt nb_tot_quad = nb_quad_per_facet * nb_facet;
Array<Real> quad_facets(nb_tot_quad, spatial_dimension);
model.getFEEngine("FacetsFEEngine")
.interpolateOnIntegrationPoints(position, quad_facets, spatial_dimension,
type_facet);
/* ------------------------------------------------------------------------ */
/* End of facet part */
/* ------------------------------------------------------------------------ */
/// compute quadrature points position of the elements
UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type);
UInt nb_element = mesh.getNbElement(type);
UInt nb_tot_quad_el = nb_quad_per_element * nb_element;
Array<Real> quad_elements(nb_tot_quad_el, spatial_dimension);
model.getFEEngine().interpolateOnIntegrationPoints(position, quad_elements,
spatial_dimension, type);
/// assign some values to stresses
Array<Real> & stress =
const_cast<Array<Real> &>(model.getMaterial(0).getStress(type));
Array<Real>::iterator<Matrix<Real>> stress_it =
stress.begin(spatial_dimension, spatial_dimension);
- for (UInt q = 0; q < nb_tot_quad_el; ++q, ++stress_it) {
+ for (Int q = 0; q < nb_tot_quad_el; ++q, ++stress_it) {
/// compute values
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = i; j < spatial_dimension; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = i; j < spatial_dimension; ++j) {
UInt index = i * spatial_dimension + j;
(*stress_it)(i, j) = function(index, quad_elements(q, 0),
quad_elements(q, 1), quad_elements(q, 2));
}
}
/// fill symmetrical part
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < i; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = 0; j < i; ++j) {
(*stress_it)(i, j) = (*stress_it)(j, i);
}
}
// stress_it->clear();
- // for (UInt i = 0; i < spatial_dimension; ++i)
+ // for (Int i = 0; i < spatial_dimension; ++i)
// (*stress_it)(i, i) = sigma_c * 5;
}
/// compute and communicate stress on facets
model.checkCohesiveStress();
/* ------------------------------------------------------------------------ */
/* Check facet stress */
/* ------------------------------------------------------------------------ */
const Array<Real> & facet_stress = model.getStressOnFacets(type_facet);
const Array<bool> & facet_check =
model.getElementInserter().getCheckFacets(type_facet);
const Array<std::vector<Element>> & elements_to_facet =
model.getMeshFacets().getElementToSubelement(type_facet);
Array<Real>::iterator<Vector<Real>> quad_facet_it =
quad_facets.begin(spatial_dimension);
Array<Real>::const_iterator<Matrix<Real>> facet_stress_it =
facet_stress.begin(spatial_dimension, spatial_dimension * 2);
Matrix<Real> current_stress(spatial_dimension, spatial_dimension);
- for (UInt f = 0; f < nb_facet; ++f) {
+ for (Int f = 0; f < nb_facet; ++f) {
if (!facet_check(f) || (elements_to_facet(f)[0].ghost_type == _not_ghost &&
elements_to_facet(f)[1].ghost_type == _not_ghost)) {
quad_facet_it += nb_quad_per_facet;
facet_stress_it += nb_quad_per_facet;
continue;
}
- for (UInt q = 0; q < nb_quad_per_facet;
+ for (Int q = 0; q < nb_quad_per_facet;
++q, ++quad_facet_it, ++facet_stress_it) {
/// compute current_stress
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = i; j < spatial_dimension; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = i; j < spatial_dimension; ++j) {
UInt index = i * spatial_dimension + j;
current_stress(i, j) =
function(index, (*quad_facet_it)(0), (*quad_facet_it)(1),
(*quad_facet_it)(2));
}
}
/// fill symmetrical part
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < i; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = 0; j < i; ++j) {
current_stress(i, j) = current_stress(j, i);
}
}
/// compare it to interpolated one
- for (UInt s = 0; s < 2; ++s) {
+ for (Int s = 0; s < 2; ++s) {
Matrix<Real> stress_to_check(facet_stress_it->storage() +
s * spatial_dimension *
spatial_dimension,
spatial_dimension, spatial_dimension);
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
+ for (Int j = 0; j < spatial_dimension; ++j) {
if (!Math::are_float_equal(stress_to_check(i, j),
current_stress(i, j))) {
std::cout << "Stress doesn't match" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
}
}
}
}
finalize();
if (prank == 0)
std::cout << "OK: test_cohesive_facet_stress_synchronizer passed!"
<< std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc
index 75e501935..ab6473eff 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc
@@ -1,457 +1,457 @@
/**
* @file test_cohesive_parallel_buildfragments.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Tue Feb 20 2018
*
* @brief Test to build fragments in parallel
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <fstream>
#include <functional>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "fragment_manager.hh"
#include "material_cohesive.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
void verticalInsertionLimit(SolidMechanicsModelCohesive &);
void displaceElements(SolidMechanicsModelCohesive &, const Real, const Real);
bool isInertiaEqual(const Vector<Real> &, const Vector<Real> &);
void rotateArray(Array<Real> & array, Real angle);
UInt getNbBigFragments(FragmentManager &, UInt);
-const UInt spatial_dimension = 3;
+const Int spatial_dimension = 3;
const UInt total_nb_fragment = 4;
const Real rotation_angle = M_PI / 4.;
const Real global_tolerance = 1.e-9;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
Math::setTolerance(global_tolerance);
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
// Read the mesh
mesh.read("mesh.msh");
/// partition the mesh
MeshUtils::purifyMesh(mesh);
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
SolidMechanicsModelCohesive model(mesh);
model.initParallel(partition, NULL, true);
delete partition;
/// model initialization
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
mesh.computeBoundingBox();
Real L = mesh.getUpperBounds()(0) - mesh.getLowerBounds()(0);
Real h = mesh.getUpperBounds()(1) - mesh.getLowerBounds()(1);
Real rho = model.getMaterial("bulk").getParam<Real>("rho");
Real theoretical_mass = L * h * h * rho;
Real frag_theo_mass = theoretical_mass / total_nb_fragment;
UInt nb_element =
mesh.getNbElement(spatial_dimension, _not_ghost, _ek_regular);
comm.allReduce(&nb_element, 1, _so_sum);
UInt nb_element_per_fragment = nb_element / total_nb_fragment;
FragmentManager fragment_manager(model);
fragment_manager.computeAllData();
getNbBigFragments(fragment_manager, nb_element_per_fragment + 1);
model.setBaseName("extrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("stress");
model.addDumpField("partitions");
model.addDumpField("fragments");
model.addDumpField("fragments mass");
model.addDumpField("moments of inertia");
model.addDumpField("elements per fragment");
model.dump();
model.setBaseNameToDumper("cohesive elements", "cohesive_elements_test");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump("cohesive elements");
/// set check facets
verticalInsertionLimit(model);
model.assembleMassLumped();
model.synchronizeBoundaries();
/// impose initial displacement
Array<Real> & displacement = model.getDisplacement();
Array<Real> & velocity = model.getVelocity();
const Array<Real> & position = mesh.getNodes();
UInt nb_nodes = mesh.getNbNodes();
for (UInt n = 0; n < nb_nodes; ++n) {
displacement(n, 0) = position(n, 0) * 0.1;
velocity(n, 0) = position(n, 0);
}
rotateArray(mesh.getNodes(), rotation_angle);
// rotateArray(displacement, rotation_angle);
// rotateArray(velocity, rotation_angle);
model.updateResidual();
model.checkCohesiveStress();
model.dump();
model.dump("cohesive elements");
const Array<Real> & fragment_mass = fragment_manager.getMass();
const Array<Real> & fragment_center = fragment_manager.getCenterOfMass();
Real el_size = L / total_nb_fragment;
Real lim = -L / 2 + el_size * 0.99;
/// define theoretical inertia moments
Vector<Real> small_frag_inertia(spatial_dimension);
small_frag_inertia(0) = frag_theo_mass * (h * h + h * h) / 12.;
small_frag_inertia(1) = frag_theo_mass * (el_size * el_size + h * h) / 12.;
small_frag_inertia(2) = frag_theo_mass * (el_size * el_size + h * h) / 12.;
- std::sort(small_frag_inertia.storage(),
- small_frag_inertia.storage() + spatial_dimension,
+ std::sort(small_frag_inertia.data(),
+ small_frag_inertia.data() + spatial_dimension,
std::greater<Real>());
const Array<Real> & inertia_moments = fragment_manager.getMomentsOfInertia();
Array<Real>::const_iterator<Vector<Real>> inertia_moments_begin =
inertia_moments.begin(spatial_dimension);
/// displace one fragment each time
for (UInt frag = 1; frag <= total_nb_fragment; ++frag) {
if (prank == 0)
std::cout << "Generating fragment: " << frag << std::endl;
fragment_manager.computeAllData();
/// check number of big fragments
UInt nb_big_fragment =
getNbBigFragments(fragment_manager, nb_element_per_fragment + 1);
model.dump();
model.dump("cohesive elements");
if (frag < total_nb_fragment) {
if (nb_big_fragment != 1) {
AKANTU_ERROR(
"The number of big fragments is wrong: " << nb_big_fragment);
return EXIT_FAILURE;
}
} else {
if (nb_big_fragment != 0) {
AKANTU_ERROR(
"The number of big fragments is wrong: " << nb_big_fragment);
return EXIT_FAILURE;
}
}
/// check number of fragments
UInt nb_fragment_num = fragment_manager.getNbFragment();
if (nb_fragment_num != frag) {
AKANTU_ERROR("The number of fragments is wrong! Numerical: "
<< nb_fragment_num << " Theoretical: " << frag);
return EXIT_FAILURE;
}
/// check mass computation
if (frag < total_nb_fragment) {
Real total_mass = 0.;
UInt small_fragments = 0;
for (UInt f = 0; f < nb_fragment_num; ++f) {
const Vector<Real> & current_inertia = inertia_moments_begin[f];
if (Math::are_float_equal(fragment_mass(f, 0), frag_theo_mass)) {
/// check center of mass
if (fragment_center(f, 0) > (L * frag / total_nb_fragment - L / 2)) {
AKANTU_ERROR("Fragment center is wrong!");
return EXIT_FAILURE;
}
/// check moment of inertia
if (!isInertiaEqual(current_inertia, small_frag_inertia)) {
AKANTU_ERROR("Inertia moments are wrong");
return EXIT_FAILURE;
}
++small_fragments;
total_mass += frag_theo_mass;
} else {
/// check the moment of inertia for the biggest fragment
Real big_frag_mass = frag_theo_mass * (total_nb_fragment - frag + 1);
Real big_frag_size = el_size * (total_nb_fragment - frag + 1);
Vector<Real> big_frag_inertia(spatial_dimension);
big_frag_inertia(0) = big_frag_mass * (h * h + h * h) / 12.;
big_frag_inertia(1) =
big_frag_mass * (big_frag_size * big_frag_size + h * h) / 12.;
big_frag_inertia(2) =
big_frag_mass * (big_frag_size * big_frag_size + h * h) / 12.;
- std::sort(big_frag_inertia.storage(),
- big_frag_inertia.storage() + spatial_dimension,
+ std::sort(big_frag_inertia.data(),
+ big_frag_inertia.data() + spatial_dimension,
std::greater<Real>());
if (!isInertiaEqual(current_inertia, big_frag_inertia)) {
AKANTU_ERROR("Inertia moments are wrong");
return EXIT_FAILURE;
}
}
}
if (small_fragments != nb_fragment_num - 1) {
AKANTU_ERROR("The number of small fragments is wrong!");
return EXIT_FAILURE;
}
if (!Math::are_float_equal(total_mass,
small_fragments * frag_theo_mass)) {
AKANTU_ERROR("The mass of small fragments is wrong!");
return EXIT_FAILURE;
}
}
/// displace fragments
rotateArray(mesh.getNodes(), -rotation_angle);
// rotateArray(displacement, -rotation_angle);
displaceElements(model, lim, el_size * 2);
rotateArray(mesh.getNodes(), rotation_angle);
// rotateArray(displacement, rotation_angle);
model.updateResidual();
lim += el_size;
}
model.dump();
model.dump("cohesive elements");
/// check centers
const Array<Real> & fragment_velocity = fragment_manager.getVelocity();
Real initial_position = -L / 2. + el_size / 2.;
for (UInt frag = 0; frag < total_nb_fragment; ++frag) {
Real theoretical_center = initial_position + el_size * frag;
UInt f_index = 0;
while (
f_index < total_nb_fragment &&
!Math::are_float_equal(fragment_center(f_index, 0), theoretical_center))
++f_index;
if (f_index == total_nb_fragment) {
AKANTU_ERROR("The fragments' center is wrong!");
return EXIT_FAILURE;
}
f_index = 0;
while (f_index < total_nb_fragment &&
!Math::are_float_equal(fragment_velocity(f_index, 0),
theoretical_center))
++f_index;
if (f_index == total_nb_fragment) {
AKANTU_ERROR("The fragments' velocity is wrong!");
return EXIT_FAILURE;
}
}
finalize();
if (prank == 0)
std::cout << "OK: test_cohesive_buildfragments was passed!" << std::endl;
return EXIT_SUCCESS;
}
void verticalInsertionLimit(SolidMechanicsModelCohesive & model) {
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
const Mesh & mesh_facets = model.getMeshFacets();
const Array<Real> & position = mesh_facets.getNodes();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it =
mesh_facets.firstType(spatial_dimension - 1, ghost_type);
Mesh::type_iterator end =
mesh_facets.lastType(spatial_dimension - 1, ghost_type);
for (; it != end; ++it) {
ElementType type = *it;
Array<bool> & check_facets =
model.getElementInserter().getCheckFacets(type, ghost_type);
const Array<UInt> & connectivity =
mesh_facets.getConnectivity(type, ghost_type);
UInt nb_nodes_per_facet = connectivity.getNbComponent();
for (UInt f = 0; f < check_facets.getSize(); ++f) {
if (!check_facets(f))
continue;
UInt nb_aligned_nodes = 1;
Real first_node_pos = position(connectivity(f, 0), 0);
for (; nb_aligned_nodes < nb_nodes_per_facet; ++nb_aligned_nodes) {
Real other_node_pos = position(connectivity(f, nb_aligned_nodes), 0);
if (!Math::are_float_equal(first_node_pos, other_node_pos))
break;
}
if (nb_aligned_nodes != nb_nodes_per_facet) {
check_facets(f) = false;
}
}
}
}
}
void displaceElements(SolidMechanicsModelCohesive & model, const Real lim,
const Real amount) {
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Array<Real> & displacement = model.getDisplacement();
Mesh & mesh = model.getMesh();
UInt nb_nodes = mesh.getNbNodes();
Array<bool> displaced(nb_nodes);
displaced.zero();
Vector<Real> barycenter(spatial_dimension);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
for (; it != end; ++it) {
ElementType type = *it;
const Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
UInt nb_element = connectivity.getSize();
UInt nb_nodes_per_element = connectivity.getNbComponent();
Array<UInt>::const_vector_iterator conn_el =
connectivity.begin(nb_nodes_per_element);
for (UInt el = 0; el < nb_element; ++el) {
- mesh.getBarycenter(el, type, barycenter.storage(), ghost_type);
+ mesh.getBarycenter(el, type, barycenter.data(), ghost_type);
if (barycenter(0) < lim) {
const Vector<UInt> & conn = conn_el[el];
for (UInt n = 0; n < nb_nodes_per_element; ++n) {
UInt node = conn(n);
if (!displaced(node)) {
displacement(node, 0) -= amount;
displaced(node) = true;
}
}
}
}
}
}
}
bool isInertiaEqual(const Vector<Real> & a, const Vector<Real> & b) {
UInt nb_terms = a.size();
UInt equal_terms = 0;
while (equal_terms < nb_terms &&
std::abs(a(equal_terms) - b(equal_terms)) / a(equal_terms) <
Math::getTolerance())
++equal_terms;
return equal_terms == nb_terms;
}
void rotateArray(Array<Real> & array, Real angle) {
- UInt spatial_dimension = array.getNbComponent();
+ Int spatial_dimension = array.getNbComponent();
Real rotation_values[] = {std::cos(angle),
std::sin(angle),
0,
-std::sin(angle),
std::cos(angle),
0,
0,
0,
1};
Matrix<Real> rotation(rotation_values, spatial_dimension, spatial_dimension);
RVector displaced_node(spatial_dimension);
auto node_it = array.begin(spatial_dimension);
auto node_end = array.end(spatial_dimension);
for (; node_it != node_end; ++node_it) {
displaced_node.mul<false>(rotation, *node_it);
*node_it = displaced_node;
}
}
UInt getNbBigFragments(FragmentManager & fragment_manager,
UInt minimum_nb_elements) {
fragment_manager.computeNbElementsPerFragment();
const Array<UInt> & nb_elements_per_fragment =
fragment_manager.getNbElementsPerFragment();
UInt nb_fragment = fragment_manager.getNbFragment();
UInt nb_big_fragment = 0;
- for (UInt frag = 0; frag < nb_fragment; ++frag) {
+ for (Int frag = 0; frag < nb_fragment; ++frag) {
if (nb_elements_per_fragment(frag) >= minimum_nb_elements) {
++nb_big_fragment;
}
}
return nb_big_fragment;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc
index 76d2f7bcc..5bc47c915 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc
@@ -1,188 +1,188 @@
/**
* @file test_cohesive_parallel_extrinsic.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 08 2017
*
* @brief parallel test for cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_paraview.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
const UInt max_steps = 500;
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
// Read the mesh
mesh.read("mesh.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
// debug::setDebugLevel(dblDump);
partition->partitionate(psize);
// debug::setDebugLevel(dblWarning);
}
SolidMechanicsModelCohesive model(mesh);
model.initParallel(partition, NULL, true);
// debug::setDebugLevel(dblDump);
// std::cout << mesh << std::endl;
// debug::setDebugLevel(dblWarning);
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
model.limitInsertion(_y, -0.30, -0.20);
model.updateAutomaticInsertion();
// debug::setDebugLevel(dblDump);
// std::cout << mesh_facets << std::endl;
// debug::setDebugLevel(dblWarning);
Real time_step = model.getStableTimeStep() * 0.1;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
Array<Real> & position = mesh.getNodes();
Array<Real> & velocity = model.getVelocity();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & displacement = model.getDisplacement();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
boundary(n, 1) = true;
if (position(n, 0) > 0.99 || position(n, 0) < -0.99)
boundary(n, 0) = true;
}
/// initial conditions
Real loading_rate = 0.5;
Real disp_update = loading_rate * time_step;
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
velocity(n, 1) = loading_rate * position(n, 1);
}
model.synchronizeBoundaries();
model.updateResidual();
model.setBaseName("extrinsic_parallel");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("residual");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("partitions");
// model.getDumper().getDumper().setMode(iohelper::BASE64);
model.dump();
model.setBaseNameToDumper("cohesive elements",
"extrinsic_parallel_cohesive_elements");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump("cohesive elements");
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
/// update displacement on extreme nodes
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
displacement(n, 1) += disp_update * position(n, 1);
}
model.checkCohesiveStress();
model.solveStep();
// model.dump();
if (s % 10 == 0) {
if (prank == 0)
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
// // update displacement
- // for (UInt n = 0; n < nb_nodes; ++n) {
+ // for (Int n = 0; n < nb_nodes; ++n) {
// if (position(n, 1) + displacement(n, 1) > 0) {
// displacement(n, 0) -= 0.01;
// }
// }
// Real Ed = dynamic_cast<MaterialCohesive&>
// (model.getMaterial(1)).getDissipatedEnergy();
// Real Er = dynamic_cast<MaterialCohesive&>
// (model.getMaterial(1)).getReversibleEnergy();
// edis << s << " "
// << Ed << std::endl;
// erev << s << " "
// << Er << std::endl;
}
model.dump();
model.dump("cohesive elements");
// edis.close();
// erev.close();
Real Ed = model.getEnergy("dissipated");
Real Edt = 200 * sqrt(2);
if (prank == 0) {
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc
index 1fd5e4839..5f702c78b 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc
@@ -1,245 +1,245 @@
/**
* @file test_cohesive_parallel_extrinsic_tetrahedron.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Tue May 08 2012
* @date last modification: Thu Mar 22 2018
*
* @brief 3D extrinsic cohesive elements test
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
Real function(Real constant, Real x, Real y, Real z) {
return constant + 2. * x + 3. * y + 4 * z;
}
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
debug::setDebugLevel(dblWarning);
// const UInt max_steps = 1000;
// Real increment = 0.005;
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
Math::setTolerance(1.e-12);
ElementType type = _tetrahedron_10;
ElementType type_facet = Mesh::getFacetType(type);
ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
// Read the mesh
mesh.read("tetrahedron.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initParallel(partition, NULL, true);
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
const MaterialCohesiveLinear<3> & mat_cohesive =
dynamic_cast<const MaterialCohesiveLinear<3> &>(model.getMaterial(1));
const Real sigma_c =
mat_cohesive.getParam<RandomInternalField<Real, FacetInternalField>>(
"sigma_c");
const Real beta = mat_cohesive.getParam<Real>("beta");
// const Real G_cI = mat_cohesive.getParam<Real>("G_cI");
Array<Real> & position = mesh.getNodes();
/* ------------------------------------------------------------------------ */
/* Facet part */
/* ------------------------------------------------------------------------ */
/// compute quadrature points positions on facets
const Mesh & mesh_facets = model.getMeshFacets();
UInt nb_facet = mesh_facets.getNbElement(type_facet);
UInt nb_quad_per_facet =
model.getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
UInt nb_tot_quad = nb_quad_per_facet * nb_facet;
Array<Real> quad_facets(nb_tot_quad, spatial_dimension);
model.getFEEngine("FacetsFEEngine")
.interpolateOnIntegrationPoints(position, quad_facets, spatial_dimension,
type_facet);
/* ------------------------------------------------------------------------ */
/* End of facet part */
/* ------------------------------------------------------------------------ */
/// compute quadrature points position of the elements
UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type);
UInt nb_element = mesh.getNbElement(type);
UInt nb_tot_quad_el = nb_quad_per_element * nb_element;
Array<Real> quad_elements(nb_tot_quad_el, spatial_dimension);
model.getFEEngine().interpolateOnIntegrationPoints(position, quad_elements,
spatial_dimension, type);
/// assign some values to stresses
Array<Real> & stress =
const_cast<Array<Real> &>(model.getMaterial(0).getStress(type));
Array<Real>::iterator<Matrix<Real>> stress_it =
stress.begin(spatial_dimension, spatial_dimension);
for (UInt q = 0; q < nb_tot_quad_el; ++q, ++stress_it) {
/// compute values
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = i; j < spatial_dimension; ++j) {
UInt index = i * spatial_dimension + j;
(*stress_it)(i, j) =
index * function(sigma_c * 5, quad_elements(q, 0),
quad_elements(q, 1), quad_elements(q, 2));
}
}
/// fill symmetrical part
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = 0; j < i; ++j) {
(*stress_it)(i, j) = (*stress_it)(j, i);
}
}
}
/// compute stress on facet quads
Array<Real> stress_facets(nb_tot_quad, spatial_dimension * spatial_dimension);
Array<Real>::iterator<Matrix<Real>> stress_facets_it =
stress_facets.begin(spatial_dimension, spatial_dimension);
for (UInt q = 0; q < nb_tot_quad; ++q, ++stress_facets_it) {
/// compute values
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = i; j < spatial_dimension; ++j) {
UInt index = i * spatial_dimension + j;
(*stress_facets_it)(i, j) =
index * function(sigma_c * 5, quad_facets(q, 0), quad_facets(q, 1),
quad_facets(q, 2));
}
}
/// fill symmetrical part
for (UInt i = 0; i < spatial_dimension; ++i) {
for (UInt j = 0; j < i; ++j) {
(*stress_facets_it)(i, j) = (*stress_facets_it)(j, i);
}
}
}
/// insert cohesive elements
model.checkCohesiveStress();
/// check insertion stress
const Array<Real> & normals = model.getFEEngine("FacetsFEEngine")
.getNormalsOnIntegrationPoints(type_facet);
const Array<Real> & tangents = model.getTangents(type_facet);
const Array<Real> & sigma_c_eff =
mat_cohesive.getInsertionTraction(type_cohesive);
Vector<Real> normal_stress(spatial_dimension);
const Array<std::vector<Element>> & coh_element_to_facet =
mesh_facets.getElementToSubelement(type_facet);
Array<Real>::iterator<Matrix<Real>> quad_facet_stress =
stress_facets.begin(spatial_dimension, spatial_dimension);
Array<Real>::const_iterator<Vector<Real>> quad_normal =
normals.begin(spatial_dimension);
Array<Real>::const_iterator<Vector<Real>> quad_tangents =
tangents.begin(tangents.getNbComponent());
for (UInt f = 0; f < nb_facet; ++f) {
const Element & cohesive_element = coh_element_to_facet(f)[1];
for (UInt q = 0; q < nb_quad_per_facet;
++q, ++quad_facet_stress, ++quad_normal, ++quad_tangents) {
if (cohesive_element == ElementNull)
continue;
normal_stress.mul<false>(*quad_facet_stress, *quad_normal);
Real normal_contrib = normal_stress.dot(*quad_normal);
Real first_tangent_contrib = 0;
- for (UInt dim = 0; dim < spatial_dimension; ++dim)
+ for (Int dim = 0; dim < spatial_dimension; ++dim)
first_tangent_contrib += normal_stress(dim) * (*quad_tangents)(dim);
Real second_tangent_contrib = 0;
- for (UInt dim = 0; dim < spatial_dimension; ++dim)
+ for (Int dim = 0; dim < spatial_dimension; ++dim)
second_tangent_contrib +=
normal_stress(dim) * (*quad_tangents)(dim + spatial_dimension);
Real tangent_contrib =
std::sqrt(first_tangent_contrib * first_tangent_contrib +
second_tangent_contrib * second_tangent_contrib);
normal_contrib = std::max(0., normal_contrib);
Real effective_norm =
std::sqrt(normal_contrib * normal_contrib +
tangent_contrib * tangent_contrib / beta / beta);
if (effective_norm < sigma_c)
continue;
if (!Math::are_float_equal(
effective_norm,
sigma_c_eff(cohesive_element.element * nb_quad_per_facet + q))) {
std::cout << "Insertion tractions do not match" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc
index c163d337f..83232f8b3 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc
@@ -1,401 +1,401 @@
/**
* @file test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 08 2017
*
* @brief Displacement test for 3D cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "dumper_paraview.hh"
#include "material_cohesive_linear.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
bool checkDisplacement(SolidMechanicsModelCohesive & model, ElementType type,
std::ofstream & error_output, UInt step,
bool barycenters);
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
debug::setDebugLevel(dblWarning);
const UInt max_steps = 500;
Math::setTolerance(1.e-12);
- UInt spatial_dimension = 3;
+ Int spatial_dimension = 3;
ElementType type = _tetrahedron_10;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
// Read the mesh
mesh.read("tetrahedron.msh");
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
// debug::setDebugLevel(dblDump);
partition->partitionate(psize);
// debug::setDebugLevel(dblWarning);
}
SolidMechanicsModelCohesive model(mesh);
model.initParallel(partition, NULL, true);
// debug::setDebugLevel(dblDump);
// std::cout << mesh << std::endl;
// debug::setDebugLevel(dblWarning);
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true));
/* ------------------------------------------------------------------------ */
/* Facet part */
/* ------------------------------------------------------------------------ */
// Array<Real> limits(spatial_dimension, 2);
// limits(0, 0) = -0.01;
// limits(0, 1) = 0.01;
// limits(1, 0) = -100;
// limits(1, 1) = 100;
// limits(2, 0) = -100;
// limits(2, 1) = 100;
// model.enableFacetsCheckOnArea(limits);
/* ------------------------------------------------------------------------ */
/* End of facet part */
/* ------------------------------------------------------------------------ */
// debug::setDebugLevel(dblDump);
// std::cout << mesh_facets << std::endl;
// debug::setDebugLevel(dblWarning);
Real time_step = model.getStableTimeStep() * 0.1;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
Array<Real> & position = mesh.getNodes();
Array<Real> & velocity = model.getVelocity();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & displacement = model.getDisplacement();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
/// boundary conditions
for (UInt n = 0; n < nb_nodes; ++n) {
if (position(n, 0) > 0.99 || position(n, 0) < -0.99) {
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
boundary(n, dim) = true;
}
}
if (position(n, 0) > 0.99 || position(n, 0) < -0.99) {
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
boundary(n, dim) = true;
}
}
}
// #if defined (AKANTU_DEBUG_TOOLS)
// Vector<Real> facet_center(spatial_dimension);
// facet_center(0) = 0;
// facet_center(1) = -0.16666667;
// facet_center(2) = 0.5;
// debug::element_manager.setMesh(mesh);
// debug::element_manager.addModule(debug::_dm_material_cohesive);
// debug::element_manager.addModule(debug::_dm_debug_tools);
// //debug::element_manager.addModule(debug::_dm_integrator);
// #endif
/// initial conditions
Real loading_rate = 1;
Real disp_update = loading_rate * time_step;
for (UInt n = 0; n < nb_nodes; ++n) {
velocity(n, 0) = loading_rate * position(n, 0);
velocity(n, 1) = loading_rate * position(n, 0);
}
model.synchronizeBoundaries();
model.updateResidual();
std::stringstream paraview_output;
paraview_output << "extrinsic_parallel_tetrahedron_" << psize;
model.setBaseName(paraview_output.str());
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("velocity");
model.addDumpFieldVector("acceleration");
model.addDumpFieldVector("residual");
model.addDumpFieldTensor("stress");
model.addDumpFieldTensor("grad_u");
model.addDumpField("partitions");
// model.getDumper().getDumper().setMode(iohelper::BASE64);
model.dump();
model.setBaseNameToDumper("cohesive elements",
paraview_output.str() + "_cohesive_elements");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump("cohesive elements");
std::stringstream error_stream;
error_stream << "error"
<< ".csv";
std::ofstream error_output;
error_output.open(error_stream.str().c_str());
error_output << "# Step, Average, Max, Min" << std::endl;
if (checkDisplacement(model, type, error_output, 0, true)) {
}
/// Main loop
for (UInt s = 1; s <= max_steps; ++s) {
/// update displacement on extreme nodes
for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
if (position(n, 0) > 0.99 || position(n, 0) < -0.99) {
displacement(n, 0) += disp_update * position(n, 0);
displacement(n, 1) += disp_update * position(n, 0);
}
}
model.checkCohesiveStress();
model.solveStep();
if (s % 100 == 0) {
if (prank == 0)
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
}
model.dump();
model.dump("cohesive elements");
if (!checkDisplacement(model, type, error_output, max_steps, false)) {
finalize();
return EXIT_FAILURE;
}
finalize();
return EXIT_SUCCESS;
}
bool checkDisplacement(SolidMechanicsModelCohesive & model, ElementType type,
std::ofstream & error_output, UInt step,
bool barycenters) {
Mesh & mesh = model.getMesh();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
const Array<UInt> & connectivity = mesh.getConnectivity(type);
const Array<Real> & displacement = model.getDisplacement();
UInt nb_element = mesh.getNbElement(type);
UInt nb_nodes_per_elem = Mesh::getNbNodesPerElement(type);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
if (psize == 1) {
std::stringstream displacement_file;
displacement_file << "displacement/displacement_" << std::setfill('0')
<< std::setw(6) << step;
std::ofstream displacement_output;
displacement_output.open(displacement_file.str().c_str());
for (UInt el = 0; el < nb_element; ++el) {
for (UInt n = 0; n < nb_nodes_per_elem; ++n) {
UInt node = connectivity(el, n);
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
displacement_output << std::setprecision(15)
<< displacement(node, dim) << " ";
}
displacement_output << std::endl;
}
}
displacement_output.close();
if (barycenters) {
std::stringstream barycenter_file;
barycenter_file << "displacement/barycenters";
std::ofstream barycenter_output;
barycenter_output.open(barycenter_file.str().c_str());
Element element(type, 0);
Vector<Real> bary(spatial_dimension);
for (UInt el = 0; el < nb_element; ++el) {
element.element = el;
mesh.getBarycenter(element, bary);
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
barycenter_output << std::setprecision(15) << bary(dim) << " ";
}
barycenter_output << std::endl;
}
barycenter_output.close();
}
} else {
if (barycenters)
return true;
/// read data
std::stringstream displacement_file;
displacement_file << "displacement/displacement_" << std::setfill('0')
<< std::setw(6) << step;
std::ifstream displacement_input;
displacement_input.open(displacement_file.str().c_str());
Array<Real> displacement_serial(0, spatial_dimension);
Vector<Real> disp_tmp(spatial_dimension);
while (displacement_input.good()) {
for (UInt i = 0; i < spatial_dimension; ++i)
displacement_input >> disp_tmp(i);
displacement_serial.push_back(disp_tmp);
}
std::stringstream barycenter_file;
barycenter_file << "displacement/barycenters";
std::ifstream barycenter_input;
barycenter_input.open(barycenter_file.str().c_str());
Array<Real> barycenter_serial(0, spatial_dimension);
while (barycenter_input.good()) {
- for (UInt dim = 0; dim < spatial_dimension; ++dim)
+ for (Int dim = 0; dim < spatial_dimension; ++dim)
barycenter_input >> disp_tmp(dim);
barycenter_serial.push_back(disp_tmp);
}
Element element(type, 0);
Vector<Real> bary(spatial_dimension);
Array<Real>::iterator<Vector<Real>> it;
Array<Real>::iterator<Vector<Real>> begin =
barycenter_serial.begin(spatial_dimension);
Array<Real>::iterator<Vector<Real>> end =
barycenter_serial.end(spatial_dimension);
Array<Real>::const_iterator<Vector<Real>> disp_it;
Array<Real>::iterator<Vector<Real>> disp_serial_it;
Vector<Real> difference(spatial_dimension);
Array<Real> error;
/// compute error
- for (UInt el = 0; el < nb_element; ++el) {
+ for (Int el = 0; el < nb_element; ++el) {
element.element = el;
mesh.getBarycenter(element, bary);
/// find element
for (it = begin; it != end; ++it) {
UInt matched_dim = 0;
while (matched_dim < spatial_dimension &&
Math::are_float_equal(bary(matched_dim), (*it)(matched_dim)))
++matched_dim;
if (matched_dim == spatial_dimension)
break;
}
if (it == end) {
std::cout << "Element barycenter not found!" << std::endl;
return false;
}
UInt matched_el = it - begin;
disp_serial_it = displacement_serial.begin(spatial_dimension) +
matched_el * nb_nodes_per_elem;
- for (UInt n = 0; n < nb_nodes_per_elem; ++n, ++disp_serial_it) {
+ for (Int n = 0; n < nb_nodes_per_elem; ++n, ++disp_serial_it) {
UInt node = connectivity(el, n);
if (!mesh.isLocalOrMasterNode(node))
continue;
disp_it = displacement.begin(spatial_dimension) + node;
difference = *disp_it;
difference -= *disp_serial_it;
error.push_back(difference.norm());
}
}
/// compute average error
Real average_error = std::accumulate(error.begin(), error.end(), 0.);
comm.allReduce(&average_error, 1, _so_sum);
UInt error_size = error.getSize();
comm.allReduce(&error_size, 1, _so_sum);
average_error /= error_size;
/// compute maximum and minimum
Real max_error = *std::max_element(error.begin(), error.end());
comm.allReduce(&max_error, 1, _so_max);
Real min_error = *std::min_element(error.begin(), error.end());
comm.allReduce(&min_error, 1, _so_min);
/// output data
if (prank == 0) {
error_output << step << ", " << average_error << ", " << max_error << ", "
<< min_error << std::endl;
}
if (max_error > 1.e-9) {
std::cout << "Displacement error is too big!" << std::endl;
return false;
}
}
return true;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc
index e596ba687..1a8c5d7a8 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc
@@ -1,317 +1,317 @@
/**
* @file test_cohesive_parallel_extrinsic_IG_TG.cc
*
* @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Jul 24 2020
*
* @brief Test for considering different cohesive properties for
* intergranular (IG) and transgranular (TG) fractures in extrinsic
* cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "material_cohesive_linear.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class MultiGrainMaterialSelector : public DefaultMaterialCohesiveSelector {
public:
MultiGrainMaterialSelector(const SolidMechanicsModelCohesive & model,
const ID & transgranular_id,
const ID & intergranular_id)
: DefaultMaterialCohesiveSelector(model),
transgranular_id(transgranular_id), intergranular_id(intergranular_id),
model(model), mesh(model.getMesh()), mesh_facets(model.getMeshFacets()),
spatial_dimension(model.getSpatialDimension()), nb_IG(0), nb_TG(0) {}
UInt operator()(const Element & element) {
if (mesh_facets.getSpatialDimension(element.type) ==
(spatial_dimension - 1)) {
const std::vector<Element> & element_to_subelement =
mesh_facets.getElementToSubelement(element.type, element.ghost_type)(
element.element);
const Element & el1 = element_to_subelement[0];
const Element & el2 = element_to_subelement[1];
UInt grain_id1 =
mesh.getData<UInt>("tag_0", el1.type, el1.ghost_type)(el1.element);
if (el2 != ElementNull) {
UInt grain_id2 =
mesh.getData<UInt>("tag_0", el2.type, el2.ghost_type)(el2.element);
if (grain_id1 == grain_id2) {
// transgranular = 0 indicator
nb_TG++;
return model.getMaterialIndex(transgranular_id);
} else {
// intergranular = 1 indicator
nb_IG++;
return model.getMaterialIndex(intergranular_id);
}
} else {
// transgranular = 0 indicator
nb_TG++;
return model.getMaterialIndex(transgranular_id);
}
} else {
return DefaultMaterialCohesiveSelector::operator()(element);
}
}
private:
ID transgranular_id, intergranular_id;
const SolidMechanicsModelCohesive & model;
const Mesh & mesh;
const Mesh & mesh_facets;
- UInt spatial_dimension;
+ Int spatial_dimension;
UInt nb_IG;
UInt nb_TG;
};
/* -------------------------------------------------------------------------- */
void limitInsertion(SolidMechanicsModelCohesive & model) {
Real tolerance = 0.1;
const Mesh & mesh = model.getMesh();
const Mesh & mesh_facets = model.getMeshFacets();
CohesiveElementInserter & inserter = model.getElementInserter();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
Vector<Real> bary_facet(spatial_dimension);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it =
mesh_facets.firstType(spatial_dimension - 1, ghost_type);
Mesh::type_iterator end =
mesh_facets.lastType(spatial_dimension - 1, ghost_type);
for (; it != end; ++it) {
ElementType type = *it;
Array<bool> & f_check = inserter.getCheckFacets(type, ghost_type);
UInt nb_facet = mesh_facets.getNbElement(type, ghost_type);
for (UInt f = 0; f < nb_facet; ++f) {
if (f_check(f)) {
- mesh_facets.getBarycenter(f, type, bary_facet.storage(), ghost_type);
+ mesh_facets.getBarycenter(f, type, bary_facet.data(), ghost_type);
if (!(bary_facet(0) > -tolerance && bary_facet(0) < tolerance) &&
!(bary_facet(1) > -tolerance && bary_facet(1) < tolerance))
f_check(f) = false;
}
}
}
}
model.updateAutomaticInsertion();
}
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
debug::setDebugLevel(dblWarning);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const UInt max_steps = 600;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("square.msh");
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
SolidMechanicsModelCohesive model(mesh);
/// model initialization
model.initParallel(partition, NULL, true);
delete partition;
MultiGrainMaterialSelector material_selector(model, "TG_cohesive",
"IG_cohesive");
model.setMaterialSelector(material_selector);
model.initFull(
SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true, false));
Real time_step = model.getStableTimeStep() * 0.1;
model.setTimeStep(time_step);
// std::cout << "Time step: " << time_step << std::endl;
limitInsertion(model);
// std::cout << mesh << std::endl;
Array<Real> & position = mesh.getNodes();
Array<Real> & velocity = model.getVelocity();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & displacement = model.getDisplacement();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (position(n, 1) > 0.99 || position(n, 1) < -0.99)
boundary(n, 1) = true;
if (position(n, 0) > 0.99 || position(n, 0) < -0.99)
boundary(n, 0) = true;
}
model.synchronizeBoundaries();
model.updateResidual();
model.setBaseName("extrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("residual");
model.addDumpField("stress");
model.addDumpField("strain");
model.addDumpField("partitions");
model.setBaseNameToDumper("cohesive elements", "extrinsic_cohesive");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.addDumpFieldToDumper("cohesive elements", "damage");
model.dump();
model.dump("cohesive elements");
/// initial conditions
Real loading_rate = 0.1;
// bar_height = 2
Real VI = loading_rate * 2 * 0.5;
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
velocity(n, 1) = loading_rate * position(n, 1);
velocity(n, 0) = loading_rate * position(n, 0);
}
// std::ofstream edis("edis.txt");
// std::ofstream erev("erev.txt");
// Array<Real> & residual = model.getResidual();
// model.dump();
// const Array<Real> & stress = model.getMaterial(0).getStress(type);
Real dispy = 0;
// UInt nb_coh_elem = 0;
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
dispy += VI * time_step;
/// update displacement on extreme nodes
- for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
+ for (Int n = 0; n < mesh.getNbNodes(); ++n) {
if (position(n, 1) > 0.99) {
displacement(n, 1) = dispy;
velocity(n, 1) = VI;
}
if (position(n, 1) < -0.99) {
displacement(n, 1) = -dispy;
velocity(n, 1) = -VI;
}
if (position(n, 0) > 0.99) {
displacement(n, 0) = dispy;
velocity(n, 0) = VI;
}
if (position(n, 0) < -0.99) {
displacement(n, 0) = -dispy;
velocity(n, 0) = -VI;
}
}
model.checkCohesiveStress();
model.solveStep();
if (s % 10 == 0) {
if (prank == 0)
std::cout << "passing step " << s << "/" << max_steps << std::endl;
// model.dump();
// model.dump("cohesive elements");
}
// Real Ed = model.getEnergy("dissipated");
// edis << s << " "
// << Ed << std::endl;
// erev << s << " "
// << Er << std::endl;
}
model.dump();
model.dump("cohesive elements");
// edis.close();
// erev.close();
// mesh.write("mesh_final.msh");
Real Ed = model.getEnergy("dissipated");
Real Edt = 40;
if (prank == 0)
std::cout << Ed << " " << Edt << std::endl;
if (Ed < Edt * 0.99 || Ed > Edt * 1.01 || std::isnan(Ed)) {
if (prank == 0)
std::cout << "The dissipated energy is incorrect" << std::endl;
finalize();
return EXIT_FAILURE;
}
- // for (UInt n = 0; n < position.getSize(); ++n) {
- // for (UInt s = 0; s < spatial_dimension; ++s) {
+ // for (Int n = 0; n < position.getSize(); ++n) {
+ // for (Int s = 0; s < spatial_dimension; ++s) {
// position(n, s) += displacement(n, s);
// }
// }
finalize();
if (prank == 0)
std::cout << "OK: test_cohesive_extrinsic_IG_TG was passed!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_insertion_along_physical_surfaces.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_insertion_along_physical_surfaces.cc
index fb0dbcdca..5b43fd465 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_insertion_along_physical_surfaces.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_insertion_along_physical_surfaces.cc
@@ -1,134 +1,134 @@
/**
* @file test_cohesive_parallel_insertion_along_physical_surfaces.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 08 2017
*
* @brief Test parallel intrinsic insertion of cohesive elements along physical
* surfaces
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_cohesive.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_io_msh.hh"
#include "mesh_utils.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("input_file.dat", argc, argv);
Math::setTolerance(1e-15);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
mesh.read("3d_spherical_inclusion.msh");
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
}
SolidMechanicsModelCohesive model(mesh);
model.initParallel(partition);
mesh.createGroupsFromMeshData<std::string>("physical_names");
model.initFull(SolidMechanicsModelCohesiveOptions(_static));
std::vector<std::string> surfaces_name = {"interface", "coh1", "coh2",
"coh3", "coh4", "coh5"};
UInt nb_surf = surfaces_name.size();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
std::string ghost_str;
if (*gt == 1)
ghost_str = "ghost";
else
ghost_str = "not ghost";
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, *gt, _ek_cohesive);
Mesh::type_iterator end =
mesh.lastType(spatial_dimension, *gt, _ek_cohesive);
for (; it != end; ++it) {
Array<UInt> & material_id = mesh.getMeshFacets().getData<UInt>(
"physical_names")(mesh.getFacetType(*it), *gt);
- for (UInt i = 0; i < nb_surf; ++i) {
+ for (Int i = 0; i < nb_surf; ++i) {
UInt expected_insertion = 0;
- for (UInt m = 0; m < material_id.getSize(); ++m) {
+ for (Int m = 0; m < material_id.getSize(); ++m) {
if (material_id(m) ==
model.SolidMechanicsModel::getMaterialIndex(surfaces_name[i]))
++expected_insertion;
}
UInt inserted_elements;
inserted_elements = model.getMaterial(surfaces_name[i])
.getElementFilter()(*it, *gt)
.getSize();
if (expected_insertion != inserted_elements) {
std::cerr << std::endl
<< "!!! Mismatch in insertion of surface named "
<< surfaces_name[i] << " in proc n° " << prank << " --> "
<< inserted_elements << " inserted elements of type "
<< ghost_str << " out of " << expected_insertion
<< std::endl;
return EXIT_FAILURE;
}
}
}
}
model.assembleStiffnessMatrix();
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_intrinsic_implicit_insertion.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_intrinsic_implicit_insertion.cc
index d00b4c34a..93c4d2650 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_intrinsic_implicit_insertion.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_insertion/test_cohesive_parallel_intrinsic_implicit_insertion.cc
@@ -1,308 +1,308 @@
/**
* @file test_cohesive_parallel_intrinsic_implicit_insertion.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Mauro Corrado <mauro.corrado@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 08 2017
*
* @brief Verifying the proper insertion and synchronization of intrinsic
* cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
#include "material_cohesive.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_io_msh.hh"
#include "mesh_utils.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
std::ofstream output;
/* -------------------------------------------------------------------------- */
void printMeshContent(Mesh & mesh) {
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
comm.barrier();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
Mesh::type_iterator first =
mesh.firstType(_all_dimensions, *gt, _ek_not_defined);
Mesh::type_iterator last =
mesh.lastType(_all_dimensions, *gt, _ek_not_defined);
for (; first != last; ++first) {
UInt nb_element = mesh.getNbElement(*first, *gt);
output << std::endl
<< "Element type: " << *first << ", " << *gt << ": " << nb_element
<< " in the mesh of processor " << prank << std::endl;
Array<UInt> & conn = mesh.getConnectivity(*first, *gt);
for (UInt i = 0; i < conn.getSize(); ++i) {
output << "Element no " << i << " ";
for (UInt j = 0; j < conn.getNbComponent(); ++j) {
output << conn(i, j) << " ";
}
output << std::endl;
}
}
}
}
/* -------------------------------------------------------------------------- */
void printNodeList(Mesh & mesh) {
Array<double> & nodes = mesh.getNodes();
output << "Number of nodes: " << mesh.getNbNodes() << std::endl;
for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
output << "Node # " << i << ", x-coord: " << nodes(i, 0)
<< ", y-coord: " << nodes(i, 1)
<< ", of type: " << mesh.getNodeType(i) << std::endl;
}
output << std::endl;
}
/* -------------------------------------------------------------------------- */
void getGlobalIDs(Mesh & mesh) {
const Array<UInt> & glob_id = mesh.getGlobalNodesIds();
if (&glob_id) {
output << "Global nodes ID: " << std::endl;
for (UInt i = 0; i < glob_id.getSize(); ++i) {
output << i << " " << glob_id(i) << std::endl;
}
}
output << std::endl;
}
/* -------------------------------------------------------------------------- */
void printSynchroinfo(Mesh & mesh, const DistributedSynchronizer & synch) {
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
Int psize = comm.getNbProc();
if (comm.getNbProc() == 1)
return;
for (Int p = 0; p < psize; ++p) {
if (p == prank)
continue;
output << "From processor " << prank << " to processor " << p << std::endl;
const Array<Element> & sele = *(synch.getSendElement() + p);
output << " Sending element(s): " << std::endl;
for (UInt i = 0; i < sele.getSize(); ++i) {
output << sele(i) << std::endl;
}
const Array<Element> & rele = *(synch.getReceiveElement() + p);
output << " Receiving element(s): " << std::endl;
for (UInt i = 0; i < rele.getSize(); ++i) {
output << rele(i) << std::endl;
}
}
output << std::endl;
}
/* -------------------------------------------------------------------------- */
void printDOF(SolidMechanicsModelCohesive & model) {
const auto & comm = Communicator::getStaticCommunicator();
if (comm.getNbProc() == 1)
return;
Int prank = comm.whoAmI();
const DOFSynchronizer & dof = model.getDOFSynchronizer();
output << "Number of global dofs " << dof.getNbGlobalDOFs()
<< " for processor " << prank << std::endl;
const Array<UInt> & dof_global_ids = dof.getDOFGlobalIDs();
for (UInt i = 0; i < dof_global_ids.getSize(); ++i) {
output << "Local dof " << i << ", global id: " << dof_global_ids(i)
<< std::endl;
}
output << std::endl;
}
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
std::string input_file = "input_file_iii.dat";
std::string mesh_file = "2d_basic_interface.msh";
std::string dir = "output_dir/";
initialize(input_file, argc, argv);
debug::setDebugLevel(dbl0);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
std::stringstream filename;
filename << dir.c_str() << "output_from_proc_" << prank << "_out_of_" << psize
<< ".out";
output.open(filename.str());
if (prank == 0) {
mesh.read(mesh_file);
partition = new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
const ElementTypeMapArray<UInt> & partitions = partition->getPartitions();
output << "The root processor read the mesh." << std::endl
<< "Only GMSH physical objects are created in the mesh."
<< std::endl;
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
Mesh::type_iterator first = mesh.firstType(_all_dimensions, *gt);
Mesh::type_iterator last = mesh.lastType(_all_dimensions, *gt);
for (; first != last; ++first) {
output << "Element type: " << *first << " ghost type: " << *gt
<< std::endl;
UInt nb_element = mesh.getNbElement(*first, *gt);
output << nb_element << " to partitionate between " << psize
<< " processsors" << std::endl;
Array<UInt> part = partitions(*first, *gt);
- for (UInt i = 0; i < part.getSize(); ++i) {
+ for (Int i = 0; i < part.getSize(); ++i) {
output << i << " " << part(i) << std::endl;
}
}
}
output << "Nodes are also read and set with type -1 (normal node)"
<< std::endl;
printNodeList(mesh);
}
SolidMechanicsModelCohesive model(mesh);
output << "Before initParallel(), non-root processors have empty Mesh object"
<< std::endl;
printMeshContent(mesh);
model.initParallel(partition);
output << "After initParallel(), Mesh object on each processor is a local "
"partionated mesh containing ghost elements"
<< std::endl;
printMeshContent(mesh);
output << "Nodes are also partionated and new node types are defined:"
<< std::endl;
printNodeList(mesh);
output << "-3: pure ghost node -> not a local node" << std::endl
<< "-2: master node -> node shared with other processor(s) -> local "
"and global node"
<< std::endl
<< ">0: slave node -> -> node shared with other processor(s) -> only "
"local node (its id is the rank of the processor owning the master "
"node)"
<< std::endl;
output
<< "Each local node has a corresponding global id used during assembly: "
<< std::endl;
getGlobalIDs(mesh);
Mesh & mesh_facets = mesh.getMeshFacets();
output << "Within cohesive element model, initParallel() creates a second "
"Mesh object usually called mesh_facet"
<< std::endl
<< "This Mesh object contains all sub-dimensional elements where "
"potential cohesive element can be inserted"
<< std::endl;
printMeshContent(mesh_facets);
const DistributedSynchronizer & synch_model = model.getSynchronizer();
output << "The distributed synchronizer of solid mechanics model is used to "
"synchronize fields with ghost element:"
<< std::endl;
printSynchroinfo(mesh, synch_model);
mesh.createGroupsFromMeshData<std::string>("physical_names");
model.initFull(SolidMechanicsModelCohesiveOptions(_static));
output << "In case of insertion along physical objects, cohesive elements "
"are created during initFull()"
<< std::endl;
output << "Elements list after insertion" << std::endl;
printMeshContent(mesh);
output << "Node list after insertion: (Total number of nodes "
<< mesh.getNbNodes() << ")" << std::endl;
printNodeList(mesh);
output << "Node global ids after insertion: (Total number of nodes "
<< mesh.getNbGlobalNodes() << ")" << std::endl;
getGlobalIDs(mesh);
const DistributedSynchronizer & coh_synch_model =
*(model.getCohesiveSynchronizer());
output << "Solid mechanics model cohesive has its own distributed "
"synchronizer to handle ghost cohesive element:"
<< std::endl;
printSynchroinfo(mesh, coh_synch_model);
output << "A synchronizer dedicated to degrees of freedom (DOFs) is used by "
"the solver to build matrices in parallel:"
<< std::endl
<< "This DOFSynchronizer is built based on nodes global id "
<< std::endl;
printDOF(model);
output.close();
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc
index 1198a4ee0..d2e5a203b 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc
@@ -1,176 +1,176 @@
/**
* @file test_cohesive_parallel_intrinsic.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 08 2017
*
* @brief parallel test for intrinsic cohesive elements
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
const UInt max_steps = 350;
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
// Read the mesh
mesh.read("mesh.msh");
// /// insert cohesive elements
// CohesiveElementInserter inserter(mesh);
// inserter.setLimit('x', -0.26, -0.24);
// inserter.insertIntrinsicElements();
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
// debug::setDebugLevel(dblDump);
partition->partitionate(psize);
// debug::setDebugLevel(dblWarning);
}
SolidMechanicsModelCohesive model(mesh);
model.initParallel(partition);
model.initFull();
model.limitInsertion(_x, -0.26, -0.24);
model.insertIntrinsicElements();
debug::setDebugLevel(dblDump);
std::cout << mesh << std::endl;
debug::setDebugLevel(dblWarning);
Real time_step = model.getStableTimeStep() * 0.8;
model.setTimeStep(time_step);
// std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
Array<Real> & position = mesh.getNodes();
Array<Real> & velocity = model.getVelocity();
Array<bool> & boundary = model.getBlockedDOFs();
// Array<Real> & displacement = model.getDisplacement();
// const Array<Real> & residual = model.getResidual();
UInt nb_nodes = mesh.getNbNodes();
Real epsilon = std::numeric_limits<Real>::epsilon();
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (std::abs(position(n, 0) - 1.) < epsilon)
boundary(n, 0) = true;
}
model.synchronizeBoundaries();
model.updateResidual();
model.setBaseName("intrinsic_parallel");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("residual");
model.addDumpField("stress");
model.addDumpField("strain");
model.addDumpField("partitions");
model.addDumpField("force");
model.dump();
model.setBaseNameToDumper("cohesive elements",
"cohesive_elements_parallel_intrinsic");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.dump("cohesive elements");
/// initial conditions
Real loading_rate = .2;
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
velocity(n, 0) = loading_rate * position(n, 0);
}
/// Main loop
- for (UInt s = 1; s <= max_steps; ++s) {
+ for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
if (s % 20 == 0) {
model.dump();
model.dump("cohesive elements");
if (prank == 0)
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
// // update displacement
- // for (UInt n = 0; n < nb_nodes; ++n) {
+ // for (Int n = 0; n < nb_nodes; ++n) {
// if (position(n, 1) + displacement(n, 1) > 0) {
// displacement(n, 0) -= 0.01;
// }
// }
// Real Ed = dynamic_cast<MaterialCohesive&>
// (model.getMaterial(1)).getDissipatedEnergy();
// Real Er = dynamic_cast<MaterialCohesive&>
// (model.getMaterial(1)).getReversibleEnergy();
// edis << s << " "
// << Ed << std::endl;
// erev << s << " "
// << Er << std::endl;
}
// edis.close();
// erev.close();
Real Ed = model.getEnergy("dissipated");
Real Edt = 2 * sqrt(2);
if (prank == 0) {
std::cout << Ed << " " << Edt << std::endl;
if (std::abs((Ed - Edt) / Edt) > 0.01 || std::isnan(Ed)) {
std::cout << "The dissipated energy is incorrect" << std::endl;
return EXIT_FAILURE;
}
}
finalize();
if (prank == 0)
std::cout << "OK: Test passed!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc
index 6b243974e..02b5b2d49 100644
--- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc
+++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc
@@ -1,714 +1,713 @@
/**
* @file test_cohesive_parallel_intrinsic_tetrahedron.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Fri Oct 13 2017
* @date last modification: Wed Nov 08 2017
*
* @brief Test for 3D intrinsic cohesive elements simulation in parallel
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dumper_paraview.hh"
#include "material_cohesive.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
void updateDisplacement(SolidMechanicsModelCohesive & model,
const ElementTypeMapArray<UInt> & elements,
Vector<Real> & increment);
bool checkTractions(SolidMechanicsModelCohesive & model, Vector<Real> & opening,
Vector<Real> & theoretical_traction,
Matrix<Real> & rotation);
void findNodesToCheck(const Mesh & mesh,
const ElementTypeMapArray<UInt> & elements,
Array<UInt> & nodes_to_check, Int psize);
bool checkEquilibrium(const Mesh & mesh, const Array<Real> & residual);
bool checkResidual(const Array<Real> & residual, const Vector<Real> & traction,
const Array<UInt> & nodes_to_check,
const Matrix<Real> & rotation);
void findElementsToDisplace(const Mesh & mesh,
ElementTypeMapArray<UInt> & elements);
int main(int argc, char * argv[]) {
initialize("material_tetrahedron.dat", argc, argv);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
const UInt max_steps = 60;
const Real increment_constant = 0.01;
ElementType type = _tetrahedron_10;
Math::setTolerance(1.e-10);
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
UInt nb_nodes_to_check_serial = 0;
UInt total_nb_nodes = 0;
UInt nb_elements_check_serial = 0;
akantu::MeshPartition * partition = NULL;
if (prank == 0) {
// Read the mesh
mesh.read("tetrahedron.msh");
/// count nodes with zero position
const Array<Real> & position = mesh.getNodes();
for (UInt n = 0; n < position.getSize(); ++n) {
if (std::abs(position(n, 0) - 0.) < 1e-6)
++nb_nodes_to_check_serial;
}
// /// insert cohesive elements
// CohesiveElementInserter inserter(mesh);
// inserter.setLimit(0, -0.01, 0.01);
// inserter.insertIntrinsicElements();
/// find nodes to check in serial
ElementTypeMapArray<UInt> elements_serial("elements_serial", "");
findElementsToDisplace(mesh, elements_serial);
nb_elements_check_serial = elements_serial(type).getSize();
total_nb_nodes = mesh.getNbNodes() + nb_nodes_to_check_serial;
/// partition the mesh
partition = new MeshPartitionScotch(mesh, spatial_dimension);
debug::setDebugLevel(dblDump);
partition->partitionate(psize);
debug::setDebugLevel(dblInfo);
}
comm.broadcast(&nb_nodes_to_check_serial, 1, 0);
comm.broadcast(&nb_elements_check_serial, 1, 0);
SolidMechanicsModelCohesive model(mesh);
model.initParallel(partition);
model.initFull();
model.limitInsertion(_x, -0.01, 0.01);
model.insertIntrinsicElements();
{
comm.broadcast(&total_nb_nodes, 1, 0);
Array<Int> nb_local_nodes(psize);
nb_local_nodes.zero();
for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
if (mesh.isLocalOrMasterNode(n))
++nb_local_nodes(prank);
}
- comm.allGather(nb_local_nodes.storage(), 1);
+ comm.allGather(nb_local_nodes.data(), 1);
UInt total_nb_nodes_parallel =
std::accumulate(nb_local_nodes.begin(), nb_local_nodes.end(), 0);
Array<UInt> global_nodes_list(total_nb_nodes_parallel);
UInt first_global_node = std::accumulate(nb_local_nodes.begin(),
nb_local_nodes.begin() + prank, 0);
for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
if (mesh.isLocalOrMasterNode(n)) {
global_nodes_list(first_global_node) = mesh.getNodeGlobalId(n);
++first_global_node;
}
}
- comm.allGatherV(global_nodes_list.storage(), nb_local_nodes.storage());
+ comm.allGatherV(global_nodes_list.data(), nb_local_nodes.data());
if (prank == 0)
std::cout << "Maximum node index: "
<< *(std::max_element(global_nodes_list.begin(),
global_nodes_list.end()))
<< std::endl;
Array<UInt> repeated_nodes;
repeated_nodes.resize(0);
for (UInt n = 0; n < total_nb_nodes_parallel; ++n) {
UInt appearances =
std::count(global_nodes_list.begin() + n, global_nodes_list.end(),
global_nodes_list(n));
if (appearances > 1) {
std::cout << "Node " << global_nodes_list(n) << " appears "
<< appearances << " times" << std::endl;
std::cout << " in position: " << n;
repeated_nodes.push_back(global_nodes_list(n));
- UInt * node_position = global_nodes_list.storage() + n;
+ UInt * node_position = global_nodes_list.data() + n;
for (UInt i = 1; i < appearances; ++i) {
node_position =
std::find(node_position + 1,
- global_nodes_list.storage() + total_nb_nodes_parallel,
+ global_nodes_list.data() + total_nb_nodes_parallel,
global_nodes_list(n));
- UInt current_index = node_position - global_nodes_list.storage();
+ UInt current_index = node_position - global_nodes_list.data();
std::cout << ", " << current_index;
}
std::cout << std::endl << std::endl;
}
}
for (UInt n = 0; n < mesh.getNbNodes(); ++n) {
UInt global_node = mesh.getNodeGlobalId(n);
if (std::find(repeated_nodes.begin(), repeated_nodes.end(),
global_node) != repeated_nodes.end()) {
std::cout << "Repeated global node " << global_node
<< " corresponds to local node " << n << std::endl;
}
}
if (total_nb_nodes != total_nb_nodes_parallel) {
if (prank == 0) {
std::cout << "Error: total number of nodes is wrong in parallel"
<< std::endl;
std::cout << "Serial: " << total_nb_nodes
<< " Parallel: " << total_nb_nodes_parallel << std::endl;
}
finalize();
return EXIT_FAILURE;
}
}
model.updateResidual();
model.setBaseName("intrinsic_parallel_tetrahedron");
model.addDumpFieldVector("displacement");
model.addDumpField("residual");
model.addDumpField("partitions");
model.dump();
model.setBaseNameToDumper("cohesive elements",
"cohesive_elements_parallel_tetrahedron");
model.addDumpFieldVectorToDumper("cohesive elements", "displacement");
model.dump("cohesive elements");
/// find elements to displace
ElementTypeMapArray<UInt> elements("elements", "");
findElementsToDisplace(mesh, elements);
UInt nb_elements_check = elements(type).getSize();
comm.allReduce(&nb_elements_check, 1, _so_sum);
if (nb_elements_check != nb_elements_check_serial) {
if (prank == 0) {
std::cout << "Error: number of elements to check is wrong" << std::endl;
std::cout << "Serial: " << nb_elements_check_serial
<< " Parallel: " << nb_elements_check << std::endl;
}
finalize();
return EXIT_FAILURE;
}
/// find nodes to check
Array<UInt> nodes_to_check;
findNodesToCheck(mesh, elements, nodes_to_check, psize);
Vector<Int> nodes_to_check_size(psize);
nodes_to_check_size(prank) = nodes_to_check.getSize();
- comm.allGather(nodes_to_check_size.storage(), 1);
+ comm.allGather(nodes_to_check_size.data(), 1);
UInt nodes_to_check_global_size = std::accumulate(
- nodes_to_check_size.storage(), nodes_to_check_size.storage() + psize, 0);
+ nodes_to_check_size.data(), nodes_to_check_size.data() + psize, 0);
if (nodes_to_check_global_size != nb_nodes_to_check_serial) {
if (prank == 0) {
std::cout << "Error: number of nodes to check is wrong in parallel"
<< std::endl;
std::cout << "Serial: " << nb_nodes_to_check_serial
<< " Parallel: " << nodes_to_check_global_size << std::endl;
}
finalize();
return EXIT_FAILURE;
}
/// rotate mesh
Real angle = 1.;
Matrix<Real> rotation(spatial_dimension, spatial_dimension);
rotation.zero();
rotation(0, 0) = std::cos(angle);
rotation(0, 1) = std::sin(angle) * -1.;
rotation(1, 0) = std::sin(angle);
rotation(1, 1) = std::cos(angle);
rotation(2, 2) = 1.;
Vector<Real> increment_tmp(spatial_dimension);
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
increment_tmp(dim) = (dim + 1) * increment_constant;
}
Vector<Real> increment(spatial_dimension);
increment.mul<false>(rotation, increment_tmp);
Array<Real> & position = mesh.getNodes();
Array<Real> position_tmp(position);
Array<Real>::iterator<Vector<Real>> position_it =
position.begin(spatial_dimension);
Array<Real>::iterator<Vector<Real>> position_end =
position.end(spatial_dimension);
Array<Real>::iterator<Vector<Real>> position_tmp_it =
position_tmp.begin(spatial_dimension);
for (; position_it != position_end; ++position_it, ++position_tmp_it)
position_it->mul<false>(rotation, *position_tmp_it);
model.dump();
model.dump("cohesive elements");
updateDisplacement(model, elements, increment);
Real theoretical_Ed = 0;
Vector<Real> opening(spatial_dimension);
Vector<Real> traction(spatial_dimension);
Vector<Real> opening_old(spatial_dimension);
Vector<Real> traction_old(spatial_dimension);
opening.zero();
traction.zero();
opening_old.zero();
traction_old.zero();
Vector<Real> Dt(spatial_dimension);
Vector<Real> Do(spatial_dimension);
const Array<Real> & residual = model.getResidual();
/// Main loop
for (UInt s = 1; s <= max_steps; ++s) {
model.updateResidual();
opening += increment_tmp;
if (checkTractions(model, opening, traction, rotation) ||
checkEquilibrium(mesh, residual) ||
checkResidual(residual, traction, nodes_to_check, rotation)) {
finalize();
return EXIT_FAILURE;
}
/// compute energy
Do = opening;
Do -= opening_old;
Dt = traction_old;
Dt += traction;
theoretical_Ed += .5 * Do.dot(Dt);
opening_old = opening;
traction_old = traction;
updateDisplacement(model, elements, increment);
if (s % 10 == 0) {
if (prank == 0)
std::cout << "passing step " << s << "/" << max_steps << std::endl;
model.dump();
model.dump("cohesive elements");
}
}
model.dump();
model.dump("cohesive elements");
Real Ed = model.getEnergy("dissipated");
theoretical_Ed *= 4.;
if (prank == 0)
std::cout << "Dissipated energy: " << Ed
<< ", theoretical value: " << theoretical_Ed << std::endl;
if (!Math::are_float_equal(Ed, theoretical_Ed) || std::isnan(Ed)) {
if (prank == 0)
std::cout << "Error: the dissipated energy is incorrect" << std::endl;
finalize();
return EXIT_FAILURE;
}
finalize();
if (prank == 0)
std::cout << "OK: Test passed!" << std::endl;
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
void updateDisplacement(SolidMechanicsModelCohesive & model,
const ElementTypeMapArray<UInt> & elements,
Vector<Real> & increment) {
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
Mesh & mesh = model.getFEEngine().getMesh();
UInt nb_nodes = mesh.getNbNodes();
Array<Real> & displacement = model.getDisplacement();
Array<bool> update(nb_nodes);
update.zero();
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type);
for (; it != last; ++it) {
ElementType type = *it;
const Array<UInt> & elem = elements(type, ghost_type);
const Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
UInt nb_nodes_per_element = connectivity.getNbComponent();
for (UInt el = 0; el < elem.getSize(); ++el) {
for (UInt n = 0; n < nb_nodes_per_element; ++n) {
UInt node = connectivity(elem(el), n);
if (!update(node)) {
- Vector<Real> node_disp(displacement.storage() +
+ Vector<Real> node_disp(displacement.data() +
node * spatial_dimension,
spatial_dimension);
node_disp += increment;
update(node) = true;
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
bool checkTractions(SolidMechanicsModelCohesive & model, Vector<Real> & opening,
Vector<Real> & theoretical_traction,
Matrix<Real> & rotation) {
- UInt spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = model.getSpatialDimension();
const Mesh & mesh = model.getMesh();
const MaterialCohesive & mat_cohesive =
dynamic_cast<const MaterialCohesive &>(model.getMaterial(1));
Real sigma_c =
mat_cohesive.getParam<RandomInternalField<Real, FacetInternalField>>(
"sigma_c");
const Real beta = mat_cohesive.getParam<Real>("beta");
const Real G_cI = mat_cohesive.getParam<Real>("G_c");
// Real G_cII = mat_cohesive.getParam<Real>("G_cII");
const Real delta_0 = mat_cohesive.getParam<Real>("delta_0");
const Real kappa = mat_cohesive.getParam<Real>("kappa");
Real delta_c = 2 * G_cI / sigma_c;
sigma_c *= delta_c / (delta_c - delta_0);
Vector<Real> normal_opening(spatial_dimension);
normal_opening.zero();
normal_opening(0) = opening(0);
Real normal_opening_norm = normal_opening.norm();
Vector<Real> tangential_opening(spatial_dimension);
tangential_opening.zero();
- for (UInt dim = 1; dim < spatial_dimension; ++dim)
+ for (Int dim = 1; dim < spatial_dimension; ++dim)
tangential_opening(dim) = opening(dim);
Real tangential_opening_norm = tangential_opening.norm();
Real beta2_kappa2 = beta * beta / kappa / kappa;
Real beta2_kappa = beta * beta / kappa;
Real delta = std::sqrt(tangential_opening_norm * tangential_opening_norm *
beta2_kappa2 +
normal_opening_norm * normal_opening_norm);
delta = std::max(delta, delta_0);
Real theoretical_damage = std::min(delta / delta_c, 1.);
if (Math::are_float_equal(theoretical_damage, 1.))
theoretical_traction.zero();
else {
theoretical_traction = tangential_opening;
theoretical_traction *= beta2_kappa;
theoretical_traction += normal_opening;
theoretical_traction *= sigma_c / delta * (1. - theoretical_damage);
}
Vector<Real> theoretical_traction_rotated(spatial_dimension);
theoretical_traction_rotated.mul<false>(rotation, theoretical_traction);
// adjust damage
theoretical_damage = std::max((delta - delta_0) / (delta_c - delta_0), 0.);
theoretical_damage = std::min(theoretical_damage, 1.);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it =
mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive);
Mesh::type_iterator last =
mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive);
for (; it != last; ++it) {
ElementType type = *it;
const Array<Real> & traction = mat_cohesive.getTraction(type, ghost_type);
const Array<Real> & damage = mat_cohesive.getDamage(type, ghost_type);
UInt nb_quad_per_el =
model.getFEEngine("CohesiveFEEngine").getNbIntegrationPoints(type);
UInt nb_element = model.getMesh().getNbElement(type, ghost_type);
UInt tot_nb_quad = nb_element * nb_quad_per_el;
for (UInt q = 0; q < tot_nb_quad; ++q) {
- for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+ for (Int dim = 0; dim < spatial_dimension; ++dim) {
if (!Math::are_float_equal(
std::abs(theoretical_traction_rotated(dim)),
std::abs(traction(q, dim)))) {
std::cout << "Error: tractions are incorrect" << std::endl;
return 1;
}
}
if (ghost_type == _not_ghost)
if (!Math::are_float_equal(theoretical_damage, damage(q))) {
std::cout << "Error: damage is incorrect" << std::endl;
return 1;
}
}
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
void findNodesToCheck(const Mesh & mesh,
const ElementTypeMapArray<UInt> & elements,
Array<UInt> & nodes_to_check, Int psize) {
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
nodes_to_check.resize(0);
Array<UInt> global_nodes_to_check;
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
const Array<Real> & position = mesh.getNodes();
UInt nb_nodes = position.getSize();
Array<bool> checked_nodes(nb_nodes);
checked_nodes.zero();
Mesh::type_iterator it = mesh.firstType(spatial_dimension);
Mesh::type_iterator last = mesh.lastType(spatial_dimension);
for (; it != last; ++it) {
ElementType type = *it;
const Array<UInt> & elem = elements(type);
const Array<UInt> & connectivity = mesh.getConnectivity(type);
UInt nb_nodes_per_elem = connectivity.getNbComponent();
for (UInt el = 0; el < elem.getSize(); ++el) {
UInt element = elem(el);
- Vector<UInt> conn_el(connectivity.storage() + nb_nodes_per_elem * element,
+ Vector<UInt> conn_el(connectivity.data() + nb_nodes_per_elem * element,
nb_nodes_per_elem);
for (UInt n = 0; n < nb_nodes_per_elem; ++n) {
UInt node = conn_el(n);
if (std::abs(position(node, 0) - 0.) < 1.e-6 && !checked_nodes(node)) {
checked_nodes(node) = true;
nodes_to_check.push_back(node);
global_nodes_to_check.push_back(mesh.getNodeGlobalId(node));
}
}
}
}
std::vector<CommunicationRequest *> requests;
for (Int p = prank + 1; p < psize; ++p) {
- requests.push_back(comm.asyncSend(global_nodes_to_check.storage(),
+ requests.push_back(comm.asyncSend(global_nodes_to_check.data(),
global_nodes_to_check.getSize(), p,
prank));
}
Array<UInt> recv_nodes;
for (Int p = 0; p < prank; ++p) {
CommunicationStatus status;
comm.probe<UInt>(p, p, status);
UInt recv_nodes_size = recv_nodes.getSize();
recv_nodes.resize(recv_nodes_size + status.getSize());
- comm.receive(recv_nodes.storage() + recv_nodes_size, status.getSize(), p,
- p);
+ comm.receive(recv_nodes.data() + recv_nodes_size, status.getSize(), p, p);
}
comm.waitAll(requests);
comm.freeCommunicationRequest(requests);
for (UInt i = 0; i < recv_nodes.getSize(); ++i) {
Array<UInt>::iterator<UInt> node_position =
std::find(global_nodes_to_check.begin(), global_nodes_to_check.end(),
recv_nodes(i));
if (node_position != global_nodes_to_check.end()) {
UInt index = node_position - global_nodes_to_check.begin();
nodes_to_check.erase(index);
global_nodes_to_check.erase(index);
}
}
}
/* -------------------------------------------------------------------------- */
bool checkEquilibrium(const Mesh & mesh, const Array<Real> & residual) {
- UInt spatial_dimension = residual.getNbComponent();
+ Int spatial_dimension = residual.getNbComponent();
Vector<Real> residual_sum(spatial_dimension);
residual_sum.zero();
Array<Real>::const_iterator<Vector<Real>> res_it =
residual.begin(spatial_dimension);
for (UInt n = 0; n < residual.getSize(); ++n, ++res_it) {
if (mesh.isLocalOrMasterNode(n))
residual_sum += *res_it;
}
const auto & comm = Communicator::getStaticCommunicator();
- comm.allReduce(residual_sum.storage(), spatial_dimension, _so_sum);
+ comm.allReduce(residual_sum.data(), spatial_dimension, _so_sum);
for (UInt s = 0; s < spatial_dimension; ++s) {
if (!Math::are_float_equal(residual_sum(s), 0.)) {
if (comm.whoAmI() == 0)
std::cout << "Error: system is not in equilibrium!" << std::endl;
return 1;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
bool checkResidual(const Array<Real> & residual, const Vector<Real> & traction,
const Array<UInt> & nodes_to_check,
const Matrix<Real> & rotation) {
- UInt spatial_dimension = residual.getNbComponent();
+ Int spatial_dimension = residual.getNbComponent();
Vector<Real> total_force(spatial_dimension);
total_force.zero();
for (UInt n = 0; n < nodes_to_check.getSize(); ++n) {
UInt node = nodes_to_check(n);
- Vector<Real> res(residual.storage() + node * spatial_dimension,
+ Vector<Real> res(residual.data() + node * spatial_dimension,
spatial_dimension);
total_force += res;
}
const auto & comm = Communicator::getStaticCommunicator();
- comm.allReduce(total_force.storage(), spatial_dimension, _so_sum);
+ comm.allReduce(total_force.data(), spatial_dimension, _so_sum);
Vector<Real> theoretical_total_force(spatial_dimension);
theoretical_total_force.mul<false>(rotation, traction);
theoretical_total_force *= -1 * 2 * 2;
for (UInt s = 0; s < spatial_dimension; ++s) {
if (!Math::are_float_equal(total_force(s), theoretical_total_force(s))) {
if (comm.whoAmI() == 0)
std::cout << "Error: total force isn't correct!" << std::endl;
return 1;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
void findElementsToDisplace(const Mesh & mesh,
ElementTypeMapArray<UInt> & elements) {
- UInt spatial_dimension = mesh.getSpatialDimension();
+ Int spatial_dimension = mesh.getSpatialDimension();
mesh.initElementTypeMapArray(elements, 1, spatial_dimension);
Vector<Real> bary(spatial_dimension);
for (ghost_type_t::iterator gt = ghost_type_t::begin();
gt != ghost_type_t::end(); ++gt) {
GhostType ghost_type = *gt;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type);
for (; it != last; ++it) {
ElementType type = *it;
Array<UInt> & elem = elements(type, ghost_type);
UInt nb_element = mesh.getNbElement(type, ghost_type);
- for (UInt el = 0; el < nb_element; ++el) {
- mesh.getBarycenter(el, type, bary.storage(), ghost_type);
+ for (Int el = 0; el < nb_element; ++el) {
+ mesh.getBarycenter(el, type, bary.data(), ghost_type);
if (bary(0) > 0.0001)
elem.push_back(el);
}
}
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_element_matrix.cc b/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_element_matrix.cc
index 5d8ea800d..017fbbb44 100644
--- a/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_element_matrix.cc
+++ b/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_element_matrix.cc
@@ -1,100 +1,100 @@
/**
* @file test_embedded_element_matrix.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Wed Mar 25 2015
* @date last modification: Wed Sep 12 2018
*
* @brief test of the class EmbeddedInterfaceModel
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "embedded_interface_model.hh"
#include "sparse_matrix_aij.hh"
#include "sparse_solver.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
debug::setDebugLevel(dblWarning);
initialize("embedded_element.dat", argc, argv);
- constexpr UInt dim = 2;
+ constexpr Int dim = 2;
constexpr ElementType type = _segment_2;
const Real height = 0.4;
Mesh mesh(dim);
mesh.read("triangle.msh");
Mesh reinforcement_mesh(dim, "reinforcement_mesh");
auto & nodes = reinforcement_mesh.getNodes();
nodes.push_back(Vector<Real>({0, height}));
nodes.push_back(Vector<Real>({1, height}));
reinforcement_mesh.addConnectivityType(type);
auto & connectivity = reinforcement_mesh.getConnectivity(type);
- connectivity.push_back(Vector<UInt>({0, 1}));
+ connectivity.push_back(Vector<Idx>({0, 1}));
Array<std::string> names_vec(1, 1, "reinforcement", "reinforcement_names");
reinforcement_mesh.getElementalData<std::string>("physical_names")
.alloc(1, 1, type);
reinforcement_mesh.getData<std::string>("physical_names")(type).copy(
names_vec);
EmbeddedInterfaceModel model(mesh, reinforcement_mesh, dim);
model.initFull(_analysis_method = _static);
if (model.getInterfaceMesh().getNbElement(type) != 1)
return EXIT_FAILURE;
if (model.getInterfaceMesh().getSpatialDimension() != 2)
return EXIT_FAILURE;
try { // matrix should be singular
model.solveStep();
} catch (debug::SingularMatrixException & e) {
std::cerr << "Matrix is singular, relax, everything is fine :)"
<< std::endl;
} catch (debug::Exception & e) {
std::cerr << "Unexpceted error: " << e.what() << std::endl;
throw e;
}
SparseMatrixAIJ & K =
dynamic_cast<SparseMatrixAIJ &>(model.getDOFManager().getMatrix("K"));
K.saveMatrix("stiffness.mtx");
Math::setTolerance(1e-8);
// Testing the assembled stiffness matrix
if (!Math::are_float_equal(K(0, 0), 1. - height) ||
!Math::are_float_equal(K(0, 2), height - 1.) ||
!Math::are_float_equal(K(2, 0), height - 1.) ||
!Math::are_float_equal(K(2, 2), 1. - height))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model.cc b/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model.cc
index f70af8382..b60f198ca 100644
--- a/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model.cc
+++ b/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model.cc
@@ -1,109 +1,109 @@
/**
* @file test_embedded_interface_model.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Wed Mar 25 2015
* @date last modification: Wed Feb 06 2019
*
* @brief Embedded model test based on potential energy
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <iostream>
#include "aka_common.hh"
#include "embedded_interface_model.hh"
#include "sparse_matrix.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
debug::setDebugLevel(dblWarning);
initialize("material.dat", argc, argv);
- UInt dim = 2;
+ Int dim = 2;
Math::setTolerance(1e-7);
// Mesh here is a 1x1 patch
Mesh mesh(dim);
mesh.read("embedded_mesh.msh");
Array<Real> nodes_vec(2, dim, "reinforcement_nodes");
- nodes_vec.storage()[0] = 0;
- nodes_vec.storage()[1] = 0.5;
- nodes_vec.storage()[2] = 1;
- nodes_vec.storage()[3] = 0.5;
+ nodes_vec.data()[0] = 0;
+ nodes_vec.data()[1] = 0.5;
+ nodes_vec.data()[2] = 1;
+ nodes_vec.data()[3] = 0.5;
- Array<UInt> conn_vec(1, 2, "reinforcement_connectivity");
- conn_vec.storage()[0] = 0;
- conn_vec.storage()[1] = 1;
+ Array<Idx> conn_vec(1, 2, "reinforcement_connectivity");
+ conn_vec.data()[0] = 0;
+ conn_vec.data()[1] = 1;
Array<std::string> names_vec(1, 1, "reinforcement", "reinforcement_names");
Mesh reinforcement_mesh(dim, "reinforcement_mesh");
reinforcement_mesh.getNodes().copy(nodes_vec);
reinforcement_mesh.addConnectivityType(_segment_2);
reinforcement_mesh.getConnectivity(_segment_2).copy(conn_vec);
reinforcement_mesh.getElementalData<std::string>("physical_names")
.alloc(1, 1, _segment_2);
reinforcement_mesh.getData<std::string>("physical_names")(_segment_2)
.copy(names_vec);
EmbeddedInterfaceModel model(mesh, reinforcement_mesh, dim);
model.initFull(_analysis_method = _static);
Array<Real> & nodes = mesh.getNodes();
Array<Real> & forces = model.getExternalForce();
Array<bool> & bound = model.getBlockedDOFs();
forces(2, 0) = -250;
forces(5, 0) = -500;
forces(8, 0) = -250;
- for (UInt i = 0; i < mesh.getNbNodes(); i++) {
+ for (Int i = 0; i < mesh.getNbNodes(); i++) {
if (Math::are_float_equal(nodes(i, 0), 0.))
bound(i, 0) = true;
if (Math::are_float_equal(nodes(i, 1), 0.))
bound(i, 1) = true;
}
model.addDumpFieldVector("displacement");
model.addDumpFieldTensor("stress");
model.setBaseNameToDumper("reinforcement", "reinforcement");
model.addDumpFieldTensorToDumper("reinforcement", "stress_embedded");
model.solveStep();
model.getDOFManager().getMatrix("K").saveMatrix("matrix_test");
model.dump();
Real pot_energy = model.getEnergy("potential");
if (std::abs(pot_energy - 7.37343e-06) > 1e-5)
return EXIT_FAILURE;
finalize();
return 0;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model_prestress.cc b/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model_prestress.cc
index 448d2160e..12cd7f587 100644
--- a/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model_prestress.cc
+++ b/test/test_model/test_solid_mechanics_model/test_embedded_interface/test_embedded_interface_model_prestress.cc
@@ -1,236 +1,231 @@
/**
* @file test_embedded_interface_model_prestress.cc
*
* @author Zineb Fouad <zineb.fouad@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Tue Apr 28 2015
* @date last modification: Fri Jun 14 2019
*
* @brief Embedded model test for prestressing (bases on stress norm)
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "aka_common.hh"
#include "embedded_interface_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
#define YG 0.483644859
#define I_eq 0.012488874
#define A_eq (1e-2 + 1. / 7. * 1.)
/* -------------------------------------------------------------------------- */
struct StressSolution : public BC::Neumann::FromHigherDim {
Real M;
Real I;
Real yg;
Real pre_stress;
- StressSolution(UInt dim, Real M, Real I, Real yg = 0, Real pre_stress = 0)
+ StressSolution(Int dim, Real M, Real I, Real yg = 0, Real pre_stress = 0)
: BC::Neumann::FromHigherDim(Matrix<Real>(dim, dim)), M(M), I(I), yg(yg),
pre_stress(pre_stress) {}
- virtual ~StressSolution() {}
+ virtual ~StressSolution() = default;
void operator()(const IntegrationPoint & /*quad_point*/, Vector<Real> & dual,
const Vector<Real> & coord,
const Vector<Real> & normals) const {
- UInt dim = coord.size();
+ Int dim = coord.size();
- if (dim < 2)
+ if (dim < 2) {
AKANTU_ERROR("Solution not valid for 1D");
+ }
Matrix<Real> stress(dim, dim);
stress.zero();
stress(0, 0) = this->stress(coord(1));
- dual.mul<false>(stress, normals);
+ dual = stress * normals;
}
inline Real stress(Real height) const {
return -M / I * (height - yg) + pre_stress;
}
inline Real neutral_axis() const { return -I * pre_stress / M + yg; }
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("prestress.dat", argc, argv);
debug::setDebugLevel(dblError);
Math::setTolerance(1e-6);
- const UInt dim = 2;
+ const Int dim = 2;
/* --------------------------------------------------------------------------
*/
Mesh mesh(dim);
mesh.read("embedded_mesh_prestress.msh");
// mesh.createGroupsFromMeshData<std::string>("physical_names");
Mesh reinforcement_mesh(dim, "reinforcement_mesh");
try {
reinforcement_mesh.read("embedded_mesh_prestress_reinforcement.msh");
} catch (debug::Exception & e) {
}
// reinforcement_mesh.createGroupsFromMeshData<std::string>("physical_names");
EmbeddedInterfaceModel model(mesh, reinforcement_mesh, dim);
model.initFull(EmbeddedInterfaceModelOptions(_static));
/* --------------------------------------------------------------------------
*/
/* Computation of analytical residual */
/* --------------------------------------------------------------------------
*/
/*
* q = 1000 N/m
* L = 20 m
* a = 1 m
*/
Real steel_area = model.getMaterial("reinforcement").get("area");
Real pre_stress = model.getMaterial("reinforcement").get("pre_stress");
Real stress_norm = 0.;
- StressSolution *concrete_stress = nullptr, *steel_stress = nullptr;
+ std::unique_ptr<StressSolution> concrete_stress;
+ std::unique_ptr<StressSolution> steel_stress;
Real pre_force = pre_stress * steel_area;
Real pre_moment = -pre_force * (YG - 0.25);
Real neutral_axis = YG - I_eq / A_eq * pre_force / pre_moment;
- concrete_stress = new StressSolution(dim, pre_moment, 7. * I_eq, YG,
- -pre_force / (7. * A_eq));
- steel_stress = new StressSolution(dim, pre_moment, I_eq, YG,
- pre_stress - pre_force / A_eq);
+ concrete_stress = std::make_unique<StressSolution>(
+ dim, pre_moment, 7. * I_eq, YG, -pre_force / (7. * A_eq));
+ steel_stress = std::make_unique<StressSolution>(
+ dim, pre_moment, I_eq, YG, pre_stress - pre_force / A_eq);
stress_norm =
std::abs(concrete_stress->stress(1)) * (1 - neutral_axis) * 0.5 +
std::abs(concrete_stress->stress(0)) * neutral_axis * 0.5 +
std::abs(steel_stress->stress(0.25)) * steel_area;
model.applyBC(*concrete_stress, "XBlocked");
auto end_node = *mesh.getElementGroup("EndNode").getNodeGroup().begin();
Vector<Real> end_node_force = model.getExternalForce().begin(dim)[end_node];
end_node_force(0) += steel_stress->stress(0.25) * steel_area;
Array<Real> analytical_residual(mesh.getNbNodes(), dim,
"analytical_residual");
analytical_residual.copy(model.getExternalForce());
model.getExternalForce().zero();
- delete concrete_stress;
- delete steel_stress;
-
- /* --------------------------------------------------------------------------
- */
-
+ /* ------------------------------------------------------------------------ */
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "XBlocked");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "YBlocked");
try {
model.solveStep();
} catch (debug::Exception & e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
/* --------------------------------------------------------------------------
*/
/* Computation of FEM residual norm */
/* --------------------------------------------------------------------------
*/
ElementGroup & xblocked = mesh.getElementGroup("XBlocked");
NodeGroup & boundary_nodes = xblocked.getNodeGroup();
- NodeGroup::const_node_iterator nodes_it = boundary_nodes.begin(),
- nodes_end = boundary_nodes.end();
+
model.assembleInternalForces();
Array<Real> residual(mesh.getNbNodes(), dim, "my_residual");
residual.copy(model.getInternalForce());
residual -= model.getExternalForce();
auto com_res = residual.begin(dim);
auto position = mesh.getNodes().begin(dim);
Real res_sum = 0.;
- UInt lower_node = -1;
- UInt upper_node = -1;
+ Idx lower_node = -1;
+ Idx upper_node = -1;
Real lower_dist = 1;
Real upper_dist = 1;
- for (; nodes_it != nodes_end; ++nodes_it) {
- UInt node_number = *nodes_it;
- const Vector<Real> res = com_res[node_number];
- const Vector<Real> pos = position[node_number];
+ for (auto && node : boundary_nodes) {
+ const auto & res = com_res[node];
+ const auto & pos = position[node];
if (!Math::are_float_equal(pos(1), 0.25)) {
if ((std::abs(pos(1) - 0.25) < lower_dist) && (pos(1) < 0.25)) {
lower_dist = std::abs(pos(1) - 0.25);
- lower_node = node_number;
+ lower_node = node;
}
if ((std::abs(pos(1) - 0.25) < upper_dist) && (pos(1) > 0.25)) {
upper_dist = std::abs(pos(1) - 0.25);
- upper_node = node_number;
+ upper_node = node;
}
}
- for (UInt i = 0; i < dim; i++) {
+ for (Int i = 0; i < dim; i++) {
if (!Math::are_float_equal(pos(1), 0.25)) {
res_sum += std::abs(res(i));
}
}
}
const Vector<Real> upper_res = com_res[upper_node],
lower_res = com_res[lower_node];
const Vector<Real> end_node_res = com_res[end_node];
Vector<Real> delta = upper_res - lower_res;
delta *= lower_dist / (upper_dist + lower_dist);
Vector<Real> concrete_residual = lower_res + delta;
Vector<Real> steel_residual = end_node_res - concrete_residual;
- for (UInt i = 0; i < dim; i++) {
+ for (Int i = 0; i < dim; i++) {
res_sum += std::abs(concrete_residual(i));
res_sum += std::abs(steel_residual(i));
}
Real relative_error = std::abs(res_sum - stress_norm) / stress_norm;
if (relative_error > 1e-3) {
std::cerr << "Relative error = " << relative_error << std::endl;
return EXIT_FAILURE;
}
finalize();
return 0;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc b/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc
index 8af11bee3..36fc59582 100644
--- a/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc
+++ b/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc
@@ -1,159 +1,163 @@
/**
* @file test_solid_mechanics_model_work_dynamics.cc
*
* @author Tobias Brink <tobias.brink@epfl.ch>
*
* @date creation: Fri Dec 15 2017
* @date last modification: Wed Nov 18 2020
*
* @brief test work in dynamic simulations
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
* @section description
*
* Assuming that the kinetic energy and the potential energy of the
* linear elastic material are bug free, the work in a dynamic
* simulation must equal the change in internal energy (first law of
* thermodynamics). Work in dynamics is an infinitesimal work Fds,
* thus we need to integrate it and compare at the end. In this test,
* we use one Dirichlet boundary condition (with u = 0.0, 0.01, and
* -0.01) and one Neumann boundary condition for F on the opposite
* side. Then we do a few steps to get reference energies for work and
* internal energy. After more steps, the change in both work and
* internal energy must be equal.
*
*/
/* -------------------------------------------------------------------------- */
#include "../test_solid_mechanics_model_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace {
template <typename type_>
class TestSMMFixtureWorkDynamic : public TestSMMFixture<type_> {
public:
void SetUp() override {
this->mesh_file =
"../../patch_tests/data/bar" + std::to_string(this->type) + ".msh";
TestSMMFixture<type_>::SetUp();
getStaticParser().parse("test_solid_mechanics_model_"
"work_material.dat");
/// model initialization
this->model->initFull();
/// Create a node group for Neumann BCs.
auto & apply_force_grp = this->mesh->createNodeGroup("apply_force");
auto & fixed_grp = this->mesh->createNodeGroup("fixed");
const auto & pos = this->mesh->getNodes();
const auto & lower = this->mesh->getLowerBounds();
const auto & upper = this->mesh->getUpperBounds();
UInt i = 0;
for (auto && posv : make_view(pos, this->spatial_dimension)) {
if (posv(_x) > upper(_x) - 1e-6) {
apply_force_grp.add(i);
} else if (posv(_x) < lower(_x) + 1e-6) {
fixed_grp.add(i);
}
++i;
}
this->mesh->createElementGroupFromNodeGroup("el_apply_force", "apply_force",
this->spatial_dimension - 1);
this->mesh->createElementGroupFromNodeGroup("el_fixed", "fixed",
this->spatial_dimension - 1);
Vector<Real> surface_traction(this->spatial_dimension);
+ surface_traction.zero();
surface_traction(_x) = 0.5;
if (this->spatial_dimension == 1) {
// TODO: this is a hack to work
// around non-implemented
// BC::Neumann::FromTraction for 1D
auto & force = this->model->getExternalForce();
for (auto && pair : zip(make_view(pos, this->spatial_dimension),
make_view(force, this->spatial_dimension))) {
auto & posv = std::get<0>(pair);
auto & forcev = std::get<1>(pair);
if (posv(_x) > upper(_x) - 1e-6) {
forcev(_x) = surface_traction(_x);
}
}
} else {
this->model->applyBC(BC::Neumann::FromTraction(surface_traction),
"el_apply_force");
}
/// set up timestep
auto time_step = this->model->getStableTimeStep() * 0.1;
this->model->setTimeStep(time_step);
}
};
TYPED_TEST_SUITE(TestSMMFixtureWorkDynamic, gtest_element_types, );
/* TODO: this is currently disabled for terrible results and performance
TYPED_TEST(TestSMMFixtureBar, WorkImplicit) {
test_body(*(this->model), *(this->mesh), _implicit_dynamic, 500);
}
*/
// model.assembleMassLumped();
TYPED_TEST(TestSMMFixtureWorkDynamic, WorkExplicit) {
/// Do the sim
std::vector<Real> displacements{0.00, 0.01, -0.01};
for (auto && u : displacements) {
this->model->applyBC(BC::Dirichlet::FixedValue(u, _x), "el_fixed");
// First, "equilibrate" a bit to get a reference state of total
// energy and work. This is needed when we have a Dirichlet with
// finite displacement on one side.
- for (UInt i = 0; i < 25; ++i) {
+ for (Int i = 0; i < 25; ++i) {
this->model->solveStep();
}
+
// Again, work reported by Akantu is infinitesimal (dW) and we
// need to integrate a while to get a decent value.
- double Etot0 =
- this->model->getEnergy("potential") + this->model->getEnergy("kinetic");
+ auto Epot = this->model->getEnergy("potential");
+ auto Ekin = this->model->getEnergy("kinetic");
+
+ auto Etot0 = Epot + Ekin;
double W = 0.0;
- for (UInt i = 0; i < 200; ++i) {
+ for (Int i = 0; i < 200; ++i) {
/// Solve.
this->model->solveStep();
const auto dW = this->model->getEnergy("external work");
W += dW;
}
// Finally check.
- const auto Epot = this->model->getEnergy("potential");
- const auto Ekin = this->model->getEnergy("kinetic");
+ Epot = this->model->getEnergy("potential");
+ Ekin = this->model->getEnergy("kinetic");
EXPECT_NEAR(W, Ekin + Epot - Etot0, 5e-2);
// Sadly not very exact for such a coarse mesh.
}
}
} // namespace
diff --git a/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_quasistatic.cc b/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_quasistatic.cc
index 77bfe11b8..b7524b2e3 100644
--- a/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_quasistatic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_quasistatic.cc
@@ -1,147 +1,148 @@
/**
* @file test_solid_mechanics_model_work_quasistatic.cc
*
* @author Tobias Brink <tobias.brink@epfl.ch>
*
* @date creation: Wed Nov 29 2017
* @date last modification: Wed Dec 04 2019
*
* @brief test work in quasistatic
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
* @section description
*
* Assuming that the potential energy of a linear elastic material
* works correctly, the work in a static simulation must equal the
* potential energy of the material. Since the work in static is an
* infinitesimal work Fds, we need to integrate by increasing F from 0
* to F_final in steps. This test uses one Dirichlet boundary
* condition (with u = 0.0, 0.1, and -0.1) and one Neumann boundary
* condition for F on the opposite side. The final work must be the
* same for all u.
*
*/
/* -------------------------------------------------------------------------- */
#include "../test_solid_mechanics_model_fixture.hh"
#include "mesh_utils.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace {
TYPED_TEST(TestSMMFixture, WorkQuasistatic) {
const auto spatial_dimension = this->spatial_dimension;
getStaticParser().parse("test_solid_mechanics_model_"
"work_material.dat");
/// model initialization
this->model->initFull(_analysis_method = _static);
/// Create a node group for Neumann BCs.
auto & apply_force_grp = this->mesh->createNodeGroup("apply_force");
auto & fixed_grp = this->mesh->createNodeGroup("fixed");
const auto & pos = this->mesh->getNodes();
auto & flags = this->model->getBlockedDOFs();
auto & lower = this->mesh->getLowerBounds();
auto & upper = this->mesh->getUpperBounds();
- UInt i = 0;
+ Int i = 0;
for (auto && data : zip(make_view(pos, spatial_dimension),
make_view(flags, spatial_dimension))) {
const auto & posv = std::get<0>(data);
auto & flag = std::get<1>(data);
if (posv(_x) > upper(_x) - 1e-6) {
apply_force_grp.add(i);
} else if (posv(_x) < lower(_x) + 1e-6) {
fixed_grp.add(i);
if ((spatial_dimension > 1) and (posv(_y) < lower(_y) + 1e-6)) {
flag(_y) = true;
if ((spatial_dimension > 2) and (posv(_z) < lower(_z) + 1e-6)) {
flag(_z) = true;
}
}
}
++i;
}
this->mesh->createElementGroupFromNodeGroup("el_apply_force", "apply_force",
spatial_dimension - 1);
this->mesh->createElementGroupFromNodeGroup("el_fixed", "fixed",
spatial_dimension - 1);
std::vector<Real> displacements{0.0, 0.1, -0.1};
for (auto && u : displacements) {
this->model->applyBC(BC::Dirichlet::FixedValue(u, _x), "el_fixed");
Vector<Real> surface_traction(spatial_dimension);
+ surface_traction.zero();
Real work = 0.0;
Real Epot;
- static const UInt N = 100;
- for (UInt i = 0; i <= N; ++i) {
+ static const Int N = 100;
+ for (Int i = 0; i <= N; ++i) {
this->model->getExternalForce().zero(); // reset external forces to zero
surface_traction(_x) = (1.0 * i) / N;
if (spatial_dimension == 1) {
// \TODO: this is a hack to work
// around non-implemented
// BC::Neumann::FromTraction for 1D
auto & force = this->model->getExternalForce();
for (auto && pair : zip(make_view(pos, spatial_dimension),
make_view(force, spatial_dimension))) {
auto & posv = std::get<0>(pair);
auto & forcev = std::get<1>(pair);
if (posv(_x) > upper(_x) - 1e-6) {
forcev(_x) = surface_traction(_x);
}
}
} else {
this->model->applyBC(BC::Neumann::FromTraction(surface_traction),
"el_apply_force");
}
/// Solve.
this->model->solveStep();
Epot = this->model->getEnergy("potential");
// In static, this is infinitesimal work!
auto Fds = this->model->getEnergy("external work");
work += Fds; // integrate
/// Check that no work was done for zero force.
if (i == 0) {
EXPECT_NEAR(work, 0.0, 1e-12);
}
}
// Due to the finite integration steps, we make a rather large error
// in our work integration, thus the allowed delta is 1e-2.
EXPECT_NEAR(work, Epot, 1e-2);
}
}
} // namespace
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc
index 67cf644b9..5abf0d7c6 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc
@@ -1,107 +1,112 @@
/**
* @file local_material_damage.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri May 03 2019
*
* @brief Specialization of the material class for the damage material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "local_material_damage.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
LocalMaterialDamage::LocalMaterialDamage(SolidMechanicsModel & model,
const ID & id)
: Material(model, id), damage("damage", *this) {
AKANTU_DEBUG_IN();
this->registerParam("E", E, 0., _pat_parsable, "Young's modulus");
this->registerParam("nu", nu, 0.5, _pat_parsable, "Poisson's ratio");
this->registerParam("lambda", lambda, _pat_readable,
"First Lamé coefficient");
this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
this->registerParam("Yd", Yd, 50., _pat_parsmod);
this->registerParam("Sd", Sd, 5000., _pat_parsmod);
damage.initialize(1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void LocalMaterialDamage::initMaterial() {
AKANTU_DEBUG_IN();
Material::initMaterial();
lambda = nu * E / ((1 + nu) * (1 - 2 * nu));
mu = E / (2 * (1 + nu));
kpa = lambda + 2. / 3. * mu;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void LocalMaterialDamage::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
+ auto dim = this->spatial_dimension;
- auto dam = damage(el_type, ghost_type).begin();
+ for (auto && data :
+ zip(make_view(this->gradu(el_type, ghost_type), dim, dim),
+ make_view(this->stress(el_type, ghost_type), dim, dim),
+ damage(el_type, ghost_type))) {
+ auto && grad_u = std::get<0>(data);
+ auto && sigma = std::get<1>(data);
+ auto && dam = std::get<2>(data);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
-
- computeStressOnQuad(grad_u, sigma, *dam);
- ++dam;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ computeStressOnQuad(grad_u, sigma, dam);
+ ++dam;
+ }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void LocalMaterialDamage::computePotentialEnergy(ElementType el_type) {
AKANTU_DEBUG_IN();
-
+ auto dim = this->spatial_dimension;
Material::computePotentialEnergy(el_type);
- Real * epot = potential_energy(el_type).storage();
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
- computePotentialEnergyOnQuad(grad_u, sigma, *epot);
- epot++;
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
+ for (auto && data : zip(make_view(this->gradu(el_type), dim, dim),
+ make_view(this->stress(el_type), dim, dim),
+ potential_energy(el_type))) {
+ auto && grad_u = std::get<0>(data);
+ auto && sigma = std::get<1>(data);
+ auto && epot = std::get<2>(data);
+ computePotentialEnergyOnQuad(grad_u, sigma, epot);
+ }
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh
index 685a724a0..656490102 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh
+++ b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh
@@ -1,127 +1,121 @@
/**
* @file local_material_damage.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri May 03 2019
*
* @brief Material isotropic elastic
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "material.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_LOCAL_MATERIAL_DAMAGE_HH_
#define AKANTU_LOCAL_MATERIAL_DAMAGE_HH_
namespace akantu {
class LocalMaterialDamage : public Material {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
LocalMaterialDamage(SolidMechanicsModel & model, const ID & id = "");
- virtual ~LocalMaterialDamage(){};
+ ~LocalMaterialDamage() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- void initMaterial();
+ void initMaterial() override;
/// constitutive law for all element of a type
- void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
+ void computeStress(ElementType el_type,
+ GhostType ghost_type = _not_ghost) override;
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(Matrix<Real> & grad_u, Matrix<Real> & sigma,
- Real & damage);
-
- /// compute tangent stiffness
- virtual void computeTangentStiffness(__attribute__((unused))
- ElementType el_type,
- __attribute__((unused))
- Array<Real> & tangent_matrix,
- __attribute__((unused))
- GhostType ghost_type = _not_ghost){};
+ inline void computeStressOnQuad(MatrixProxy<Real> & grad_u,
+ MatrixProxy<Real> & sigma, Real & damage);
/// compute the potential energy for all elements
- void computePotentialEnergy(ElementType el_type);
+ void computePotentialEnergy(ElementType el_type) override;
/// compute the potential energy for on element
- inline void computePotentialEnergyOnQuad(Matrix<Real> & grad_u,
- Matrix<Real> & sigma, Real & epot);
+ inline void computePotentialEnergyOnQuad(MatrixProxy<Real> & grad_u,
+ MatrixProxy<Real> & sigma,
+ Real & epot);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// compute the celerity of wave in the material
- inline Real getCelerity(const Element & element) const;
+ inline Real getCelerity(const Element & element) const override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real);
private:
/// the young modulus
Real E;
/// Poisson coefficient
Real nu;
/// First Lamé coefficient
Real lambda;
/// Second Lamé coefficient (shear modulus)
Real mu;
/// resistance to damage
Real Yd;
/// damage threshold
Real Sd;
/// Bulk modulus
Real kpa;
/// damage internal variable
InternalField<Real> damage;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "local_material_damage_inline_impl.hh"
} // namespace akantu
#endif /* AKANTU_LOCAL_MATERIAL_DAMAGE_HH_ */
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage_inline_impl.hh b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage_inline_impl.hh
index 53cf33433..cc7cace42 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage_inline_impl.hh
+++ b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage_inline_impl.hh
@@ -1,80 +1,72 @@
/**
* @file local_material_damage_inline_impl.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Sep 11 2017
*
* @brief Implementation of the inline functions of the material damage
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-inline void LocalMaterialDamage::computeStressOnQuad(Matrix<Real> & grad_u,
- Matrix<Real> & sigma,
+inline void LocalMaterialDamage::computeStressOnQuad(MatrixProxy<Real> & grad_u,
+ MatrixProxy<Real> & sigma,
Real & dam) {
Real trace = grad_u.trace();
/// \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla
/// u_{ij} + \nabla u_{ji})
auto && epsilon = (grad_u + grad_u.transpose()) / 2.;
- sigma = Matrix<Real>::eye(spatial_dimension) * trace * lambda + mu * epsilon;
-
- Real Y = 0;
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- Y += sigma(i, j) * epsilon(i, j);
- }
- }
- Y *= 0.5;
+ sigma = Matrix<Real>::Identity(spatial_dimension, spatial_dimension) * trace *
+ lambda +
+ mu * epsilon;
+ Real Y = sigma.doubleDot(epsilon) / 2.;
Real Fd = Y - Yd - Sd * dam;
- if (Fd > 0)
+ if (Fd > 0) {
dam = (Y - Yd) / Sd;
+ }
dam = std::min(dam, 1.);
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
inline void LocalMaterialDamage::computePotentialEnergyOnQuad(
- Matrix<Real> & grad_u, Matrix<Real> & sigma, Real & epot) {
- epot = 0.;
- for (UInt i = 0, t = 0; i < spatial_dimension; ++i)
- for (UInt j = 0; j < spatial_dimension; ++j, ++t)
- epot += sigma(i, j) * (grad_u(i, j) - (i == j));
- epot *= .5;
+ MatrixProxy<Real> & grad_u, MatrixProxy<Real> & sigma, Real & epot) {
+ epot = sigma.doubleDot(grad_u) / 2.;
}
/* -------------------------------------------------------------------------- */
-inline Real LocalMaterialDamage::getCelerity(__attribute__((unused))
- const Element & element) const {
+inline Real
+LocalMaterialDamage::getCelerity(const Element & /*element*/) const {
return (std::sqrt(E / rho));
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc
index 1a5608d09..c4e5e4aae 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc
@@ -1,246 +1,256 @@
/**
* @file test_damage_materials.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Nov 17 2017
* @date last modification: Wed Nov 18 2020
*
* @brief Tests for damage materials
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_material_fixtures.hh"
/* -------------------------------------------------------------------------- */
#include <material_marigo.hh>
#include <material_mazars.hh>
#include <py_aka_array.hh>
#include <solid_mechanics_model.hh>
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <gtest/gtest.h>
#include <pybind11/embed.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <type_traits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace py = pybind11;
using namespace py::literals;
+template <Int dim> using MaterialMazars_ = MaterialMazars<dim, MaterialElastic>;
+
using mat_types = ::testing::Types<
// Traits<MaterialMarigo, 1>, Traits<MaterialMarigo, 2>,
// Traits<MaterialMarigo, 3>,
- Traits<MaterialMazars, 1>, Traits<MaterialMazars, 2>,
- Traits<MaterialMazars, 3>>;
+ Traits<MaterialMazars_, 1>, Traits<MaterialMazars_, 2>,
+ Traits<MaterialMazars_, 3>>;
/*****************************************************************/
template <> void FriendMaterial<MaterialMazars<1>>::setParams() {
K0.setDefaultValue(1e-4);
At = 1.0;
Bt = 5e3;
Ac = 0.8;
Bc = 1391.3;
beta = 1.;
E = 25e9;
nu = 0.2;
updateInternalParameters();
}
template <> void FriendMaterial<MaterialMazars<2>>::setParams() {
K0.setDefaultValue(1e-4);
At = 1.0;
Bt = 5e3;
Ac = 0.8;
Bc = 1391.3;
beta = 1.;
E = 25e9;
nu = 0.2;
plane_stress = true;
updateInternalParameters();
}
template <> void FriendMaterial<MaterialMazars<3>>::setParams() {
K0.setDefaultValue(1e-4);
At = 1.0;
Bt = 5e3;
Ac = 0.8;
Bc = 1391.3;
beta = 1.;
E = 25e9;
nu = 0.2;
updateInternalParameters();
}
template <> void FriendMaterial<MaterialMazars<1>>::testComputeStress() {
Array<Real> epsilons(1001, 1);
Array<Real> sigmas(1001, 1);
Array<Real> damages(1001, 1);
for (auto && data : enumerate(epsilons)) {
std::get<1>(data) = 2e-6 * std::get<0>(data);
}
Real _K0 = K0;
py::module py_engine = py::module::import("py_mazars");
auto kwargs_mat_params =
py::dict("K0"_a = _K0, "At"_a = At, "Bt"_a = Bt, "Ac"_a = Ac, "Bc"_a = Bc,
"E"_a = E, "nu"_a = nu);
auto kwargs = py::dict("epsilons"_a = epsilons, "sigmas"_a = sigmas,
"damages"_a = damages);
auto py_mazars = py_engine.attr("Mazars")(**kwargs_mat_params);
// auto Gf_py = py_mazars.attr("compute")(**kwargs);
Real dam = 0.;
Real dam_ref = 0.;
Real ehat = 0.;
+ Matrix<Real> strain(this->spatial_dimension, this->spatial_dimension);
+ Matrix<Real> sigma(this->spatial_dimension, this->spatial_dimension);
for (auto && epsilon : epsilons) {
- Matrix<Real> strain(this->spatial_dimension, this->spatial_dimension, 0.);
- Matrix<Real> sigma(this->spatial_dimension, this->spatial_dimension, 0.);
+ strain.zero();
strain(0, 0) = epsilon;
- computeStressOnQuad(strain, sigma, dam, ehat);
+ computeStressOnQuad(make_named_tuple("grad_u"_n = strain, "sigma"_n = sigma,
+ "damage"_n = dam, "Ehat"_n = ehat));
Real sigma_ref;
auto py_data =
py_mazars.attr("compute_step")(epsilon, sigma_ref, dam_ref, false);
std::tie(sigma_ref, dam_ref) = py::cast<std::pair<double, double>>(py_data);
EXPECT_NEAR(sigma(0, 0), sigma_ref, 1e-5);
EXPECT_NEAR(dam, dam_ref, 1e-10);
}
}
template <> void FriendMaterial<MaterialMazars<2>>::testComputeStress() {
Array<Real> epsilons(1001, 1);
Array<Real> sigmas(1001, 1);
Array<Real> damages(1001, 1);
for (auto && data : enumerate(epsilons)) {
std::get<1>(data) = 2e-6 * std::get<0>(data);
}
Real _K0 = K0;
py::module py_engine = py::module::import("py_mazars");
auto kwargs_mat_params =
py::dict("K0"_a = _K0, "At"_a = At, "Bt"_a = Bt, "Ac"_a = Ac, "Bc"_a = Bc,
"E"_a = E, "nu"_a = nu);
auto kwargs = py::dict("epsilons"_a = epsilons, "sigmas"_a = sigmas,
"damages"_a = damages);
auto py_mazars = py_engine.attr("Mazars")(**kwargs_mat_params);
// auto Gf_py = py_mazars.attr("compute")(**kwargs);
Real dam = 0.;
Real dam_ref = 0.;
Real ehat = 0.;
+ Matrix<Real> strain(this->spatial_dimension, this->spatial_dimension);
+ Matrix<Real> sigma(this->spatial_dimension, this->spatial_dimension);
+
for (auto && epsilon : epsilons) {
- Matrix<Real> strain(this->spatial_dimension, this->spatial_dimension, 0.);
- Matrix<Real> sigma(this->spatial_dimension, this->spatial_dimension, 0.);
+ strain.zero();
strain(0, 0) = epsilon;
strain(1, 1) = -this->nu * epsilon;
- computeStressOnQuad(strain, sigma, dam, ehat);
+ computeStressOnQuad(make_named_tuple("grad_u"_n = strain, "sigma"_n = sigma,
+ "damage"_n = dam, "Ehat"_n = ehat));
Real sigma_ref;
auto py_data =
py_mazars.attr("compute_step")(epsilon, sigma_ref, dam_ref, false);
std::tie(sigma_ref, dam_ref) = py::cast<std::pair<double, double>>(py_data);
EXPECT_NEAR(sigma(0, 0), sigma_ref, 1e-5);
EXPECT_NEAR(dam, dam_ref, 1e-10);
}
}
template <> void FriendMaterial<MaterialMazars<3>>::testComputeStress() {
Array<Real> epsilons(1001, 1);
Array<Real> sigmas(1001, 1);
Array<Real> damages(1001, 1);
for (auto && data : enumerate(epsilons)) {
std::get<1>(data) = 2e-6 * std::get<0>(data);
}
Real _K0 = K0;
py::module py_engine = py::module::import("py_mazars");
auto kwargs_mat_params =
py::dict("K0"_a = _K0, "At"_a = At, "Bt"_a = Bt, "Ac"_a = Ac, "Bc"_a = Bc,
"E"_a = E, "nu"_a = nu);
auto kwargs = py::dict("epsilons"_a = epsilons, "sigmas"_a = sigmas,
"damages"_a = damages);
auto py_mazars = py_engine.attr("Mazars")(**kwargs_mat_params);
// auto Gf_py = py_mazars.attr("compute")(**kwargs);
Real dam = 0.;
Real dam_ref = 0.;
Real ehat = 0.;
+ Matrix<Real> strain(this->spatial_dimension, this->spatial_dimension);
+ Matrix<Real> sigma(this->spatial_dimension, this->spatial_dimension);
+
for (auto && epsilon : epsilons) {
- Matrix<Real> strain(this->spatial_dimension, this->spatial_dimension, 0.);
- Matrix<Real> sigma(this->spatial_dimension, this->spatial_dimension, 0.);
+ strain.zero();
strain(0, 0) = epsilon;
strain(1, 1) = strain(2, 2) = -this->nu * epsilon;
- computeStressOnQuad(strain, sigma, dam, ehat);
+ computeStressOnQuad(make_named_tuple("grad_u"_n = strain, "sigma"_n = sigma,
+ "damage"_n = dam, "Ehat"_n = ehat));
Real sigma_ref;
auto py_data =
py_mazars.attr("compute_step")(epsilon, sigma_ref, dam_ref, false);
std::tie(sigma_ref, dam_ref) = py::cast<std::pair<double, double>>(py_data);
EXPECT_NEAR(sigma(0, 0), sigma_ref, 1e-5);
EXPECT_NEAR(dam, dam_ref, 1e-10);
}
}
namespace {
template <typename T>
class TestDamageMaterialFixture : public ::TestMaterialFixture<T> {};
TYPED_TEST_SUITE(TestDamageMaterialFixture, mat_types, );
TYPED_TEST(TestDamageMaterialFixture, ComputeStress) {
this->material->testComputeStress();
}
TYPED_TEST(TestDamageMaterialFixture, DISABLED_EnergyDensity) {
this->material->testEnergyDensity();
}
TYPED_TEST(TestDamageMaterialFixture, DISABLED_ComputeTangentModuli) {
this->material->testComputeTangentModuli();
}
TYPED_TEST(TestDamageMaterialFixture, DISABLED_ComputeCelerity) {
this->material->testCelerity();
}
} // namespace
/*****************************************************************/
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc
index 78ec6baca..12fc3040c 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc
@@ -1,887 +1,906 @@
/**
* @file test_elastic_materials.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Enrico Milanese <enrico.milanese@epfl.ch>
*
* @date creation: Fri Nov 17 2017
* @date last modification: Wed Nov 18 2020
*
* @brief Tests the Elastic materials
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_gtest_utils.hh"
#include "test_material_fixtures.hh"
/* -------------------------------------------------------------------------- */
+#include <aka_voigthelper.hh>
#include <material_elastic.hh>
#include <material_elastic_orthotropic.hh>
#include <solid_mechanics_model.hh>
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <type_traits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
using mat_types =
::testing::Types<Traits<MaterialElastic, 1>, Traits<MaterialElastic, 2>,
Traits<MaterialElastic, 3>,
Traits<MaterialElasticOrthotropic, 2>,
Traits<MaterialElasticOrthotropic, 3>,
Traits<MaterialElasticLinearAnisotropic, 2>,
Traits<MaterialElasticLinearAnisotropic, 3>>;
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<1>>::setParams() {
Real E = 3.;
Real rho = 2;
setParam("E", E);
setParam("rho", rho);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<1>>::testComputeStress() {
- Matrix<Real> eps = {{2}};
+ Matrix<Real> eps{{2}};
Matrix<Real> sigma(1, 1);
Real sigma_th = 2;
- this->computeStressOnQuad(eps, sigma, sigma_th);
+ this->computeStressOnQuad(make_named_tuple(
+ "grad_u"_n = eps, "sigma"_n = sigma, "sigma_th"_n = sigma_th));
auto solution = E * eps(0, 0) + sigma_th;
EXPECT_NEAR(sigma(0, 0), solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<1>>::testEnergyDensity() {
Real eps = 2, sigma = 2;
Real epot = 0;
- this->computePotentialEnergyOnQuad({{eps}}, {{sigma}}, epot);
+ this->computePotentialEnergyOnQuad(
+ make_named_tuple("grad_u"_n = Matrix<Real>{{eps}},
+ "sigma"_n = Matrix<Real>{{sigma}}),
+ epot);
Real solution = 2;
EXPECT_NEAR(epot, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElastic<1>>::testComputeTangentModuli() {
Matrix<Real> tangent(1, 1);
- this->computeTangentModuliOnQuad(tangent);
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
EXPECT_NEAR(tangent(0, 0), E, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<1>>::testCelerity() {
auto wave_speed = this->getCelerity(Element());
auto solution = std::sqrt(E / rho);
EXPECT_NEAR(wave_speed, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<2>>::setParams() {
Real E = 1.;
Real nu = .3;
Real rho = 2;
setParam("E", E);
setParam("nu", nu);
setParam("rho", rho);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<2>>::testComputeStress() {
Real bulk_modulus_K = E / (3 * (1 - 2 * nu));
Real shear_modulus_mu = E / (2 * (1 + nu));
- auto rotation_matrix = getRandomRotation();
+ Matrix<Real> rotation_matrix = getRandomRotation();
- auto grad_u = this->getComposedStrain(1.).block(0, 0, 2, 2);
+ Matrix<Real, 2, 2> grad_u = this->getComposedStrain(1.).block<2, 2>(0, 0);
auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix);
- Matrix<Real> sigma_rot(2, 2);
- this->computeStressOnQuad(grad_u_rot, sigma_rot, sigma_th);
+ Matrix<Real, 2, 2> sigma_rot;
+ this->computeStressOnQuad(make_named_tuple(
+ "grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot, "sigma_th"_n = sigma_th));
auto sigma = this->reverseRotation(sigma_rot, rotation_matrix);
- auto identity = Matrix<Real>::eye(2, 1.);
+ auto identity = Matrix<Real, 2, 2>::Identity();
- auto strain = 0.5 * (grad_u + grad_u.transpose());
- auto deviatoric_strain = strain - 1. / 3. * strain.trace() * identity;
+ Matrix<Real, 2, 2> strain = 0.5 * (grad_u + grad_u.transpose());
+ Matrix<Real, 2, 2> deviatoric_strain =
+ strain - 1. / 3. * strain.trace() * identity;
- auto sigma_expected = 2 * shear_modulus_mu * deviatoric_strain +
- (sigma_th + 2. * bulk_modulus_K) * identity;
+ Matrix<Real, 2, 2> sigma_expected =
+ 2 * shear_modulus_mu * deviatoric_strain +
+ (sigma_th + 2. * bulk_modulus_K) * identity;
auto diff = sigma - sigma_expected;
- Real stress_error = diff.norm<L_inf>() / sigma_expected.norm<L_inf>();
+ Real stress_error =
+ diff.lpNorm<Eigen::Infinity>() / sigma_expected.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<2>>::testEnergyDensity() {
- Matrix<Real> sigma = {{1, 2}, {2, 4}};
- Matrix<Real> eps = {{1, 0}, {0, 1}};
+ Matrix<Real, 2, 2> sigma{{1, 2}, {2, 4}};
+ Matrix<Real, 2, 2> eps{{1, 0}, {0, 1}};
Real epot = 0;
Real solution = 2.5;
- this->computePotentialEnergyOnQuad(eps, sigma, epot);
+ this->computePotentialEnergyOnQuad(
+ make_named_tuple("grad_u"_n = eps, "sigma"_n = sigma), epot);
EXPECT_NEAR(epot, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElastic<2>>::testComputeTangentModuli() {
- Matrix<Real> tangent(3, 3);
+ Matrix<Real, 3, 3> tangent;
/* Plane Strain */
// clang-format off
- Matrix<Real> solution = {
+ Matrix<Real, 3,3> solution{
{1 - nu, nu, 0},
{nu, 1 - nu, 0},
{0, 0, (1 - 2 * nu) / 2},
};
// clang-format on
solution *= E / ((1 + nu) * (1 - 2 * nu));
- this->computeTangentModuliOnQuad(tangent);
- Real tangent_error = (tangent - solution).norm<L_2>();
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
+ Real tangent_error = (tangent - solution).lpNorm<Eigen::Infinity>();
EXPECT_NEAR(tangent_error, 0, 1e-14);
/* Plane Stress */
this->plane_stress = true;
this->updateInternalParameters();
// clang-format off
- solution = {
+ solution = Matrix<Real, 3,3>{
{1, nu, 0},
{nu, 1, 0},
{0, 0, (1 - nu) / 2},
};
// clang-format on
solution *= E / (1 - nu * nu);
- this->computeTangentModuliOnQuad(tangent);
- tangent_error = (tangent - solution).norm<L_2>();
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
+ tangent_error = (tangent - solution).lpNorm<Eigen::Infinity>();
EXPECT_NEAR(tangent_error, 0, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<2>>::testCelerity() {
auto push_wave_speed = this->getPushWaveSpeed(Element());
auto celerity = this->getCelerity(Element());
Real K = E / (3 * (1 - 2 * nu));
Real mu = E / (2 * (1 + nu));
Real sol = std::sqrt((K + 4. / 3 * mu) / rho);
EXPECT_NEAR(push_wave_speed, sol, 1e-14);
EXPECT_NEAR(celerity, sol, 1e-14);
auto shear_wave_speed = this->getShearWaveSpeed(Element());
sol = std::sqrt(mu / rho);
EXPECT_NEAR(shear_wave_speed, sol, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<3>>::setParams() {
Real E = 1.;
Real nu = .3;
Real rho = 2;
setParam("E", E);
setParam("nu", nu);
setParam("rho", rho);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<3>>::testComputeStress() {
Real bulk_modulus_K = E / 3. / (1 - 2. * nu);
Real shear_modulus_mu = 0.5 * E / (1 + nu);
- Matrix<Real> rotation_matrix = getRandomRotation();
-
- auto grad_u = this->getComposedStrain(1.);
-
- auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix);
+ Matrix<Real, 3, 3> rotation_matrix = getRandomRotation();
+ Matrix<Real, 3, 3> grad_u = this->getComposedStrain(1.);
+ Matrix<Real, 3, 3> grad_u_rot = this->applyRotation(grad_u, rotation_matrix);
- Matrix<Real> sigma_rot(3, 3);
- this->computeStressOnQuad(grad_u_rot, sigma_rot, sigma_th);
+ Matrix<Real, 3, 3> sigma_rot;
+ this->computeStressOnQuad(make_named_tuple(
+ "grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot, "sigma_th"_n = sigma_th));
- auto sigma = this->reverseRotation(sigma_rot, rotation_matrix);
+ Matrix<Real, 3, 3> sigma = this->reverseRotation(sigma_rot, rotation_matrix);
- Matrix<Real> identity(3, 3);
- identity.eye();
+ Matrix<Real, 3, 3> identity = Matrix<Real, 3, 3>::Identity();
- Matrix<Real> strain = 0.5 * (grad_u + grad_u.transpose());
- Matrix<Real> deviatoric_strain = strain - 1. / 3. * strain.trace() * identity;
+ Matrix<Real, 3, 3> strain = 0.5 * (grad_u + grad_u.transpose());
+ Matrix<Real, 3, 3> deviatoric_strain =
+ strain - 1. / 3. * strain.trace() * identity;
- Matrix<Real> sigma_expected = 2 * shear_modulus_mu * deviatoric_strain +
- (sigma_th + 3. * bulk_modulus_K) * identity;
+ Matrix<Real, 3, 3> sigma_expected =
+ 2 * shear_modulus_mu * deviatoric_strain +
+ (sigma_th + 3. * bulk_modulus_K) * identity;
auto diff = sigma - sigma_expected;
- Real stress_error = diff.norm<L_inf>();
+ Real stress_error = diff.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<3>>::testEnergyDensity() {
- Matrix<Real> sigma = {{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
- Matrix<Real> eps = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+ Matrix<Real, 3, 3> sigma{{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
+ Matrix<Real, 3, 3> eps{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Real epot = 0;
Real solution = 5.5;
- this->computePotentialEnergyOnQuad(eps, sigma, epot);
+ this->computePotentialEnergyOnQuad(
+ make_named_tuple("grad_u"_n = eps, "sigma"_n = sigma), epot);
EXPECT_NEAR(epot, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElastic<3>>::testComputeTangentModuli() {
Matrix<Real> tangent(6, 6);
// clang-format off
- Matrix<Real> solution = {
+ Matrix<Real,6,6> solution{
{1 - nu, nu, nu, 0, 0, 0},
{nu, 1 - nu, nu, 0, 0, 0},
{nu, nu, 1 - nu, 0, 0, 0},
{0, 0, 0, (1 - 2 * nu) / 2, 0, 0},
{0, 0, 0, 0, (1 - 2 * nu) / 2, 0},
{0, 0, 0, 0, 0, (1 - 2 * nu) / 2},
};
// clang-format on
solution *= E / ((1 + nu) * (1 - 2 * nu));
- this->computeTangentModuliOnQuad(tangent);
- Real tangent_error = (tangent - solution).norm<L_2>();
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
+ Real tangent_error = (tangent - solution).norm();
EXPECT_NEAR(tangent_error, 0, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<3>>::testCelerity() {
auto push_wave_speed = this->getPushWaveSpeed(Element());
auto celerity = this->getCelerity(Element());
Real K = E / (3 * (1 - 2 * nu));
Real mu = E / (2 * (1 + nu));
Real sol = std::sqrt((K + 4. / 3 * mu) / rho);
EXPECT_NEAR(push_wave_speed, sol, 1e-14);
EXPECT_NEAR(celerity, sol, 1e-14);
auto shear_wave_speed = this->getShearWaveSpeed(Element());
sol = std::sqrt(mu / rho);
EXPECT_NEAR(shear_wave_speed, sol, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElasticOrthotropic<2>>::setParams() {
// Note: for this test material and canonical basis coincide
- Vector<Real> n1 = {1, 0};
- Vector<Real> n2 = {0, 1};
+ Vector<Real, 2> n1{1, 0};
+ Vector<Real, 2> n2{0, 1};
Real E1 = 1.;
Real E2 = 2.;
Real nu12 = 0.1;
Real G12 = 2.;
Real rho = 2.5;
*this->dir_vecs[0] = n1;
*this->dir_vecs[1] = n2;
this->E1 = E1;
this->E2 = E2;
this->nu12 = nu12;
this->G12 = G12;
this->rho = rho;
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<2>>::testComputeStress() {
- UInt Dim = 2;
+ const Int Dim = 2;
// material frame of reference is rotate by rotation_matrix starting from
// canonical basis
Matrix<Real> rotation_matrix = getRandomRotation();
// canonical basis as expressed in the material frame of reference, as
// required by MaterialElasticOrthotropic class (it is simply given by the
// columns of the rotation_matrix; the lines give the material basis expressed
// in the canonical frame of reference)
*this->dir_vecs[0] = rotation_matrix(0);
*this->dir_vecs[1] = rotation_matrix(1);
// set internal Cijkl matrix expressed in the canonical frame of reference
this->updateInternalParameters();
// gradient in material frame of reference
- auto grad_u = this->getComposedStrain(2.).block(0, 0, 2, 2);
+ Matrix<Real, Dim, Dim> grad_u = this->getComposedStrain(2.).block<2, 2>(0, 0);
// gradient in canonical basis (we need to rotate *back* to the canonical
// basis)
auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
// stress in the canonical basis
- Matrix<Real> sigma_rot(2, 2);
- this->computeStressOnQuad(grad_u_rot, sigma_rot);
+ Matrix<Real, Dim, Dim> sigma_rot;
+ this->computeStressOnQuad(
+ make_named_tuple("grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot));
// stress in the material reference (we need to apply the rotation)
auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
// construction of Cijkl engineering tensor in the *material* frame of
// reference
// ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
Real nu21 = nu12 * E2 / E1;
Real gamma = 1 / (1 - nu12 * nu21);
- Matrix<Real> C_expected(2 * Dim, 2 * Dim, 0);
+ Matrix<Real, 2 * Dim, 2 * Dim> C_expected;
+ C_expected.zero();
+
C_expected(0, 0) = gamma * E1;
C_expected(1, 1) = gamma * E2;
C_expected(2, 2) = G12;
C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * nu21;
// epsilon is computed directly in the *material* frame of reference
- Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
+ Matrix<Real, Dim, Dim> epsilon = (grad_u + grad_u.transpose()) / 2.;
// sigma_expected is computed directly in the *material* frame of reference
- Matrix<Real> sigma_expected(Dim, Dim);
- for (UInt i = 0; i < Dim; ++i) {
- for (UInt j = 0; j < Dim; ++j) {
+ Matrix<Real, Dim, Dim> sigma_expected;
+ sigma_expected.zero();
+
+ for (Int i = 0; i < Dim; ++i) {
+ for (Int j = 0; j < Dim; ++j) {
sigma_expected(i, i) += C_expected(i, j) * epsilon(j, j);
}
}
sigma_expected(0, 1) = sigma_expected(1, 0) =
C_expected(2, 2) * 2 * epsilon(0, 1);
// sigmas are checked in the *material* frame of reference
auto diff = sigma - sigma_expected;
- Real stress_error = diff.norm<L_inf>();
+ Real stress_error = diff.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<2>>::testEnergyDensity() {
- Matrix<Real> sigma = {{1, 2}, {2, 4}};
- Matrix<Real> eps = {{1, 0}, {0, 1}};
+ Matrix<Real, 2, 2> sigma{{1, 2}, {2, 4}};
+ Matrix<Real, 2, 2> eps{{1, 0}, {0, 1}};
Real epot = 0;
Real solution = 2.5;
- this->computePotentialEnergyOnQuad(eps, sigma, epot);
+ this->computePotentialEnergyOnQuad(
+ make_named_tuple("grad_u"_n = eps, "sigma"_n = sigma), epot);
EXPECT_NEAR(epot, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<2>>::testComputeTangentModuli() {
// construction of Cijkl engineering tensor in the *material* frame of
// reference
// ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
Real nu21 = nu12 * E2 / E1;
Real gamma = 1 / (1 - nu12 * nu21);
Matrix<Real> C_expected(3, 3);
+ C_expected.zero();
+
C_expected(0, 0) = gamma * E1;
C_expected(1, 1) = gamma * E2;
C_expected(2, 2) = G12;
C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * nu21;
Matrix<Real> tangent(3, 3);
- this->computeTangentModuliOnQuad(tangent);
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
- Real tangent_error = (tangent - C_expected).norm<L_2>();
+ Real tangent_error = (tangent - C_expected).norm();
EXPECT_NEAR(tangent_error, 0, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElasticOrthotropic<2>>::testCelerity() {
// construction of Cijkl engineering tensor in the *material* frame of
// reference
// ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
Real nu21 = nu12 * E2 / E1;
Real gamma = 1 / (1 - nu12 * nu21);
- Matrix<Real> C_expected(3, 3);
+ Matrix<Real, 3, 3> C_expected;
+ C_expected.zero();
+
C_expected(0, 0) = gamma * E1;
C_expected(1, 1) = gamma * E2;
C_expected(2, 2) = G12;
C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * nu21;
- Vector<Real> eig_expected(3);
+ Vector<Real, 3> eig_expected;
C_expected.eig(eig_expected);
auto celerity_expected = std::sqrt(eig_expected(0) / rho);
auto celerity = this->getCelerity(Element());
EXPECT_NEAR(celerity_expected, celerity, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElasticOrthotropic<3>>::setParams() {
- Vector<Real> n1 = {1, 0, 0};
- Vector<Real> n2 = {0, 1, 0};
- Vector<Real> n3 = {0, 0, 1};
+ Vector<Real, 3> n1{1, 0, 0};
+ Vector<Real, 3> n2{0, 1, 0};
+ Vector<Real, 3> n3{0, 0, 1};
Real E1 = 1.;
Real E2 = 2.;
Real E3 = 3.;
Real nu12 = 0.1;
Real nu13 = 0.2;
Real nu23 = 0.3;
Real G12 = 2.;
Real G13 = 3.;
Real G23 = 1.;
Real rho = 2.3;
*this->dir_vecs[0] = n1;
*this->dir_vecs[1] = n2;
*this->dir_vecs[2] = n3;
this->E1 = E1;
this->E2 = E2;
this->E3 = E3;
this->nu12 = nu12;
this->nu13 = nu13;
this->nu23 = nu23;
this->G12 = G12;
this->G13 = G13;
this->G23 = G23;
this->rho = rho;
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<3>>::testComputeStress() {
- UInt Dim = 3;
+ const Int Dim = 3;
// material frame of reference is rotate by rotation_matrix starting from
// canonical basis
- Matrix<Real> rotation_matrix = getRandomRotation();
+ Matrix<Real, Dim, Dim> rotation_matrix = getRandomRotation();
// canonical basis as expressed in the material frame of reference, as
// required by MaterialElasticOrthotropic class (it is simply given by the
// columns of the rotation_matrix; the lines give the material basis expressed
// in the canonical frame of reference)
*this->dir_vecs[0] = rotation_matrix(0);
*this->dir_vecs[1] = rotation_matrix(1);
*this->dir_vecs[2] = rotation_matrix(2);
// set internal Cijkl matrix expressed in the canonical frame of reference
this->updateInternalParameters();
// gradient in material frame of reference
- auto grad_u = this->getComposedStrain(2.);
+ Matrix<Real, Dim, Dim> grad_u = this->getComposedStrain(2.);
// gradient in canonical basis (we need to rotate *back* to the canonical
// basis)
auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
// stress in the canonical basis
Matrix<Real> sigma_rot(3, 3);
- this->computeStressOnQuad(grad_u_rot, sigma_rot);
+ this->computeStressOnQuad(
+ make_named_tuple("grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot));
// stress in the material reference (we need to apply the rotation)
auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
// construction of Cijkl engineering tensor in the *material* frame of
// reference
// ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
Real nu21 = nu12 * E2 / E1;
Real nu31 = nu13 * E3 / E1;
Real nu32 = nu23 * E3 / E2;
Real gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
2 * nu21 * nu32 * nu13);
- Matrix<Real> C_expected(6, 6);
+ Matrix<Real, 2 * Dim, 2 * Dim> C_expected;
+ C_expected.zero();
+
C_expected(0, 0) = gamma * E1 * (1 - nu23 * nu32);
C_expected(1, 1) = gamma * E2 * (1 - nu13 * nu31);
C_expected(2, 2) = gamma * E3 * (1 - nu12 * nu21);
C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * (nu21 + nu31 * nu23);
C_expected(2, 0) = C_expected(0, 2) = gamma * E1 * (nu31 + nu21 * nu32);
C_expected(2, 1) = C_expected(1, 2) = gamma * E2 * (nu32 + nu12 * nu31);
C_expected(3, 3) = G23;
C_expected(4, 4) = G13;
C_expected(5, 5) = G12;
// epsilon is computed directly in the *material* frame of reference
- Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
+ Matrix<Real, Dim, Dim> epsilon = 0.5 * (grad_u + grad_u.transpose());
// sigma_expected is computed directly in the *material* frame of reference
- Matrix<Real> sigma_expected(Dim, Dim);
- for (UInt i = 0; i < Dim; ++i) {
- for (UInt j = 0; j < Dim; ++j) {
+ Matrix<Real, Dim, Dim> sigma_expected;
+ sigma_expected.zero();
+
+ for (Int i = 0; i < Dim; ++i) {
+ for (Int j = 0; j < Dim; ++j) {
sigma_expected(i, i) += C_expected(i, j) * epsilon(j, j);
}
}
sigma_expected(0, 1) = C_expected(5, 5) * 2 * epsilon(0, 1);
sigma_expected(0, 2) = C_expected(4, 4) * 2 * epsilon(0, 2);
sigma_expected(1, 2) = C_expected(3, 3) * 2 * epsilon(1, 2);
sigma_expected(1, 0) = sigma_expected(0, 1);
sigma_expected(2, 0) = sigma_expected(0, 2);
sigma_expected(2, 1) = sigma_expected(1, 2);
// sigmas are checked in the *material* frame of reference
auto diff = sigma - sigma_expected;
- Real stress_error = diff.norm<L_inf>();
+ Real stress_error = diff.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<3>>::testEnergyDensity() {
- Matrix<Real> sigma = {{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
- Matrix<Real> eps = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+ Matrix<Real, 3, 3> sigma{{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
+ Matrix<Real, 3, 3> eps{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Real epot = 0;
Real solution = 5.5;
- this->computePotentialEnergyOnQuad(eps, sigma, epot);
+ this->computePotentialEnergyOnQuad(
+ make_named_tuple("grad_u"_n = eps, "sigma"_n = sigma), epot);
EXPECT_NEAR(epot, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<3>>::testComputeTangentModuli() {
// Note: for this test material and canonical basis coincide
UInt Dim = 3;
// construction of Cijkl engineering tensor in the *material* frame of
// reference
// ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
- Real nu21 = nu12 * E2 / E1;
- Real nu31 = nu13 * E3 / E1;
- Real nu32 = nu23 * E3 / E2;
- Real gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
+ auto nu21 = nu12 * E2 / E1;
+ auto nu31 = nu13 * E3 / E1;
+ auto nu32 = nu23 * E3 / E2;
+ auto gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
2 * nu21 * nu32 * nu13);
- Matrix<Real> C_expected(2 * Dim, 2 * Dim, 0);
+ Matrix<Real> C_expected(2 * Dim, 2 * Dim);
+ C_expected.zero();
+
C_expected(0, 0) = gamma * E1 * (1 - nu23 * nu32);
C_expected(1, 1) = gamma * E2 * (1 - nu13 * nu31);
C_expected(2, 2) = gamma * E3 * (1 - nu12 * nu21);
C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * (nu21 + nu31 * nu23);
C_expected(2, 0) = C_expected(0, 2) = gamma * E1 * (nu31 + nu21 * nu32);
C_expected(2, 1) = C_expected(1, 2) = gamma * E2 * (nu32 + nu12 * nu31);
C_expected(3, 3) = G23;
C_expected(4, 4) = G13;
C_expected(5, 5) = G12;
Matrix<Real> tangent(6, 6);
- this->computeTangentModuliOnQuad(tangent);
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
- Real tangent_error = (tangent - C_expected).norm<L_2>();
+ Real tangent_error = (tangent - C_expected).norm();
EXPECT_NEAR(tangent_error, 0, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElasticOrthotropic<3>>::testCelerity() {
// Note: for this test material and canonical basis coincide
UInt Dim = 3;
// construction of Cijkl engineering tensor in the *material* frame of
// reference
// ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
- Real nu21 = nu12 * E2 / E1;
- Real nu31 = nu13 * E3 / E1;
- Real nu32 = nu23 * E3 / E2;
- Real gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
+ auto nu21 = nu12 * E2 / E1;
+ auto nu31 = nu13 * E3 / E1;
+ auto nu32 = nu23 * E3 / E2;
+ auto gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
2 * nu21 * nu32 * nu13);
- Matrix<Real> C_expected(2 * Dim, 2 * Dim, 0);
+ Matrix<Real> C_expected(2 * Dim, 2 * Dim);
+ C_expected.zero();
+
C_expected(0, 0) = gamma * E1 * (1 - nu23 * nu32);
C_expected(1, 1) = gamma * E2 * (1 - nu13 * nu31);
C_expected(2, 2) = gamma * E3 * (1 - nu12 * nu21);
C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * (nu21 + nu31 * nu23);
C_expected(2, 0) = C_expected(0, 2) = gamma * E1 * (nu31 + nu21 * nu32);
C_expected(2, 1) = C_expected(1, 2) = gamma * E2 * (nu32 + nu12 * nu31);
C_expected(3, 3) = G23;
C_expected(4, 4) = G13;
C_expected(5, 5) = G12;
Vector<Real> eig_expected(6);
C_expected.eig(eig_expected);
auto celerity_expected = std::sqrt(eig_expected(0) / rho);
auto celerity = this->getCelerity(Element());
EXPECT_NEAR(celerity_expected, celerity, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<2>>::setParams() {
- Matrix<Real> C = {
- {1.0, 0.3, 0.4},
- {0.3, 2.0, 0.1},
- {0.4, 0.1, 1.5},
- };
+ Matrix<Real, 3, 3> C{{1.0, 0.3, 0.4}, {0.3, 2.0, 0.1}, {0.4, 0.1, 1.5}};
- for (auto i = 0u; i < C.rows(); ++i)
- for (auto j = 0u; j < C.cols(); ++j)
- this->Cprime(i, j) = C(i, j);
+ Cprime.block<3, 3>(0, 0) = C;
this->rho = 2.7;
// material frame of reference is rotate by rotation_matrix starting from
// canonical basis
Matrix<Real> rotation_matrix = getRandomRotation();
// canonical basis as expressed in the material frame of reference, as
// required by MaterialElasticLinearAnisotropic class (it is simply given by
// the columns of the rotation_matrix; the lines give the material basis
// expressed in the canonical frame of reference)
*this->dir_vecs[0] = rotation_matrix(0);
*this->dir_vecs[1] = rotation_matrix(1);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<2>>::testComputeStress() {
- Matrix<Real> C = {
- {1.0, 0.3, 0.4},
- {0.3, 2.0, 0.1},
- {0.4, 0.1, 1.5},
- };
+ Matrix<Real, 3, 3> C{{1.0, 0.3, 0.4}, {0.3, 2.0, 0.1}, {0.4, 0.1, 1.5}};
- Matrix<Real> rotation_matrix(2, 2);
+ Matrix<Real, 2, 2> rotation_matrix;
rotation_matrix(0) = *this->dir_vecs[0];
rotation_matrix(1) = *this->dir_vecs[1];
// gradient in material frame of reference
- auto grad_u = this->getComposedStrain(1.).block(0, 0, 2, 2);
+ Matrix<Real, 2, 2> grad_u = this->getComposedStrain(1.).block<2, 2>(0, 0);
// gradient in canonical basis (we need to rotate *back* to the canonical
// basis)
- auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
+ Matrix<Real, 2, 2> grad_u_rot =
+ this->reverseRotation(grad_u, rotation_matrix);
// stress in the canonical basis
- Matrix<Real> sigma_rot(2, 2);
- this->computeStressOnQuad(grad_u_rot, sigma_rot);
+ Matrix<Real, 2, 2> sigma_rot;
+ this->computeStressOnQuad(
+ make_named_tuple("grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot));
// stress in the material reference (we need to apply the rotation)
auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
// epsilon is computed directly in the *material* frame of reference
- Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
- Vector<Real> epsilon_voigt(3);
- epsilon_voigt(0) = epsilon(0, 0);
- epsilon_voigt(1) = epsilon(1, 1);
- epsilon_voigt(2) = 2 * epsilon(0, 1);
+ Matrix<Real, 2, 2> epsilon = (grad_u + grad_u.transpose()) / 2.;
+ Vector<Real, 3> epsilon_voigt =
+ VoigtHelper<2>::matrixToVoigtWithFactors(epsilon);
// sigma_expected is computed directly in the *material* frame of reference
- Vector<Real> sigma_voigt = C * epsilon_voigt;
- Matrix<Real> sigma_expected(2, 2);
- sigma_expected(0, 0) = sigma_voigt(0);
- sigma_expected(1, 1) = sigma_voigt(1);
- sigma_expected(0, 1) = sigma_expected(1, 0) = sigma_voigt(2);
+ Vector<Real, 3> sigma_voigt = C * epsilon_voigt;
+
+ Matrix<Real, 2, 2> sigma_expected =
+ VoigtHelper<2>::voigtToMatrix(sigma_voigt);
// sigmas are checked in the *material* frame of reference
auto diff = sigma - sigma_expected;
- Real stress_error = diff.norm<L_inf>();
+ Real stress_error = diff.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<2>>::testEnergyDensity() {
- Matrix<Real> sigma = {{1, 2}, {2, 4}};
- Matrix<Real> eps = {{1, 0}, {0, 1}};
+ Matrix<Real> sigma{{1, 2}, {2, 4}};
+ Matrix<Real> eps{{1, 0}, {0, 1}};
Real epot = 0;
Real solution = 2.5;
- this->computePotentialEnergyOnQuad(eps, sigma, epot);
+ this->computePotentialEnergyOnQuad(
+ make_named_tuple("grad_u"_n = eps, "sigma"_n = sigma), epot);
EXPECT_NEAR(epot, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<
MaterialElasticLinearAnisotropic<2>>::testComputeTangentModuli() {
Matrix<Real> tangent(3, 3);
- this->computeTangentModuliOnQuad(tangent);
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
- Real tangent_error = (tangent - C).norm<L_2>();
+ Real tangent_error = (tangent - C).norm();
EXPECT_NEAR(tangent_error, 0, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<2>>::testCelerity() {
Vector<Real> eig_expected(3);
C.eig(eig_expected);
auto celerity_expected = std::sqrt(eig_expected(0) / this->rho);
auto celerity = this->getCelerity(Element());
EXPECT_NEAR(celerity_expected, celerity, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::setParams() {
// Note: for this test material and canonical basis coincide
- Matrix<Real> C = {
+ Matrix<Real, 6, 6> C{
{1.0, 0.3, 0.4, 0.3, 0.2, 0.1}, {0.3, 2.0, 0.1, 0.2, 0.3, 0.2},
{0.4, 0.1, 1.5, 0.1, 0.4, 0.3}, {0.3, 0.2, 0.1, 2.4, 0.1, 0.4},
- {0.2, 0.3, 0.4, 0.1, 0.9, 0.1}, {0.1, 0.2, 0.3, 0.4, 0.1, 1.2},
- };
+ {0.2, 0.3, 0.4, 0.1, 0.9, 0.1}, {0.1, 0.2, 0.3, 0.4, 0.1, 1.2}};
- for (auto i = 0u; i < C.rows(); ++i)
- for (auto j = 0u; j < C.cols(); ++j)
+ for (auto i = 0; i < C.rows(); ++i)
+ for (auto j = 0; j < C.cols(); ++j)
this->Cprime(i, j) = C(i, j);
this->rho = 2.9;
// material frame of reference is rotate by rotation_matrix starting from
// canonical basis
Matrix<Real> rotation_matrix = getRandomRotation();
// canonical basis as expressed in the material frame of reference, as
// required by MaterialElasticLinearAnisotropic class (it is simply given by
// the columns of the rotation_matrix; the lines give the material basis
// expressed in the canonical frame of reference)
*this->dir_vecs[0] = rotation_matrix(0);
*this->dir_vecs[1] = rotation_matrix(1);
*this->dir_vecs[2] = rotation_matrix(2);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testComputeStress() {
- Matrix<Real> C = {
+ Matrix<Real, 6, 6> C{
{1.0, 0.3, 0.4, 0.3, 0.2, 0.1}, {0.3, 2.0, 0.1, 0.2, 0.3, 0.2},
{0.4, 0.1, 1.5, 0.1, 0.4, 0.3}, {0.3, 0.2, 0.1, 2.4, 0.1, 0.4},
- {0.2, 0.3, 0.4, 0.1, 0.9, 0.1}, {0.1, 0.2, 0.3, 0.4, 0.1, 1.2},
- };
+ {0.2, 0.3, 0.4, 0.1, 0.9, 0.1}, {0.1, 0.2, 0.3, 0.4, 0.1, 1.2}};
- Matrix<Real> rotation_matrix(3, 3);
+ Matrix<Real, 3, 3> rotation_matrix;
rotation_matrix(0) = *this->dir_vecs[0];
rotation_matrix(1) = *this->dir_vecs[1];
rotation_matrix(2) = *this->dir_vecs[2];
// gradient in material frame of reference
auto grad_u = this->getComposedStrain(2.);
// gradient in canonical basis (we need to rotate *back* to the canonical
// basis)
auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
// stress in the canonical basis
- Matrix<Real> sigma_rot(3, 3);
- this->computeStressOnQuad(grad_u_rot, sigma_rot);
+ Matrix<Real, 3, 3> sigma_rot;
+ this->computeStressOnQuad(
+ make_named_tuple("grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot));
// stress in the material reference (we need to apply the rotation)
auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
// epsilon is computed directly in the *material* frame of reference
- Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
- Vector<Real> epsilon_voigt(6);
- epsilon_voigt(0) = epsilon(0, 0);
- epsilon_voigt(1) = epsilon(1, 1);
- epsilon_voigt(2) = epsilon(2, 2);
- epsilon_voigt(3) = 2 * epsilon(1, 2);
- epsilon_voigt(4) = 2 * epsilon(0, 2);
- epsilon_voigt(5) = 2 * epsilon(0, 1);
+ Matrix<Real, 3, 3> epsilon = (grad_u + grad_u.transpose()) / 2.;
+ Vector<Real, 6> epsilon_voigt =
+ VoigtHelper<3>::matrixToVoigtWithFactors(epsilon);
// sigma_expected is computed directly in the *material* frame of reference
- Vector<Real> sigma_voigt = C * epsilon_voigt;
- Matrix<Real> sigma_expected(3, 3);
- sigma_expected(0, 0) = sigma_voigt(0);
- sigma_expected(1, 1) = sigma_voigt(1);
- sigma_expected(2, 2) = sigma_voigt(2);
- sigma_expected(1, 2) = sigma_expected(2, 1) = sigma_voigt(3);
- sigma_expected(0, 2) = sigma_expected(2, 0) = sigma_voigt(4);
- sigma_expected(0, 1) = sigma_expected(1, 0) = sigma_voigt(5);
+ Vector<Real, 6> sigma_voigt = C * epsilon_voigt;
+ Matrix<Real, 3, 3> sigma_expected =
+ VoigtHelper<3>::voigtToMatrix(sigma_voigt);
// sigmas are checked in the *material* frame of reference
auto diff = sigma - sigma_expected;
- Real stress_error = diff.norm<L_inf>();
+ Real stress_error = diff.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testEnergyDensity() {
- Matrix<Real> sigma = {{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
- Matrix<Real> eps = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+ Matrix<Real, 3, 3> sigma{{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
+ Matrix<Real, 3, 3> eps{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Real epot = 0;
Real solution = 5.5;
- this->computePotentialEnergyOnQuad(eps, sigma, epot);
+ this->computePotentialEnergyOnQuad(
+ make_named_tuple("grad_u"_n = eps, "sigma"_n = sigma), epot);
EXPECT_NEAR(epot, solution, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<
MaterialElasticLinearAnisotropic<3>>::testComputeTangentModuli() {
- Matrix<Real> tangent(6, 6);
- this->computeTangentModuliOnQuad(tangent);
+ Matrix<Real, 6, 6> tangent;
+ this->computeTangentModuliOnQuad(
+ make_named_tuple("tangent_moduli"_n = tangent));
- Real tangent_error = (tangent - C).norm<L_2>();
+ Real tangent_error = (tangent - C).norm();
EXPECT_NEAR(tangent_error, 0, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testCelerity() {
- Vector<Real> eig_expected(6);
+ Vector<Real, 6> eig_expected;
C.eig(eig_expected);
auto celerity_expected = std::sqrt(eig_expected(0) / this->rho);
auto celerity = this->getCelerity(Element());
EXPECT_NEAR(celerity_expected, celerity, 1e-14);
}
/* -------------------------------------------------------------------------- */
namespace {
template <typename T>
class TestElasticMaterialFixture : public ::TestMaterialFixture<T> {};
TYPED_TEST_SUITE(TestElasticMaterialFixture, mat_types, );
TYPED_TEST(TestElasticMaterialFixture, ComputeStress) {
this->material->testComputeStress();
}
TYPED_TEST(TestElasticMaterialFixture, EnergyDensity) {
this->material->testEnergyDensity();
}
TYPED_TEST(TestElasticMaterialFixture, ComputeTangentModuli) {
this->material->testComputeTangentModuli();
}
TYPED_TEST(TestElasticMaterialFixture, ComputeCelerity) {
this->material->testCelerity();
}
} // namespace
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_finite_deformation.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_finite_deformation.cc
index 896b25148..fc243553e 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_finite_deformation.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_finite_deformation.cc
@@ -1,139 +1,139 @@
/**
* @file test_finite_deformation.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Nov 11 2019
* @date last modification: Wed May 27 2020
*
* @brief Test for dinite deformation
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <solid_mechanics_model.hh>
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <type_traits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
TEST(TestFiniteDeformation, NotUnit) {
getStaticParser().parse("material_finite_deformation.dat");
const double pi = std::atan(1) * 4;
constexpr int dim = 3;
Mesh mesh(dim);
mesh.read("1_tetrahedron.msh");
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _static);
#if DEBUG_TEST
model.addDumpField("displacement");
model.addDumpField("internal_force");
model.addDumpField("stress");
model.addDumpField("strain");
model.dump();
#endif
Matrix<Real> alpha{{0.00, 0.02, 0.03, 0.04},
{0.00, 0.06, 0.07, 0.08},
{0.00, 0.10, 0.11, 0.12}};
auto impose_disp = [&] {
model.getDisplacement().zero();
for (auto data : zip(make_view(mesh.getNodes(), dim),
make_view(model.getDisplacement(), dim),
make_view(model.getBlockedDOFs(), dim))) {
auto & pos = std::get<0>(data);
auto & dis = std::get<1>(data);
auto & blocked = std::get<2>(data);
blocked.set(true);
- dis += Vector<Real>(alpha(0));
+ dis += alpha(0);
for (auto p : arange(dim)) {
- dis += Vector<Real>(alpha(1 + p)) * pos(p);
+ dis += alpha(1 + p) * pos(p);
}
}
};
impose_disp();
model.solveStep();
#if DEBUG_TEST
model.dump();
#endif
auto stesses0 = model.getMaterial(0).getStress();
auto displacement0 = model.getDisplacement();
auto internal_force0 = model.getInternalForce();
auto theta = pi / 4;
Matrix<Real> R{{1., 0., 0.},
{0., std::cos(theta), -std::sin(theta)},
{0., std::sin(theta), std::cos(theta)}};
impose_disp();
for (auto data : zip(make_view(mesh.getNodes(), dim),
make_view(model.getDisplacement(), dim))) {
auto & X = std::get<0>(data);
auto & u = std::get<1>(data);
u = R * (X + u) - X;
}
model.solveStep();
#if DEBUG_TEST
model.dump();
#endif
for (auto data : zip(make_view(mesh.getNodes(), dim),
make_view(model.getDisplacement(), dim),
make_view(displacement0, dim),
make_view(model.getInternalForce(), dim),
make_view(internal_force0, dim))) {
auto pos = std::get<0>(data);
- Vector<Real> refdis(dim, 0.);
+ Vector<Real> refdis(dim);
- refdis += Vector<Real>(alpha(0));
+ refdis = alpha(0);
for (auto p : arange(dim)) {
- refdis += Vector<Real>(alpha(1 + p)) * pos(p);
+ refdis += alpha(1 + p) * pos(p);
}
auto dis = std::get<1>(data);
auto dis0 = std::get<2>(data);
auto err = refdis.distance(dis0);
EXPECT_NEAR(err, 0, 1e-14);
auto err1 = dis.distance(R * (pos + dis0) - pos);
EXPECT_NEAR(err1, 0, 1e-14);
auto f = std::get<3>(data);
auto f0 = std::get<4>(data);
auto err3 = f.distance(R * f0);
EXPECT_NEAR(err3, 0, 1e-5);
}
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc
index 9fe106177..91797ae30 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc
@@ -1,183 +1,183 @@
/**
* @file test_interpolate_stress.cc
*
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Sep 08 2020
*
* @brief Test for the stress interpolation function
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
#include "integrator_gauss.hh"
#include "mesh_utils.hh"
#include "shape_lagrange.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
Real function(Real x, Real y, Real z) { return 100. + 2. * x + 3. * y + 4 * z; }
int main(int argc, char * argv[]) {
initialize("material_interpolate.dat", argc, argv);
debug::setDebugLevel(dblWarning);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
const ElementType type = _tetrahedron_10;
Mesh mesh(spatial_dimension);
mesh.read("interpolation.msh");
const ElementType type_facet = mesh.getFacetType(type);
Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets");
MeshUtils::buildAllFacets(mesh, mesh_facets);
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull();
Array<Real> & position = mesh.getNodes();
- UInt nb_facet = mesh_facets.getNbElement(type_facet);
- UInt nb_element = mesh.getNbElement(type);
+ Int nb_facet = mesh_facets.getNbElement(type_facet);
+ Int nb_element = mesh.getNbElement(type);
/// compute quadrature points positions on facets
- typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange> MyFEEngineType;
+ using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
model.registerFEEngineObject<MyFEEngineType>("FacetsFEEngine", mesh_facets,
spatial_dimension - 1);
model.getFEEngine("FacetsFEEngine").initShapeFunctions();
- UInt nb_quad_per_facet =
+ Int nb_quad_per_facet =
model.getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
- UInt nb_tot_quad = nb_quad_per_facet * nb_facet;
+ Int nb_tot_quad = nb_quad_per_facet * nb_facet;
Array<Real> quad_facets(nb_tot_quad, spatial_dimension);
model.getFEEngine("FacetsFEEngine")
.interpolateOnIntegrationPoints(position, quad_facets, spatial_dimension,
type_facet);
auto && facet_to_element = mesh_facets.getSubelementToElement(type);
- UInt nb_facet_per_elem = facet_to_element.getNbComponent();
+ Int nb_facet_per_elem = facet_to_element.getNbComponent();
ElementTypeMapArray<Real> element_quad_facet;
element_quad_facet.alloc(nb_element * nb_facet_per_elem * nb_quad_per_facet,
spatial_dimension, type);
ElementTypeMapArray<Real> interpolated_stress("interpolated_stress", "");
interpolated_stress.initialize(
mesh, _nb_component = spatial_dimension * spatial_dimension,
_spatial_dimension = spatial_dimension);
Array<Real> & interp_stress = interpolated_stress(type);
interp_stress.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet);
Array<Real> & el_q_facet = element_quad_facet(type);
- for (UInt el = 0; el < nb_element; ++el) {
- for (UInt f = 0; f < nb_facet_per_elem; ++f) {
- UInt global_facet = facet_to_element(el, f).element;
+ for (Int el = 0; el < nb_element; ++el) {
+ for (Int f = 0; f < nb_facet_per_elem; ++f) {
+ Int global_facet = facet_to_element(el, f).element;
- for (UInt q = 0; q < nb_quad_per_facet; ++q) {
- for (UInt s = 0; s < spatial_dimension; ++s) {
+ for (Int q = 0; q < nb_quad_per_facet; ++q) {
+ for (Int s = 0; s < spatial_dimension; ++s) {
el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet +
f * nb_quad_per_facet + q,
s) = quad_facets(global_facet * nb_quad_per_facet + q, s);
}
}
}
}
/// compute quadrature points position of the elements
- UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type);
- UInt nb_tot_quad_el = nb_quad_per_element * nb_element;
+ Int nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type);
+ Int nb_tot_quad_el = nb_quad_per_element * nb_element;
Array<Real> quad_elements(nb_tot_quad_el, spatial_dimension);
model.getFEEngine().interpolateOnIntegrationPoints(position, quad_elements,
spatial_dimension, type);
/// assign some values to stresses
- Array<Real> & stress =
+ auto & stress =
const_cast<Array<Real> &>(model.getMaterial(0).getStress(type));
- for (UInt q = 0; q < nb_tot_quad_el; ++q) {
- for (UInt s = 0; s < spatial_dimension * spatial_dimension; ++s) {
+ for (Int q = 0; q < nb_tot_quad_el; ++q) {
+ for (Int s = 0; s < spatial_dimension * spatial_dimension; ++s) {
stress(q, s) = s * function(quad_elements(q, 0), quad_elements(q, 1),
quad_elements(q, 2));
}
}
/// interpolate stresses on facets' quadrature points
model.getMaterial(0).initElementalFieldInterpolation(element_quad_facet);
model.getMaterial(0).interpolateStress(interpolated_stress);
Real tolerance = 1.e-10;
/// check results
- for (UInt el = 0; el < nb_element; ++el) {
- for (UInt f = 0; f < nb_facet_per_elem; ++f) {
+ for (Int el = 0; el < nb_element; ++el) {
+ for (Int f = 0; f < nb_facet_per_elem; ++f) {
- for (UInt q = 0; q < nb_quad_per_facet; ++q) {
- for (UInt s = 0; s < spatial_dimension * spatial_dimension; ++s) {
+ for (Int q = 0; q < nb_quad_per_facet; ++q) {
+ for (Int s = 0; s < spatial_dimension * spatial_dimension; ++s) {
Real x = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet +
f * nb_quad_per_facet + q,
0);
Real y = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet +
f * nb_quad_per_facet + q,
1);
Real z = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet +
f * nb_quad_per_facet + q,
2);
Real theoretical = s * function(x, y, z);
Real numerical =
interp_stress(el * nb_facet_per_elem * nb_quad_per_facet +
f * nb_quad_per_facet + q,
s);
if (std::abs(theoretical - numerical) > tolerance) {
std::cout << "Theoretical and numerical values aren't coincident!"
<< std::endl;
return EXIT_FAILURE;
}
}
}
}
}
std::cout << "OK: Stress interpolation test passed." << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc
index 326728e2b..35ffc5976 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc
@@ -1,134 +1,134 @@
/**
* @file test_local_material.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Marion Estelle Chambart <marion.chambart@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Jun 05 2019
*
* @brief test of the class SolidMechanicsModel with custom local damage on a
* notched plate
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "local_material_damage.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
akantu::initialize("material.dat", argc, argv);
- UInt max_steps = 1100;
+ Int max_steps = 1100;
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("mesh_section_gap.msh");
/// model initialization
MaterialFactory::getInstance().registerAllocator(
"local_damage",
[](UInt, const ID &, SolidMechanicsModel & model,
const ID & id) -> std::unique_ptr<Material> {
return std::make_unique<LocalMaterialDamage>(model, id);
});
SolidMechanicsModel model(mesh);
model.initFull();
std::cout << model.getMaterial(0) << std::endl;
model.addDumpField("damage");
model.addDumpField("strain");
model.addDumpField("stress");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("external_force");
model.addDumpFieldVector("internal_force");
model.dump();
Real time_step = model.getStableTimeStep();
model.setTimeStep(time_step / 2.5);
/// Dirichlet boundary conditions
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed");
// model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed");
- Matrix<Real> stress(2, 2);
- stress.eye(5e7);
+ Matrix<Real> stress = Matrix<Real, 2, 2>::Identity() * 5e7;
model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction");
- for (UInt s = 0; s < max_steps; ++s)
+ for (Int s = 0; s < max_steps; ++s) {
model.solveStep();
+ }
model.dump();
// This should throw a bad_cast if not the proper material
auto & mat =
dynamic_cast<LocalMaterialDamage &>(model.getMaterial("concrete"));
const auto & filter = mat.getElementFilter();
- for (auto & type : filter.elementTypes(spatial_dimension)) {
+ for (const auto & type : filter.elementTypes(spatial_dimension)) {
std::cout << mat.getDamage(type) << std::endl;
}
// This part of the test is to mesh dependent and as nothing to do with the
// fact that we can create a user defined material or not
// const auto & lower_bounds = mesh.getLowerBounds();
// const auto & upper_bounds = mesh.getUpperBounds();
// Real L = upper_bounds(_x) - lower_bounds(_x);
// Real H = upper_bounds(_y) - lower_bounds(_y);
// const auto & filter = model.getMaterial("concrete").getElementFilter();
// Vector<Real> barycenter(spatial_dimension);
// for (auto & type : filter.elementTypes(spatial_dimension)) {
// UInt nb_elem = mesh.getNbElement(type);
// const UInt nb_gp = model.getFEEngine().getNbIntegrationPoints(type);
// const auto & material_damage_array =
// model.getMaterial(0).getArray<Real>("damage", type);
// UInt cpt = 0;
// for (auto nel : arange(nb_elem)) {
// mesh.getBarycenter({type, nel, _not_ghost}, barycenter);
// if ((std::abs(barycenter(_x) - (L / 2) + 0.025) < 0.025) &&
// (std::abs(barycenter(_y) - (H / 2) + 0.045) < 0.045)) {
// if (material_damage_array(cpt, 0) < 0.9) {
// std::terminate();
// } else {
// std::cout << "element " << nel << " is correctly broken" <<
// std::endl;
// }
// }
// cpt += nb_gp;
// }
// }
akantu::finalize();
return 0;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_elasto_plastic_linear_isotropic_hardening/test_material_elasto_plastic_linear_isotropic_hardening.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_elasto_plastic_linear_isotropic_hardening/test_material_elasto_plastic_linear_isotropic_hardening.cc
index e7e2e080e..82e9fa710 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_elasto_plastic_linear_isotropic_hardening/test_material_elasto_plastic_linear_isotropic_hardening.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_elasto_plastic_linear_isotropic_hardening/test_material_elasto_plastic_linear_isotropic_hardening.cc
@@ -1,93 +1,93 @@
/**
* @file test_material_elasto_plastic_linear_isotropic_hardening.cc
*
* @author Jaehyun Cho <jaehyun.cho@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue May 21 2019
*
* @brief test for material type elasto plastic linear isotropic hardening
* using tension-compression test
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("test_material_elasto_plastic_linear_isotropic_hardening.dat",
argc, argv);
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
const Real u_increment = 0.1;
- const UInt steps = 20;
+ const Int steps = 20;
Mesh mesh(spatial_dimension);
mesh.read("test_material_elasto_plastic_linear_isotropic_hardening.msh");
SolidMechanicsModel model(mesh);
model.initFull(_analysis_method = _static);
auto & solver = model.getNonLinearSolver("static");
solver.set("max_iterations", 300);
solver.set("threshold", 1e-5);
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "left");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "bottom");
std::cout.precision(4);
- for (UInt i = 0; i < steps; ++i) {
+ for (Int i = 0; i < steps; ++i) {
model.applyBC(BC::Dirichlet::FixedValue(i * u_increment, _x), "right");
try {
model.solveStep();
} catch (debug::NLSNotConvergedException & e) {
std::cout << e.niter << " " << e.error << std::endl;
throw;
}
Real strainxx = i * u_increment / 10.;
- const Array<UInt> & edge_nodes =
+ const auto & edge_nodes =
mesh.getElementGroup("right").getNodeGroup().getNodes();
- Array<Real> & residual = model.getInternalForce();
+ auto & residual = model.getInternalForce();
Real reaction = 0;
- for (UInt n = 0; n < edge_nodes.size(); n++) {
+ for (Int n = 0; n < edge_nodes.size(); n++) {
reaction -= residual(edge_nodes(n), 0);
}
std::cout << strainxx << "," << reaction << std::endl;
}
finalize();
return 0;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_fixtures.hh b/test/test_model/test_solid_mechanics_model/test_materials/test_material_fixtures.hh
index 462a9dc09..62e57edda 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_fixtures.hh
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_fixtures.hh
@@ -1,215 +1,211 @@
/**
* @file test_material_fixtures.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Nov 17 2017
* @date last modification: Fri Dec 13 2019
*
* @brief Fixture for material tests
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <material_elastic.hh>
#include <solid_mechanics_model.hh>
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <random>
#include <type_traits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
template <typename T> class FriendMaterial : public T {
public:
~FriendMaterial() = default;
FriendMaterial(SolidMechanicsModel & model, const ID & id = "material")
: T(model, id) {
gen.seed(::testing::GTEST_FLAG(random_seed));
}
virtual void testComputeStress() { AKANTU_TO_IMPLEMENT(); };
virtual void testComputeTangentModuli() { AKANTU_TO_IMPLEMENT(); };
virtual void testEnergyDensity() { AKANTU_TO_IMPLEMENT(); };
virtual void testCelerity() { AKANTU_TO_IMPLEMENT(); }
virtual void setParams() {}
virtual void SetUp() {
this->setParams();
this->initMaterial();
}
virtual void TearDown() {}
inline Matrix<Real> getDeviatoricStrain(Real intensity);
inline Matrix<Real> getHydrostaticStrain(Real intensity);
inline Matrix<Real> getComposedStrain(Real intensity);
- inline const Matrix<Real> reverseRotation(Matrix<Real> mat,
- Matrix<Real> rotation_matrix) {
- Matrix<Real> R = rotation_matrix;
- Matrix<Real> m2 = mat * R;
- Matrix<Real> m1 = R.transpose();
- return m1 * m2;
+ inline Matrix<Real> reverseRotation(const Matrix<Real> & A,
+ const Matrix<Real> & R) {
+ Matrix<Real> res = R.transpose() * A * R;
+ return res;
};
- inline const Matrix<Real> applyRotation(Matrix<Real> mat,
- const Matrix<Real> rotation_matrix) {
- Matrix<Real> R = rotation_matrix;
- Matrix<Real> m2 = mat * R.transpose();
- Matrix<Real> m1 = R;
- return m1 * m2;
+ inline Matrix<Real> applyRotation(const Matrix<Real> & A,
+ const Matrix<Real> & R) {
+ Matrix<Real> res = R * A * R.transpose();
+ return res;
};
inline Vector<Real> getRandomVector();
inline Matrix<Real> getRandomRotation();
protected:
std::mt19937 gen;
};
/* -------------------------------------------------------------------------- */
template <typename T>
Matrix<Real> FriendMaterial<T>::getDeviatoricStrain(Real intensity) {
- Matrix<Real> dev = {{0., 1., 2.}, {1., 0., 3.}, {2., 3., 0.}};
+ Matrix<Real> dev{{0., 1., 2.}, {1., 0., 3.}, {2., 3., 0.}};
dev *= intensity;
return dev;
}
/* -------------------------------------------------------------------------- */
template <typename T>
Matrix<Real> FriendMaterial<T>::getHydrostaticStrain(Real intensity) {
- Matrix<Real> dev = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+ Matrix<Real> dev{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
dev *= intensity;
return dev;
}
/* -------------------------------------------------------------------------- */
template <typename T>
Matrix<Real> FriendMaterial<T>::getComposedStrain(Real intensity) {
Matrix<Real> s = FriendMaterial<T>::getHydrostaticStrain(intensity) +
FriendMaterial<T>::getDeviatoricStrain(intensity);
s *= intensity;
return s;
}
/* -------------------------------------------------------------------------- */
template <typename T> Vector<Real> FriendMaterial<T>::getRandomVector() {
auto dim = this->spatial_dimension;
std::uniform_real_distribution<Real> dis;
- Vector<Real> vector(dim, 0.);
+ Vector<Real> vector(dim);
+ vector.zero();
while (vector.norm() < 1e-9) {
- for (auto s : arange(dim))
+ for (auto s : arange(dim)) {
vector(s) = dis(gen);
+ }
}
return vector;
}
/* -------------------------------------------------------------------------- */
template <typename T> Matrix<Real> FriendMaterial<T>::getRandomRotation() {
- auto dim = this->spatial_dimension;
+ const auto dim = this->spatial_dimension;
Matrix<Real> rotation(dim, dim);
- Vector<Real> v1 = rotation(0);
- v1 = getRandomVector().normalize();
+ auto && v1_ = rotation(0);
+ v1_ = getRandomVector().normalized();
if (dim == 2) {
- Vector<Real> v1_ = {v1(0), v1(1), 0};
- Vector<Real> v2_(3);
- Vector<Real> v3_ = {0, 0, 1};
- v2_.crossProduct(v3_, v1_);
-
- Vector<Real> v2 = rotation(1);
- v2(0) = v2_(0);
- v2(1) = v2_(1);
+ Vector<Real, 3> v1{v1_(0), v1_(1), 0};
+ Vector<Real, 3> v3{0, 0, 1};
+
+ Vector<Real, 3> v2 = v3.cross(v1);
+
+ rotation(1) = v2.block<2, 1>(0, 0);
}
if (dim == 3) {
- auto v2 = getRandomVector();
- v2 = (v2 - v2.dot(v1) * v1).normalize();
+ Vector<Real, 3> v2 = getRandomVector();
+ Vector<Real, 3> v1 = v1_;
+ v2 = (v2 - v2.dot(v1) * v1).normalized();
- Vector<Real> v3(3);
- v3.crossProduct(v1, v2);
+ Vector<Real, 3> v3 = v1.cross(v2);
rotation(1) = v2;
rotation(2) = v3;
}
//#define debug_
#if defined(debug_)
if (dim == 2)
- rotation = Matrix<Real>{{1., 0.}, {0., 1.}};
+ rotation = Matrix<Rea, 2, 2>{{1., 0.}, {0., 1.}};
if (dim == 3)
- rotation = Matrix<Real>{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}};
+ rotation = Matrix<Real, 3, 3>{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}};
#endif
- rotation = rotation.transpose();
+ rotation.transposeInPlace();
return rotation;
}
/* -------------------------------------------------------------------------- */
template <typename T, class Model>
class TestMaterialBaseFixture : public ::testing::Test {
public:
using mat_class = typename T::mat_class;
void SetUp() override {
constexpr auto spatial_dimension = T::Dim;
mesh = std::make_unique<Mesh>(spatial_dimension);
model = std::make_unique<Model>(*mesh);
material = std::make_unique<friend_class>(*model);
material->SetUp();
}
void TearDown() override {
material->TearDown();
material.reset(nullptr);
model.reset(nullptr);
mesh.reset(nullptr);
}
using friend_class = FriendMaterial<mat_class>;
protected:
std::unique_ptr<Mesh> mesh;
std::unique_ptr<Model> model;
std::unique_ptr<friend_class> material;
};
/* -------------------------------------------------------------------------- */
-template <template <UInt> class T, UInt _Dim> struct Traits {
+template <template <Int> class T, Int _Dim> struct Traits {
using mat_class = T<_Dim>;
- static constexpr UInt Dim = _Dim;
+ static constexpr Int Dim = _Dim;
};
/* -------------------------------------------------------------------------- */
template <typename T>
using TestMaterialFixture = TestMaterialBaseFixture<T, SolidMechanicsModel>;
/* -------------------------------------------------------------------------- */
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc
index 455b811db..caa3a6424 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc
@@ -1,290 +1,290 @@
/**
* @file test_material_mazars.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
*
* @date creation: Thu Oct 08 2015
* @date last modification: Wed Jun 05 2019
*
* @brief test for material mazars, dissymmetric
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_accessor.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
debug::setDebugLevel(akantu::dblWarning);
akantu::initialize("material_mazars.dat", argc, argv);
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
// ElementType type = _quadrangle_4;
ElementType type = _hexahedron_8;
Mesh mesh(spatial_dimension);
MeshAccessor mesh_accessor(mesh);
Array<Real> & nodes = mesh_accessor.getNodes();
Array<UInt> & connectivity = mesh_accessor.getConnectivity(type);
const Real width = 1;
UInt nb_dof = 0;
connectivity.resize(1);
if (type == _hexahedron_8) {
nb_dof = 8;
nodes.resize(nb_dof);
nodes(0, 0) = 0.;
nodes(0, 1) = 0.;
nodes(0, 2) = 0.;
nodes(1, 0) = width;
nodes(1, 1) = 0.;
nodes(1, 2) = 0.;
nodes(2, 0) = width;
nodes(2, 1) = width;
nodes(2, 2) = 0;
nodes(3, 0) = 0;
nodes(3, 1) = width;
nodes(3, 2) = 0;
nodes(4, 0) = 0.;
nodes(4, 1) = 0.;
nodes(4, 2) = width;
nodes(5, 0) = width;
nodes(5, 1) = 0.;
nodes(5, 2) = width;
nodes(6, 0) = width;
nodes(6, 1) = width;
nodes(6, 2) = width;
nodes(7, 0) = 0;
nodes(7, 1) = width;
nodes(7, 2) = width;
connectivity(0, 0) = 0;
connectivity(0, 1) = 1;
connectivity(0, 2) = 2;
connectivity(0, 3) = 3;
connectivity(0, 4) = 4;
connectivity(0, 5) = 5;
connectivity(0, 6) = 6;
connectivity(0, 7) = 7;
} else if (type == _quadrangle_4) {
nb_dof = 4;
nodes.resize(nb_dof);
nodes(0, 0) = 0.;
nodes(0, 1) = 0.;
nodes(1, 0) = width;
nodes(1, 1) = 0;
nodes(2, 0) = width;
nodes(2, 1) = width;
nodes(3, 0) = 0.;
nodes(3, 1) = width;
connectivity(0, 0) = 0;
connectivity(0, 1) = 1;
connectivity(0, 2) = 2;
connectivity(0, 3) = 3;
}
mesh_accessor.makeReady();
SolidMechanicsModel model(mesh);
model.initFull();
Material & mat = model.getMaterial(0);
std::cout << mat << std::endl;
/// boundary conditions
Array<Real> & disp = model.getDisplacement();
Array<Real> & velo = model.getVelocity();
Array<bool> & boun = model.getBlockedDOFs();
- for (UInt i = 0; i < nb_dof; ++i) {
+ for (Int i = 0; i < nb_dof; ++i) {
boun(i, 0) = true;
}
Real time_step = model.getStableTimeStep() * .5;
// Real time_step = 1e-5;
std::cout << "Time Step = " << time_step
<< "s - nb elements : " << mesh.getNbElement(type) << std::endl;
model.setTimeStep(time_step);
std::ofstream energy;
energy.open("energies_and_scalar_mazars.csv");
energy << "id,rtime,epot,ekin,u,wext,kin+pot,D,strain_xx,strain_yy,stress_xx,"
"stress_yy,edis,tot"
<< std::endl;
/// Set dumper
model.setBaseName("uniaxial_comp-trac_mazars");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("damage");
model.addDumpField("strain");
model.addDumpField("stress");
model.addDumpField("partitions");
model.dump();
const Array<Real> & strain = mat.getGradU(type);
const Array<Real> & stress = mat.getStress(type);
const Array<Real> & damage = mat.getArray<Real>("damage", type);
/* ------------------------------------------------------------------------ */
/* Main loop */
/* ------------------------------------------------------------------------ */
Real wext = 0.;
Real sigma_max = 0, sigma_min = 0;
Real max_disp;
Real stress_xx_compression_1;
UInt nb_steps = 7e5 / 150;
Real adisp = 0;
- for (UInt s = 0; s < nb_steps; ++s) {
+ for (Int s = 0; s < nb_steps; ++s) {
if (s == 0) {
max_disp = 0.003;
adisp = -(max_disp * 8. / nb_steps) / 2.;
std::cout << "Step " << s << " compression: " << max_disp << std::endl;
}
if (s == (2 * nb_steps / 8)) {
stress_xx_compression_1 = stress(0, 0);
max_disp = 0 + max_disp;
adisp = max_disp * 8. / nb_steps;
std::cout << "Step " << s << " discharge" << std::endl;
}
if (s == (3 * nb_steps / 8)) {
max_disp = 0.004;
adisp = -max_disp * 8. / nb_steps;
std::cout << "Step " << s << " compression: " << max_disp << std::endl;
}
if (s == (4 * nb_steps / 8)) {
if (stress(0, 0) < stress_xx_compression_1) {
std::cout << "after this second compression step softening should have "
"started"
<< std::endl;
return EXIT_FAILURE;
}
max_disp = 0.0015 + max_disp;
adisp = max_disp * 8. / nb_steps;
std::cout << "Step " << s << " discharge tension: " << max_disp
<< std::endl;
}
if (s == (5 * nb_steps / 8)) {
max_disp = 0. + 0.0005;
adisp = -max_disp * 8. / nb_steps;
std::cout << "Step " << s << " discharge" << std::endl;
}
if (s == (6 * nb_steps / 8)) {
max_disp = 0.0035 - 0.001;
adisp = max_disp * 8. / nb_steps;
std::cout << "Step " << s << " tension: " << max_disp << std::endl;
}
if (s == (7 * nb_steps / 8)) {
// max_disp = max_disp;
adisp = -max_disp * 8. / nb_steps;
std::cout << "Step " << s << " discharge" << std::endl;
}
- for (UInt i = 0; i < nb_dof; ++i) {
+ for (Int i = 0; i < nb_dof; ++i) {
if (std::abs(nodes(i, 0) - width) <
std::numeric_limits<Real>::epsilon()) {
disp(i, 0) += adisp;
velo(i, 0) = adisp / time_step;
}
}
std::cout << "S: " << s << "/" << nb_steps << " inc disp: " << adisp
<< " disp: " << std::setw(5) << disp(2, 0) << "\r" << std::flush;
model.solveStep();
Real epot = model.getEnergy("potential");
Real ekin = model.getEnergy("kinetic");
Real edis = model.getEnergy("dissipated");
wext += model.getEnergy("external work");
sigma_max = std::max(sigma_max, stress(0, 0));
sigma_min = std::min(sigma_min, stress(0, 0));
if (s % 10 == 0)
energy << s << "," // 1
<< s * time_step << "," // 2
<< epot << "," // 3
<< ekin << "," // 4
<< disp(2, 0) << "," // 5
<< wext << "," // 6
<< epot + ekin << "," // 7
<< damage(0) << "," // 8
<< strain(0, 0) << "," // 9
<< strain(0, 3) << "," // 11
<< stress(0, 0) << "," // 10
<< stress(0, 3) << "," // 10
<< edis << "," // 12
<< epot + ekin + edis // 13
<< std::endl;
if (s % 100 == 0)
model.dump();
}
std::cout << std::endl
<< "sigma_max = " << sigma_max << ", sigma_min = " << sigma_min
<< std::endl;
/// Verif the maximal/minimal stress values
if ((std::abs(sigma_max) > std::abs(sigma_min)) or
(std::abs(sigma_max - 6.24e6) > 1e5) or
(std::abs(sigma_min + 2.943e7) > 1e6))
return EXIT_FAILURE;
energy.close();
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc
index 0bcff4bf8..fbbe83f5e 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc
@@ -1,96 +1,101 @@
/**
* @file custom_non_local_test_material.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Mar 01 2015
* @date last modification: Mon Sep 11 2017
*
* @brief Custom material to test the non local implementation
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "custom_non_local_test_material.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
CustomNonLocalTestMaterial<dim>::CustomNonLocalTestMaterial(
SolidMechanicsModel & model, const ID & id)
: MyNonLocalParent(model, id), local_damage("local_damage", *this),
damage("damage", *this) {
// Initialize the internal field by specifying the number of components
this->local_damage.initialize(1);
this->damage.initialize(1);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void CustomNonLocalTestMaterial<dim>::registerNonLocalVariables() {
/// register the non-local variable in the manager
this->model.getNonLocalManager().registerNonLocalVariable(
this->local_damage.getName(), this->damage.getName(), 1);
this->model.getNonLocalManager()
.getNeighborhood(this->name)
.registerNonLocalVariable(damage.getName());
}
/* -------------------------------------------------------------------------- */
-template <UInt dim> void CustomNonLocalTestMaterial<dim>::initMaterial() {
+template <Int dim> void CustomNonLocalTestMaterial<dim>::initMaterial() {
MyNonLocalParent::initMaterial();
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void CustomNonLocalTestMaterial<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
MyNonLocalParent::computeStress(el_type, ghost_type);
}
/* -------------------------------------------------------------------------- */
-template <UInt dim>
+template <Int dim>
void CustomNonLocalTestMaterial<dim>::computeNonLocalStress(
ElementType el_type, GhostType ghost_type) {
Array<Real>::const_scalar_iterator dam =
this->damage(el_type, ghost_type).begin();
Array<Real>::matrix_iterator stress =
this->stress(el_type, ghost_type).begin(dim, dim);
Array<Real>::matrix_iterator stress_end =
this->stress(el_type, ghost_type).end(dim, dim);
// compute the damage and update the stresses
for (; stress != stress_end; ++stress, ++dam) {
*stress *= (1. - *dam);
}
}
/* -------------------------------------------------------------------------- */
// Instantiate the material for the 3 dimensions
-INSTANTIATE_MATERIAL(custom_non_local_test_material,
- CustomNonLocalTestMaterial);
+template class CustomNonLocalTestMaterial<1>;
+template class CustomNonLocalTestMaterial<2>;
+template class CustomNonLocalTestMaterial<3>;
+
+static bool material_is_allocated_custom_non_local_test_material =
+ instantiateMaterial<CustomNonLocalTestMaterial>(
+ "custom_non_local_test_material");
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.hh b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.hh
index 83c24ef76..0fd2622a3 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.hh
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.hh
@@ -1,81 +1,82 @@
/**
* @file custom_non_local_test_material.hh
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Jun 26 2020
*
* @brief Custom material to test the non local implementation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_elastic.hh"
#include "material_non_local.hh"
/* -------------------------------------------------------------------------- */
#ifndef CUSTOM_NON_LOCAL_TEST_MATERIAL_HH_
#define CUSTOM_NON_LOCAL_TEST_MATERIAL_HH_
namespace akantu {
-template <UInt dim>
+template <Int dim>
class CustomNonLocalTestMaterial
: public MaterialNonLocal<dim, MaterialElastic<dim>> {
public:
using MyNonLocalParent = MaterialNonLocal<dim, MaterialElastic<dim>>;
CustomNonLocalTestMaterial(SolidMechanicsModel & model, const ID & id);
/* ------------------------------------------------------------------------ */
void initMaterial() override;
void computeNonLocalStress(ElementType el_type, GhostType ghost_type);
void computeStress(ElementType el_type, GhostType ghost_type) override;
protected:
void registerNonLocalVariables() override;
/* ------------------------------------------------------------------------ */
void computeNonLocalStresses(GhostType ghost_type) override {
AKANTU_DEBUG_IN();
- for (auto & type : this->element_filter.elementTypes(dim, ghost_type)) {
+ for (const auto & type :
+ this->element_filter.elementTypes(dim, ghost_type)) {
computeNonLocalStress(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
public:
void setDamage(Real dam) { this->local_damage.setDefaultValue(dam); }
protected:
InternalField<Real> local_damage;
InternalField<Real> damage;
};
} // namespace akantu
#endif /* CUSTOM_NON_LOCAL_TEST_MATERIAL_HH_ */
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc
index 3bc68d7f8..a8176f921 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc
@@ -1,117 +1,116 @@
/**
* @file test_material_damage_non_local.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Clement Roux <clement.roux@epfl.ch>
*
* @date creation: Wed Aug 04 2010
* @date last modification: Thu Dec 14 2017
*
* @brief test for non-local damage materials on a 2D plate with a section gap
* the sample should break at the notch
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
debug::setDebugLevel(dblWarning);
akantu::initialize("material_damage_non_local.dat", argc, argv);
- UInt max_steps = 1100;
+ Int max_steps = 1100;
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("mesh_section_gap.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull();
Real time_step = model.getStableTimeStep();
model.setTimeStep(time_step / 2.5);
std::cout << model << std::endl;
model.applyBC(BC::Dirichlet::FixedValue(0.0), "Fixed");
// Boundary condition (Neumann)
- Matrix<Real> stress(2, 2);
- stress.eye(5e8);
+ Matrix<Real, 2, 2> stress = Matrix<Real, 2, 2>::Identity() * 5e8;
model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction");
model.setBaseName("damage_non_local");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpFieldVector("external_force");
model.addDumpFieldVector("internal_force");
model.addDumpField("damage");
model.addDumpField("stress");
model.addDumpField("strain");
model.dump();
- for (UInt s = 0; s < max_steps; ++s) {
+ for (Int s = 0; s < max_steps; ++s) {
model.solveStep();
// if(s % 100 == 0) std::cout << "Step " << s+1 << "/" << max_steps
// <<std::endl; if(s % 100 == 0) model.dump();
}
model.dump();
const auto & lower_bounds = mesh.getLowerBounds();
const auto & upper_bounds = mesh.getUpperBounds();
Real L = upper_bounds(0) - lower_bounds(0);
Real H = upper_bounds(1) - lower_bounds(1);
const auto & mat = model.getMaterial(0);
const auto & filter = mat.getElementFilter();
Vector<Real> barycenter(spatial_dimension);
- for (auto & type : filter.elementTypes(spatial_dimension)) {
- UInt nb_elem = mesh.getNbElement(type);
- const UInt nb_gp = model.getFEEngine().getNbIntegrationPoints(type);
+ for (const auto & type : filter.elementTypes(spatial_dimension)) {
+ auto nb_elem = mesh.getNbElement(type);
+ const auto nb_gp = model.getFEEngine().getNbIntegrationPoints(type);
auto & material_damage_array = mat.getArray<Real>("damage", type);
- UInt cpt = 0;
- for (UInt nel = 0; nel < nb_elem; ++nel) {
+ Int cpt = 0;
+ for (Int nel = 0; nel < nb_elem; ++nel) {
mesh.getBarycenter({type, nel, _not_ghost}, barycenter);
if ((std::abs(barycenter(0) - (L / 2) + 0.025) < 0.025) &&
(std::abs(barycenter(1) - (H / 2) + 0.025) < 0.025)) {
if (material_damage_array(cpt, 0) < 0.9) {
std::terminate();
}
}
cpt += nb_gp;
}
}
return 0;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc
index 34ea1a015..84404d090 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc
@@ -1,104 +1,104 @@
/**
* @file test_material_non_local.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Aug 31 2011
* @date last modification: Thu Mar 22 2018
*
* @brief test of the main part of the non local materials
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "custom_non_local_test_material.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material.dat", argc, argv);
// some configuration variables
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
// mesh creation and read
if (prank == 0) {
mesh.read("mesh.msh");
}
mesh.distribute();
/// model creation
SolidMechanicsModel model(mesh);
/// model initialization changed to use our material
model.initFull();
CustomNonLocalTestMaterial<spatial_dimension> & mat =
dynamic_cast<CustomNonLocalTestMaterial<spatial_dimension> &>(
model.getMaterial("test"));
if (prank == 0)
std::cout << mat << std::endl;
// Setting up the dumpers + first dump
model.setBaseName("non_local_material");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("external_force");
model.addDumpFieldVector("internal_force");
model.addDumpField("partitions");
model.addDumpField("stress");
model.addDumpField("stress");
model.addDumpField("local_damage");
model.addDumpField("damage");
model.assembleInternalForces();
model.dump();
// Array<Real> & damage = mat.getArray("local_damage", _quadrangle_4);
Array<Real> & damage = mat.getArray<Real>("local_damage", _triangle_3);
RandomGenerator<UInt> gen;
- for (UInt i = 0; i < 1; ++i) {
+ for (Int i = 0; i < 1; ++i) {
UInt g = (gen() / Real(RandomGenerator<UInt>::max() -
RandomGenerator<UInt>::min())) *
damage.size();
std::cout << prank << " -> " << g << std::endl;
damage(g) = 1.;
}
model.assembleInternalForces();
model.dump();
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc
index 6c0d747da..6ebab4b59 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc
@@ -1,101 +1,102 @@
/**
* @file test_material_orthotropic.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu May 09 2019
*
* @brief test of the class SolidMechanicsModel
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
// akantu::initialize("orthotropic.dat", argc, argv);
akantu::initialize("orthotropic.dat", argc, argv);
- UInt max_steps = 1000;
+ Int max_steps = 1000;
Real epot, ekin;
Mesh mesh(2);
mesh.read("square.msh");
mesh.createBoundaryGroupFromGeometry();
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull();
Real time_step = model.getStableTimeStep();
model.setTimeStep(time_step / 10.);
model.assembleMassLumped();
std::cout << model << std::endl;
// Boundary condition (Neumann)
- Matrix<Real> stress(2, 2);
- stress.eye(Real(1e3));
+ Matrix<Real> stress = Matrix<Real, 2, 2>::Identity() * 1e3;
+
model.applyBC(BC::Neumann::FromHigherDim(stress), "boundary_0");
model.setBaseName("square-orthotrope");
model.addDumpFieldVector("displacement");
model.addDumpField("mass");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpFieldVector("external_force");
model.addDumpFieldVector("internal_force");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.dump();
std::ofstream energy;
energy.open("energy.csv");
energy << "id,epot,ekin,tot" << std::endl;
- for (UInt s = 0; s < max_steps; ++s) {
+ for (Int s = 0; s < max_steps; ++s) {
model.solveStep();
epot = model.getEnergy("potential");
ekin = model.getEnergy("kinetic");
std::cerr << "passing step " << s << "/" << max_steps << std::endl;
energy << s << "," << epot << "," << ekin << "," << epot + ekin
<< std::endl;
- if (s % 100 == 0)
+ if (s % 100 == 0) {
model.dump();
+ }
}
energy.close();
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc
index 8dfe2b79a..476c58d6e 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc
@@ -1,106 +1,109 @@
/**
* @file test_material_thermal.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Nov 18 2020
*
* @brief Test the thermal material
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_thermal.hh"
#include "solid_mechanics_model.hh"
#include "test_material_fixtures.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <type_traits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
using mat_types =
::testing::Types<Traits<MaterialThermal, 1>, Traits<MaterialThermal, 2>,
Traits<MaterialThermal, 3>>;
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialThermal<3>>::testComputeStress() {
Real E = 1.;
Real nu = .3;
Real alpha = 2;
setParam("E", E);
setParam("nu", nu);
setParam("alpha", alpha);
Real deltaT = 1;
Real sigma = 0;
- this->computeStressOnQuad(sigma, deltaT);
+ this->computeStressOnQuad(
+ make_named_tuple("sigma_th"_n = sigma, "delta_T"_n = deltaT));
Real solution = -E / (1 - 2 * nu) * alpha * deltaT;
auto error = std::abs(sigma - solution);
ASSERT_NEAR(error, 0, 1e-14);
}
template <> void FriendMaterial<MaterialThermal<2>>::testComputeStress() {
Real E = 1.;
Real nu = .3;
Real alpha = 2;
setParam("E", E);
setParam("nu", nu);
setParam("alpha", alpha);
Real deltaT = 1;
Real sigma = 0;
- this->computeStressOnQuad(sigma, deltaT);
+ this->computeStressOnQuad(
+ make_named_tuple("sigma_th"_n = sigma, "delta_T"_n = deltaT));
Real solution = -E / (1 - 2 * nu) * alpha * deltaT;
auto error = std::abs(sigma - solution);
ASSERT_NEAR(error, 0, 1e-14);
}
template <> void FriendMaterial<MaterialThermal<1>>::testComputeStress() {
Real E = 1.;
Real nu = .3;
Real alpha = 2;
setParam("E", E);
setParam("nu", nu);
setParam("alpha", alpha);
Real deltaT = 1;
Real sigma = 0;
- this->computeStressOnQuad(sigma, deltaT);
+ this->computeStressOnQuad(
+ make_named_tuple("sigma_th"_n = sigma, "delta_T"_n = deltaT));
Real solution = -E * alpha * deltaT;
auto error = std::abs(sigma - solution);
ASSERT_NEAR(error, 0, 1e-14);
}
namespace {
template <typename T>
class TestMaterialThermalFixture : public ::TestMaterialFixture<T> {};
TYPED_TEST_SUITE(TestMaterialThermalFixture, mat_types, );
TYPED_TEST(TestMaterialThermalFixture, ThermalComputeStress) {
this->material->testComputeStress();
}
} // namespace
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc
index 2cd8a5e0e..9ffd1cbf6 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc
@@ -1,171 +1,169 @@
/**
* @file test_material_standard_linear_solid_deviatoric_relaxation.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Vladislav Yastrebov <vladislav.yastrebov@epfl.ch>
*
* @date creation: Mon Aug 09 2010
* @date last modification: Sat Dec 19 2020
*
* @brief test of the viscoelastic material: relaxation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
akantu::initialize("material_standard_linear_solid_deviatoric_relaxation.dat",
argc, argv);
akantu::debug::setDebugLevel(akantu::dblWarning);
// sim data
Real T = 10.;
Real eps = 0.001;
- const UInt dim = 2;
+ const Int dim = 2;
Real sim_time = 25.;
Real time_factor = 0.1;
Real tolerance = 1e-7;
Mesh mesh(dim);
mesh.read("test_material_standard_linear_solid_deviatoric_relaxation.msh");
const ElementType element_type = _quadrangle_4;
SolidMechanicsModel model(mesh);
/* ------------------------------------------------------------------------ */
/* Initialization */
/* ------------------------------------------------------------------------ */
model.initFull();
std::cout << model.getMaterial(0) << std::endl;
model.assembleMassLumped();
std::stringstream filename_sstr;
filename_sstr
<< "test_material_standard_linear_solid_deviatoric_relaxation.out";
std::ofstream output_data;
output_data.open(filename_sstr.str().c_str());
output_data << "#[1]-time [2]-sigma_analytic [3+]-sigma_measurements"
<< std::endl;
Material & mat = model.getMaterial(0);
- const Array<Real> & stress = mat.getStress(element_type);
+ const Array<Real> & stresses = mat.getStress(element_type);
Real Eta = mat.get("Eta");
Real EV = mat.get("Ev");
Real Einf = mat.get("Einf");
Real nu = mat.get("nu");
Real Ginf = Einf / (2 * (1 + nu));
Real G = EV / (2 * (1 + nu));
Real G0 = G + Ginf;
Real gamma = G / G0;
Real tau = Eta / EV;
Real gammainf = Ginf / G0;
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
const Array<Real> & coordinate = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
/// Setting time step
Real time_step = model.getStableTimeStep() * time_factor;
std::cout << "Time Step = " << time_step << "s" << std::endl;
model.setTimeStep(time_step);
- UInt max_steps = sim_time / time_step;
- UInt out_interval = 1;
+ Int max_steps = sim_time / time_step;
+ Int out_interval = 1;
Real time = 0.;
/* ------------------------------------------------------------------------ */
/* Main loop */
/* ------------------------------------------------------------------------ */
- for (UInt s = 0; s <= max_steps; ++s) {
+ for (Int s = 0; s <= max_steps; ++s) {
if (s % 1000 == 0)
std::cerr << "passing step " << s << "/" << max_steps << std::endl;
time = s * time_step;
// impose displacement
Real epsilon = 0.;
if (time < T) {
epsilon = eps * time / T;
} else {
epsilon = eps;
}
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
displacement(n, 0) = epsilon * coordinate(n, 1);
displacement(n, 1) = epsilon * coordinate(n, 0);
}
// compute stress
model.assembleInternalForces();
// print output
if (s % out_interval == 0) {
// analytical solution
Real solution = 0.;
if (time < T) {
solution = 2 * G0 * eps / T *
(gammainf * time + gamma * tau * (1 - exp(-time / tau)));
} else {
solution = 2 * G0 * eps *
(gammainf + gamma * tau / T *
(exp((T - time) / tau) - exp(-time / tau)));
}
output_data << s * time_step << " " << solution;
// data output
- Array<Real>::const_matrix_iterator stress_it = stress.begin(dim, dim);
- Array<Real>::const_matrix_iterator stress_end = stress.end(dim, dim);
- for (; stress_it != stress_end; ++stress_it) {
- output_data << " " << (*stress_it)(0, 1) << " " << (*stress_it)(1, 0);
+ for (auto && stress : make_view(stresses, dim, dim)) {
+ output_data << " " << stress(0, 1) << " " << stress(1, 0);
// test error
- Real rel_error_1 = std::abs(((*stress_it)(0, 1) - solution) / solution);
- Real rel_error_2 = std::abs(((*stress_it)(1, 0) - solution) / solution);
+ Real rel_error_1 = std::abs((stress(0, 1) - solution) / solution);
+ Real rel_error_2 = std::abs((stress(1, 0) - solution) / solution);
if (rel_error_1 > tolerance || rel_error_2 > tolerance) {
std::cerr << "Relative error: " << rel_error_1 << " " << rel_error_2
<< std::endl;
return EXIT_FAILURE;
}
}
output_data << std::endl;
}
}
finalize();
std::cout << "Test successful!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc
index fad4b3cc7..83b275398 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc
@@ -1,181 +1,181 @@
/**
* @file test_material_standard_linear_solid_deviatoric_relaxation_tension.cc
*
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Mon Aug 09 2010
* @date last modification: Sat Dec 19 2020
*
* @brief test of the viscoelastic material: relaxation
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
akantu::initialize("material_standard_linear_solid_deviatoric_relaxation.dat",
argc, argv);
// sim data
Real T = 10.;
Real eps = 0.001;
- // const UInt dim = 3;
- const UInt dim = 2;
+ // const Int dim = 3;
+ const Int dim = 2;
Real sim_time = 25.;
// Real sim_time = 250.;
Real time_factor = 0.1;
Real tolerance = 1e-5;
Mesh mesh(dim);
mesh.read("test_material_standard_linear_solid_deviatoric_relaxation.msh");
// mesh_io.read("hexa_structured.msh",mesh);
// const ElementType element_type = _hexahedron_8;
const ElementType element_type = _quadrangle_4;
SolidMechanicsModel model(mesh);
/* ------------------------------------------------------------------------ */
/* Initialization */
/* ------------------------------------------------------------------------ */
model.initFull();
std::cout << model.getMaterial(0) << std::endl;
model.assembleMassLumped();
model.assembleInternalForces();
model.getMaterial(0).setToSteadyState();
std::stringstream filename_sstr;
filename_sstr << "test_material_standard_linear_solid_deviatoric_relaxation_"
"tension.out";
std::ofstream output_data;
output_data.open(filename_sstr.str().c_str());
output_data << "#[1]-time [2]-sigma_analytic [3+]-sigma_measurements"
<< std::endl;
Material & mat = model.getMaterial(0);
const Array<Real> & stress = mat.getStress(element_type);
Real Eta = mat.get("Eta");
Real EV = mat.get("Ev");
Real Einf = mat.get("Einf");
Real E0 = mat.get("E");
Real kpa = mat.get("kapa");
Real mu = mat.get("mu");
Real gamma = EV / E0;
Real gammainf = Einf / E0;
Real tau = Eta / EV;
std::cout << "relaxation time = " << tau << std::endl;
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
const Array<Real> & coordinate = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
/// Setting time step
Real time_step = model.getStableTimeStep() * time_factor;
std::cout << "Time Step = " << time_step << "s" << std::endl;
model.setTimeStep(time_step);
- UInt max_steps = sim_time / time_step;
- UInt out_interval = 1;
+ Int max_steps = sim_time / time_step;
+ Int out_interval = 1;
Real time = 0.;
/* ------------------------------------------------------------------------ */
/* Main loop */
/* ------------------------------------------------------------------------ */
- for (UInt s = 0; s <= max_steps; ++s) {
+ for (Int s = 0; s <= max_steps; ++s) {
if (s % 1000 == 0)
std::cerr << "passing step " << s << "/" << max_steps << std::endl;
time = s * time_step;
// impose displacement
Real epsilon = 0.;
if (time < T) {
epsilon = eps * time / T;
} else {
epsilon = eps;
}
- for (UInt n = 0; n < nb_nodes; ++n) {
- for (UInt d = 0; d < dim; ++d)
+ for (Int n = 0; n < nb_nodes; ++n) {
+ for (Int d = 0; d < dim; ++d)
displacement(n, d) = epsilon * coordinate(n, d);
}
// compute stress
model.assembleInternalForces();
// print output
if (s % out_interval == 0) {
// analytical solution
Real epskk = dim * eps;
Real solution = 0.;
if (time < T) {
solution =
2 * mu * (eps - epskk / 3.) / T *
(gammainf * time + gamma * tau * (1 - exp(-time / tau))) +
gammainf * kpa * epskk * time / T;
} else {
solution =
2 * mu * (eps - epskk / 3.) *
(gammainf +
gamma * tau / T * (exp((T - time) / tau) - exp(-time / tau))) +
gammainf * kpa * epskk;
}
output_data << s * time_step << " " << solution;
// data output
Array<Real>::const_matrix_iterator stress_it = stress.begin(dim, dim);
Array<Real>::const_matrix_iterator stress_end = stress.end(dim, dim);
for (; stress_it != stress_end; ++stress_it) {
output_data << " " << (*stress_it)(1, 1);
// test error
Real rel_error_1 = std::abs(((*stress_it)(1, 1) - solution) / solution);
if (rel_error_1 > tolerance) {
std::cerr << "Relative error: " << rel_error_1 << std::endl;
return EXIT_FAILURE;
}
}
output_data << std::endl;
}
}
finalize();
std::cout << "Test successful!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic_maxwell/test_material_viscoelastic_maxwell_relaxation.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic_maxwell/test_material_viscoelastic_maxwell_relaxation.cc
index 692c80fa3..9e019e6cf 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic_maxwell/test_material_viscoelastic_maxwell_relaxation.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic_maxwell/test_material_viscoelastic_maxwell_relaxation.cc
@@ -1,196 +1,196 @@
/**
* @file test_material_viscoelastic_maxwell_relaxation.cc
*
* @author Emil Gallyamov <emil.gallyamov@epfl.ch>
*
* @date creation: Tue Nov 20 2018
* @date last modification: Sun Dec 30 2018
*
* @brief test of the viscoelastic material: relaxation
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
/* -------------------------------------------------------------------------- */
#include "material_viscoelastic_maxwell.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "sparse_matrix.hh"
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize("material_viscoelastic_maxwell.dat", argc, argv);
// sim data
Real eps = 0.1;
- const UInt dim = 2;
+ const Int dim = 2;
Real sim_time = 100.;
Real T = 10.;
Real tolerance = 1e-6;
Mesh mesh(dim);
mesh.read("test_material_viscoelastic_maxwell.msh");
const ElementType element_type = _quadrangle_4;
SolidMechanicsModel model(mesh);
/* ------------------------------------------------------------------------ */
/* Initialization */
/* ------------------------------------------------------------------------ */
model.initFull(_analysis_method = _static);
std::cout << model.getMaterial(0) << std::endl;
std::stringstream filename_sstr;
filename_sstr << "test_material_viscoelastic_maxwell.out";
std::ofstream output_data;
output_data.open(filename_sstr.str().c_str());
Material & mat = model.getMaterial(0);
const Array<Real> & stress = mat.getStress(element_type);
Vector<Real> Eta = mat.get("Eta");
Vector<Real> Ev = mat.get("Ev");
Real Einf = mat.get("Einf");
Real nu = mat.get("nu");
Real lambda = Eta(0) / Ev(0);
Real pre_mult = 1 / (1 + nu) / (1 - 2 * nu);
Real time_step = 0.1;
UInt nb_nodes = mesh.getNbNodes();
const Array<Real> & coordinate = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
Array<bool> & blocked = model.getBlockedDOFs();
/// Setting time step
model.setTimeStep(time_step);
UInt max_steps = sim_time / time_step + 1;
Real time = 0.;
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 200);
solver.set("threshold", 1e-7);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
/* ------------------------------------------------------------------------ */
/* Main loop */
/* ------------------------------------------------------------------------ */
- for (UInt s = 0; s <= max_steps; ++s) {
+ for (Int s = 0; s <= max_steps; ++s) {
std::cout << "Time Step = " << time_step << "s" << std::endl;
std::cout << "Time = " << time << std::endl;
// impose displacement
Real epsilon = 0;
if (time < T) {
epsilon = eps * time / T;
} else {
epsilon = eps;
}
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
if (Math::are_float_equal(coordinate(n, 0), 0.0)) {
displacement(n, 0) = 0;
blocked(n, 0) = true;
displacement(n, 1) = epsilon * coordinate(n, 1);
blocked(n, 1) = true;
} else if (Math::are_float_equal(coordinate(n, 1), 0.0)) {
displacement(n, 0) = epsilon * coordinate(n, 0);
blocked(n, 0) = true;
displacement(n, 1) = 0;
blocked(n, 1) = true;
} else if (Math::are_float_equal(coordinate(n, 0), 0.001)) {
displacement(n, 0) = epsilon * coordinate(n, 0);
blocked(n, 0) = true;
displacement(n, 1) = epsilon * coordinate(n, 1);
blocked(n, 1) = true;
} else if (Math::are_float_equal(coordinate(n, 1), 0.001)) {
displacement(n, 0) = epsilon * coordinate(n, 0);
blocked(n, 0) = true;
displacement(n, 1) = epsilon * coordinate(n, 1);
blocked(n, 1) = true;
}
}
try {
model.solveStep();
} catch (debug::Exception & e) {
}
Int nb_iter = solver.get("nb_iterations");
Real error = solver.get("error");
bool converged = solver.get("converged");
if (converged) {
std::cout << "Converged in " << nb_iter << " iterations" << std::endl;
} else {
std::cout << "Didn't converge after " << nb_iter
<< " iterations. Error is " << error << std::endl;
return EXIT_FAILURE;
}
// analytical solution
Real solution_11 = 0.;
if (time < T) {
solution_11 = pre_mult * eps / T *
(Einf * time + lambda * Ev(0) * (1 - exp(-time / lambda)));
} else {
solution_11 =
pre_mult * eps *
(Einf + lambda * Ev(0) / T *
(exp((T - time) / lambda) - exp(-time / lambda)));
}
// data output
output_data << s * time_step << " " << epsilon << " " << solution_11;
Array<Real>::const_matrix_iterator stress_it = stress.begin(dim, dim);
Array<Real>::const_matrix_iterator stress_end = stress.end(dim, dim);
for (; stress_it != stress_end; ++stress_it) {
output_data << " " << (*stress_it)(0, 0);
// test error
Real rel_error_11 =
std::abs(((*stress_it)(0, 0) - solution_11) / solution_11);
if (rel_error_11 > tolerance) {
std::cerr << "Relative error: " << rel_error_11 << std::endl;
return EXIT_FAILURE;
}
}
output_data << std::endl;
time += time_step;
}
output_data.close();
finalize();
std::cout << "Test successful!" << std::endl;
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc
index 6dcd6dfad..d9633a0d3 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc
@@ -1,124 +1,116 @@
/**
* @file test_multi_material_elastic.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Mar 03 2017
* @date last modification: Thu May 09 2019
*
* @brief Test with 2 elastic materials
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "non_linear_solver.hh"
#include <solid_mechanics_model.hh>
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("test_multi_material_elastic.dat", argc, argv);
- UInt spatial_dimension = 2;
- Mesh mesh(spatial_dimension);
+ const Int dim = 2;
+ Mesh mesh(dim);
mesh.read("test_multi_material_elastic.msh");
SolidMechanicsModel model(mesh);
auto && mat_sel = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names", model);
model.setMaterialSelector(mat_sel);
model.initFull(_analysis_method = _static);
model.applyBC(BC::Dirichlet::FlagOnly(_y), "ground");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "corner");
- Vector<Real> trac(spatial_dimension, 0.);
+ Vector<Real> trac = Vector<Real>::Zero(dim);
trac(_y) = 1.;
model.applyBC(BC::Neumann::FromTraction(trac), "air");
model.addDumpField("external_force");
model.addDumpField("internal_force");
model.addDumpField("blocked_dofs");
model.addDumpField("displacement");
model.addDumpField("stress");
model.addDumpField("grad_u");
// model.dump();
auto & solver = model.getNonLinearSolver("static");
solver.set("max_iterations", 1);
solver.set("threshold", 1e-8);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
model.solveStep();
// model.dump();
std::map<std::string, Matrix<Real>> ref_strain;
- ref_strain["strong"] = Matrix<Real>(spatial_dimension, spatial_dimension, 0.);
+ ref_strain["strong"] = Matrix<Real, dim, dim>::Zero();
ref_strain["strong"](_y, _y) = .5;
- ref_strain["weak"] = Matrix<Real>(spatial_dimension, spatial_dimension, 0.);
+ ref_strain["weak"] = Matrix<Real, dim, dim>::Zero();
ref_strain["weak"](_y, _y) = 1;
- Matrix<Real> ref_stress(spatial_dimension, spatial_dimension, 0.);
+ Matrix<Real, dim, dim> ref_stress = Matrix<Real, dim, dim>::Zero();
ref_stress(_y, _y) = 1.;
std::vector<std::string> mats = {"strong", "weak"};
- typedef Array<Real>::const_matrix_iterator mat_it;
- auto check = [](mat_it it, mat_it end, const Matrix<Real> & ref) -> bool {
- for (; it != end; ++it) {
- Real dist = (*it - ref).norm<L_2>();
-
- // std::cout << *it << " " << dist << " " << (dist < 1e-10 ? "OK" : "Not
- // OK") << std::endl;
-
- if (dist > 1e-10)
+ auto check = [](auto && view, const Matrix<Real> & ref) -> bool {
+ for (auto && mat : view) {
+ Real dist = (mat - ref).norm();
+ if (dist > 1e-10) {
return false;
+ }
}
-
return true;
};
- for (auto & type : mesh.elementTypes(spatial_dimension)) {
+ for (const auto & type : mesh.elementTypes(dim)) {
for (auto mat_id : mats) {
auto & stress = model.getMaterial(mat_id).getStress(type);
auto & grad_u = model.getMaterial(mat_id).getGradU(type);
- auto sit = stress.begin(spatial_dimension, spatial_dimension);
- auto send = stress.end(spatial_dimension, spatial_dimension);
+ auto sview = make_view<dim, dim>(stress);
+ auto gview = make_view<dim, dim>(grad_u);
- auto git = grad_u.begin(spatial_dimension, spatial_dimension);
- auto gend = grad_u.end(spatial_dimension, spatial_dimension);
-
- if (!check(sit, send, ref_stress))
+ if (not check(sview, ref_stress)) {
AKANTU_ERROR("The stresses are not correct");
- if (!check(git, gend, ref_strain[mat_id]))
+ }
+ if (not check(gview, ref_strain[mat_id])) {
AKANTU_ERROR("The grad_u are not correct");
+ }
}
}
- finalize();
-
return 0;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc
index e144af29b..9a74ae782 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc
@@ -1,194 +1,207 @@
/**
* @file test_plastic_materials.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date creation: Fri Nov 17 2017
* @date last modification: Tue Jan 19 2021
*
* @brief Tests the plastic material
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "material_linear_isotropic_hardening.hh"
#include "solid_mechanics_model.hh"
#include "test_material_fixtures.hh"
#include <gtest/gtest.h>
#include <type_traits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
using mat_types = ::testing::Types<
// Traits<MaterialLinearIsotropicHardening, 1>,
// Traits<MaterialLinearIsotropicHardening, 2>,
Traits<MaterialLinearIsotropicHardening, 3>>;
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialLinearIsotropicHardening<3>>::testComputeStress() {
Real E = 1.;
// Real nu = .3;
Real nu = 0.;
Real rho = 1.;
Real sigma_0 = 1.;
Real h = 0.;
Real bulk_modulus_K = E / 3. / (1 - 2. * nu);
Real shear_modulus_mu = 0.5 * E / (1 + nu);
setParam("E", E);
setParam("nu", nu);
setParam("rho", rho);
setParam("sigma_y", sigma_0);
setParam("h", h);
auto rotation_matrix = getRandomRotation();
Real max_strain = 10.;
Real strain_steps = 100;
Real dt = max_strain / strain_steps;
std::vector<double> steps(strain_steps);
std::iota(steps.begin(), steps.end(), 0.);
- Matrix<Real> previous_grad_u_rot(3, 3, 0.);
- Matrix<Real> previous_sigma(3, 3, 0.);
- Matrix<Real> previous_sigma_rot(3, 3, 0.);
- Matrix<Real> inelastic_strain_rot(3, 3, 0.);
- Matrix<Real> inelastic_strain(3, 3, 0.);
- Matrix<Real> previous_inelastic_strain(3, 3, 0.);
- Matrix<Real> previous_inelastic_strain_rot(3, 3, 0.);
- Matrix<Real> sigma_rot(3, 3, 0.);
+ Matrix<Real, 3, 3> previous_grad_u_rot = Matrix<Real, 3, 3>::Zero();
+ Matrix<Real, 3, 3> previous_sigma = Matrix<Real, 3, 3>::Zero();
+ Matrix<Real, 3, 3> previous_sigma_rot = Matrix<Real, 3, 3>::Zero();
+ Matrix<Real, 3, 3> inelastic_strain_rot = Matrix<Real, 3, 3>::Zero();
+ // Matrix<Real, 3, 3> inelastic_strain = Matrix<Real, 3, 3>::Zero();
+ Matrix<Real, 3, 3> previous_inelastic_strain = Matrix<Real, 3, 3>::Zero();
+ Matrix<Real, 3, 3> previous_inelastic_strain_rot = Matrix<Real, 3, 3>::Zero();
+ Matrix<Real, 3, 3> sigma_rot = Matrix<Real, 3, 3>::Zero();
+
Real iso_hardening = 0.;
Real previous_iso_hardening = 0.;
// hydrostatic loading (should not plastify)
for (auto && i : steps) {
auto t = i * dt;
- auto grad_u = this->getHydrostaticStrain(t);
- auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix);
+ Matrix<Real, 3, 3> grad_u = this->getHydrostaticStrain(t);
+ Matrix<Real, 3, 3> grad_u_rot =
+ this->applyRotation(grad_u, rotation_matrix);
- this->computeStressOnQuad(grad_u_rot, previous_grad_u_rot, sigma_rot,
- previous_sigma_rot, inelastic_strain_rot,
- previous_inelastic_strain_rot, iso_hardening,
- previous_iso_hardening, 0., 0.);
+ this->computeStressOnQuad(make_named_tuple(
+ "grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot,
+ "previous_sigma"_n = previous_sigma_rot,
+ "previous_grad_u"_n = previous_grad_u_rot,
+ "inelastic_strain"_n = inelastic_strain_rot,
+ "previous_inelastic_strain"_n = previous_inelastic_strain_rot,
+ "iso_hardening"_n = iso_hardening,
+ "previous_iso_hardening"_n = previous_iso_hardening));
- auto sigma = this->reverseRotation(sigma_rot, rotation_matrix);
+ Matrix<Real, 3, 3> sigma =
+ this->reverseRotation(sigma_rot, rotation_matrix);
- Matrix<Real> sigma_expected =
- t * 3. * bulk_modulus_K * Matrix<Real>::eye(3, 1.);
+ Matrix<Real, 3, 3> sigma_expected =
+ t * 3. * bulk_modulus_K * Matrix<Real, 3, 3>::Identity();
- Real stress_error = (sigma - sigma_expected).norm<L_inf>();
+ Real stress_error = (sigma - sigma_expected).lpNorm<Eigen::Infinity>();
ASSERT_NEAR(stress_error, 0., 1e-13);
- ASSERT_NEAR(inelastic_strain_rot.norm<L_inf>(), 0., 1e-13);
+ ASSERT_NEAR(inelastic_strain_rot.lpNorm<Eigen::Infinity>(), 0., 1e-13);
previous_grad_u_rot = grad_u_rot;
previous_sigma_rot = sigma_rot;
previous_inelastic_strain_rot = inelastic_strain_rot;
previous_iso_hardening = iso_hardening;
}
// deviatoric loading (should plastify)
// stress at onset of plastication
Real beta = sqrt(42);
Real t_P = sigma_0 / 2. / shear_modulus_mu / beta;
- Matrix<Real> sigma_P = sigma_0 / beta * this->getDeviatoricStrain(1.);
+ // Matrix<Real, 3, 3> sigma_P = sigma_0 / beta *
+ // this->getDeviatoricStrain(1.);
for (auto && i : steps) {
auto t = i * dt;
auto grad_u = this->getDeviatoricStrain(t);
auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix);
Real iso_hardening{0.};
Real previous_iso_hardening{0.};
- this->computeStressOnQuad(grad_u_rot, previous_grad_u_rot, sigma_rot,
- previous_sigma_rot, inelastic_strain_rot,
- previous_inelastic_strain_rot, iso_hardening,
- previous_iso_hardening, 0., 0.);
+ this->computeStressOnQuad(make_named_tuple(
+ "grad_u"_n = grad_u_rot, "sigma"_n = sigma_rot,
+ "previous_grad_u"_n = previous_grad_u_rot,
+ "previous_sigma"_n = previous_sigma_rot,
+ "inelastic_strain"_n = inelastic_strain_rot,
+ "previous_inelastic_strain"_n = previous_inelastic_strain_rot,
+ "iso_hardening"_n = iso_hardening,
+ "previous_iso_hardening"_n = previous_iso_hardening));
auto sigma = this->reverseRotation(sigma_rot, rotation_matrix);
auto inelastic_strain =
this->reverseRotation(inelastic_strain_rot, rotation_matrix);
if (t < t_P) {
-
- Matrix<Real> sigma_expected =
+ Matrix<Real, 3, 3> sigma_expected =
shear_modulus_mu * (grad_u + grad_u.transpose());
- Real stress_error = (sigma - sigma_expected).norm<L_inf>();
+ Real stress_error = (sigma - sigma_expected).lpNorm<Eigen::Infinity>();
ASSERT_NEAR(stress_error, 0., 1e-13);
- ASSERT_NEAR(inelastic_strain_rot.norm<L_inf>(), 0., 1e-13);
+ ASSERT_NEAR(inelastic_strain_rot.lpNorm<Eigen::Infinity>(), 0., 1e-13);
} else if (t > t_P + dt) {
// skip the transition from non plastic to plastic
auto delta_lambda_expected =
dt / t * previous_sigma.doubleDot(grad_u + grad_u.transpose()) / 2.;
- auto delta_inelastic_strain_expected =
+ Matrix<Real, 3, 3> delta_inelastic_strain_expected =
delta_lambda_expected * 3. / 2. / sigma_0 * previous_sigma;
- auto inelastic_strain_expected =
+ Matrix<Real, 3, 3> inelastic_strain_expected =
delta_inelastic_strain_expected + previous_inelastic_strain;
- ASSERT_NEAR((inelastic_strain - inelastic_strain_expected).norm<L_inf>(),
+ ASSERT_NEAR((inelastic_strain - inelastic_strain_expected)
+ .lpNorm<Eigen::Infinity>(),
0., 1e-13);
- auto delta_sigma_expected =
+ Matrix<Real, 3, 3> delta_sigma_expected =
2. * shear_modulus_mu *
(0.5 * dt / t * (grad_u + grad_u.transpose()) -
delta_inelastic_strain_expected);
- auto delta_sigma = sigma - previous_sigma;
- ASSERT_NEAR((delta_sigma_expected - delta_sigma).norm<L_inf>(), 0.,
- 1e-13);
+ Matrix<Real, 3, 3> delta_sigma = sigma - previous_sigma;
+ ASSERT_NEAR(
+ (delta_sigma_expected - delta_sigma).lpNorm<Eigen::Infinity>(), 0.,
+ 1e-13);
}
previous_sigma = sigma;
previous_sigma_rot = sigma_rot;
previous_grad_u_rot = grad_u_rot;
previous_inelastic_strain = inelastic_strain;
previous_inelastic_strain_rot = inelastic_strain_rot;
}
}
namespace {
template <typename T>
class TestPlasticMaterialFixture : public ::TestMaterialFixture<T> {};
TYPED_TEST_SUITE(TestPlasticMaterialFixture, mat_types, );
TYPED_TEST(TestPlasticMaterialFixture, ComputeStress) {
this->material->testComputeStress();
}
TYPED_TEST(TestPlasticMaterialFixture, DISABLED_EnergyDensity) {
this->material->testEnergyDensity();
}
TYPED_TEST(TestPlasticMaterialFixture, DISABLED_ComputeTangentModuli) {
this->material->testComputeTangentModuli();
}
TYPED_TEST(TestPlasticMaterialFixture, DISABLED_ComputeCelerity) {
this->material->testCelerity();
}
} // namespace
/*****************************************************************/
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc
index 79eae42d7..b7a3854d7 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc
@@ -1,323 +1,333 @@
/**
* @file test_solid_mechanics_model_dynamics.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Nov 29 2017
* @date last modification: Wed Nov 18 2020
*
* @brief test of the class SolidMechanicsModel on the 3d cube
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "boundary_condition_functor.hh"
#include "test_solid_mechanics_model_fixture.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
namespace {
const Real A = 1e-1;
const Real E = 1.;
const Real poisson = 3. / 10;
-const Real lambda = E * poisson / (1 + poisson) / (1 - 2 * poisson);
-const Real mu = E / 2 / (1. + poisson);
+const auto lambda = E * poisson / (1 + poisson) / (1 - 2 * poisson);
+const auto mu = E / 2 / (1. + poisson);
const Real rho = 1.;
-const Real cp = std::sqrt((lambda + 2 * mu) / rho);
-const Real cs = std::sqrt(mu / rho);
-const Real c = std::sqrt(E / rho);
+const auto cp = std::sqrt((lambda + 2 * mu) / rho);
+const auto cs = std::sqrt(mu / rho);
+const auto c = std::sqrt(E / rho);
-const Vector<Real> k = {.5, 0., 0.};
-const Vector<Real> psi1 = {0., 0., 1.};
-const Vector<Real> psi2 = {0., 1., 0.};
-const Real knorm = k.norm();
+const Vector<Real, 3> k{.5, 0., 0.};
+const Vector<Real, 3> psi1{0., 0., 1.};
+const Vector<Real, 3> psi2{0., 1., 0.};
+const auto knorm = k.norm();
/* -------------------------------------------------------------------------- */
-template <UInt dim> struct Verification {};
+template <Int dim> struct Verification {};
/* -------------------------------------------------------------------------- */
template <> struct Verification<1> {
- void displacement(Vector<Real> & disp, const Vector<Real> & coord,
- Real current_time) {
+ template <typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors_v<D1, D2>> * = nullptr>
+ void displacement(Eigen::MatrixBase<D1> & disp,
+ const Eigen::MatrixBase<D2> & coord, Real current_time) {
const auto & x = coord(_x);
- const Real omega = c * k[0];
- disp(_x) = A * cos(k[0] * x - omega * current_time);
+ const auto omega = c * k[0];
+ disp(_x) = A * std::cos(k[0] * x - omega * current_time);
}
- void velocity(Vector<Real> & vel, const Vector<Real> & coord,
- Real current_time) {
+ template <typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors_v<D1, D2>> * = nullptr>
+ void velocity(Eigen::MatrixBase<D1> & vel,
+ const Eigen::MatrixBase<D2> & coord, Real current_time) {
const auto & x = coord(_x);
- const Real omega = c * k[0];
- vel(_x) = omega * A * sin(k[0] * x - omega * current_time);
+ const auto omega = c * k[0];
+ vel(_x) = omega * A * std::sin(k[0] * x - omega * current_time);
}
};
/* -------------------------------------------------------------------------- */
template <> struct Verification<2> {
- void displacement(Vector<Real> & disp, const Vector<Real> & X,
- Real current_time) {
- Vector<Real> kshear = {k[1], k[0]};
- Vector<Real> kpush = {k[0], k[1]};
+ template <typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors_v<D1, D2>> * = nullptr>
+ void displacement(Eigen::MatrixBase<D1> & disp,
+ const Eigen::MatrixBase<D2> & X, Real current_time) {
+ Vector<Real> kshear{k[1], k[0]};
+ Vector<Real> kpush{k[0], k[1]};
- const Real omega_p = knorm * cp;
- const Real omega_s = knorm * cs;
+ const auto omega_p = knorm * cp;
+ const auto omega_s = knorm * cs;
- Real phase_p = X.dot(kpush) - omega_p * current_time;
- Real phase_s = X.dot(kpush) - omega_s * current_time;
+ auto phase_p = X.dot(kpush) - omega_p * current_time;
+ auto phase_s = X.dot(kpush) - omega_s * current_time;
- disp = A * (kpush * cos(phase_p) + kshear * cos(phase_s));
+ disp = A * (kpush * std::cos(phase_p) + kshear * std::cos(phase_s));
}
- void velocity(Vector<Real> & vel, const Vector<Real> & X, Real current_time) {
- Vector<Real> kshear = {k[1], k[0]};
- Vector<Real> kpush = {k[0], k[1]};
+ template <typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors_v<D1, D2>> * = nullptr>
+ void velocity(Eigen::MatrixBase<D1> & vel, const Eigen::MatrixBase<D2> & X,
+ Real current_time) {
+ Vector<Real> kshear{k[1], k[0]};
+ Vector<Real> kpush{k[0], k[1]};
- const Real omega_p = knorm * cp;
- const Real omega_s = knorm * cs;
+ const auto omega_p = knorm * cp;
+ const auto omega_s = knorm * cs;
- Real phase_p = X.dot(kpush) - omega_p * current_time;
- Real phase_s = X.dot(kpush) - omega_s * current_time;
+ auto phase_p = X.dot(kpush) - omega_p * current_time;
+ auto phase_s = X.dot(kpush) - omega_s * current_time;
- vel =
- A * (kpush * omega_p * cos(phase_p) + kshear * omega_s * cos(phase_s));
+ vel = A * (kpush * omega_p * std::cos(phase_p) +
+ kshear * omega_s * std::cos(phase_s));
}
};
/* -------------------------------------------------------------------------- */
template <> struct Verification<3> {
- void displacement(Vector<Real> & disp, const Vector<Real> & coord,
- Real current_time) {
+ template <typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors_v<D1, D2>> * = nullptr>
+ void displacement(Eigen::MatrixBase<D1> & disp,
+ const Eigen::MatrixBase<D2> & coord, Real current_time) {
const auto & X = coord;
- Vector<Real> kpush = k;
- Vector<Real> kshear1(3);
- Vector<Real> kshear2(3);
- kshear1.crossProduct(k, psi1);
- kshear2.crossProduct(k, psi2);
+ auto kpush = k;
+ Vector<Real, 3> kshear1 = k.cross(psi1);
+ Vector<Real, 3> kshear2 = k.cross(psi2);
- const Real omega_p = knorm * cp;
- const Real omega_s = knorm * cs;
+ const auto omega_p = knorm * cp;
+ const auto omega_s = knorm * cs;
- Real phase_p = X.dot(kpush) - omega_p * current_time;
- Real phase_s = X.dot(kpush) - omega_s * current_time;
+ auto phase_p = X.dot(kpush) - omega_p * current_time;
+ auto phase_s = X.dot(kpush) - omega_s * current_time;
- disp = A * (kpush * cos(phase_p) + kshear1 * cos(phase_s) +
- kshear2 * cos(phase_s));
+ disp = A * (kpush * std::cos(phase_p) + kshear1 * std::cos(phase_s) +
+ kshear2 * std::cos(phase_s));
}
- void velocity(Vector<Real> & vel, const Vector<Real> & coord,
- Real current_time) {
+ template <typename D1, typename D2,
+ std::enable_if_t<aka::are_vectors_v<D1, D2>> * = nullptr>
+ void velocity(Eigen::MatrixBase<D1> & vel,
+ const Eigen::MatrixBase<D2> & coord, Real current_time) {
const auto & X = coord;
- Vector<Real> kpush = k;
- Vector<Real> kshear1(3);
- Vector<Real> kshear2(3);
- kshear1.crossProduct(k, psi1);
- kshear2.crossProduct(k, psi2);
+ auto kpush = k;
+ Vector<Real, 3> kshear1 = k.cross(psi1);
+ Vector<Real, 3> kshear2 = k.cross(psi2);
- const Real omega_p = knorm * cp;
- const Real omega_s = knorm * cs;
+ const auto omega_p = knorm * cp;
+ const auto omega_s = knorm * cs;
- Real phase_p = X.dot(kpush) - omega_p * current_time;
- Real phase_s = X.dot(kpush) - omega_s * current_time;
+ auto phase_p = X.dot(kpush) - omega_p * current_time;
+ auto phase_s = X.dot(kpush) - omega_s * current_time;
- vel =
- A * (kpush * omega_p * cos(phase_p) + kshear1 * omega_s * cos(phase_s) +
- kshear2 * omega_s * cos(phase_s));
+ vel = A * (kpush * omega_p * std::cos(phase_p) +
+ kshear1 * omega_s * std::cos(phase_s) +
+ kshear2 * omega_s * std::cos(phase_s));
}
};
/* -------------------------------------------------------------------------- */
template <ElementType _type>
class SolutionFunctor : public BC::Dirichlet::DirichletFunctor {
public:
SolutionFunctor(Real current_time, SolidMechanicsModel & model)
: current_time(current_time), model(model) {}
public:
- static constexpr UInt dim = ElementClass<_type>::getSpatialDimension();
+ static constexpr auto dim = ElementClass<_type>::getSpatialDimension();
- inline void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal,
+ inline void operator()(Int node, Vector<bool> & flags, Vector<Real> & primal,
const Vector<Real> & coord) const {
flags(0) = true;
- auto & vel = model.getVelocity();
+ const auto & vel = model.getVelocity();
auto it = vel.begin(model.getSpatialDimension());
- Vector<Real> v = it[node];
+ auto v = it[node];
Verification<dim> verif;
verif.displacement(primal, coord, current_time);
verif.velocity(v, coord, current_time);
}
private:
Real current_time;
SolidMechanicsModel & model;
};
/* -------------------------------------------------------------------------- */
// This fixture uses somewhat finer meshes representing bars.
template <typename type_, typename analysis_method_>
class TestSMMFixtureBar : public TestSMMFixture<type_> {
using parent = TestSMMFixture<type_>;
public:
void SetUp() override {
this->mesh_file =
"../patch_tests/data/bar" + std::to_string(this->type) + ".msh";
parent::SetUp();
auto analysis_method = analysis_method_::value;
this->initModel("test_solid_mechanics_model_"
"dynamics_material.dat",
analysis_method);
const auto & position = this->mesh->getNodes();
auto & displacement = this->model->getDisplacement();
auto & velocity = this->model->getVelocity();
constexpr auto dim = parent::spatial_dimension;
Verification<dim> verif;
for (auto && tuple :
zip(make_view(position, dim), make_view(displacement, dim),
make_view(velocity, dim))) {
verif.displacement(std::get<1>(tuple), std::get<0>(tuple), 0.);
verif.velocity(std::get<2>(tuple), std::get<0>(tuple), 0.);
}
- if (this->dump_paraview)
+ if (this->dump_paraview) {
this->model->dump();
+ }
/// boundary conditions
this->model->applyBC(SolutionFunctor<parent::type>(0., *this->model), "BC");
wave_velocity = 1.; // sqrt(E/rho) = sqrt(1/1) = 1
simulation_time = 5 / wave_velocity;
time_step = this->model->getTimeStep();
max_steps = simulation_time / time_step; // 100
}
void solveStep() {
constexpr auto dim = parent::spatial_dimension;
Real current_time = 0.;
const auto & position = this->mesh->getNodes();
const auto & displacement = this->model->getDisplacement();
- UInt nb_nodes = this->mesh->getNbNodes();
- UInt nb_global_nodes = this->mesh->getNbGlobalNodes();
+ auto nb_nodes = this->mesh->getNbNodes();
+ auto nb_global_nodes = this->mesh->getNbGlobalNodes();
max_error = -1.;
Array<Real> displacement_solution(nb_nodes, dim);
Verification<dim> verif;
auto ndump = 50;
auto dump_freq = max_steps / ndump;
- for (UInt s = 0; s < this->max_steps;
- ++s, current_time += this->time_step) {
- if (s % dump_freq == 0 && this->dump_paraview)
+ for (Int s = 0; s < this->max_steps; ++s, current_time += this->time_step) {
+ if (s % dump_freq == 0 && this->dump_paraview) {
this->model->dump();
+ }
/// boundary conditions
this->model->applyBC(
SolutionFunctor<parent::type>(current_time, *this->model), "BC");
// compute the disp solution
for (auto && tuple : zip(make_view(position, dim),
make_view(displacement_solution, dim))) {
verif.displacement(std::get<1>(tuple), std::get<0>(tuple),
current_time);
}
// compute the error solution
Real disp_error = 0.;
auto n = 0;
for (auto && tuple : zip(make_view(displacement, dim),
make_view(displacement_solution, dim))) {
if (this->mesh->isLocalOrMasterNode(n)) {
auto diff = std::get<1>(tuple) - std::get<0>(tuple);
disp_error += diff.dot(diff);
}
++n;
}
this->mesh->getCommunicator().allReduce(disp_error,
SynchronizerOperation::_sum);
disp_error = sqrt(disp_error) / nb_global_nodes;
max_error = std::max(disp_error, max_error);
this->model->solveStep();
}
}
protected:
Real time_step;
Real wave_velocity;
Real simulation_time;
- UInt max_steps;
+ Int max_steps;
Real max_error{-1};
};
template <AnalysisMethod t>
using analysis_method_t = std::integral_constant<AnalysisMethod, t>;
using TestTypes = gtest_list_t<TestElementTypes>;
template <typename type_>
using TestSMMFixtureBarExplicit =
TestSMMFixtureBar<type_, analysis_method_t<_explicit_lumped_mass>>;
TYPED_TEST_SUITE(TestSMMFixtureBarExplicit, TestTypes, );
/* -------------------------------------------------------------------------- */
TYPED_TEST(TestSMMFixtureBarExplicit, Dynamics) {
this->solveStep();
EXPECT_NEAR(this->max_error, 0., 2e-3);
// std::cout << "max error: " << max_error << std::endl;
}
/* -------------------------------------------------------------------------- */
#if defined(AKANTU_IMPLICIT)
template <typename type_>
using TestSMMFixtureBarImplicit =
TestSMMFixtureBar<type_, analysis_method_t<_implicit_dynamic>>;
TYPED_TEST_SUITE(TestSMMFixtureBarImplicit, TestTypes, );
TYPED_TEST(TestSMMFixtureBarImplicit, Dynamics) {
if (this->type == _segment_2 and
(this->mesh->getCommunicator().getNbProc() > 2)) {
// The error are just to high after (hopefully because of the two small test
// case)
SUCCEED();
return;
}
this->solveStep();
EXPECT_NEAR(this->max_error, 0., 2e-3);
}
#endif
} // namespace
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc
index 107adfade..6a5ea21ad 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc
@@ -1,202 +1,196 @@
/**
* @file test_solid_mechanics_model_material_eigenstrain.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sat Apr 16 2011
* @date last modification: Sat Dec 19 2020
*
* @brief test the internal field prestrain
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_utils.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
-Real alpha[3][4] = {{0.01, 0.02, 0.03, 0.04},
- {0.05, 0.06, 0.07, 0.08},
- {0.09, 0.10, 0.11, 0.12}};
+Matrix<Real, 3, 4> alpha{{0.01, 0.02, 0.03, 0.04},
+ {0.05, 0.06, 0.07, 0.08},
+ {0.09, 0.10, 0.11, 0.12}};
/* -------------------------------------------------------------------------- */
template <ElementType type> static Matrix<Real> prescribed_strain() {
- UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
+ Int spatial_dimension = ElementClass<type>::getSpatialDimension();
Matrix<Real> strain(spatial_dimension, spatial_dimension);
- for (UInt i = 0; i < spatial_dimension; ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- strain(i, j) = alpha[i][j + 1];
- }
- }
+ strain = alpha.block(0, 1, spatial_dimension, spatial_dimension);
+
return strain;
}
template <ElementType type>
static Matrix<Real> prescribed_stress(Matrix<Real> prescribed_eigengradu) {
- UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
+ Int spatial_dimension = ElementClass<type>::getSpatialDimension();
Matrix<Real> stress(spatial_dimension, spatial_dimension);
// plane strain in 2d
Matrix<Real> strain(spatial_dimension, spatial_dimension);
Matrix<Real> pstrain;
pstrain = prescribed_strain<type>();
Real nu = 0.3;
Real E = 2.1e11;
Real trace = 0;
/// symetric part of the strain tensor
- for (UInt i = 0; i < spatial_dimension; ++i)
- for (UInt j = 0; j < spatial_dimension; ++j)
- strain(i, j) = 0.5 * (pstrain(i, j) + pstrain(j, i));
+ strain = (pstrain + pstrain.transpose()) / 2.;
// elastic strain is equal to elastic strain minus the eigenstrain
strain -= prescribed_eigengradu;
- for (UInt i = 0; i < spatial_dimension; ++i)
- trace += strain(i, i);
+ trace = strain.trace();
Real lambda = nu * E / ((1 + nu) * (1 - 2 * nu));
Real mu = E / (2 * (1 + nu));
if (spatial_dimension == 1) {
- stress(0, 0) = E * strain(0, 0);
+ stress = E * strain;
} else {
- for (UInt i = 0; i < spatial_dimension; ++i)
- for (UInt j = 0; j < spatial_dimension; ++j) {
- stress(i, j) = (i == j) * lambda * trace + 2 * mu * strain(i, j);
- }
+ auto I = Matrix<Real>::Identity(spatial_dimension, spatial_dimension);
+
+ stress = I * trace * lambda + 2. * mu * strain;
}
return stress;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material_elastic_plane_strain.dat", argc, argv);
- UInt dim = 3;
+ Int dim = 3;
const ElementType element_type = _tetrahedron_4;
Matrix<Real> prescribed_eigengradu(dim, dim);
prescribed_eigengradu.set(0.1);
/// load mesh
Mesh mesh(dim);
mesh.read("cube_3d_tet_4.msh");
/// declaration of model
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull(_analysis_method = _static);
// model.getNewSolver("static", TimeStepSolverType::_static,
// NonLinearSolverType::_newton_raphson_modified);
auto & solver = model.getNonLinearSolver("static");
solver.set("threshold", 2e-4);
solver.set("max_iterations", 2);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
const Array<Real> & coordinates = mesh.getNodes();
Array<Real> & displacement = model.getDisplacement();
Array<bool> & boundary = model.getBlockedDOFs();
MeshUtils::buildFacets(mesh);
mesh.createBoundaryGroupFromGeometry();
// Loop over (Sub)Boundar(ies)
for (auto & group : mesh.iterateElementGroups()) {
for (const auto & n : group.getNodeGroup()) {
std::cout << "Node " << n << std::endl;
- for (UInt i = 0; i < dim; ++i) {
- displacement(n, i) = alpha[i][0];
- for (UInt j = 0; j < dim; ++j) {
- displacement(n, i) += alpha[i][j + 1] * coordinates(n, j);
+ for (Int i = 0; i < dim; ++i) {
+ displacement(n, i) = alpha(i, 0);
+ for (Int j = 0; j < dim; ++j) {
+ displacement(n, i) += alpha(i, j + 1) * coordinates(n, j);
}
boundary(n, i) = true;
}
}
}
/* ------------------------------------------------------------------------ */
/* Apply eigenstrain in each element */
/* ------------------------------------------------------------------------ */
Array<Real> & eigengradu_vect =
model.getMaterial(0).getInternal<Real>("eigen_grad_u")(element_type);
auto eigengradu_it = eigengradu_vect.begin(dim, dim);
auto eigengradu_end = eigengradu_vect.end(dim, dim);
for (; eigengradu_it != eigengradu_end; ++eigengradu_it) {
*eigengradu_it = prescribed_eigengradu;
}
/* ------------------------------------------------------------------------ */
/* Static solve */
/* ------------------------------------------------------------------------ */
model.solveStep();
std::cout << "Converged in " << Int(solver.get("nb_iterations")) << " ("
<< Real(solver.get("error")) << ")" << std::endl;
/* ------------------------------------------------------------------------ */
/* Checks */
/* ------------------------------------------------------------------------ */
const Array<Real> & stress_vect =
model.getMaterial(0).getStress(element_type);
auto stress_it = stress_vect.begin(dim, dim);
auto stress_end = stress_vect.end(dim, dim);
Matrix<Real> presc_stress;
presc_stress = prescribed_stress<element_type>(prescribed_eigengradu);
Real stress_tolerance = 1e-13;
for (; stress_it != stress_end; ++stress_it) {
const auto & stress = *stress_it;
Matrix<Real> diff(dim, dim);
diff = stress;
diff -= presc_stress;
- Real stress_error = diff.norm<L_inf>() / stress.norm<L_inf>();
+ Real stress_error =
+ diff.lpNorm<Eigen::Infinity>() / stress.lpNorm<Eigen::Infinity>();
if (stress_error > stress_tolerance) {
std::cerr << "stress error: " << stress_error << " > " << stress_tolerance
<< std::endl;
std::cerr << "stress: " << stress << std::endl
<< "prescribed stress: " << presc_stress << std::endl;
return EXIT_FAILURE;
} // else {
// std::cerr << "stress error: " << stress_error
// << " < " << stress_tolerance << std::endl;
// }
}
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_large_rotation.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_large_rotation.cc
index d948c46b5..aa4a455c7 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_large_rotation.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_large_rotation.cc
@@ -1,122 +1,122 @@
/**
* @file test_solid_mechanics_model_material_large_rotation.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Nov 27 2019
*
* @brief test the internal field prestrain
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "mesh_utils.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model.hh"
#include "sparse_matrix_aij.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material_elastic.dat", argc, argv);
- UInt dim = 3;
+ Int dim = 3;
/// load mesh
Mesh mesh(dim);
mesh.read("cube_3d_tet_4.msh");
/// declaration of model
SolidMechanicsModel model(mesh);
/// model initialization
// model.initFull(_analysis_method=akantu._explicit_lumped_mass)
model.initFull(_analysis_method = _implicit_dynamic);
// model.initFull(_analysis_method = akantu._implicit_dynamic)
auto & solver = model.getNonLinearSolver();
solver.set("threshold", 1e-4);
solver.set("max_iterations", 100);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
model.setBaseName("waves");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("acceleration");
model.addDumpFieldVector("velocity");
model.addDumpFieldVector("internal_force");
model.addDumpFieldVector("external_force");
model.addDumpField("strain");
model.addDumpField("stress");
model.addDumpField("blocked_dofs");
/* ------------------------------------------------------------------------ */
// get mass center
/* ------------------------------------------------------------------------ */
model.assembleMass();
auto & M = model.getDOFManager().getMatrix("M");
Array<Real> _mass(M.size(), 1);
_mass.zero();
std::cout << "AAAA " << M.size() << std::endl;
std::cout << "AAAA " << _mass.size() << std::endl;
- for (UInt i = 0; i < M.size(); ++i) {
- for (UInt j = 0; j < M.size(); ++j) {
+ for (Int i = 0; i < M.size(); ++i) {
+ for (Int j = 0; j < M.size(); ++j) {
std::cout << i << ", " << j << std::endl;
_mass[i] += M(i, j);
}
}
std::array<Real, 3> mass_center{0., 0., 0.};
std::cout << "AAAA " << _mass.size() << std::endl;
Real total_mass = 0.;
- for (UInt i = 0; i < _mass.size(); ++i) {
- for (UInt j = 0; j < 3; ++j) {
+ for (Int i = 0; i < _mass.size(); ++i) {
+ for (Int j = 0; j < 3; ++j) {
mass_center[j] += _mass(i * 3 + j);
total_mass += _mass(i * 3 + j);
}
}
mass_center[0] /= total_mass / 3.;
mass_center[1] /= total_mass / 3.;
mass_center[2] /= total_mass / 3.;
std::cout << "total mass" << total_mass << std::endl;
std::cout << mass_center[0] << " " << mass_center[1] << " " << mass_center[2]
<< std::endl;
/* ---------------------------------------------------------------------- */
/* Dynamic evolution */
/* ---------------------------------------------------------------------- */
model.dump();
model.solveStep();
model.dump();
std::cout << "Converged in " << Int(solver.get("nb_iterations")) << " ("
<< Real(solver.get("error")) << ")" << std::endl;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc
index 0ed52e2a8..2e28b38f1 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc
@@ -1,196 +1,196 @@
/**
* @file test_solid_mechanics_model_reassign_material.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Mar 11 2021
*
* @brief test the function reassign material
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_grid_dynamic.hh"
#include "communicator.hh"
#include "material.hh"
#include "mesh_iterators.hh"
#include "mesh_utils.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
class StraightInterfaceMaterialSelector : public MaterialSelector {
public:
StraightInterfaceMaterialSelector(SolidMechanicsModel & model,
UInt horizontal, Real & pos_interface,
const std::string & mat_1_material,
const std::string & mat_2_material)
: model(model), horizontal(horizontal), pos_interface(pos_interface),
mat_1_material(mat_1_material), mat_2_material(mat_2_material) {
- Mesh & mesh = model.getMesh();
- UInt spatial_dimension = mesh.getSpatialDimension();
+ auto & mesh = model.getMesh();
+ auto spatial_dimension = mesh.getSpatialDimension();
/// store barycenters of all elements
barycenters.initialize(mesh, _spatial_dimension = spatial_dimension,
_nb_component = spatial_dimension,
_with_nb_element = true);
for_each_element(mesh, [&](auto && el) {
Vector<Real> bary(barycenters.get(el));
mesh.getBarycenter(el, bary);
});
}
void setMaterials() {
mat_ids[0] = model.getMaterialIndex(mat_1_material);
mat_ids[1] = model.getMaterialIndex(mat_2_material);
}
- UInt operator()(const Element & elem) override {
+ Int operator()(const Element & elem) override {
if (not materials_set) {
setMaterials();
}
- const Vector<Real> bary = barycenters.get(elem);
+ const auto bary = barycenters.get(elem);
/// check for a given element on which side of the material interface plane
/// the bary center lies and assign corresponding material
if (bary(horizontal) < pos_interface) {
return mat_ids[0];
}
return mat_ids[1];
}
bool isConditonVerified() {
/// check if material has been (re)-assigned correctly
auto & mesh = model.getMesh();
auto spatial_dimension = mesh.getSpatialDimension();
for (const auto & type : mesh.elementTypes(spatial_dimension)) {
- auto & mat_indexes = model.getMaterialByElement(type);
+ const auto & mat_indexes = model.getMaterialByElement(type);
for (auto && data :
enumerate(make_view(barycenters(type), spatial_dimension))) {
auto elem = std::get<0>(data);
auto & bary = std::get<1>(data);
/// compare element_index_by material to material index that should be
/// assigned due to the geometry of the interface
- UInt mat_index;
+ Int mat_index;
if (bary(horizontal) < pos_interface) {
mat_index = mat_ids[0];
} else {
mat_index = mat_ids[1];
}
if (mat_indexes(elem) != mat_index) {
/// wrong material index, make test fail
return false;
}
}
}
return true;
}
void moveInterface(Real & pos_new, UInt horizontal_new) {
/// update position and orientation of material interface plane
pos_interface = pos_new;
horizontal = horizontal_new;
model.reassignMaterial();
}
protected:
SolidMechanicsModel & model;
ElementTypeMapArray<Real> barycenters;
std::array<UInt, 2> mat_ids;
UInt horizontal;
Real pos_interface;
bool materials_set{false};
std::string mat_1_material;
std::string mat_2_material;
};
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
bool test_passed;
debug::setDebugLevel(dblWarning);
initialize("two_materials.dat", argc, argv);
/// specify position and orientation of material interface plane
Real pos_interface = 0.;
- UInt spatial_dimension = 3;
+ Int spatial_dimension = 3;
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
Mesh mesh(spatial_dimension);
if (prank == 0) {
mesh.read("cube_two_materials.msh");
}
mesh.distribute();
/// model creation
SolidMechanicsModel model(mesh);
/// assign the two different materials using the
/// StraightInterfaceMaterialSelector
auto && mat_selector = std::make_shared<StraightInterfaceMaterialSelector>(
model, _x, pos_interface, "mat_1", "mat_2");
model.setMaterialSelector(mat_selector);
model.initFull(_analysis_method = _static);
MeshUtils::buildFacets(mesh);
/// check if different materials have been assigned correctly
test_passed = mat_selector->isConditonVerified();
if (not test_passed) {
AKANTU_ERROR("materials not correctly assigned");
return EXIT_FAILURE;
}
model.addDumpField("material_index");
/// change orientation of material interface plane
model.dump();
mat_selector->moveInterface(pos_interface, _y);
model.dump();
/// test if material has been reassigned correctly
test_passed = mat_selector->isConditonVerified();
if (not test_passed) {
AKANTU_ERROR("materials not correctly reassigned");
return EXIT_FAILURE;
}
finalize();
if (prank == 0)
std::cout << "OK: test passed!" << std::endl;
return EXIT_SUCCESS;
}
/* -------------------------------------------------------------------------- */
diff --git a/test/test_model/test_structural_mechanics_model/CMakeLists.txt b/test/test_model/test_structural_mechanics_model/CMakeLists.txt
index 6dd0090b5..2c23053fd 100644
--- a/test/test_model/test_structural_mechanics_model/CMakeLists.txt
+++ b/test/test_model/test_structural_mechanics_model/CMakeLists.txt
@@ -1,74 +1,72 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Fabian Barras <fabian.barras@epfl.ch>
#
# @date creation: Sun Oct 19 2014
# @date last modification: Mon Mar 15 2021
#
# @brief Structural Mechanics Model Tests
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
# Adding sources
register_gtest_sources(
SOURCES test_structural_mechanics_model_bernoulli_beam_2.cc
PACKAGE implicit structural_mechanics
)
register_gtest_sources(
SOURCES test_structural_mechanics_model_bernoulli_beam_3.cc
PACKAGE implicit structural_mechanics
)
register_gtest_sources(
SOURCES test_structural_mechanics_model_discrete_kirchhoff_triangle_18.cc
PACKAGE implicit structural_mechanics
)
register_gtest_sources(
SOURCES test_structural_mechanics_model_bernoulli_beam_dynamics.cc
PACKAGE implicit structural_mechanics
)
#===============================================================================
# Adding meshes for element types
-package_get_element_types(structural_mechanics _types)
-
-foreach(_type ${_types})
+foreach(_type _bernoulli_beam_2 _bernoulli_beam_3 _discrete_kirchhoff_triangle_18)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_type}.msh)
list(APPEND _meshes ${_type}.msh)
#register_fem_test(fe_engine_precomputation ${_type })
else()
if(NOT ${_type} STREQUAL _point_1)
message("The mesh ${_type}.msh is missing, the fe_engine test cannot be activated without it")
endif()
endif()
endforeach()
#===============================================================================
# Registering google test
register_gtest_test(test_structural_mechanics
FILES_TO_COPY ${_meshes}
)
diff --git a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_2.cc b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_2.cc
index f1a5d1772..bc43e767c 100644
--- a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_2.cc
+++ b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_2.cc
@@ -1,115 +1,115 @@
/**
* @file test_structural_mechanics_model_bernoulli_beam_2.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Feb 25 2021
*
* @brief Computation of the analytical exemple 1.1 in the TGC vol 6
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_structural_mechanics_model_fixture.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
using namespace akantu;
/* -------------------------------------------------------------------------- */
class TestStructBernoulli2
: public TestStructuralFixture<element_type_t<_bernoulli_beam_2>> {
using parent = TestStructuralFixture<element_type_t<_bernoulli_beam_2>>;
public:
void addMaterials() override {
mat.E = 3e10;
mat.I = 0.0025;
mat.A = 0.01;
this->model->addMaterial(mat);
mat.E = 3e10;
mat.I = 0.00128;
mat.A = 0.01;
this->model->addMaterial(mat);
}
void assignMaterials() override {
auto & materials = this->model->getElementMaterial(parent::type);
materials(0) = 0;
materials(1) = 1;
}
void setDirichletBCs() override {
auto boundary = this->model->getBlockedDOFs().begin(parent::ndof);
// clang-format off
- *boundary = {true, true, true}; ++boundary;
- *boundary = {false, true, false}; ++boundary;
- *boundary = {false, true, false}; ++boundary;
+ *boundary = Vector<bool>{true, true, true}; ++boundary;
+ *boundary = Vector<bool>{false, true, false}; ++boundary;
+ *boundary = Vector<bool>{false, true, false}; ++boundary;
// clang-format on
}
void setNeumannBCs() override {
Real M = 3600; // Nm
Real q = 6000; // kN/m
Real L = 10; // m
auto & forces = this->model->getExternalForce();
forces(2, 2) = -M; // moment on last node
#if 1 // as long as integration is not available
forces(0, 1) = -q * L / 2;
forces(0, 2) = -q * L * L / 12;
forces(1, 1) = -q * L / 2;
forces(1, 2) = q * L * L / 12;
#else
auto & group = mesh.createElementGroup("lin_force");
group.add({type, 0, _not_ghost});
Vector<Real> lin_force = {0, q, 0};
// a linear force is not actually a *boundary* condition
// it is equivalent to a volume force
model.applyBC(BC::Neumann::FromSameDim(lin_force), group);
#endif
forces(2, 0) = mat.E * mat.A / 18;
}
protected:
StructuralMaterial mat;
};
/* -------------------------------------------------------------------------- */
TEST_F(TestStructBernoulli2, TestDisplacements) {
model->solveStep();
auto d1 = model->getDisplacement()(1, 2);
auto d2 = model->getDisplacement()(2, 2);
auto d3 = model->getDisplacement()(1, 0);
Real tol = Math::getTolerance();
EXPECT_NEAR(d1, 5.6 / 4800, tol); // first rotation
EXPECT_NEAR(d2, -3.7 / 4800, tol); // second rotation
EXPECT_NEAR(d3, 10. / 18, tol); // axial deformation
}
diff --git a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_3.cc b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_3.cc
index f24169ec4..a0ca69d11 100644
--- a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_3.cc
+++ b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_3.cc
@@ -1,99 +1,99 @@
/**
* @file test_structural_mechanics_model_bernoulli_beam_3.cc
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Feb 25 2021
*
* @brief Computation of the analytical exemple 1.1 in the TGC vol 6
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_structural_mechanics_model_fixture.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
class TestStructBernoulli3Static
: public TestStructuralFixture<element_type_t<_bernoulli_beam_3>> {
using parent = TestStructuralFixture<element_type_t<_bernoulli_beam_3>>;
public:
void readMesh(std::string filename) override { parent::readMesh(filename); }
void setNormals() override {
auto & normals = this->mesh->getData<Real>("extra_normal", parent::type);
normals(0, _z) = 1;
normals(1, _z) = 1;
}
void addMaterials() override {
StructuralMaterial mat;
mat.E = 1;
mat.Iz = 1;
mat.Iy = 1;
mat.A = 1;
mat.GJ = 1;
this->model->addMaterial(mat);
}
void setDirichletBCs() override {
// Boundary conditions (blocking all DOFs of nodes 2 & 3)
auto boundary = ++this->model->getBlockedDOFs().begin(parent::ndof);
// clang-format off
- *boundary = {true, true, true, true, true, true}; ++boundary;
- *boundary = {true, true, true, true, true, true}; ++boundary;
+ *boundary = Vector<bool>{true, true, true, true, true, true}; ++boundary;
+ *boundary = Vector<bool>{true, true, true, true, true, true}; ++boundary;
// clang-format on
}
void setNeumannBCs() override {
// Forces
Real P = 1; // N
auto & forces = this->model->getExternalForce();
forces.zero();
forces(0, 2) = -P; // vertical force on first node
}
void assignMaterials() override {
model->getElementMaterial(parent::type).set(0);
}
};
/* -------------------------------------------------------------------------- */
TEST_F(TestStructBernoulli3Static, TestDisplacements) {
model->solveStep();
auto vz = model->getDisplacement()(0, 2);
auto thy = model->getDisplacement()(0, 4);
auto thx = model->getDisplacement()(0, 3);
auto thz = model->getDisplacement()(0, 5);
Real tol = Math::getTolerance();
EXPECT_NEAR(vz, -5. / 48, tol);
EXPECT_NEAR(thy, -std::sqrt(2) / 8, tol);
EXPECT_NEAR(thz, 0, tol);
EXPECT_NEAR(thx, 0, tol);
}
diff --git a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_dynamics.cc b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_dynamics.cc
index f2f05e8da..ab0d666f5 100644
--- a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_dynamics.cc
+++ b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_bernoulli_beam_dynamics.cc
@@ -1,369 +1,371 @@
/**
* @file test_structural_mechanics_model_bernoulli_beam_dynamics.cc
*
* @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Mon Mar 15 2021
*
* @brief Test for _bernouilli_beam in dynamic
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_structural_mechanics_model_fixture.hh"
/* -------------------------------------------------------------------------- */
#include "dof_manager.hh"
#include "mesh_accessor.hh"
#include "non_linear_solver_newton_raphson.hh"
#include "structural_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
#include <limits>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
static Real analytical_solution(Real time, Real L, Real rho, Real E,
__attribute__((unused)) Real A, Real I,
Real F) {
Real omega = M_PI * M_PI / L / L * sqrt(E * I / rho);
Real sum = 0.;
- UInt i = 5;
- for (UInt n = 1; n <= i; n += 2) {
+ Int i = 5;
+ for (Int n = 1; n <= i; n += 2) {
sum += (1. - cos(n * n * omega * time)) / pow(n, 4);
}
return 2. * F * pow(L, 3) / pow(M_PI, 4) / E / I * sum;
}
template <class Type>
class TestStructBernoulliDynamic : public TestStructuralFixture<Type> {
using parent = TestStructuralFixture<Type>;
public:
const UInt nb_element{40};
const Real L{2};
const Real le{L / nb_element};
const UInt nb_nodes{nb_element + 1};
const Real F{1e4};
StructuralMaterial mat;
void readMesh(std::string /*filename*/) override {
MeshAccessor mesh_accessor(*this->mesh);
auto & nodes = mesh_accessor.getNodes();
nodes.resize(nb_nodes);
nodes.set(0.);
for (auto && data : enumerate(make_view(nodes, this->spatial_dimension))) {
auto & node = std::get<1>(data);
- UInt i = std::get<0>(data);
+ Int i = std::get<0>(data);
node[_x] = i * le;
}
this->mesh->addConnectivityType(parent::type);
auto & connectivities = mesh_accessor.getConnectivity(parent::type);
connectivities.resize(nb_element);
for (auto && data : enumerate(make_view(connectivities, 2))) {
- UInt i = std::get<0>(data);
+ Idx i = std::get<0>(data);
auto & connectivity = std::get<1>(data);
- connectivity = {i, i + 1};
+ connectivity = Vector<Idx>{i, i + 1};
}
mesh_accessor.makeReady();
}
void setNormals() override {
if (this->spatial_dimension != 3) {
return;
}
auto & normals =
this->mesh->template getData<Real>("extra_normal", parent::type);
normals.resize(nb_element);
for (auto && normal : make_view(normals, this->spatial_dimension)) {
- normal = {0., 0., 1.};
+ normal = Vector<Real>{0., 0., 1.};
}
}
AnalysisMethod getAnalysisMethod() const override {
return _implicit_dynamic;
}
void addMaterials() override {
this->mat.E = 1e9;
this->mat.rho = 10;
this->mat.I = 1;
this->mat.Iz = 1;
this->mat.Iy = 1;
this->mat.A = 1;
this->mat.GJ = 1;
this->model->addMaterial(mat);
}
void setDirichletBCs() override {
auto & boundary = this->model->getBlockedDOFs();
boundary.set(false);
boundary(0, _x) = true;
boundary(0, _y) = true;
boundary(nb_nodes - 1, _y) = true;
if (this->spatial_dimension == 3) {
boundary(0, _z) = true;
boundary(nb_nodes - 1, _z) = true;
}
}
void setNeumannBCs() override {
auto node_to_print = nb_nodes / 2;
// Forces
auto & forces = this->model->getExternalForce();
forces.zero();
forces(node_to_print, _y) = F;
}
void assignMaterials() override {
this->model->getElementMaterial(parent::type).set(0);
}
};
using beam_types = gtest_list_t<std::tuple<element_type_t<_bernoulli_beam_2>,
element_type_t<_bernoulli_beam_3>>>;
TYPED_TEST_SUITE(TestStructBernoulliDynamic, beam_types, );
template <class Type>
void getElementMassMatrix(const StructuralMaterial & /*material*/, Real /*l*/,
Matrix<Real> & /*M*/) {}
template <class Type>
void getElementStifnessMatrix(const StructuralMaterial & /*material*/,
Real /*l*/, Matrix<Real> & /*M*/) {}
template <>
void getElementMassMatrix<element_type_t<_bernoulli_beam_2>>(
const StructuralMaterial & material, Real l, Matrix<Real> & M) {
auto A = material.A;
auto rho = material.rho;
// clang-format off
M = rho * A * l / 420. * Matrix<Real>({
{140, 0, 0, 70, 0, 0},
{ 0, 156, 22*l, 0, 54, -13*l},
{ 0, 22*l, 4*l*l, 0, 13*l, -3*l*l},
{ 70, 0, 0, 140, 0, 0},
{ 0, 54, 13*l, 0, 156, -22*l},
{ 0,-13*l, -3*l*l, 0, -22*l, 4*l*l}});
// clang-format on
}
template <>
void getElementStifnessMatrix<element_type_t<_bernoulli_beam_2>>(
const StructuralMaterial & material, Real l, Matrix<Real> & K) {
auto E = material.E;
auto A = material.A;
auto I = material.I;
auto l_2 = l * l;
auto l_3 = l * l * l;
// clang-format off
K = Matrix<Real>({
{ E*A/l, 0, 0, -E*A/l, 0, 0},
{ 0, 12*E*I/l_3, 6*E*I/l_2, 0, -12*E*I/l_3, 6*E*I/l_2},
{ 0, 6*E*I/l_2, 4*E*I/l, 0, -6*E*I/l_2, 2*E*I/l},
{-E*A/l, 0, 0, E*A/l, 0, 0},
{ 0, -12*E*I/l_3, -6*E*I/l_2, 0, 12*E*I/l_3, -6*E*I/l_2},
{ 0, 6*E*I/l_2, 2*E*I/l, 0, -6*E*I/l_2, 4*E*I/l}});
// clang-format on
}
template <>
void getElementMassMatrix<element_type_t<_bernoulli_beam_3>>(
const StructuralMaterial & material, Real l, Matrix<Real> & M) {
auto A = material.A;
auto rho = material.rho;
// clang-format off
M = rho * A * l / 420. * Matrix<Real>({
{140, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0},
{ 0, 156, 0, 0, 0, 22*l, 0, 54, 0, 0, 0, -13*l},
{ 0, 0, 156, 0, -22*l, 0, 0, 0, 54, 0, 13*l, 0},
{ 0, 0, 0, 140, 0, 0, 0, 0, 0, 70, 0, 0},
{ 0, 0, -22*l, 0, 4*l*l, 0, 0, 0, -13*l, 0, -3*l*l, 0},
{ 0, 22*l, 0, 0, 0, 4*l*l, 0, 13*l, 0, 0, 0, -3*l*l},
{ 70, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0},
{ 0, 54, 0, 0, 0, 13*l, 0, 156, 0, 0, 0, -22*l},
{ 0, 0, 54, 0, -13*l, 0, 0, 0, 156, 0, 22*l, 0},
{ 0, 0, 0, 70, 0, 0, 0, 0, 0, 140, 0, 0},
{ 0, 0, 13*l, 0, -3*l*l, 0, 0, 0, 22*l, 0, 4*l*l, 0},
{ 0, -13*l, 0, 0, 0, -3*l*l, 0, -22*l, 0, 0, 0, 4*l*l}});
// clang-format on
}
template <>
void getElementStifnessMatrix<element_type_t<_bernoulli_beam_3>>(
const StructuralMaterial & material, Real l, Matrix<Real> & K) {
auto E = material.E;
auto A = material.A;
auto Iy = material.Iy;
auto Iz = material.Iz;
auto GJ = material.GJ;
auto a1 = E * A / l;
auto b1 = 12 * E * Iz / l / l / l;
auto b2 = 6 * E * Iz / l / l;
auto b3 = 4 * E * Iz / l;
auto b4 = 2 * E * Iz / l;
auto c1 = 12 * E * Iy / l / l / l;
auto c2 = 6 * E * Iy / l / l;
auto c3 = 4 * E * Iy / l;
auto c4 = 2 * E * Iy / l;
auto d1 = GJ / l;
// clang-format off
K = Matrix<Real>({
{ a1, 0, 0, 0, 0, 0, -a1, 0, 0, 0, 0, 0},
{ 0, b1, 0, 0, 0, b2, 0, -b1, 0, 0, 0, b2},
{ 0, 0, c1, 0, -c2, 0, 0, 0, -c1, 0, -c2, 0},
{ 0, 0, 0, d1, 0, 0, 0, 0, 0, -d1, 0, 0},
{ 0, 0, -c2, 0, c3, 0, 0, 0, c2, 0, c4, 0},
{ 0, b2, 0, 0, 0, b3, 0, -b2, 0, 0, 0, b4},
{ -a1, 0, 0, 0, 0, 0, a1, 0, 0, 0, 0, 0},
{ 0, -b1, 0, 0, 0, -b2, 0, b1, 0, 0, 0, -b2},
{ 0, 0, -c1, 0, c2, 0, 0, 0, c1, 0, c2, 0},
{ 0, 0, 0, -d1, 0, 0, 0, 0, 0, d1, 0, 0},
{ 0, 0, -c2, 0, c4, 0, 0, 0, c2, 0, c3, 0},
{ 0, b2, 0, 0, 0, b4, 0, -b2, 0, 0, 0, b3}});
// clang-format on
}
TYPED_TEST(TestStructBernoulliDynamic, TestBeamMatrices) {
this->model->assembleMatrix("M");
this->model->assembleMatrix("K");
const auto & K = this->model->getDOFManager().getMatrix("K");
const auto & M = this->model->getDOFManager().getMatrix("M");
- Matrix<Real> Ka(this->nb_nodes * this->ndof, this->nb_nodes * this->ndof, 0.);
- Matrix<Real> Ma(this->nb_nodes * this->ndof, this->nb_nodes * this->ndof, 0.);
+ Matrix<Real> Ka(this->nb_nodes * this->ndof, this->nb_nodes * this->ndof);
+ Matrix<Real> Ma(this->nb_nodes * this->ndof, this->nb_nodes * this->ndof);
+ Ka.zero();
+ Ma.zero();
Matrix<Real> Ke(this->ndof * 2, this->ndof * 2);
Matrix<Real> Me(this->ndof * 2, this->ndof * 2);
getElementMassMatrix<TypeParam>(this->mat, this->le, Me);
getElementStifnessMatrix<TypeParam>(this->mat, this->le, Ke);
auto assemble = [&](auto && nodes, auto && M, auto && Me) {
auto n1 = nodes[0];
auto n2 = nodes[1];
for (auto i : arange(this->ndof)) {
for (auto j : arange(this->ndof)) {
M(n1 * this->ndof + i, n1 * this->ndof + j) += Me(i, j);
M(n2 * this->ndof + i, n2 * this->ndof + j) +=
Me(this->ndof + i, this->ndof + j);
M(n1 * this->ndof + i, n2 * this->ndof + j) += Me(i, this->ndof + j);
M(n2 * this->ndof + i, n1 * this->ndof + j) += Me(this->ndof + i, j);
}
}
};
auto && connectivities = this->mesh->getConnectivity(this->type);
for (auto && connectivity : make_view(connectivities, 2)) {
assemble(connectivity, Ka, Ke);
assemble(connectivity, Ma, Me);
}
auto tol = 1e-13;
- auto Ka_max = Ka.template norm<L_inf>();
- auto Ma_max = Ma.template norm<L_inf>();
+ auto Ka_max = Ka.template lpNorm<Eigen::Infinity>();
+ auto Ma_max = Ma.template lpNorm<Eigen::Infinity>();
for (auto i : arange(Ka.rows())) {
for (auto j : arange(Ka.cols())) {
EXPECT_NEAR(Ka(i, j), K(i, j), tol * Ka_max);
EXPECT_NEAR(Ma(i, j), M(i, j), tol * Ma_max);
}
}
}
TYPED_TEST(TestStructBernoulliDynamic, TestBeamOscilation) {
Real time_step = 1e-6;
this->model->setTimeStep(time_step);
auto & solver = this->model->getNonLinearSolver();
solver.set("max_iterations", 100);
solver.set("threshold", 1e-8);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
auto node_to_print = this->nb_nodes / 2;
auto & d = this->model->getDisplacement()(node_to_print, _y);
std::ofstream pos;
std::string filename = "position" + std::to_string(this->type) + ".csv";
pos.open(filename);
if (not pos.good()) {
AKANTU_ERROR("Cannot open file \"position.csv\"");
}
pos << "id,time,position,solution" << std::endl;
//#define debug
#ifdef debug
this->model->addDumpFieldVector("displacement");
this->model->addDumpField("blocked_dofs");
this->model->addDumpFieldVector("external_force");
this->model->addDumpFieldVector("internal_force");
this->model->addDumpFieldVector("acceleration");
this->model->addDumpFieldVector("velocity");
this->model->dump();
#endif
this->model->getDisplacement().set(0.);
Real tol = 1e-6;
Real time = 0.;
- for (UInt s = 1; s < 300; ++s) {
+ for (Int s = 1; s < 300; ++s) {
EXPECT_NO_THROW(this->model->solveStep());
time = s * time_step;
auto da = analytical_solution(time, this->L, this->mat.rho, this->mat.E,
this->mat.A, this->mat.Iy, this->F);
pos << s << "," << time << "," << d << "," << da << std::endl;
#ifdef debug
this->model->dump();
#endif
EXPECT_NEAR(d, da, tol);
}
}
diff --git a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_discrete_kirchhoff_triangle_18.cc b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_discrete_kirchhoff_triangle_18.cc
index fb93700cc..09da84bae 100644
--- a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_discrete_kirchhoff_triangle_18.cc
+++ b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_discrete_kirchhoff_triangle_18.cc
@@ -1,113 +1,113 @@
/**
* @file test_structural_mechanics_model_discrete_kirchhoff_triangle_18.cc
*
* @author Fabian Barras <fabian.barras@epfl.ch>
* @author Lucas Frerot <lucas.frerot@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Thu Feb 25 2021
*
* @brief Computation of the analytical exemple 1.1 in the TGC vol 6
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "sparse_matrix.hh"
#include "test_structural_mechanics_model_fixture.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
using namespace akantu;
/* -------------------------------------------------------------------------- */
class TestStructDKT18 : public TestStructuralFixture<
element_type_t<_discrete_kirchhoff_triangle_18>> {
using parent =
TestStructuralFixture<element_type_t<_discrete_kirchhoff_triangle_18>>;
public:
void addMaterials() override {
mat.E = 1;
mat.t = 1;
mat.nu = 0.3;
this->model->addMaterial(mat);
}
void assignMaterials() override {
auto & materials = this->model->getElementMaterial(parent::type);
std::fill(materials.begin(), materials.end(), 0);
}
void setDirichletBCs() override {
this->model->getBlockedDOFs().set(true);
auto center_node = this->model->getBlockedDOFs().end(parent::ndof) - 1;
- *center_node = {false, false, false, false, false, true};
+ *center_node << false, false, false, false, false, true;
this->model->getDisplacement().zero();
auto disp = ++this->model->getDisplacement().begin(parent::ndof);
// Displacement field from Batoz Vol. 2 p. 392
// with theta to beta correction from discrete Kirchhoff condition
// see also the master thesis of Michael Lozano
// clang-format off
// This displacement field tests membrane and bending modes
- *disp = {40, 20, -800 , -20, 40, 0}; ++disp;
- *disp = {50, 40, -1400, -40, 50, 0}; ++disp;
- *disp = {10, 20, -200 , -20, 10, 0}; ++disp;
+ *disp << 40, 20, -800 , -20, 40, 0; ++disp;
+ *disp << 50, 40, -1400, -40, 50, 0; ++disp;
+ *disp << 10, 20, -200 , -20, 10, 0; ++disp;
// This displacement tests the bending mode
// *disp = {0, 0, -800 , -20, 40, 0}; ++disp;
// *disp = {0, 0, -1400, -40, 50, 0}; ++disp;
// *disp = {0, 0, -200 , -20, 10, 0}; ++disp;
// This displacement tests the membrane mode
// *disp = {40, 20, 0, 0, 0, 0}; ++disp;
// *disp = {50, 40, 0, 0, 0, 0}; ++disp;
// *disp = {10, 20, 0, 0, 0, 0}; ++disp;
// clang-format on
}
void setNeumannBCs() override {}
protected:
StructuralMaterial mat;
};
/* -------------------------------------------------------------------------- */
// Batoz Vol 2. patch test, ISBN 2-86601-259-3
TEST_F(TestStructDKT18, TestDisplacements) {
model->solveStep();
- Vector<Real> solution = {22.5, 22.5, -337.5, -22.5, 22.5, 0};
+ Vector<Real> solution = Vector<Real>{22.5, 22.5, -337.5, -22.5, 22.5, 0};
auto nb_nodes = this->model->getDisplacement().size();
Vector<Real> center_node_disp =
model->getDisplacement().begin(solution.size())[nb_nodes - 1];
auto error = solution - center_node_disp;
- EXPECT_NEAR(error.norm<L_2>(), 0., 1e-12);
+ EXPECT_NEAR(error.norm(), 0., 1e-12);
}
diff --git a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_fixture.hh b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_fixture.hh
index 86ccef582..bd4fe8fef 100644
--- a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_fixture.hh
+++ b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_fixture.hh
@@ -1,117 +1,117 @@
/**
* @file test_structural_mechanics_model_fixture.hh
*
* @author Lucas Frerot <lucas.frerot@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Nov 14 2017
* @date last modification: Thu Feb 25 2021
*
* @brief Main test for structural model
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "element_class_structural.hh"
+#include "element_class.hh"
#include "structural_mechanics_model.hh"
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <vector>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_TEST_STRUCTURAL_MECHANICS_MODEL_FIXTURE_HH_
#define AKANTU_TEST_STRUCTURAL_MECHANICS_MODEL_FIXTURE_HH_
using namespace akantu;
template <typename type_> class TestStructuralFixture : public ::testing::Test {
public:
static constexpr const ElementType type = type_::value;
- static constexpr const size_t spatial_dimension =
+ static constexpr const Int spatial_dimension =
ElementClass<type>::getSpatialDimension();
- static const UInt ndof = ElementClass<type>::getNbDegreeOfFreedom();
+ static const Int ndof = ElementClass<type>::getNbDegreeOfFreedom();
void SetUp() override {
const auto spatial_dimension = this->spatial_dimension;
mesh = std::make_unique<Mesh>(spatial_dimension);
readMesh(makeMeshName());
std::stringstream element_type;
element_type << this->type;
model = std::make_unique<StructuralMechanicsModel>(*mesh, _all_dimensions,
element_type.str());
setNormals();
initModel();
}
virtual void initModel() {
this->addMaterials();
auto method = getAnalysisMethod();
this->model->initFull(_analysis_method = method);
this->assignMaterials();
this->setDirichletBCs();
this->setNeumannBCs();
}
virtual AnalysisMethod getAnalysisMethod() const { return _static; }
virtual void readMesh(std::string filename) {
mesh->read(filename, _miot_gmsh_struct);
}
virtual std::string makeMeshName() {
std::stringstream element_type;
element_type << type;
SCOPED_TRACE(element_type.str().c_str());
return element_type.str() + ".msh";
}
void TearDown() override {
model.reset(nullptr);
mesh.reset(nullptr);
}
virtual void addMaterials() = 0;
virtual void assignMaterials() = 0;
virtual void setDirichletBCs() = 0;
virtual void setNeumannBCs() = 0;
virtual void setNormals() {}
protected:
std::unique_ptr<Mesh> mesh;
std::unique_ptr<StructuralMechanicsModel> model;
};
template <typename type_>
constexpr ElementType TestStructuralFixture<type_>::type;
template <typename type_>
-constexpr size_t TestStructuralFixture<type_>::spatial_dimension;
-template <typename type_> const UInt TestStructuralFixture<type_>::ndof;
+constexpr Int TestStructuralFixture<type_>::spatial_dimension;
+template <typename type_> const Int TestStructuralFixture<type_>::ndof;
-using structural_types = gtest_list_t<StructuralTestElementTypes>;
+using structural_types = gtest_list_t<ElementTypes_t<_ek_structural>>;
#endif /* AKANTU_TEST_STRUCTURAL_MECHANICS_MODEL_FIXTURE_HH_ */
diff --git a/test/test_python_interface/CMakeLists.txt b/test/test_python_interface/CMakeLists.txt
index 92b7680e5..8e46509b5 100644
--- a/test/test_python_interface/CMakeLists.txt
+++ b/test/test_python_interface/CMakeLists.txt
@@ -1,43 +1,47 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Fabian Barras <fabian.barras@epfl.ch>
# @author Lucas Frerot <lucas.frerot@epfl.ch>
#
# @date creation: Sun Oct 19 2014
# @date last modification: Tue Jun 30 2020
#
# @brief Python Interface tests
#
#
# @section LICENSE
#
# Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
akantu_pybind11_add_module(py11_akantu_test_common MODULE test_common.cc)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ target_compile_options(py11_akantu_test_common PUBLIC -fsized-deallocation)
+endif()
+
add_mesh(mesh_dcb_2d mesh_dcb_2d.geo 2 2)
register_test(test_python_interface
SCRIPT test_pybind.py
PYTHON
FILES_TO_COPY elastic.dat
DEPENDS mesh_dcb_2d py11_akantu_test_common
PACKAGE python_interface
)
diff --git a/test/test_python_interface/test_common.cc b/test/test_python_interface/test_common.cc
index 3fc70fd9e..816635a1c 100644
--- a/test/test_python_interface/test_common.cc
+++ b/test/test_python_interface/test_common.cc
@@ -1,156 +1,156 @@
/**
* @file test_common.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Wed Oct 31 2018
* @date last modification: Tue Jun 30 2020
*
* @brief pybind11 interface for test
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "py_akantu.hh"
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
#include <map>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
namespace _aka = akantu;
std::map<long, std::shared_ptr<_aka::Array<_aka::Real>>> arrays;
std::map<long, std::shared_ptr<_aka::Vector<_aka::Real>>> vectors;
std::map<long, std::shared_ptr<_aka::Matrix<_aka::Real>>> matrices;
PYBIND11_MODULE(py11_akantu_test_common, mod) {
mod.doc() = "Akantu Test function for common ";
mod.def(
"createArray",
[&](_aka::UInt size, _aka::UInt nb_components) {
auto ptr =
std::make_shared<_aka::Array<_aka::Real>>(size, nb_components);
ptr->zero();
- long addr = (long)ptr->storage();
+ long addr = (long)ptr->data();
py::print("initial pointer: " + std::to_string(addr));
arrays[addr] = ptr;
return std::tuple<long, _aka::Array<_aka::Real> &>(addr, *ptr);
},
py::return_value_policy::reference);
mod.def(
"getArray",
[&](long addr) -> _aka::Array<_aka::Real> & {
auto & array = *arrays[addr];
- py::print("gotten pointer: " + std::to_string((long)array.storage()));
+ py::print("gotten pointer: " + std::to_string((long)array.data()));
return array;
},
py::return_value_policy::reference);
mod.def(
"copyArray",
[&](long addr) -> _aka::Array<_aka::Real> {
auto & array = *arrays[addr];
- py::print("gotten pointer: " + std::to_string((long)array.storage()));
+ py::print("gotten pointer: " + std::to_string((long)array.data()));
return array;
},
py::return_value_policy::copy);
mod.def("getRawPointerArray", [](_aka::Array<_aka::Real> & _data) {
py::print("received proxy: " + std::to_string((long)&_data));
- py::print("raw pointer: " + std::to_string((long)_data.storage()));
- return (long)_data.storage();
+ py::print("raw pointer: " + std::to_string((long)_data.data()));
+ return (long)_data.data();
});
mod.def(
"createVector",
- [&](_aka::UInt size) {
+ [&](_aka::Int size) {
auto ptr = std::make_shared<_aka::Vector<_aka::Real>>(size);
ptr->zero();
- long addr = (long)ptr->storage();
+ long addr = (long)ptr->data();
py::print("initial pointer: " + std::to_string(addr));
vectors[addr] = ptr;
return std::tuple<long, _aka::Vector<_aka::Real> &>(addr, *ptr);
},
py::return_value_policy::reference);
mod.def(
"getVector",
[&](long addr) -> _aka::Vector<_aka::Real> & {
auto & vector = *vectors[addr];
- py::print("gotten pointer: " + std::to_string((long)vector.storage()));
+ py::print("gotten pointer: " + std::to_string((long)vector.data()));
return vector;
},
py::return_value_policy::reference);
mod.def(
"copyVector",
[&](long addr) -> _aka::Vector<_aka::Real> {
auto & vector = *vectors[addr];
- py::print("gotten pointer: " + std::to_string((long)vector.storage()));
+ py::print("gotten pointer: " + std::to_string((long)vector.data()));
return vector;
},
py::return_value_policy::copy);
mod.def("getRawPointerVector", [](_aka::Vector<_aka::Real> & _data) {
py::print("received proxy: " + std::to_string((long)&_data));
- py::print("raw pointer: " + std::to_string((long)_data.storage()));
- return (long)_data.storage();
+ py::print("raw pointer: " + std::to_string((long)_data.data()));
+ return (long)_data.data();
});
mod.def(
"createMatrix",
- [&](_aka::UInt size1, _aka::UInt size2) {
+ [&](_aka::Int size1, _aka::Int size2) {
auto ptr = std::make_shared<_aka::Matrix<_aka::Real>>(size1, size2);
ptr->zero();
- long addr = (long)ptr->storage();
+ long addr = (long)ptr->data();
py::print("initial pointer: " + std::to_string(addr));
matrices[addr] = ptr;
return std::tuple<long, _aka::Matrix<_aka::Real> &>(addr, *ptr);
},
py::return_value_policy::reference);
mod.def(
"getMatrix",
[&](long addr) -> _aka::Matrix<_aka::Real> & {
auto & matrix = *matrices[addr];
- py::print("gotten pointer: " + std::to_string((long)matrix.storage()));
+ py::print("gotten pointer: " + std::to_string((long)matrix.data()));
return matrix;
},
py::return_value_policy::reference);
mod.def(
"copyMatrix",
[&](long addr) -> _aka::Matrix<_aka::Real> {
auto & matrix = *matrices[addr];
- py::print("gotten pointer: " + std::to_string((long)matrix.storage()));
+ py::print("gotten pointer: " + std::to_string((long)matrix.data()));
return matrix;
},
py::return_value_policy::copy);
mod.def("getRawPointerMatrix", [](_aka::Matrix<_aka::Real> & _data) {
py::print("received proxy: " + std::to_string((long)&_data));
- py::print("raw pointer: " + std::to_string((long)_data.storage()));
- return (long)_data.storage();
+ py::print("raw pointer: " + std::to_string((long)_data.data()));
+ return (long)_data.data();
});
} // Module akantu_test_common
diff --git a/test/test_solver/test_petsc_matrix_apply_boundary.cc b/test/test_solver/test_petsc_matrix_apply_boundary.cc
index 3a2682a97..828bd8fa1 100644
--- a/test/test_solver/test_petsc_matrix_apply_boundary.cc
+++ b/test/test_solver/test_petsc_matrix_apply_boundary.cc
@@ -1,150 +1,150 @@
/**
* @file test_petsc_matrix_apply_boundary.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Nov 08 2017
*
* @brief test the applyBoundary method of the PETScMatrix class
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <cstdlib>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_csr.hh"
#include "communicator.hh"
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "fe_engine.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_utils.hh"
#include "petsc_matrix.hh"
#include "mesh_partition_scotch.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
initialize(argc, argv);
const ElementType element_type = _triangle_3;
const GhostType ghost_type = _not_ghost;
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
const auto & comm = akantu::Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partition it
Mesh mesh(spatial_dimension);
/* ------------------------------------------------------------------------ */
/* Parallel initialization */
/* ------------------------------------------------------------------------ */
ElementSynchronizer * communicator = NULL;
if (prank == 0) {
/// creation mesh
mesh.read("triangle.msh");
MeshPartitionScotch * partition =
new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
delete partition;
} else {
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
}
FEEngine * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>(
mesh, spatial_dimension, "my_fem");
DOFSynchronizer dof_synchronizer(mesh, spatial_dimension);
- UInt nb_global_nodes = mesh.getNbGlobalNodes();
+ Int nb_global_nodes = mesh.getNbGlobalNodes();
dof_synchronizer.initGlobalDOFEquationNumbers();
// fill the matrix with
- UInt nb_element = mesh.getNbElement(element_type);
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
- UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
+ Int nb_element = mesh.getNbElement(element_type);
+ Int nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
+ Int nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
SparseMatrix K(nb_global_nodes * spatial_dimension, _symmetric);
K.buildProfile(mesh, dof_synchronizer, spatial_dimension);
Matrix<Real> element_input(nb_dofs_per_element, nb_dofs_per_element, 1);
Array<Real> K_e =
Array<Real>(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e");
Array<Real>::matrix_iterator K_e_it =
K_e.begin(nb_dofs_per_element, nb_dofs_per_element);
Array<Real>::matrix_iterator K_e_end =
K_e.end(nb_dofs_per_element, nb_dofs_per_element);
for (; K_e_it != K_e_end; ++K_e_it)
*K_e_it = element_input;
// assemble the test matrix
fem->assembleMatrix(K_e, K, spatial_dimension, element_type, ghost_type);
// create petsc matrix
PETScMatrix petsc_matrix(nb_global_nodes * spatial_dimension, _symmetric);
petsc_matrix.buildProfile(mesh, dof_synchronizer, spatial_dimension);
// add stiffness matrix to petsc matrix
petsc_matrix.add(K, 1);
// create boundary array: block all dofs
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
Array<bool> boundary = Array<bool>(nb_nodes, spatial_dimension, true);
// apply boundary
petsc_matrix.applyBoundary(boundary);
// test if all entries except the diagonal ones have been zeroed
Real test_passed = 0;
- for (UInt i = 0; i < nb_nodes * spatial_dimension; ++i) {
+ for (Int i = 0; i < nb_nodes * spatial_dimension; ++i) {
if (dof_synchronizer.isLocalOrMasterDOF(i)) {
- for (UInt j = 0; j < nb_nodes * spatial_dimension; ++j) {
+ for (Int j = 0; j < nb_nodes * spatial_dimension; ++j) {
if (dof_synchronizer.isLocalOrMasterDOF(j)) {
if (i == j)
test_passed += petsc_matrix(i, j) - 1;
else
test_passed += petsc_matrix(i, j) - 0;
}
}
}
}
if (std::abs(test_passed) > Math::getTolerance()) {
finalize();
return EXIT_FAILURE;
}
delete communicator;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_petsc_matrix_diagonal.cc b/test/test_solver/test_petsc_matrix_diagonal.cc
index 52b6cabf6..9c7d4a915 100644
--- a/test/test_solver/test_petsc_matrix_diagonal.cc
+++ b/test/test_solver/test_petsc_matrix_diagonal.cc
@@ -1,163 +1,163 @@
/**
* @file test_petsc_matrix_diagonal.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Nov 08 2017
*
* @brief test the connectivity is correctly represented in the PETScMatrix
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_csr.hh"
#include "communicator.hh"
#include "dof_synchronizer.hh"
#include "dumper_paraview.hh"
#include "element_synchronizer.hh"
#include "fe_engine.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_partition_scotch.hh"
#include "mesh_utils.hh"
#include "petsc_matrix.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
initialize(argc, argv);
const ElementType element_type = _triangle_3;
const GhostType ghost_type = _not_ghost;
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
const auto & comm = akantu::Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partition it
Mesh mesh(spatial_dimension);
/* ------------------------------------------------------------------------ */
/* Parallel initialization */
/* ------------------------------------------------------------------------ */
ElementSynchronizer * communicator = NULL;
if (prank == 0) {
/// creation mesh
mesh.read("triangle.msh");
MeshPartitionScotch * partition =
new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
delete partition;
} else {
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
}
// DumperParaview mesh_dumper("mesh_dumper");
// mesh_dumper.registerMesh(mesh, spatial_dimension, _not_ghost);
// mesh_dumper.dump();
/// initialize the FEEngine and the dof_synchronizer
FEEngine * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>(
mesh, spatial_dimension, "my_fem");
DOFSynchronizer dof_synchronizer(mesh, spatial_dimension);
- UInt nb_global_nodes = mesh.getNbGlobalNodes();
+ Int nb_global_nodes = mesh.getNbGlobalNodes();
dof_synchronizer.initGlobalDOFEquationNumbers();
// construct an Akantu sparse matrix, build the profile and fill the matrix
// for the given mesh
- UInt nb_element = mesh.getNbElement(element_type);
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
- UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
+ Int nb_element = mesh.getNbElement(element_type);
+ Int nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
+ Int nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
SparseMatrix K_akantu(nb_global_nodes * spatial_dimension, _unsymmetric);
K_akantu.buildProfile(mesh, dof_synchronizer, spatial_dimension);
/// use as elemental matrices a matrix with values equal to 1 every where
Matrix<Real> element_input(nb_dofs_per_element, nb_dofs_per_element, 1.);
Array<Real> K_e =
Array<Real>(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e");
Array<Real>::matrix_iterator K_e_it =
K_e.begin(nb_dofs_per_element, nb_dofs_per_element);
Array<Real>::matrix_iterator K_e_end =
K_e.end(nb_dofs_per_element, nb_dofs_per_element);
for (; K_e_it != K_e_end; ++K_e_it)
*K_e_it = element_input;
// assemble the test matrix
fem->assembleMatrix(K_e, K_akantu, spatial_dimension, element_type,
ghost_type);
/// construct a PETSc matrix
PETScMatrix K_petsc(nb_global_nodes * spatial_dimension, _unsymmetric);
/// build the profile of the PETSc matrix for the mesh of this example
K_petsc.buildProfile(mesh, dof_synchronizer, spatial_dimension);
/// add an Akantu sparse matrix to a PETSc sparse matrix
K_petsc.add(K_akantu, 1);
/// check to how many elements each node is connected
CSR<Element> node_to_elem;
MeshUtils::buildNode2Elements(mesh, node_to_elem, spatial_dimension);
/// test the diagonal of the PETSc matrix: the diagonal entries
/// of the PETSc matrix correspond to the number of elements
/// connected to the node of the dof. Note: for an Akantu matrix this is only
/// true for the serial case
Real error = 0.;
/// loop over all diagonal values of the matrix
- for (UInt i = 0; i < mesh.getNbNodes(); ++i) {
- for (UInt j = 0; j < spatial_dimension; ++j) {
- UInt dof = i * spatial_dimension + j;
+ for (Int i = 0; i < mesh.getNbNodes(); ++i) {
+ for (Int j = 0; j < spatial_dimension; ++j) {
+ Int dof = i * spatial_dimension + j;
/// for PETSc matrix only DOFs on the processor and be accessed
if (dof_synchronizer.isLocalOrMasterDOF(dof)) {
- UInt global_dof = dof_synchronizer.getDOFGlobalID(dof);
+ Int global_dof = dof_synchronizer.getDOFGlobalID(dof);
std::cout << "Number of elements connected: "
<< node_to_elem.getNbCols(i) << std::endl;
std::cout << "K_petsc(" << global_dof << "," << global_dof
<< ")=" << K_petsc(dof, dof) << std::endl;
error += std::abs(K_petsc(dof, dof) - node_to_elem.getNbCols(i));
}
}
}
if (error > Math::getTolerance()) {
std::cout << "error in the stiffness matrix!!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
delete communicator;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_petsc_matrix_profile.cc b/test/test_solver/test_petsc_matrix_profile.cc
index 9ba395d83..8ea42c7a7 100644
--- a/test/test_solver/test_petsc_matrix_profile.cc
+++ b/test/test_solver/test_petsc_matrix_profile.cc
@@ -1,144 +1,144 @@
/**
* @file test_petsc_matrix_profile.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Jan 01 2019
*
* @brief test the profile generation of the PETScMatrix class
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <fstream>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_csr.hh"
#include "communicator.hh"
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "fe_engine.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_utils.hh"
#include "sparse_matrix_petsc.hh"
/// #include "dumper_paraview.hh"
#include "mesh_partition_scotch.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
initialize(argc, argv);
const ElementType element_type = _triangle_3;
const GhostType ghost_type = _not_ghost;
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
const auto & comm = akantu::Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partition it
Mesh mesh(spatial_dimension);
/* ------------------------------------------------------------------------ */
/* Parallel initialization */
/* ------------------------------------------------------------------------ */
ElementSynchronizer * communicator = NULL;
if (prank == 0) {
/// creation mesh
mesh.read("square.msh");
MeshPartitionScotch * partition =
new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
delete partition;
} else {
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
}
// dump mesh in paraview
// DumperParaview mesh_dumper("mesh_dumper");
// mesh_dumper.registerMesh(mesh, spatial_dimension, _not_ghost);
// mesh_dumper.dump();
/// initialize the FEEngine and the dof_synchronizer
FEEngine * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>(
mesh, spatial_dimension, "my_fem");
DOFSynchronizer dof_synchronizer(mesh, spatial_dimension);
- UInt nb_global_nodes = mesh.getNbGlobalNodes();
+ Int nb_global_nodes = mesh.getNbGlobalNodes();
dof_synchronizer.initGlobalDOFEquationNumbers();
// construct an Akantu sparse matrix, build the profile and fill the matrix
// for the given mesh
- UInt nb_element = mesh.getNbElement(element_type);
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
- UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
+ Int nb_element = mesh.getNbElement(element_type);
+ Int nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
+ Int nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
SparseMatrix K_akantu(nb_global_nodes * spatial_dimension, _unsymmetric);
K_akantu.buildProfile(mesh, dof_synchronizer, spatial_dimension);
/// use as elemental matrices a matrix with values equal to 1 every where
Matrix<Real> element_input(nb_dofs_per_element, nb_dofs_per_element, 1.);
Array<Real> K_e =
Array<Real>(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e");
Array<Real>::matrix_iterator K_e_it =
K_e.begin(nb_dofs_per_element, nb_dofs_per_element);
Array<Real>::matrix_iterator K_e_end =
K_e.end(nb_dofs_per_element, nb_dofs_per_element);
for (; K_e_it != K_e_end; ++K_e_it)
*K_e_it = element_input;
// assemble the test matrix
fem->assembleMatrix(K_e, K_akantu, spatial_dimension, element_type,
ghost_type);
/// construct a PETSc matrix
PETScMatrix K_petsc(nb_global_nodes * spatial_dimension, _unsymmetric);
/// build the profile of the PETSc matrix for the mesh of this example
K_petsc.buildProfile(mesh, dof_synchronizer, spatial_dimension);
/// add an Akantu sparse matrix to a PETSc sparse matrix
K_petsc.add(K_akantu, 1);
/// save the profile
K_petsc.saveMatrix("profile.txt");
/// print the matrix to screen
std::ifstream profile;
profile.open("profile.txt");
std::string current_line;
while (getline(profile, current_line))
std::cout << current_line << std::endl;
profile.close();
delete communicator;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_petsc_matrix_profile_parallel.cc b/test/test_solver/test_petsc_matrix_profile_parallel.cc
index 164783a19..a29339983 100644
--- a/test/test_solver/test_petsc_matrix_profile_parallel.cc
+++ b/test/test_solver/test_petsc_matrix_profile_parallel.cc
@@ -1,144 +1,144 @@
/**
* @file test_petsc_matrix_profile_parallel.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Jan 01 2019
*
* @brief test the profile generation of the PETScMatrix class in parallel
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <cstdlib>
#include <fstream>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_csr.hh"
#include "communicator.hh"
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "fe_engine.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_utils.hh"
#include "sparse_matrix_petsc.hh"
/// #include "dumper_paraview.hh"
#include "mesh_partition_scotch.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
initialize(argc, argv);
const ElementType element_type = _triangle_3;
const GhostType ghost_type = _not_ghost;
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
const auto & comm = akantu::Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partition it
Mesh mesh(spatial_dimension);
/* ------------------------------------------------------------------------ */
/* Parallel initialization */
/* ------------------------------------------------------------------------ */
ElementSynchronizer * communicator = NULL;
if (prank == 0) {
/// creation mesh
mesh.read("square.msh");
MeshPartitionScotch * partition =
new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
delete partition;
} else {
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
}
// dump mesh in paraview
// DumperParaview mesh_dumper("mesh_dumper");
// mesh_dumper.registerMesh(mesh, spatial_dimension, _not_ghost);
// mesh_dumper.dump();
/// initialize the FEEngine and the dof_synchronizer
FEEngine * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>(
mesh, spatial_dimension, "my_fem");
DOFSynchronizer dof_synchronizer(mesh, spatial_dimension);
- UInt nb_global_nodes = mesh.getNbGlobalNodes();
+ Int nb_global_nodes = mesh.getNbGlobalNodes();
dof_synchronizer.initGlobalDOFEquationNumbers();
// construct an Akantu sparse matrix, build the profile and fill the matrix
// for the given mesh
- UInt nb_element = mesh.getNbElement(element_type);
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
- UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
+ Int nb_element = mesh.getNbElement(element_type);
+ Int nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
+ Int nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
SparseMatrix K_akantu(nb_global_nodes * spatial_dimension, _unsymmetric);
K_akantu.buildProfile(mesh, dof_synchronizer, spatial_dimension);
/// use as elemental matrices a matrix with values equal to 1 every where
Matrix<Real> element_input(nb_dofs_per_element, nb_dofs_per_element, 1.);
Array<Real> K_e =
Array<Real>(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e");
Array<Real>::matrix_iterator K_e_it =
K_e.begin(nb_dofs_per_element, nb_dofs_per_element);
Array<Real>::matrix_iterator K_e_end =
K_e.end(nb_dofs_per_element, nb_dofs_per_element);
for (; K_e_it != K_e_end; ++K_e_it)
*K_e_it = element_input;
// assemble the test matrix
fem->assembleMatrix(K_e, K_akantu, spatial_dimension, element_type,
ghost_type);
/// construct a PETSc matrix
PETScMatrix K_petsc(nb_global_nodes * spatial_dimension, _unsymmetric);
/// build the profile of the PETSc matrix for the mesh of this example
K_petsc.buildProfile(mesh, dof_synchronizer, spatial_dimension);
/// add an Akantu sparse matrix to a PETSc sparse matrix
K_petsc.add(K_akantu, 1);
/// save the profile
K_petsc.saveMatrix("profile_parallel.txt");
/// print the matrix to screen
if (prank == 0) {
std::ifstream profile;
profile.open("profile_parallel.txt");
std::string current_line;
while (getline(profile, current_line))
std::cout << current_line << std::endl;
profile.close();
}
delete communicator;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_solver_petsc.cc b/test/test_solver/test_solver_petsc.cc
index 0972c9bc2..918f2ddc8 100644
--- a/test/test_solver/test_solver_petsc.cc
+++ b/test/test_solver/test_solver_petsc.cc
@@ -1,173 +1,174 @@
/**
* @file test_solver_petsc.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Jan 01 2019
*
* @brief test the PETSc solver interface
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include <cstdlib>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_csr.hh"
#include "communicator.hh"
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "fe_engine.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "mesh_utils.hh"
#include "solver_petsc.hh"
#include "sparse_matrix_petsc.hh"
#include "mesh_partition_scotch.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
initialize(argc, argv);
const ElementType element_type = _segment_2;
const GhostType ghost_type = _not_ghost;
- UInt spatial_dimension = 1;
+ Int spatial_dimension = 1;
const auto & comm = akantu::Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
/// read the mesh and partition it
Mesh mesh(spatial_dimension);
/* ------------------------------------------------------------------------ */
/* Parallel initialization */
/* ------------------------------------------------------------------------ */
ElementSynchronizer * communicator = NULL;
if (prank == 0) {
/// creation mesh
mesh.read("1D_bar.msh");
MeshPartitionScotch * partition =
new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
delete partition;
} else {
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
}
FEEngine * fem =
new FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>(
mesh, spatial_dimension, "my_fem");
DOFSynchronizer dof_synchronizer(mesh, spatial_dimension);
- UInt nb_global_nodes = mesh.getNbGlobalNodes();
+ Int nb_global_nodes = mesh.getNbGlobalNodes();
dof_synchronizer.initGlobalDOFEquationNumbers();
// fill the matrix with
- UInt nb_element = mesh.getNbElement(element_type);
- UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
- UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
+ Int nb_element = mesh.getNbElement(element_type);
+ Int nb_nodes_per_element = mesh.getNbNodesPerElement(element_type);
+ Int nb_dofs_per_element = spatial_dimension * nb_nodes_per_element;
SparseMatrix K(nb_global_nodes * spatial_dimension, _symmetric);
K.buildProfile(mesh, dof_synchronizer, spatial_dimension);
- Matrix<Real> element_input(nb_dofs_per_element, nb_dofs_per_element, 0);
- for (UInt i = 0; i < nb_dofs_per_element; ++i) {
- for (UInt j = 0; j < nb_dofs_per_element; ++j) {
+ Matrix<Real> element_input(nb_dofs_per_element, nb_dofs_per_element);
+ element_input.zero();
+ for (Int i = 0; i < nb_dofs_per_element; ++i) {
+ for (Int j = 0; j < nb_dofs_per_element; ++j) {
element_input(i, j) = ((i == j) ? 1 : -1);
}
}
Array<Real> K_e =
Array<Real>(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e");
Array<Real>::matrix_iterator K_e_it =
K_e.begin(nb_dofs_per_element, nb_dofs_per_element);
Array<Real>::matrix_iterator K_e_end =
K_e.end(nb_dofs_per_element, nb_dofs_per_element);
for (; K_e_it != K_e_end; ++K_e_it)
*K_e_it = element_input;
// assemble the test matrix
fem->assembleMatrix(K_e, K, spatial_dimension, element_type, ghost_type);
// apply boundary: block first node
const Array<Real> & position = mesh.getNodes();
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
Array<bool> boundary = Array<bool>(nb_nodes, spatial_dimension, false);
- for (UInt i = 0; i < nb_nodes; ++i) {
+ for (Int i = 0; i < nb_nodes; ++i) {
if (std::abs(position(i, 0)) < Math::getTolerance())
boundary(i, 0) = true;
}
K.applyBoundary(boundary);
/// create the PETSc matrix for the solve step
PETScMatrix petsc_matrix(nb_global_nodes * spatial_dimension, _symmetric);
petsc_matrix.buildProfile(mesh, dof_synchronizer, spatial_dimension);
/// copy the stiffness matrix into the petsc matrix
petsc_matrix.add(K, 1);
// initialize internal forces: they are zero because imposed displacement is
// zero
Array<Real> internal_forces(nb_nodes, spatial_dimension, 0.);
// compute residual: apply nodal force on last node
Array<Real> residual(nb_nodes, spatial_dimension, 0.);
- for (UInt i = 0; i < nb_nodes; ++i) {
+ for (Int i = 0; i < nb_nodes; ++i) {
if (std::abs(position(i, 0) - 10) < Math::getTolerance())
residual(i, 0) += 2;
}
residual -= internal_forces;
/// initialize solver and solution
Array<Real> solution(nb_nodes, spatial_dimension, 0.);
SolverPETSc solver(petsc_matrix);
solver.initialize();
solver.setOperators();
solver.setRHS(residual);
solver.solve(solution);
/// verify solution
Math::setTolerance(1e-11);
- for (UInt i = 0; i < nb_nodes; ++i) {
+ for (Int i = 0; i < nb_nodes; ++i) {
if (!dof_synchronizer.isPureGhostDOF(i) &&
!Math::are_float_equal(2 * position(i, 0), solution(i, 0))) {
std::cout << "The solution is not correct!!!!" << std::endl;
finalize();
return EXIT_FAILURE;
}
}
delete communicator;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_sparse_matrix_assemble.cc b/test/test_solver/test_sparse_matrix_assemble.cc
index 130128358..ab340b1a5 100644
--- a/test/test_solver/test_sparse_matrix_assemble.cc
+++ b/test/test_solver/test_sparse_matrix_assemble.cc
@@ -1,86 +1,86 @@
/**
* @file test_sparse_matrix_assemble.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri May 19 2017
*
* @brief test the assembling method of the SparseMatrix class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <cstdlib>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "mesh.hh"
#include "mesh_io.hh"
#include "dof_synchronizer.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize(argc, argv);
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("triangle.msh");
UInt nb_nodes = mesh.getNbNodes();
DOFManagerDefault dof_manager(mesh, "test_dof_manager");
Array<Real> test_synchronize(nb_nodes, spatial_dimension, "Test vector");
dof_manager.registerDOFs("test_synchronize", test_synchronize, _dst_nodal);
auto & A = dof_manager.getNewMatrix("A", _symmetric);
// const akantu::Mesh::ConnectivityTypeList & type_list =
// mesh.getConnectivityTypeList();
// akantu::Mesh::ConnectivityTypeList::const_iterator it;
// for(it = type_list.begin(); it != type_list.end(); ++it) {
// if(mesh.getSpatialDimension(*it) != spatial_dimension) continue;
// akantu::UInt nb_element = mesh.getNbElement(*it);
// akantu::UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it);
// akantu::Element element(*it);
// akantu::UInt m = nb_nodes_per_element * spatial_dimension;
// akantu::Array<akantu::Real> local_mat(m, m, 1, "local_mat");
// for(akantu::UInt e = 0; e < nb_element; ++e) {
// element.element = e;
- // sparse_matrix.addToMatrix(local_mat.storage(), element,
+ // sparse_matrix.addToMatrix(local_mat.data(), element,
// nb_nodes_per_element);
// }
// }
A.saveMatrix("matrix.mtx");
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_sparse_matrix_product.cc b/test/test_solver/test_sparse_matrix_product.cc
index 9bda5fc60..572884524 100644
--- a/test/test_solver/test_sparse_matrix_product.cc
+++ b/test/test_solver/test_sparse_matrix_product.cc
@@ -1,123 +1,123 @@
/**
* @file test_sparse_matrix_product.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Jan 01 2019
*
* @brief test the matrix vector product in parallel
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "mesh.hh"
#include "mesh_partition_scotch.hh"
#include "sparse_matrix_aij.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
- const UInt spatial_dimension = 2;
- const UInt nb_dof = 2;
+ const Int spatial_dimension = 2;
+ const Int nb_dof = 2;
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
Mesh mesh(spatial_dimension);
mesh.read("bar.msh");
mesh.distribute();
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
DOFManagerDefault dof_manager(mesh, "test_dof_manager");
Array<Real> test_synchronize(nb_nodes, nb_dof, "Test vector");
dof_manager.registerDOFs("test_synchronize", test_synchronize, _dst_nodal);
if (prank == 0)
std::cout << "Creating a SparseMatrix" << std::endl;
auto & A = dynamic_cast<SparseMatrixAIJ &>(
dof_manager.getNewMatrix("A", _symmetric));
Array<Real> dof_vector(nb_nodes, nb_dof, "vector");
if (prank == 0)
std::cout << "Filling the matrix" << std::endl;
- for (UInt i = 0; i < nb_nodes * nb_dof; ++i) {
+ for (Int i = 0; i < nb_nodes * nb_dof; ++i) {
if (dof_manager.isLocalOrMasterDOF(i))
A.add(i, i, 2.);
}
std::stringstream str;
str << "Matrix_" << prank << ".mtx";
A.saveMatrix(str.str());
- for (UInt n = 0; n < nb_nodes; ++n) {
- for (UInt d = 0; d < nb_dof; ++d) {
+ for (Int n = 0; n < nb_nodes; ++n) {
+ for (Int d = 0; d < nb_dof; ++d) {
dof_vector(n, d) = 1.;
}
}
Array<Real> dof_vector_tmp(dof_vector);
if (prank == 0)
std::cout << "Computing x = A * x" << std::endl;
A.matVecMul(dof_vector, dof_vector_tmp);
dof_vector.copy(dof_vector_tmp);
auto & sync =
dynamic_cast<DOFManagerDefault &>(dof_manager).getSynchronizer();
if (prank == 0)
std::cout << "Gathering the results on proc 0" << std::endl;
if (psize > 1) {
if (prank == 0) {
Array<Real> gathered;
sync.gather(dof_vector, gathered);
debug::setDebugLevel(dblTest);
std::cout << gathered << std::endl;
debug::setDebugLevel(dblWarning);
} else {
sync.gather(dof_vector);
}
} else {
debug::setDebugLevel(dblTest);
std::cout << dof_vector << std::endl;
debug::setDebugLevel(dblWarning);
}
finalize();
return 0;
}
diff --git a/test/test_solver/test_sparse_matrix_profile.cc b/test/test_solver/test_sparse_matrix_profile.cc
index facf232c1..3a29d74c3 100644
--- a/test/test_solver/test_sparse_matrix_profile.cc
+++ b/test/test_solver/test_sparse_matrix_profile.cc
@@ -1,76 +1,76 @@
/**
* @file test_sparse_matrix_profile.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Aug 29 2017
*
* @brief test the profile generation of the SparseMatrix class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "dof_manager_default.hh"
#include "mesh.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
#include <cstdlib>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
- UInt spatial_dimension = 2;
+ Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("triangle.msh");
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
DOFManagerDefault dof_manager(mesh, "test_dof_manager");
Array<Real> test_synchronize(nb_nodes, spatial_dimension, "Test vector");
dof_manager.registerDOFs("test_synchronize", test_synchronize, _dst_nodal);
auto & A = dof_manager.getNewMatrix("A", _symmetric);
- for (UInt i = 0; i < 10; ++i) {
+ for (Int i = 0; i < 10; ++i) {
A.add(i, i);
}
A.add(0, 9);
A.saveProfile("profile_hand.mtx");
- for (UInt i = 0; i < 10; ++i) {
+ for (Int i = 0; i < 10; ++i) {
A.add(i, i, i * 10);
}
A.add(0, 9, 100);
A.saveMatrix("matrix_hand.mtx");
/* ------------------------------------------------------------------------ */
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_sparse_matrix_profile_parallel.cc b/test/test_solver/test_sparse_matrix_profile_parallel.cc
index c15cedce0..236c6f884 100644
--- a/test/test_solver/test_sparse_matrix_profile_parallel.cc
+++ b/test/test_solver/test_sparse_matrix_profile_parallel.cc
@@ -1,112 +1,112 @@
/**
* @file test_sparse_matrix_profile_parallel.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Nov 08 2017
*
* @brief test the sparse matrix class in parallel
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "communicator.hh"
#include "mesh.hh"
#include "mesh_io_msh.hh"
#include "mesh_partition_scotch.hh"
#include "solver_mumps.hh"
#include "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
int dim = 2;
// akantu::ElementType type = akantu::_triangle_6;
akantu::Mesh mesh(dim);
// akantu::debug::setDebugLevel(akantu::dblDump);
akantu::StaticCommunicator * comm =
akantu::Communicator::getStaticCommunicator();
akantu::Int psize = comm->getNbProc();
akantu::Int prank = comm->whoAmI();
- akantu::UInt n = 0;
+ akantu::Int n = 0;
/* ------------------------------------------------------------------------ */
/* Parallel initialization */
/* ------------------------------------------------------------------------ */
akantu::Communicator * communicator;
if (prank == 0) {
akantu::MeshIOMSH mesh_io;
mesh_io.read("triangle.msh", mesh);
akantu::MeshPartition * partition =
new akantu::MeshPartitionScotch(mesh, dim);
// partition->reorder();
mesh_io.write("triangle_reorder.msh", mesh);
n = mesh.getNbNodes();
partition->partitionate(psize);
communicator =
akantu::Communicator::createCommunicatorDistributeMesh(mesh, partition);
delete partition;
} else {
communicator =
akantu::Communicator::createCommunicatorDistributeMesh(mesh, NULL);
}
std::cout << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
<< mesh.getNbGlobalNodes() << std::endl;
akantu::SparseMatrix sparse_matrix(mesh, akantu::_symmetric, 2, "mesh");
sparse_matrix.buildProfile();
akantu::Solver * solver = new akantu::SolverMumps(sparse_matrix);
if (prank == 0) {
- for (akantu::UInt i = 0; i < n; ++i) {
- solver->getRHS().storage()[i] = 1.;
+ for (akantu::Int i = 0; i < n; ++i) {
+ solver->getRHS().data()[i] = 1.;
}
}
akantu::debug::setDebugLevel(akantu::dblDump);
solver->initialize();
std::stringstream sstr;
sstr << "profile_" << prank << ".mtx";
sparse_matrix.saveProfile(sstr.str());
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_solver/test_sparse_solver_mumps.cc b/test/test_solver/test_sparse_solver_mumps.cc
index ed881567c..2c8cc3f71 100644
--- a/test/test_solver/test_sparse_solver_mumps.cc
+++ b/test/test_solver/test_sparse_solver_mumps.cc
@@ -1,169 +1,169 @@
/**
* @file test_sparse_solver_mumps.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri May 19 2017
* @date last modification: Sun Dec 30 2018
*
* @brief test the matrix vector product in parallel
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "mesh.hh"
#include "mesh_accessor.hh"
#include "mesh_partition_scotch.hh"
#include "sparse_matrix_aij.hh"
#include "sparse_solver_mumps.hh"
#include "terms_to_assemble.hh"
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
-void genMesh(Mesh & mesh, UInt nb_nodes);
+void genMesh(Mesh & mesh, Int nb_nodes);
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
- const UInt spatial_dimension = 1;
- const UInt nb_global_dof = 11;
+ const Int spatial_dimension = 1;
+ const Int nb_global_dof = 11;
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
Mesh mesh(spatial_dimension);
if (prank == 0) {
genMesh(mesh, nb_global_dof);
- RandomGenerator<UInt>::seed(1496137735);
+ RandomGenerator<Idx>::seed(1496137735);
} else {
- RandomGenerator<UInt>::seed(2992275470);
+ RandomGenerator<Idx>::seed(2992275470);
}
mesh.distribute();
UInt node = 0;
for (auto pos : mesh.getNodes()) {
std::cout << prank << " " << node << " pos: " << pos << " ["
<< mesh.getNodeGlobalId(node) << "] " << mesh.getNodeFlag(node)
<< std::endl;
++node;
}
- UInt nb_nodes = mesh.getNbNodes();
+ Int nb_nodes = mesh.getNbNodes();
DOFManagerDefault dof_manager(mesh, "test_dof_manager");
Array<Real> x(nb_nodes);
dof_manager.registerDOFs("x", x, _dst_nodal);
const auto & local_equation_number =
dof_manager.getLocalEquationsNumbers("x");
auto & A = dof_manager.getNewMatrix("A", _symmetric);
Array<Real> b(nb_nodes);
TermsToAssemble terms("x", "x");
- for (UInt i = 0; i < nb_nodes; ++i) {
+ for (Int i = 0; i < nb_nodes; ++i) {
if (dof_manager.isLocalOrMasterDOF(i)) {
auto li = local_equation_number(i);
auto gi = dof_manager.localToGlobalEquationNumber(li);
terms(i, i) = 1. / (1. + gi);
}
}
dof_manager.assemblePreassembledMatrix("A", terms);
std::stringstream str;
str << "Matrix_" << prank << ".mtx";
A.saveMatrix(str.str());
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
b(n) = 1.;
}
SparseSolverMumps solver(dof_manager, "A");
solver.solve(x, b);
auto && check = [&](auto && xs) {
debug::setDebugLevel(dblTest);
std::cout << xs << std::endl;
debug::setDebugLevel(dblWarning);
- UInt d = 1.;
+ Int d = 1.;
for (auto x : xs) {
if (std::abs(x - d) / d > 1e-15)
AKANTU_EXCEPTION("Error in the solution: " << x << " != " << d << " ["
<< (std::abs(x - d) / d)
<< "].");
++d;
}
};
if (psize > 1) {
auto & sync =
dynamic_cast<DOFManagerDefault &>(dof_manager).getSynchronizer();
if (prank == 0) {
Array<Real> x_gathered(dof_manager.getSystemSize());
sync.gather(x, x_gathered);
check(x_gathered);
} else {
sync.gather(x);
}
} else {
check(x);
}
finalize();
return 0;
}
/* -------------------------------------------------------------------------- */
-void genMesh(Mesh & mesh, UInt nb_nodes) {
+void genMesh(Mesh & mesh, Int nb_nodes) {
MeshAccessor mesh_accessor(mesh);
Array<Real> & nodes = mesh_accessor.getNodes();
- Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2);
+ Array<Idx> & conn = mesh_accessor.getConnectivity(_segment_2);
nodes.resize(nb_nodes);
- for (UInt n = 0; n < nb_nodes; ++n) {
+ for (Int n = 0; n < nb_nodes; ++n) {
nodes(n, _x) = n * (1. / (nb_nodes - 1));
}
conn.resize(nb_nodes - 1);
- for (UInt n = 0; n < nb_nodes - 1; ++n) {
+ for (Int n = 0; n < nb_nodes - 1; ++n) {
conn(n, 0) = n;
conn(n, 1) = n + 1;
}
mesh_accessor.makeReady();
}
diff --git a/test/test_synchronizer/test_data_accessor.hh b/test/test_synchronizer/test_data_accessor.hh
index 839124539..5ebc859f4 100644
--- a/test/test_synchronizer/test_data_accessor.hh
+++ b/test/test_synchronizer/test_data_accessor.hh
@@ -1,125 +1,106 @@
/**
* @file test_data_accessor.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
* @author Marco Vocialta <marco.vocialta@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Jan 26 2018
*
* @brief Data Accessor class for testing
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "data_accessor.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
class TestAccessor : public DataAccessor<Element> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
inline TestAccessor(const Mesh & mesh,
const ElementTypeMapArray<Real> & barycenters);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Barycenter, barycenters, Real);
/* ------------------------------------------------------------------------ */
/* Ghost Synchronizer inherited members */
/* ------------------------------------------------------------------------ */
protected:
- inline UInt getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const;
+ inline Int getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const;
inline void packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const;
inline void unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
const ElementTypeMapArray<Real> & barycenters;
const Mesh & mesh;
};
/* -------------------------------------------------------------------------- */
/* TestSynchronizer implementation */
/* -------------------------------------------------------------------------- */
inline TestAccessor::TestAccessor(const Mesh & mesh,
const ElementTypeMapArray<Real> & barycenters)
: barycenters(barycenters), mesh(mesh) {}
-inline UInt TestAccessor::getNbData(const Array<Element> & elements,
- const SynchronizationTag &) const {
- if (elements.size())
- // return Mesh::getSpatialDimension(elements(0).type) * sizeof(Real) *
- // elements.size();
- return mesh.getSpatialDimension() * sizeof(Real) * elements.size();
- else
- return 0;
+inline Int TestAccessor::getNbData(const Array<Element> & elements,
+ const SynchronizationTag &) const {
+ return mesh.getSpatialDimension() * sizeof(Real) * elements.size();
}
inline void TestAccessor::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag &) const {
- UInt spatial_dimension = mesh.getSpatialDimension();
- Array<Element>::const_iterator<Element> bit = elements.begin();
- Array<Element>::const_iterator<Element> bend = elements.end();
- for (; bit != bend; ++bit) {
- const Element & element = *bit;
-
- Vector<Real> bary(
- this->barycenters(element.type, element.ghost_type).storage() +
- element.element * spatial_dimension,
- spatial_dimension);
+ for (const auto & element : elements) {
+ auto && bary = this->barycenters.get(element);
buffer << bary;
}
}
inline void TestAccessor::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag &) {
- UInt spatial_dimension = mesh.getSpatialDimension();
-
for (const auto & element : elements) {
- Vector<Real> barycenter_loc(
- this->barycenters(element.type, element.ghost_type).storage() +
- element.element * spatial_dimension,
- spatial_dimension);
-
- Vector<Real> bary(spatial_dimension);
+ auto && barycenter_loc = this->barycenters.get(element);
+ Vector<Real> bary(barycenter_loc.size());
buffer >> bary;
- auto dist = (barycenter_loc - bary).template norm<L_inf>();
+ auto dist = (barycenter_loc - bary).template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(0, dist, 1e-15);
}
}
diff --git a/test/test_synchronizer/test_data_distribution.cc b/test/test_synchronizer/test_data_distribution.cc
index 02b94ff20..0591ca70c 100644
--- a/test/test_synchronizer/test_data_distribution.cc
+++ b/test/test_synchronizer/test_data_distribution.cc
@@ -1,89 +1,90 @@
/**
* @file test_data_distribution.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Dec 28 2018
*
* @brief Test the mesh distribution on creation of a distributed synchonizer
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_synchronizers_fixture.hh"
/* -------------------------------------------------------------------------- */
TEST_F(TestSynchronizerFixture, DataDistribution) {
auto & barycenters = this->mesh->getElementalData<Real>("barycenters");
auto spatial_dimension = this->mesh->getSpatialDimension();
barycenters.initialize(*this->mesh, _spatial_dimension = _all_dimensions,
_nb_component = spatial_dimension);
this->initBarycenters(barycenters, *this->mesh);
auto & gids = this->mesh->getNodalData<UInt>("gid");
gids.resize(this->mesh->getNbNodes());
for (auto && data : enumerate(gids)) {
std::get<1>(data) = std::get<0>(data);
}
this->distribute();
for (auto && ghost_type : ghost_types) {
for (const auto & type :
this->mesh->elementTypes(_all_dimensions, ghost_type)) {
auto & barycenters =
this->mesh->getData<Real>("barycenters", type, ghost_type);
for (auto && data :
enumerate(make_view(barycenters, spatial_dimension))) {
- Element element{type, UInt(std::get<0>(data)), ghost_type};
+ Element element{type, std::get<0>(data), ghost_type};
Vector<Real> barycenter(spatial_dimension);
this->mesh->getBarycenter(element, barycenter);
- auto dist = (std::get<1>(data) - barycenter).template norm<L_inf>();
+ auto dist =
+ (std::get<1>(data) - barycenter).template lpNorm<Eigen::Infinity>();
EXPECT_NEAR(dist, 0, 1e-7);
}
}
}
if (psize > 1) {
for (auto && data : zip(gids, this->mesh->getGlobalNodesIds())) {
EXPECT_EQ(std::get<0>(data), std::get<1>(data));
}
}
}
TEST_F(TestSynchronizerFixture, DataDistributionTags) {
this->distribute();
for (const auto & type : this->mesh->elementTypes(_all_dimensions)) {
- auto & tags = this->mesh->getData<UInt>("tag_0", type);
- Array<UInt>::const_vector_iterator tags_it = tags.begin(1);
- Array<UInt>::const_vector_iterator tags_end = tags.end(1);
+ auto & tags = this->mesh->getData<Int>("tag_0", type);
+ auto tags_it = tags.begin(1);
+ auto tags_end = tags.end(1);
// The number of tags should match the number of elements on rank"
EXPECT_EQ(this->mesh->getNbElement(type), tags.size());
}
}
diff --git a/test/test_synchronizer/test_dof_synchronizer.cc b/test/test_synchronizer/test_dof_synchronizer.cc
index dd7d89890..0695aea6a 100644
--- a/test/test_synchronizer/test_dof_synchronizer.cc
+++ b/test/test_synchronizer/test_dof_synchronizer.cc
@@ -1,145 +1,144 @@
/**
* @file test_dof_synchronizer.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Wed Jan 15 2020
*
* @brief Test the functionality of the DOFSynchronizer class
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "mesh_io.hh"
#include "mesh_partition_scotch.hh"
/* -------------------------------------------------------------------------- */
#include "io_helper.hh"
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
- const UInt spatial_dimension = 2;
+ const Int spatial_dimension = 2;
initialize(argc, argv);
const auto & comm = akantu::Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
Mesh mesh(spatial_dimension);
if (prank == 0)
mesh.read("bar.msh");
mesh.distribute();
DOFManagerDefault dof_manager(mesh, "test_dof_manager");
UInt nb_nodes = mesh.getNbNodes();
/* ------------------------------------------------------------------------ */
/* test the synchronization */
/* ------------------------------------------------------------------------ */
Array<Real> test_synchronize(nb_nodes, spatial_dimension, "Test vector");
dof_manager.registerDOFs("test_synchronize", test_synchronize, _dst_nodal);
- auto & equation_number =
+ const auto & equation_number =
dof_manager.getLocalEquationsNumbers("test_synchronize");
- DOFSynchronizer & dof_synchronizer = dof_manager.getSynchronizer();
+ auto & dof_synchronizer = dof_manager.getSynchronizer();
std::cout << "Synchronizing a dof vector" << std::endl;
Array<Int> local_data_array(dof_manager.getLocalSystemSize(), 2);
auto it_data = local_data_array.begin(2);
- for (UInt local_dof = 0; local_dof < dof_manager.getLocalSystemSize();
+ for (Int local_dof = 0; local_dof < dof_manager.getLocalSystemSize();
++local_dof) {
- UInt equ_number = equation_number(local_dof);
+ auto equ_number = equation_number(local_dof);
Vector<Int> val;
if (dof_manager.isLocalOrMasterDOF(equ_number)) {
- UInt global_dof = dof_manager.localToGlobalEquationNumber(local_dof);
+ Int global_dof = dof_manager.localToGlobalEquationNumber(local_dof);
val = {0, 1};
- val += global_dof * 2;
+ val.array() += global_dof * 2;
} else {
val = {-1, -1};
}
- Vector<Int> data = it_data[local_dof];
- data = val;
+ it_data[local_dof] = val;
}
dof_synchronizer.synchronizeArray(local_data_array);
auto test_data = [&]() -> void {
auto it_data = local_data_array.begin(2);
- for (UInt local_dof = 0; local_dof < dof_manager.getLocalSystemSize();
+ for (Int local_dof = 0; local_dof < dof_manager.getLocalSystemSize();
++local_dof) {
- UInt equ_number = equation_number(local_dof);
+ Int equ_number = equation_number(local_dof);
Vector<Int> exp_val;
- UInt global_dof = dof_manager.localToGlobalEquationNumber(local_dof);
+ auto global_dof = dof_manager.localToGlobalEquationNumber(local_dof);
if (dof_manager.isLocalOrMasterDOF(equ_number) ||
dof_manager.isSlaveDOF(equ_number)) {
exp_val = {0, 1};
- exp_val += global_dof * 2;
+ exp_val.array() += global_dof * 2;
} else {
exp_val = {-1, -1};
}
- Vector<Int> val = it_data[local_dof];
+ auto && val = it_data[local_dof];
if (exp_val != val) {
std::cerr << "Failed !" << prank << " DOF: " << global_dof << " - l"
<< local_dof << " value:" << val << " expected: " << exp_val
<< std::endl;
exit(1);
}
}
};
test_data();
if (prank == 0) {
Array<Int> test_gathered(dof_manager.getSystemSize(), 2);
dof_synchronizer.gather(local_data_array, test_gathered);
local_data_array.set(-1);
dof_synchronizer.scatter(local_data_array, test_gathered);
} else {
dof_synchronizer.gather(local_data_array);
local_data_array.set(-1);
dof_synchronizer.scatter(local_data_array);
}
test_data();
finalize();
return 0;
}
diff --git a/test/test_synchronizer/test_dof_synchronizer_communication.cc b/test/test_synchronizer/test_dof_synchronizer_communication.cc
index 3b9be2840..3bd475d03 100644
--- a/test/test_synchronizer/test_dof_synchronizer_communication.cc
+++ b/test/test_synchronizer/test_dof_synchronizer_communication.cc
@@ -1,107 +1,107 @@
/**
* @file test_dof_synchronizer_communication.cc
*
* @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Tue Dec 09 2014
* @date last modification: Sun Dec 30 2018
*
* @brief test to synchronize global equation numbers
*
*
* @section LICENSE
*
* Copyright (©) 2015-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "dof_synchronizer.hh"
#include "element_synchronizer.hh"
#include "mesh.hh"
#include "mesh_partition_scotch.hh"
#include "synchronizer_registry.hh"
/* -------------------------------------------------------------------------- */
#include "dumper_paraview.hh"
#include "test_dof_data_accessor.hh"
using namespace akantu;
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize(argc, argv);
- UInt spatial_dimension = 3;
+ Int spatial_dimension = 3;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
bool wait = true;
if (argc > 1) {
if (prank == 0)
while (wait)
;
}
ElementSynchronizer * communicator = NULL;
if (prank == 0) {
mesh.read("cube.msh");
MeshPartition * partition =
new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
delete partition;
} else {
communicator =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
}
/* --------------------------------------------------------------------------
*/
/* test the communications of the dof synchronizer */
/* --------------------------------------------------------------------------
*/
std::cout << "Initializing the synchronizer" << std::endl;
DOFSynchronizer dof_synchronizer(mesh, spatial_dimension);
dof_synchronizer.initGlobalDOFEquationNumbers();
AKANTU_DEBUG_INFO("Creating TestDOFAccessor");
TestDOFAccessor test_dof_accessor(
dof_synchronizer.getGlobalDOFEquationNumbers());
SynchronizerRegistry synch_registry(test_dof_accessor);
synch_registry.registerSynchronizer(dof_synchronizer,
SynchronizationTag::_test);
AKANTU_DEBUG_INFO("Synchronizing tag");
synch_registry.synchronize(SynchronizationTag::_test);
delete communicator;
finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_synchronizer/test_grid_synchronizer.cc b/test/test_synchronizer/test_grid_synchronizer.cc
index 276d4272d..0a986f9a6 100644
--- a/test/test_synchronizer/test_grid_synchronizer.cc
+++ b/test/test_synchronizer/test_grid_synchronizer.cc
@@ -1,309 +1,309 @@
/**
* @file test_grid_synchronizer.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Sun Dec 30 2018
*
* @brief test the GridSynchronizer object
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_grid_dynamic.hh"
#include "grid_synchronizer.hh"
+#include "io_helper.hh"
#include "mesh.hh"
#include "mesh_partition.hh"
#include "synchronizer_registry.hh"
#include "test_data_accessor.hh"
-#include "io_helper.hh"
using namespace akantu;
-const UInt spatial_dimension = 2;
+const Int spatial_dimension = 2;
typedef std::map<std::pair<Element, Element>, Real> pair_list;
#include "test_grid_tools.hh"
static void
updatePairList(const ElementTypeMapArray<Real> & barycenter,
const SpatialGrid<Element> & grid, Real radius,
pair_list & neighbors,
neighbors_map_t<spatial_dimension>::type & neighbors_map) {
AKANTU_DEBUG_IN();
GhostType ghost_type = _not_ghost;
Element e;
e.ghost_type = ghost_type;
// generate the pair of neighbor depending of the cell_list
ElementTypeMapArray<Real>::type_iterator it =
barycenter.firstType(_all_dimensions, ghost_type);
ElementTypeMapArray<Real>::type_iterator last_type =
barycenter.lastType(0, ghost_type);
for (; it != last_type; ++it) {
// loop over quad points
e.type = *it;
e.element = 0;
const Array<Real> & barycenter_vect = barycenter(*it, ghost_type);
UInt sp = barycenter_vect.getNbComponent();
Array<Real>::const_iterator<Vector<Real>> bary = barycenter_vect.begin(sp);
Array<Real>::const_iterator<Vector<Real>> bary_end =
barycenter_vect.end(sp);
for (; bary != bary_end; ++bary, e.element++) {
#if !defined(AKANTU_NDEBUG)
Point<spatial_dimension> pt1(*bary);
#endif
SpatialGrid<Element>::CellID cell_id = grid.getCellID(*bary);
SpatialGrid<Element>::neighbor_cells_iterator first_neigh_cell =
grid.beginNeighborCells(cell_id);
SpatialGrid<Element>::neighbor_cells_iterator last_neigh_cell =
grid.endNeighborCells(cell_id);
// loop over neighbors cells of the one containing the current element
for (; first_neigh_cell != last_neigh_cell; ++first_neigh_cell) {
SpatialGrid<Element>::Cell::const_iterator first_neigh_el =
grid.beginCell(*first_neigh_cell);
SpatialGrid<Element>::Cell::const_iterator last_neigh_el =
grid.endCell(*first_neigh_cell);
// loop over the quadrature point in the current cell of the cell list
for (; first_neigh_el != last_neigh_el; ++first_neigh_el) {
const Element & elem = *first_neigh_el;
Array<Real>::const_iterator<Vector<Real>> neigh_it =
barycenter(elem.type, elem.ghost_type).begin(sp);
const Vector<Real> & neigh_bary = neigh_it[elem.element];
Real distance = bary->distance(neigh_bary);
if (distance <= radius) {
#if !defined(AKANTU_NDEBUG)
Point<spatial_dimension> pt2(neigh_bary);
neighbors_map[pt1].push_back(pt2);
#endif
std::pair<Element, Element> pair = std::make_pair(e, elem);
pair_list::iterator p = neighbors.find(pair);
if (p != neighbors.end()) {
AKANTU_ERROR("Pair already registered ["
<< e << " " << elem << "] -> " << p->second << " "
<< distance);
} else {
neighbors[pair] = distance;
}
}
}
}
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/* Main */
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
akantu::initialize(argc, argv);
Real radius = 0.001;
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
ElementSynchronizer * dist = NULL;
if (prank == 0) {
mesh.read("bar.msh");
MeshPartition * partition =
new MeshPartitionScotch(mesh, spatial_dimension);
partition->partitionate(psize);
dist =
ElementSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
delete partition;
} else {
dist = ElementSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
}
mesh.computeBoundingBox();
const Vector<Real> & lower_bounds = mesh.getLowerBounds();
const Vector<Real> & upper_bounds = mesh.getUpperBounds();
Vector<Real> center = 0.5 * (upper_bounds + lower_bounds);
Vector<Real> spacing(spatial_dimension);
- for (UInt i = 0; i < spatial_dimension; ++i) {
+ for (Int i = 0; i < spatial_dimension; ++i) {
spacing[i] = radius * 1.2;
}
SpatialGrid<Element> grid(spatial_dimension, spacing, center);
GhostType ghost_type = _not_ghost;
Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
ElementTypeMapArray<Real> barycenters("", "");
mesh.initElementTypeMapArray(barycenters, spatial_dimension,
spatial_dimension);
Element e;
e.ghost_type = ghost_type;
for (; it != last_type; ++it) {
UInt nb_element = mesh.getNbElement(*it, ghost_type);
e.type = *it;
Array<Real> & barycenter = barycenters(*it, ghost_type);
barycenter.resize(nb_element);
Array<Real>::iterator<Vector<Real>> bary_it =
barycenter.begin(spatial_dimension);
- for (UInt elem = 0; elem < nb_element; ++elem) {
+ for (Int elem = 0; elem < nb_element; ++elem) {
mesh.getBarycenter(elem, *it, bary_it->storage(), ghost_type);
e.element = elem;
grid.insert(e, *bary_it);
++bary_it;
}
}
std::stringstream sstr;
sstr << "mesh_" << prank << ".msh";
mesh.write(sstr.str());
Mesh grid_mesh(spatial_dimension, "grid_mesh", 0);
std::stringstream sstr_grid;
sstr_grid << "grid_mesh_" << prank << ".msh";
grid.saveAsMesh(grid_mesh);
grid_mesh.write(sstr_grid.str());
std::cout << "Pouet 1" << std::endl;
AKANTU_DEBUG_INFO("Creating TestAccessor");
TestAccessor test_accessor(mesh, barycenters);
SynchronizerRegistry synch_registry(test_accessor);
GridSynchronizer * grid_communicator =
GridSynchronizer::createGridSynchronizer(mesh, grid);
std::cout << "Pouet 2" << std::endl;
ghost_type = _ghost;
it = mesh.firstType(spatial_dimension, ghost_type);
last_type = mesh.lastType(spatial_dimension, ghost_type);
e.ghost_type = ghost_type;
for (; it != last_type; ++it) {
UInt nb_element = mesh.getNbElement(*it, ghost_type);
e.type = *it;
Array<Real> & barycenter = barycenters(*it, ghost_type);
barycenter.resize(nb_element);
Array<Real>::iterator<Vector<Real>> bary_it =
barycenter.begin(spatial_dimension);
- for (UInt elem = 0; elem < nb_element; ++elem) {
+ for (Int elem = 0; elem < nb_element; ++elem) {
mesh.getBarycenter(elem, *it, bary_it->storage(), ghost_type);
e.element = elem;
grid.insert(e, *bary_it);
++bary_it;
}
}
Mesh grid_mesh_ghost(spatial_dimension, "grid_mesh_ghost", 0);
std::stringstream sstr_gridg;
sstr_gridg << "grid_mesh_ghost_" << prank << ".msh";
grid.saveAsMesh(grid_mesh_ghost);
grid_mesh_ghost.write(sstr_gridg.str());
std::cout << "Pouet 3" << std::endl;
neighbors_map_t<spatial_dimension>::type neighbors_map;
pair_list neighbors;
updatePairList(barycenters, grid, radius, neighbors, neighbors_map);
pair_list::iterator nit = neighbors.begin();
pair_list::iterator nend = neighbors.end();
std::stringstream sstrp;
sstrp << "pairs_" << prank;
std::ofstream fout(sstrp.str().c_str());
for (; nit != nend; ++nit) {
fout << "[" << nit->first.first << "," << nit->first.second << "] -> "
<< nit->second << std::endl;
}
std::string file = "neighbors_ref";
std::stringstream sstrf;
sstrf << file << "_" << psize << "_" << prank;
file = sstrf.str();
std::ofstream nout;
nout.open(file.c_str());
neighbors_map_t<spatial_dimension>::type::iterator it_n =
neighbors_map.begin();
neighbors_map_t<spatial_dimension>::type::iterator end_n =
neighbors_map.end();
for (; it_n != end_n; ++it_n) {
std::sort(it_n->second.begin(), it_n->second.end());
std::vector<Point<spatial_dimension>>::iterator it_v = it_n->second.begin();
std::vector<Point<spatial_dimension>>::iterator end_v = it_n->second.end();
nout << "####" << std::endl;
nout << it_n->second.size() << std::endl;
nout << it_n->first << std::endl;
nout << "#" << std::endl;
for (; it_v != end_v; ++it_v) {
nout << *it_v << std::endl;
}
}
fout.close();
synch_registry.registerSynchronizer(*dist, SynchronizationTag::_smm_mass);
synch_registry.registerSynchronizer(*grid_communicator,
SynchronizationTag::_test);
AKANTU_DEBUG_INFO("Synchronizing tag on Dist");
synch_registry.synchronize(SynchronizationTag::_smm_mass);
AKANTU_DEBUG_INFO("Synchronizing tag on Grid");
synch_registry.synchronize(SynchronizationTag::_test);
delete grid_communicator;
delete dist;
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_synchronizer/test_grid_synchronizer_check_neighbors.cc b/test/test_synchronizer/test_grid_synchronizer_check_neighbors.cc
index 8449c5936..73cd3f44e 100644
--- a/test/test_synchronizer/test_grid_synchronizer_check_neighbors.cc
+++ b/test/test_synchronizer/test_grid_synchronizer_check_neighbors.cc
@@ -1,132 +1,132 @@
/**
* @file test_grid_synchronizer_check_neighbors.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Tue Feb 20 2018
*
* @brief Test the generation of neighbors list based on a akaentu::Grid
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <fstream>
#include <iostream>
#include <string>
#include "aka_common.hh"
#include "communicator.hh"
using namespace akantu;
-const UInt spatial_dimension = 3;
+const Int spatial_dimension = 3;
#include "test_grid_tools.hh"
void readNeighbors(
std::ifstream & nin,
neighbors_map_t<spatial_dimension>::type & neighbors_map_read) {
std::string line;
while (std::getline(nin, line)) {
std::getline(nin, line);
std::istringstream iss(line);
UInt nb_neig;
iss >> nb_neig;
std::getline(nin, line);
Point<spatial_dimension> pt;
pt.read(line);
std::getline(nin, line);
- for (UInt i = 0; i < nb_neig; ++i) {
+ for (Int i = 0; i < nb_neig; ++i) {
std::getline(nin, line);
Point<spatial_dimension> ne;
ne.read(line);
neighbors_map_read[pt].push_back(ne);
}
}
}
int main(int argc, char * argv[]) {
initialize(argc, argv);
const auto & comm = Communicator::getStaticCommunicator();
Int psize = comm.getNbProc();
Int prank = comm.whoAmI();
std::string file_ref = "neighbors_ref_1_0";
std::string file = "neighbors_ref";
std::stringstream sstr;
sstr << file << "_" << psize << "_" << prank;
file = sstr.str();
std::ifstream nin;
neighbors_map_t<spatial_dimension>::type neighbors_map_read;
nin.open(file_ref.c_str());
readNeighbors(nin, neighbors_map_read);
nin.close();
neighbors_map_t<spatial_dimension>::type neighbors_map;
nin.open(file.c_str());
readNeighbors(nin, neighbors_map);
nin.close();
neighbors_map_t<spatial_dimension>::type::iterator it_n =
neighbors_map.begin();
neighbors_map_t<spatial_dimension>::type::iterator end_n =
neighbors_map.end();
for (; it_n != end_n; ++it_n) {
std::sort(it_n->second.begin(), it_n->second.end());
std::vector<Point<spatial_dimension>>::iterator it_v = it_n->second.begin();
std::vector<Point<spatial_dimension>>::iterator end_v = it_n->second.end();
neighbors_map_t<spatial_dimension>::type::iterator it_nr =
neighbors_map_read.find(it_n->first);
if (it_nr == neighbors_map_read.end())
AKANTU_ERROR(
"Argh what is this point that is not present in the ref file "
<< it_n->first);
std::vector<Point<spatial_dimension>>::iterator it_vr =
it_nr->second.begin();
std::vector<Point<spatial_dimension>>::iterator end_vr =
it_nr->second.end();
for (; it_v != end_v && it_vr != end_vr; ++it_v, ++it_vr) {
if (*it_vr != *it_v)
AKANTU_ERROR("Neighbors does not match " << *it_v << " != " << *it_vr
<< " neighbor of "
<< it_n->first);
}
if (it_v == end_v && it_vr != end_vr) {
AKANTU_ERROR("Some neighbors of " << it_n->first << " are missing!");
}
if (it_v != end_v && it_vr == end_vr)
AKANTU_ERROR("Some neighbors of " << it_n->first << " are in excess!");
}
akantu::finalize();
return EXIT_SUCCESS;
}
diff --git a/test/test_synchronizer/test_grid_tools.hh b/test/test_synchronizer/test_grid_tools.hh
index 2c2fdf28d..92fe7c2ca 100644
--- a/test/test_synchronizer/test_grid_tools.hh
+++ b/test/test_synchronizer/test_grid_tools.hh
@@ -1,116 +1,116 @@
/**
* @file test_grid_tools.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Sun Oct 19 2014
* @date last modification: Fri Jan 15 2016
*
* @brief Tools to help for the akantu::Grid class tests
*
*
* @section LICENSE
*
* Copyright (©) 2014-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <map>
#include "aka_common.hh"
#include "aka_types.hh"
#define TOLERANCE 1e-7
-template <UInt dim> class Point {
+template <Int dim> class Point {
public:
Point() : id(0), tol(TOLERANCE) {
- for (UInt i = 0; i < dim; ++i)
+ for (Int i = 0; i < dim; ++i)
pos[i] = 0.;
}
Point(const Point & pt) : id(pt.id), tol(pt.tol) {
- for (UInt i = 0; i < dim; ++i)
+ for (Int i = 0; i < dim; ++i)
pos[i] = pt.pos[i];
}
Point(const Vector<Real> & pt, UInt id = 0) : id(id), tol(TOLERANCE) {
- for (UInt i = 0; i < dim; ++i)
+ for (Int i = 0; i < dim; ++i)
pos[i] = pt(i);
}
bool operator==(const Point & pt) const {
- for (UInt i = 0; i < dim; ++i) {
+ for (Int i = 0; i < dim; ++i) {
// std::cout << i << " " << pos[i] << " " << pt.pos[i] << " " <<
// std::abs(pos[i] - pt.pos[i]);
if (std::abs(pos[i] - pt.pos[i]) > tol) {
// std::cout << " " << false << std::endl;
return false;
} // else
// std::cout << " " << true << std::endl;
}
return true;
}
bool operator<(const Point & pt) const {
UInt i = 0, j = 0;
for (; (i < dim) && (j < dim); i++, j++) {
if (pos[i] < pt.pos[j])
return true;
if (pt.pos[j] < pos[i])
return false;
}
return (i == dim) && (j != dim);
}
bool operator!=(const Point & pt) const { return !(operator==(pt)); }
Real & operator()(UInt d) { return pos[d]; }
const Real & operator()(UInt d) const { return pos[d]; }
void read(const std::string & str) {
std::stringstream sstr(str);
- for (UInt i = 0; i < dim; ++i)
+ for (Int i = 0; i < dim; ++i)
sstr >> pos[i];
}
void write(std::ostream & ostr) const {
- for (UInt i = 0; i < dim; ++i) {
+ for (Int i = 0; i < dim; ++i) {
if (i != 0)
ostr << " ";
// ostr << std::setprecision(std::numeric_limits<Real>::digits) <<
// pos[i];
ostr << std::setprecision(9) << pos[i];
}
}
private:
UInt id;
Real pos[dim];
double tol;
};
-template <UInt dim> struct neighbors_map_t {
+template <Int dim> struct neighbors_map_t {
typedef std::map<Point<dim>, std::vector<Point<dim>>> type;
};
-template <UInt dim>
+template <Int dim>
inline std::ostream & operator<<(std::ostream & stream,
const Point<dim> & _this) {
_this.write(stream);
return stream;
}
diff --git a/test/test_synchronizer/test_node_synchronizer.cc b/test/test_synchronizer/test_node_synchronizer.cc
index 4508419d4..337b2b72f 100644
--- a/test/test_synchronizer/test_node_synchronizer.cc
+++ b/test/test_synchronizer/test_node_synchronizer.cc
@@ -1,213 +1,213 @@
/**
* @file test_node_synchronizer.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu May 11 2017
* @date last modification: Wed Jan 15 2020
*
* @brief test the default node synchronizer present in the mesh
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "test_synchronizers_fixture.hh"
/* -------------------------------------------------------------------------- */
#include "communicator.hh"
#include "data_accessor.hh"
#include "mesh.hh"
#include "node_synchronizer.hh"
/* -------------------------------------------------------------------------- */
#include <chrono>
#include <limits>
#include <random>
#include <thread>
/* -------------------------------------------------------------------------- */
using namespace akantu;
-class DataAccessorTest : public DataAccessor<UInt> {
+class DataAccessorTest : public DataAccessor<Idx> {
public:
explicit DataAccessorTest(Array<int> & data) : data(data) {}
- UInt getNbData(const Array<UInt> & nodes, const SynchronizationTag &) const {
+ Int getNbData(const Array<Idx> & nodes, const SynchronizationTag &) const {
return nodes.size() * sizeof(int);
}
- void packData(CommunicationBuffer & buffer, const Array<UInt> & nodes,
+ void packData(CommunicationBuffer & buffer, const Array<Idx> & nodes,
const SynchronizationTag &) const {
for (auto node : nodes) {
buffer << data(node);
}
}
- void unpackData(CommunicationBuffer & buffer, const Array<UInt> & nodes,
+ void unpackData(CommunicationBuffer & buffer, const Array<Idx> & nodes,
const SynchronizationTag &) {
for (auto node : nodes) {
buffer >> data(node);
}
}
protected:
Array<int> & data;
};
class TestNodeSynchronizerFixture : public TestSynchronizerFixture {
public:
static constexpr int max_int = std::numeric_limits<int>::max();
void SetUp() override {
TestSynchronizerFixture::SetUp();
this->distribute();
UInt nb_nodes = this->mesh->getNbNodes();
node_data = std::make_unique<Array<int>>(nb_nodes);
for (auto && data : enumerate(*node_data)) {
auto n = std::get<0>(data);
auto & d = std::get<1>(data);
UInt gn = this->mesh->getNodeGlobalId(n);
if (this->mesh->isMasterNode(n))
d = gn;
else if (this->mesh->isLocalNode(n))
d = -gn;
else if (this->mesh->isSlaveNode(n))
d = max_int;
else
d = -max_int;
}
data_accessor = std::make_unique<DataAccessorTest>(*node_data);
}
void TearDown() override {
data_accessor.reset(nullptr);
node_data.reset(nullptr);
}
void checkData() {
for (auto && data : enumerate(*this->node_data)) {
auto n = std::get<0>(data);
auto & d = std::get<1>(data);
UInt gn = this->mesh->getNodeGlobalId(n);
if (this->mesh->isMasterNode(n))
EXPECT_EQ(d, gn);
else if (this->mesh->isLocalNode(n))
EXPECT_EQ(d, -gn);
else if (this->mesh->isSlaveNode(n))
EXPECT_EQ(d, gn);
else
EXPECT_EQ(d, -max_int);
}
}
protected:
std::unique_ptr<Array<int>> node_data;
std::unique_ptr<DataAccessorTest> data_accessor;
};
/* -------------------------------------------------------------------------- */
constexpr int TestNodeSynchronizerFixture::max_int;
/* -------------------------------------------------------------------------- */
TEST_F(TestNodeSynchronizerFixture, SynchroneOnce) {
auto & synchronizer = this->mesh->getNodeSynchronizer();
synchronizer.synchronizeOnce(*this->data_accessor, SynchronizationTag::_test);
this->checkData();
}
/* -------------------------------------------------------------------------- */
TEST_F(TestNodeSynchronizerFixture, Synchrone) {
auto & node_synchronizer = this->mesh->getNodeSynchronizer();
node_synchronizer.synchronize(*this->data_accessor,
SynchronizationTag::_test);
this->checkData();
}
/* -------------------------------------------------------------------------- */
TEST_F(TestNodeSynchronizerFixture, Asynchrone) {
auto & synchronizer = this->mesh->getNodeSynchronizer();
synchronizer.asynchronousSynchronize(*this->data_accessor,
SynchronizationTag::_test);
std::random_device r;
std::default_random_engine engine(r());
std::uniform_int_distribution<int> uniform_dist(10, 100);
std::chrono::microseconds delay(uniform_dist(engine));
std::this_thread::sleep_for(delay);
synchronizer.waitEndSynchronize(*this->data_accessor,
SynchronizationTag::_test);
this->checkData();
}
/* -------------------------------------------------------------------------- */
TEST_F(TestNodeSynchronizerFixture, Gather) {
auto & synchronizer = this->mesh->getNodeSynchronizer();
const auto & comm = akantu::Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
if (prank == 0) {
Array<int> all_data(this->mesh->getNbGlobalNodes());
synchronizer.gather(*(this->node_data), all_data);
for (auto && data : enumerate(all_data)) {
EXPECT_EQ(std::get<0>(data), std::abs(std::get<1>(data)));
}
} else {
synchronizer.gather(*(this->node_data));
}
}
/* -------------------------------------------------------------------------- */
TEST_F(TestNodeSynchronizerFixture, Scatter) {
Array<int> local_data(this->mesh->getNbNodes(), 1, this->max_int);
auto & synchronizer = this->mesh->getNodeSynchronizer();
if (prank == 0) {
Array<int> all_data(this->mesh->getNbGlobalNodes());
for (auto && data : enumerate(all_data)) {
std::get<1>(data) = std::get<0>(data);
}
synchronizer.scatter(local_data, all_data);
} else {
synchronizer.scatter(local_data);
}
for (auto && data : enumerate(local_data)) {
auto && n = std::get<0>(data);
auto && d = std::get<1>(data);
UInt gn = this->mesh->getNodeGlobalId(n);
if (this->mesh->isPureGhostNode(n)) {
EXPECT_EQ(d, this->max_int);
} else {
EXPECT_EQ(d, gn);
}
}
}
diff --git a/test/test_synchronizer/test_synchronizers_fixture.hh b/test/test_synchronizer/test_synchronizers_fixture.hh
index 08daef52f..88bd2a961 100644
--- a/test/test_synchronizer/test_synchronizers_fixture.hh
+++ b/test/test_synchronizer/test_synchronizers_fixture.hh
@@ -1,83 +1,83 @@
/**
* @file test_synchronizers_fixture.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jan 26 2018
* @date last modification: Wed Feb 28 2018
*
* @brief Fixture for synchronizer tests
*
*
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
#include "communicator.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
using namespace akantu;
class TestSynchronizerFixture : public ::testing::Test {
public:
virtual void SetUp() {
- const UInt spatial_dimension = 3;
+ const Int spatial_dimension = 3;
mesh = std::make_unique<Mesh>(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
prank = comm.whoAmI();
psize = comm.getNbProc();
if (prank == 0) {
this->mesh->read("cube.msh");
}
}
virtual void TearDown() { this->mesh.reset(nullptr); }
void initBarycenters(ElementTypeMapArray<Real> & barycenters, Mesh & mesh) {
auto spatial_dimension = mesh.getSpatialDimension();
barycenters.initialize(mesh, _spatial_dimension = _all_dimensions,
_nb_component = spatial_dimension,
_with_nb_element = true);
for (auto && ghost_type : ghost_types) {
for (const auto & type : mesh.elementTypes(_all_dimensions, ghost_type)) {
for (auto && data : enumerate(
make_view(barycenters(type, ghost_type), spatial_dimension))) {
- Element element{type, UInt(std::get<0>(data)), ghost_type};
+ Element element{type, std::get<0>(data), ghost_type};
mesh.getBarycenter(element, std::get<1>(data));
}
}
}
}
void distribute() { this->mesh->distribute(); }
protected:
std::unique_ptr<Mesh> mesh;
Int prank;
Int psize;
};
diff --git a/third-party/akantu_iterators/.clang-tidy b/third-party/akantu_iterators/.clang-tidy
index 53e81de7b..6964dee38 100644
--- a/third-party/akantu_iterators/.clang-tidy
+++ b/third-party/akantu_iterators/.clang-tidy
@@ -1,3 +1,3 @@
-Checks: 'modernize-use-*, performance-*, bugprone-*, readability-*'
+Checks: 'modernize-use-*, performance-*, bugprone-*, readability-* cppcoreguidlines-*'
HeaderFilterRegex: 'include/.*'
FormatStyle: file
diff --git a/third-party/akantu_iterators/CMakeLists.txt b/third-party/akantu_iterators/CMakeLists.txt
index e8fb878d1..a7f38da02 100644
--- a/third-party/akantu_iterators/CMakeLists.txt
+++ b/third-party/akantu_iterators/CMakeLists.txt
@@ -1,73 +1,73 @@
cmake_minimum_required(VERSION 3.5.1)
project(akantu_iterators)
# ------------------------------------------------------------------------------
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(BUILD_SHARED_LIBS ON)
if (NOT AKANTU_ITERATORS_PYTHON_MAJOR_VERSION)
set(AKANTU_ITERATORS_PYTHON_MAJOR_VERSION 3)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
include(AkantuIteratorsTools)
# ------------------------------------------------------------------------------
set(AKANTU_ITERATORS_PUBLIC_HDRS
include/aka_compatibilty_with_cpp_standard.hh
include/aka_iterators.hh
include/aka_static_if.hh
include/aka_tuple_tools.hh
include/aka_str_hash.hh
include/iterators/aka_arange_iterator.hh
include/iterators/aka_enumerate_iterator.hh
include/iterators/aka_filter_iterator.hh
include/iterators/aka_transform_iterator.hh
include/iterators/aka_zip_iterator.hh
)
add_library(akantu_iterators INTERFACE)
target_include_directories(akantu_iterators
INTERFACE $<INSTALL_INTERFACE:include/${PROJECT_NAME}>
)
# small trick for build includes in public
set_property(TARGET akantu_iterators APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
set_target_properties(akantu_iterators
PROPERTIES
- INTERFACE_CXX_STANDARD 14
+ INTERFACE_CXX_STANDARD 17
)
# ------------------------------------------------------------------------------
option(AKANTU_ITERATORS_TESTS "Activating tests" OFF)
mark_as_advanced(AKANTU_ITERATORS_TESTS)
if(AKANTU_ITERATORS_TESTS)
enable_testing()
add_external_package(GTest)
add_subdirectory(test)
endif()
# ------------------------------------------------------------------------------
if(NOT AKANTU_ITERATORS_TARGETS_EXPORT)
set(AKANTU_ITERATORS_TARGETS_EXPORT AkantuIteratorsTargets)
endif()
include(GNUInstallDirs)
install(TARGETS akantu_iterators
EXPORT ${AKANTU_ITERATORS_TARGETS_EXPORT}
)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
if("${AKANTU_ITERATORS_TARGETS_EXPORT}" STREQUAL "AkantuIteratorsTargets")
install(EXPORT AkantuIteratorsTargets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
#Export for build tree
export(EXPORT AkantuIteratorsTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/AkantuIteratorsTargets.cmake")
export(PACKAGE AkantuIterators)
endif()
diff --git a/third-party/akantu_iterators/cmake/GTest.cmake b/third-party/akantu_iterators/cmake/GTest.cmake
index 3f9402c1b..0f7c85e39 100644
--- a/third-party/akantu_iterators/cmake/GTest.cmake
+++ b/third-party/akantu_iterators/cmake/GTest.cmake
@@ -1,31 +1,31 @@
if(NOT _GTest_version)
- set(_GTest_version "master")
+ set(_GTest_version "main")
endif()
-if(NOT EXISTS ${_GTest_external_dir})
+if(NOT EXISTS ${_GTest_external_dir}/CMakeLists.txt)
download_external_project(google-test
URL "https://github.com/google/googletest.git"
TAG "${_GTest_version}"
BACKEND GIT
THIRD_PARTY_SRC_DIR ${_GTest_external_dir}
${_GTest_update}
)
endif()
set(gtest_build_tests OFF CACHE INTERNAL "" FORCE)
set(INSTALL_GTEST OFF CACHE INTERNAL "" FORCE)
set(BUILD_GTEST ON CACHE INTERNAL "" FORCE)
set(BUILD_GMOCK OFF CACHE INTERNAL "" FORCE)
set(Python_ADDITIONAL_VERSIONS ${AKANTU_ITERATORS_PYTHON_MAJOR_VERSION})
add_subdirectory(${_GTest_external_dir}/google-test)
set_property(TARGET gtest_main PROPERTY CXX_STANDARD 14)
set_property(TARGET gtest PROPERTY CXX_STANDARD 14)
add_library(GTest::Main ALIAS gtest_main)
add_library(GTest::GTest ALIAS gtest)
mark_as_advanced(INSTALL_GTEST)
mark_as_advanced_prefix(gtest)
diff --git a/third-party/akantu_iterators/include/aka_compatibilty_with_cpp_standard.hh b/third-party/akantu_iterators/include/aka_compatibilty_with_cpp_standard.hh
index 5861502d3..40bbf93a9 100644
--- a/third-party/akantu_iterators/include/aka_compatibilty_with_cpp_standard.hh
+++ b/third-party/akantu_iterators/include/aka_compatibilty_with_cpp_standard.hh
@@ -1,193 +1,225 @@
/**
* @file aka_compatibilty_with_cpp_standard.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jun 18 2010
* @date last modification: Wed Jan 10 2018
*
* @brief The content of this file is taken from the possible implementations
* on
* http://en.cppreference.com
*
*
* Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_static_if.hh"
/* -------------------------------------------------------------------------- */
#include <iterator>
#include <tuple>
#include <type_traits>
#include <utility>
+
#if __cplusplus >= 201703L
#include <functional>
#endif
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH
#define AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH
namespace aka {
/* -------------------------------------------------------------------------- */
// Part taken from C++14
#if __cplusplus < 201402L
template <bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;
#else
template <bool B, class T = void> using enable_if_t = std::enable_if_t<B, T>;
#endif
/* -------------------------------------------------------------------------- */
// Part taken from C++17
#if __cplusplus < 201703L
/* -------------------------------------------------------------------------- */
// bool_constant
template <bool B> using bool_constant = std::integral_constant<bool, B>;
namespace {
template <bool B> constexpr bool bool_constant_v = bool_constant<B>::value;
}
/* -------------------------------------------------------------------------- */
// conjunction
template <class...> struct conjunction : std::true_type {};
template <class B1> struct conjunction<B1> : B1 {};
template <class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
/* -------------------------------------------------------------------------- */
// disjunction
template <class...> struct disjunction : std::false_type {};
template <class B1> struct disjunction<B1> : B1 {};
template <class B1, class... Bn>
struct disjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> {};
/* -------------------------------------------------------------------------- */
// negations
template <class B> struct negation : bool_constant<!bool(B::value)> {};
/* -------------------------------------------------------------------------- */
// invoke
namespace detail {
template <class T> struct is_reference_wrapper : std::false_type {};
template <class U>
struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {};
template <class T, class Type, class T1, class... Args>
decltype(auto) INVOKE(Type T::*f, T1 && t1, Args &&... args) {
static_if(std::is_member_function_pointer<decltype(f)>{})
.then_([&](auto && f) {
static_if(std::is_base_of<T, std::decay_t<T1>>{})
.then_([&](auto && f) {
return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
})
.elseif(is_reference_wrapper<std::decay_t<T1>>{})([&](auto && f) {
return (t1.get().*f)(std::forward<Args>(args)...);
})
.else_([&](auto && f) {
return ((*std::forward<T1>(t1)).*
f)(std::forward<Args>(args)...);
})(std::forward<decltype(f)>(f));
})
.else_([&](auto && f) {
static_assert(std::is_member_object_pointer<decltype(f)>::value,
"f is not a member object");
static_assert(sizeof...(args) == 0, "f takes arguments");
static_if(std::is_base_of<T, std::decay_t<T1>>{})
.then_([&](auto && f) { return std::forward<T1>(t1).*f; })
.elseif(std::is_base_of<T, std::decay_t<T1>>{})(
[&](auto && f) { return t1.get().*f; })
.else_([&](auto && f) { return (*std::forward<T1>(t1)).*f; })(
std::forward<decltype(f)>(f));
})(std::forward<decltype(f)>(f));
}
template <class F, class... Args>
decltype(auto) INVOKE(F && f, Args &&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
} // namespace detail
template <class F, class... Args>
decltype(auto) invoke(F && f, Args &&... args) {
return detail::INVOKE(std::forward<F>(f), std::forward<Args>(args)...);
}
/* -------------------------------------------------------------------------- */
// apply
namespace detail {
template <class F, class Tuple, std::size_t... Is>
constexpr decltype(auto) apply_impl(F && f, Tuple && t,
std::index_sequence<Is...> /*unused*/) {
return invoke(std::forward<F>(f), std::get<Is>(std::forward<Tuple>(t))...);
}
} // namespace detail
/* -------------------------------------------------------------------------- */
template <class F, class Tuple>
constexpr decltype(auto) apply(F && f, Tuple && t) {
return detail::apply_impl(
std::forward<F>(f), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{});
}
/* -------------------------------------------------------------------------- */
// count_if
template <class InputIt, class UnaryPredicate>
-typename std::iterator_traits<InputIt>::difference_type
-count_if(InputIt first, InputIt last, UnaryPredicate p) {
+auto count_if(InputIt first, InputIt last, UnaryPredicate p) ->
+ typename std::iterator_traits<InputIt>::difference_type {
typename std::iterator_traits<InputIt>::difference_type ret = 0;
for (; first != last; ++first) {
if (p(*first)) {
ret++;
}
}
return ret;
}
+namespace detail {
+ template <class T, class Tuple, std::size_t... I>
+ constexpr T make_from_tuple_impl(Tuple && t, std::index_sequence<I...>) {
+ static_assert(
+ std::is_constructible<T, decltype(std::get<I>(
+ std::declval<Tuple>()))...>::value,
+ "make_from_tuple needs T to be constructible");
+ return T(std::get<I>(std::forward<Tuple>(t))...);
+ }
+} // namespace detail
+
+template <class T, class Tuple> constexpr T make_from_tuple(Tuple && t) {
+ return detail::make_from_tuple_impl<T>(
+ std::forward<Tuple>(t),
+ std::make_index_sequence<
+ std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
+}
+
#else
template <bool B> using bool_constant = std::bool_constant<B>;
template <bool B> constexpr bool bool_constant_v = std::bool_constant<B>::value;
template <class... Args> using conjunction = std::conjunction<Args...>;
template <class... Args> using disjunction = std::disjunction<Args...>;
template <class B> using negation = std::negation<B>;
template <class F, class Tuple>
constexpr decltype(auto) apply(F && f, Tuple && t) {
return std::apply(std::forward<F>(f), std::forward<Tuple>(t));
}
template <class InputIt, class UnaryPredicate>
decltype(auto) count_if(InputIt first, InputIt last, UnaryPredicate p) {
- return std::count_if(first, last, p);
+ return std::count_if(std::forward<InputIt>(first),
+ std::forward<InputIt>(last),
+ std::forward<UnaryPredicate>(p));
+}
+
+template <class T, class Tuple>
+constexpr auto make_from_tuple(Tuple && t) -> T {
+ return std::make_from_tuple<T>(std::forward<Tuple>(t));
}
#endif
template <typename cat1, typename cat2>
using is_iterator_category_at_least =
std::is_same<std::common_type_t<cat1, cat2>, cat2>;
+template <typename T> struct size_type {
+ using type = typename std::decay_t<T>::size_type;
+};
+
+template <typename T> using size_type_t = typename size_type<T>::type;
+
} // namespace aka
#endif /* AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH */
diff --git a/third-party/akantu_iterators/include/aka_iterators.hh b/third-party/akantu_iterators/include/aka_iterators.hh
index 91b676892..732914f49 100644
--- a/third-party/akantu_iterators/include/aka_iterators.hh
+++ b/third-party/akantu_iterators/include/aka_iterators.hh
@@ -1,37 +1,38 @@
/**
* @file aka_iterators.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Aug 11 2017
* @date last modification: Mon Jan 29 2018
*
* @brief iterator interfaces
*
*
* Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "iterators/aka_arange_iterator.hh"
#include "iterators/aka_concatenate_iterator.hh"
#include "iterators/aka_enumerate_iterator.hh"
#include "iterators/aka_filter_iterator.hh"
+#include "iterators/aka_repeat_iterator.hh"
#include "iterators/aka_transform_iterator.hh"
#include "iterators/aka_zip_iterator.hh"
/* -------------------------------------------------------------------------- */
diff --git a/third-party/akantu_iterators/include/aka_named_tuple.hh b/third-party/akantu_iterators/include/aka_named_tuple.hh
new file mode 100644
index 000000000..74c231976
--- /dev/null
+++ b/third-party/akantu_iterators/include/aka_named_tuple.hh
@@ -0,0 +1,311 @@
+/**
+ * @file aka_tuple_tools.hh
+ *
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ *
+ * @date creation: Fri Aug 11 2017
+ * @date last modification: Mon Jan 29 2018
+ *
+ * @brief iterator interfaces
+ *
+ *
+ * Copyright 2019 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "aka_compatibilty_with_cpp_standard.hh"
+#include "aka_str_hash.hh"
+/* -------------------------------------------------------------------------- */
+#include <iostream>
+#include <tuple>
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_AKA_NAMED_TUPLE_HH
+#define AKANTU_AKA_NAMED_TUPLE_HH
+
+#ifndef AKANTU_ITERATORS_NAMESPACE
+#define AKANTU_ITERATORS_NAMESPACE akantu
+#endif
+
+namespace AKANTU_ITERATORS_NAMESPACE {
+
+namespace tuple {
+ using hash_type = uint64_t;
+
+ /* ------------------------------------------------------------------------ */
+ template <typename tag, typename type> struct named_tag {
+ using _tag = tag;
+ using _type = type;
+
+ template <typename T,
+ std::enable_if_t<not std::is_same_v<named_tag, T>> * = nullptr>
+ named_tag(T && value) : _value(std::forward<T>(value)) {}
+
+ type _value;
+ };
+
+#if (defined(__GNUC__) || defined(__GNUG__))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Weffc++"
+#endif
+ namespace details {
+ template <typename tag> struct named_tag_proxy {
+ using _tag = tag;
+
+ template <typename T> auto operator=(T && value) -> decltype(auto) {
+ return named_tag<tag, T>{std::forward<T>(value)};
+ }
+ };
+ } // namespace details
+#if (defined(__GNUC__) || defined(__GNUG__))
+#pragma GCC diagnostic pop
+#endif
+
+ template <typename CharT, CharT... chars> struct string_literal {
+ static constexpr tuple::hash_type hash =
+ hash::details::fnv1a<tuple::hash_type, CharT, chars...>();
+ using hash_type = std::integral_constant<tuple::hash_type, hash>;
+ };
+
+ /* ------------------------------------------------------------------------ */
+ template <typename T> struct is_named_tag : public std::false_type {};
+ template <typename tag>
+ struct is_named_tag<details::named_tag_proxy<tag>> : public std::true_type {};
+ template <typename tag, typename type>
+ struct is_named_tag<named_tag<tag, type>> : public std::true_type {};
+
+ template <typename T> constexpr bool is_named_tag_v = is_named_tag<T>::value;
+ /* ------------------------------------------------------------------------ */
+
+ template <class... Params>
+ struct named_tuple : public std::tuple<typename Params::_type...> {
+ using Index = int;
+ using Names_t = std::tuple<typename Params::_tag...>;
+ using parent = std::tuple<typename Params::_type...>;
+
+ named_tuple(Params &&... params)
+ : parent(std::forward<typename Params::_type>(params._value)...) {}
+
+ named_tuple(typename Params::_type &&... args)
+ : parent(std::forward<typename Params::_type>(args)...) {}
+
+ template <typename tag, Index Idx>
+ struct get_element_index_helper
+ : public std::integral_constant<
+ Index, (std::is_same_v<std::tuple_element_t<Idx, Names_t>, tag>)
+ ? Idx
+ : get_element_index_helper<tag, Idx + 1>()> {};
+
+ template <typename tag>
+ struct get_element_index_helper<tag, sizeof...(Params)>
+ : public std::integral_constant<Index, -1> {};
+
+ template <typename NT>
+ static constexpr auto get_element_index() noexcept -> Index {
+ return get_element_index_helper<typename NT::_tag, 0>::value;
+ }
+
+ template <typename NT>
+ static constexpr auto get_element_index(NT && /*unused*/) noexcept
+ -> Index {
+ return get_element_index_helper<typename NT::_tag, 0>::value;
+ }
+
+ template <typename NT, std::enable_if_t<is_named_tag_v<NT>> * = nullptr>
+ inline constexpr auto get(NT && /*unused*/) noexcept -> decltype(auto) {
+ const auto index = get_element_index<NT>();
+ static_assert((index != Index(-1)), "wrong named_tag");
+ return (std::get<index>(*this));
+ }
+
+ template <typename NT, std::enable_if_t<is_named_tag_v<NT>> * = nullptr>
+ inline constexpr auto get(NT && /*unused*/) const noexcept
+ -> decltype(auto) {
+ const auto index = get_element_index<NT>();
+ static_assert((index != Index(-1)), "wrong named_tag");
+ return (std::get<index>(*this));
+ }
+
+ template <typename NT,
+ std::enable_if_t<is_named_tag<NT>::value> * = nullptr>
+ inline constexpr auto operator[](NT && name_tag) const noexcept
+ -> decltype(auto) {
+ return get(std::forward<NT>(name_tag));
+ }
+
+ template <typename NT,
+ std::enable_if_t<is_named_tag<NT>::value> * = nullptr>
+ inline static constexpr auto has(NT && /*unused*/) noexcept -> bool {
+ const auto index = get_element_index<NT>();
+ return (index != Index(-1));
+ }
+
+ template <typename NT,
+ std::enable_if_t<is_named_tag<NT>::value> * = nullptr>
+ static constexpr auto has() noexcept -> bool {
+ constexpr auto index = get_element_index<NT>();
+ return (index != Index(-1));
+ }
+
+ // template <hash_type HashCode> static constexpr auto has() noexcept ->
+ // bool {
+ // constexpr auto index =
+ // get_element_index_helper<std::integral_constant<hash_type,
+ // HashCode>,
+ // 0>::value;
+ // return (index != Index(-1));
+ // }
+ };
+
+ /* ---------------------------------------------------------------------- */
+ template <typename T> struct is_named_tuple : public std::false_type {};
+ template <typename... Params>
+ struct is_named_tuple<named_tuple<Params...>> : public std::true_type {};
+
+ template <typename T>
+ constexpr bool is_named_tuple_v = is_named_tuple<T>::value;
+ /* ---------------------------------------------------------------------- */
+
+ template <typename... Params>
+ constexpr auto make_named_tuple(Params &&... params) noexcept
+ -> named_tuple<Params...> {
+ return named_tuple<Params...>(std::forward<Params>(params)...);
+ }
+
+ template <typename tag>
+ constexpr auto make_named_tag() noexcept -> decltype(auto) {
+ return details::named_tag_proxy<tag>{};
+ }
+
+ template <typename Tag, class Tuple> constexpr auto has() -> bool {
+ return std::decay_t<Tuple>::template has<Tag>();
+ }
+
+ template <typename Tag, class Tuple>
+ constexpr auto has(Tag && /**/, Tuple && /**/) -> bool {
+ return has<std::decay_t<Tag>, std::decay_t<Tuple>>();
+ }
+
+ template <typename Tag, class Tuple> constexpr auto has(Tag && /**/) -> bool {
+ return has<std::decay_t<Tag>, std::decay_t<Tuple>>();
+ }
+
+ template <typename Param, typename Tuple,
+ std::enable_if_t<is_named_tag_v<Param>> * = nullptr>
+ constexpr auto get(Tuple && tuple) noexcept -> decltype(auto) {
+ return tuple.template get<typename Param::hash>();
+ }
+
+ template <std::size_t I, class Tuple> struct tuple_name_tag {
+ using type = std::decay_t<
+ std::tuple_element_t<I, typename std::decay_t<Tuple>::Names_t>>;
+ };
+
+ template <std::size_t I, class Tuple>
+ using tuple_name_tag_t = typename tuple_name_tag<I, Tuple>::type;
+
+ template <std::size_t I, class Tuple> struct tuple_element {
+ using type = std::tuple_element_t<I, typename Tuple::parent>;
+ };
+
+ template <std::size_t I, class Tuple>
+ using tuple_element_t = typename tuple_element<I, Tuple>::type;
+
+ namespace details {
+ template <class Tuple, std::size_t... Is>
+ void printTuple(std::ostream & stream, Tuple && /*tuple*/,
+ std::index_sequence<Is...> && /*unused*/) {
+ std::initializer_list<int>{
+ ((stream << "{"
+ << std::tuple_element_t<
+ Is, typename std::decay_t<Tuple>::Names_t>::value
+ << "}"),
+ 0)...};
+ }
+ } // namespace details
+
+ template <class... Params>
+ std::ostream & operator<<(std::ostream & stream,
+ const named_tuple<Params...> & tuple) {
+ details::printTuple(stream, tuple,
+ std::make_index_sequence<sizeof...(Params)>{});
+ return stream;
+ }
+
+} // namespace tuple
+
+#if defined(__INTEL_COMPILER)
+// intel warnings here
+#elif defined(__clang__)
+// clang warnings here
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
+#elif (defined(__GNUC__) || defined(__GNUG__))
+// gcc warnings here
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+
+/// this is a GNU exstension
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3599.html
+template <typename C, C... chars>
+constexpr auto operator"" _n() -> decltype(auto) {
+ return tuple::make_named_tag<tuple::string_literal<C, chars...>>();
+}
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif (defined(__GNUC__) || defined(__GNUG__))
+#pragma GCC diagnostic pop
+#endif
+
+template <typename T> struct named_tuple_type {
+ static_assert(tuple::is_named_tuple_v<std::decay_t<T>>,
+ "T is not named_tuple type");
+ using type = std::decay_t<T>;
+};
+
+// just for readability
+template <typename T> using named_tuple_t = typename named_tuple_type<T>::type;
+
+} // namespace AKANTU_ITERATORS_NAMESPACE
+
+namespace aka {
+template <typename tag, typename type_>
+struct size_type<AKANTU_ITERATORS_NAMESPACE::tuple::named_tag<tag, type_>> {
+ using type = typename std::decay_t<type_>::size_type;
+};
+} // namespace aka
+
+/* -------------------------------------------------------------------------- */
+#include <iterator>
+/* -------------------------------------------------------------------------- */
+
+namespace std {
+template <typename tag, typename type>
+struct iterator_traits<
+ ::AKANTU_ITERATORS_NAMESPACE::tuple::named_tag<tag, type>>
+ : public iterator_traits<type> {};
+
+template <class... Types>
+struct tuple_size<AKANTU_ITERATORS_NAMESPACE::tuple::named_tuple<Types...>>
+ : std::integral_constant<std::size_t, sizeof...(Types)> {};
+
+} // namespace std
+
+#endif /* AKANTU_AKA_NAMED_TUPLE_HH */
diff --git a/third-party/akantu_iterators/include/aka_str_hash.hh b/third-party/akantu_iterators/include/aka_str_hash.hh
index bd2452a13..15424c3c1 100644
--- a/third-party/akantu_iterators/include/aka_str_hash.hh
+++ b/third-party/akantu_iterators/include/aka_str_hash.hh
@@ -1,184 +1,175 @@
/**
* @file aka_str_hash.hh
*
* @author Nicolas Richart
*
* @date creation lun déc 09 2019
*
* @brief A Documented file.
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <limits>
#include <type_traits>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_STR_HASH_HH
#define AKANTU_AKA_STR_HASH_HH
#ifndef AKANTU_ITERATORS_NAMESPACE
#define AKANTU_ITERATORS_NAMESPACE akantu
#endif
namespace AKANTU_ITERATORS_NAMESPACE {
namespace hash {
namespace details {
// CRC32 Table (zlib polynomial)
static constexpr uint32_t crc_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL};
/* --------------------------------------------------------------------------
*/
/// CRC32 hashing algorithm
constexpr uint32_t crc32_hash(const char * str, size_t idx) {
constexpr uint8_t mask_size = 8;
auto crc = (idx == 0 ? std::numeric_limits<uint32_t>::max()
: crc32_hash(str, idx - 1));
return (crc >> mask_size) ^
crc_table[(crc ^ str[idx]) & std::numeric_limits<uint8_t>::max()];
}
namespace {
template <typename Hash> constexpr Hash fnv1a_offset = 0x0;
template <>
constexpr uint64_t fnv1a_offset<uint64_t> = 0xcbf29ce484222325;
template <> constexpr uint32_t fnv1a_offset<uint32_t> = 0x811c9dc5;
template <typename Hash> constexpr Hash fnv1a_prime = 0x0;
template <> constexpr uint64_t fnv1a_prime<uint64_t> = 0x00000100000001b3;
template <> constexpr uint32_t fnv1a_prime<uint32_t> = 0x01000193;
} // namespace
template <class T, T offset = fnv1a_offset<T>, T prime = fnv1a_prime<T>>
constexpr T fnv1a_hash(const char * str, size_t idx) {
return ((idx ? fnv1a_hash<T, offset, prime>(str, idx - 1) : offset) ^
str[idx]) *
prime;
}
// FNV-1a 32bit hashing algorithm.
constexpr decltype(auto) fnv1a_32_hash(const char * str, size_t idx) {
return fnv1a_hash<uint32_t>(str, idx);
}
// FNV-1a 32bit hashing algorithm.
constexpr decltype(auto) fnv1a_64_hash(const char * str, size_t idx) {
return fnv1a_hash<uint64_t>(str, idx);
}
template <typename Hash, typename CharT, CharT... chars>
constexpr Hash fnv1a() {
auto result = fnv1a_offset<Hash>;
(void)std::initializer_list<Hash>{
(result = (result ^ chars) * fnv1a_prime<Hash>, Hash{})...};
return result;
}
} // namespace details
constexpr uint32_t operator"" _crc32(const char * str, size_t size) {
return details::crc32_hash(str, size - 1) ^
std::numeric_limits<uint32_t>::max();
}
constexpr uint32_t operator"" _fnv1a32(const char * str, size_t size) {
return details::fnv1a_32_hash(str, size - 1);
}
constexpr uint64_t operator"" _fnv1a64(const char * str, size_t size) {
return details::fnv1a_64_hash(str, size - 1);
}
} // namespace hash
-template <typename CharT, CharT... chars> struct string_literal {
- static constexpr std::size_t hash =
- hash::details::fnv1a<std::size_t, CharT, chars...>();
- using hash_type = std::integral_constant<uint64_t, hash>;
-};
-
-template <typename CharT, CharT... chars>
-constexpr std::size_t string_literal<CharT, chars...>::hash;
-
-constexpr auto operator"" _h(const char * str, size_t size) {
- return hash::details::fnv1a_64_hash(str, size - 1);
-}
+// constexpr auto operator"" _h(const char * str, size_t size) {
+// return hash::details::fnv1a_64_hash(str, size - 1);
+// }
} // namespace AKANTU_ITERATORS_NAMESPACE
#endif /* AKANTU_AKA_STR_HASH_HH */
diff --git a/third-party/akantu_iterators/include/aka_tuple_tools.hh b/third-party/akantu_iterators/include/aka_tuple_tools.hh
index 38eac8e3c..03e53b2ae 100644
--- a/third-party/akantu_iterators/include/aka_tuple_tools.hh
+++ b/third-party/akantu_iterators/include/aka_tuple_tools.hh
@@ -1,407 +1,438 @@
/**
* @file aka_tuple_tools.hh
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Aug 11 2017
* @date last modification: Mon Jan 29 2018
*
* @brief iterator interfaces
*
*
* Copyright 2019 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_compatibilty_with_cpp_standard.hh"
-#include "aka_str_hash.hh"
+#include "aka_named_tuple.hh"
/* -------------------------------------------------------------------------- */
#include <tuple>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_AKA_TUPLE_TOOLS_HH
#define AKANTU_AKA_TUPLE_TOOLS_HH
#ifndef AKANTU_ITERATORS_NAMESPACE
#define AKANTU_ITERATORS_NAMESPACE akantu
#endif
+#define AKA_ITERATOR_EXPORT_NAMESPACE __attribute__((visibility("hidden")))
+#define FWD(x) std::forward<decltype(x)>(x)
+
namespace AKANTU_ITERATORS_NAMESPACE {
namespace tuple {
- /* ---------------------------------------------------------------------- */
- template <typename tag, typename type> struct named_tag {
- using _tag = tag; ///< key
- using _type = type; ///< value type
-
- template <
- typename T,
- std::enable_if_t<not std::is_same<named_tag, T>::value> * = nullptr>
- explicit named_tag(T && value) // NOLINT
- : _value(std::forward<T>(value)) {}
-
- type _value;
- };
-
- namespace details {
-/* ---------------------------------------------------------------------- */
-#if (defined(__GNUC__) || defined(__GNUG__))
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Weffc++"
-#endif
- template <typename tag> struct named_tag_proxy {
- using _tag = tag;
-
- template <typename T> decltype(auto) operator=(T && value) {
- return named_tag<_tag, T>{std::forward<T>(value)};
- }
- };
-#if (defined(__GNUC__) || defined(__GNUG__))
-#pragma GCC diagnostic pop
-#endif
- } // namespace details
-
- /* ---------------------------------------------------------------------- */
- template <typename T> struct is_named_tag : public std::false_type {};
- template <typename tag>
- struct is_named_tag<details::named_tag_proxy<tag>> : public std::true_type {};
- template <typename tag, typename type>
- struct is_named_tag<named_tag<tag, type>> : public std::true_type {};
- /* ---------------------------------------------------------------------- */
-
- template <class... Params>
- struct named_tuple : public std::tuple<typename Params::_type...> {
- using Names_t = std::tuple<typename Params::_tag...>;
- using parent = std::tuple<typename Params::_type...>;
-
- named_tuple(Params &&... params)
- : parent(std::forward<typename Params::_type>(params._value)...) {}
-
- named_tuple(typename Params::_type &&... args)
- : parent(std::forward<typename Params::_type>(args)...) {}
-
- private:
- template <typename tag, std::size_t Idx,
- std::enable_if_t<Idx == sizeof...(Params)> * = nullptr>
- static constexpr std::size_t get_element_index() noexcept {
- return -1;
- }
-
- template <typename tag, std::size_t Idx,
- std::enable_if_t<(Idx < sizeof...(Params))> * = nullptr>
- static constexpr std::size_t get_element_index() noexcept {
- using _tag = std::tuple_element_t<Idx, Names_t>;
- return (std::is_same<_tag, tag>::value)
- ? Idx
- : get_element_index<tag, Idx + 1>();
- }
-
- public:
- template <typename NT,
- std::enable_if_t<is_named_tag<NT>::value> * = nullptr>
- constexpr decltype(auto) get(NT && /*unused*/) noexcept {
- const auto index = get_element_index<typename NT::_tag, 0>();
- static_assert((index != -1), "wrong named_tag");
- return (std::get<index>(*this));
- }
-
- template <typename NT,
- std::enable_if_t<is_named_tag<NT>::value> * = nullptr>
- constexpr decltype(auto) get(NT && /*unused*/) const noexcept {
- const auto index = get_element_index<typename NT::_tag, 0>();
- static_assert((index != -1), "wrong named_tag");
- return std::get<index>(*this);
- }
- };
-
- /* ---------------------------------------------------------------------- */
- template <typename T> struct is_named_tuple : public std::false_type {};
+ template <typename T> struct is_tuple : public std::false_type {};
template <typename... Params>
- struct is_named_tuple<named_tuple<Params...>> : public std::true_type {};
- /* ---------------------------------------------------------------------- */
-
- template <typename... Params>
- constexpr decltype(auto) make_named_tuple(Params &&... params) noexcept {
- return named_tuple<Params...>(std::forward<Params>(params)...);
- }
-
- template <typename tag> constexpr decltype(auto) make_named_tag() noexcept {
- return details::named_tag_proxy<tag>{};
- }
-
- template <size_t HashCode> constexpr decltype(auto) get() {
- return make_named_tag<std::integral_constant<size_t, HashCode>>();
- }
+ struct is_tuple<std::tuple<Params...>> : public std::true_type {};
- template <size_t HashCode, class Tuple>
- constexpr decltype(auto) get(Tuple && tuple) {
- return tuple.get(get<HashCode>());
- }
-
- template <typename Param, typename Tuple,
- std::enable_if_t<is_named_tag<Param>::value> * = nullptr>
- constexpr decltype(auto) get(Tuple && tuple) noexcept {
- return tuple.template get<typename Param::hash>();
- }
-
-#if !defined(__INTEL_COMPILER)
-# if defined(__clang__)
-// clang warnings here
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
-# elif (defined(__GNUC__) || defined(__GNUG__))
-// gcc warnings here
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wpedantic"
-# endif
- /// this is a GNU exstension
- /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3599.html
- template <class CharT, CharT... chars>
- constexpr decltype(auto) operator"" _n() {
- return make_named_tag<std::integral_constant<
- std::size_t, string_literal<CharT, chars...>::hash>>();
- }
-# if defined(__clang__)
-# pragma clang diagnostic pop
-# elif (defined(__GNUC__) || defined(__GNUG__))
-# pragma GCC diagnostic pop
-# endif
-#endif
/* ------------------------------------------------------------------------ */
- namespace details {
+ namespace details AKA_ITERATOR_EXPORT_NAMESPACE {
template <std::size_t N> struct Foreach {
template <class Tuple>
static constexpr inline auto not_equal(Tuple && a, Tuple && b) -> bool {
if (std::get<N - 1>(std::forward<Tuple>(a)) ==
std::get<N - 1>(std::forward<Tuple>(b))) {
return false;
}
return Foreach<N - 1>::not_equal(std::forward<Tuple>(a),
std::forward<Tuple>(b));
}
template <class Tuple, class V>
static constexpr inline auto find(Tuple && tuple, V && value)
-> std::size_t {
constexpr auto size = std::tuple_size<std::decay_t<Tuple>>::value;
if (std::get<size - N>(std::forward<Tuple>(tuple)) == value) {
return size - N;
}
return Foreach<N - 1>::find(std::forward<Tuple>(tuple),
std::forward<V>(value));
}
};
/* ---------------------------------------------------------------------- */
template <> struct Foreach<0> {
template <class Tuple>
static constexpr inline auto not_equal(Tuple && a, Tuple && b) -> bool {
return std::get<0>(std::forward<Tuple>(a)) !=
std::get<0>(std::forward<Tuple>(b));
}
template <class Tuple, class V>
static constexpr inline auto find(Tuple && tuple, V && value)
-> std::size_t {
constexpr auto size = std::tuple_size<std::decay_t<Tuple>>::value;
if (std::get<size - 1>(std::forward<Tuple>(tuple)) == value) {
return size - 1;
}
return size;
}
};
template <typename... Ts>
- decltype(auto) make_tuple_no_decay(Ts &&... args) {
+ auto make_tuple_no_decay(Ts &&... args) -> decltype(auto) {
return std::tuple<Ts...>(std::forward<Ts>(args)...);
}
template <typename... Names, typename... Ts>
- constexpr decltype(auto)
- make_named_tuple_no_decay(std::tuple<Names...> /*unused*/, Ts &&... args) {
+ auto make_named_tuple_no_decay(std::tuple<Names...> /*unused*/,
+ Ts &&... args) -> decltype(auto) {
return named_tuple<named_tag<Names, Ts>...>(std::forward<Ts>(args)...);
}
template <class F, class Tuple, std::size_t... Is>
constexpr void foreach_impl(F && func, Tuple && tuple,
std::index_sequence<Is...> && /*unused*/) {
(void)std::initializer_list<int>{
(std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(tuple))),
0)...};
}
template <class F, class Tuple, std::size_t... Is>
- constexpr decltype(auto)
- transform_impl(F && func, Tuple && tuple,
- std::index_sequence<Is...> && /*unused*/) {
+ constexpr auto transform_impl(F && func, Tuple && tuple,
+ std::index_sequence<Is...> && /*unused*/)
+ -> decltype(auto) {
return make_tuple_no_decay(
std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(tuple)))...);
}
template <class F, class Tuple, std::size_t... Is>
- constexpr decltype(auto)
- transform_impl(F && func, Tuple && tuple1, Tuple && tuple2,
- std::index_sequence<Is...> && /*unused*/) {
+ constexpr auto transform_impl(F && func, Tuple && tuple1, Tuple && tuple2,
+ std::index_sequence<Is...> && /*unused*/)
+ -> decltype(auto) {
return make_tuple_no_decay(
std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(tuple1)),
std::get<Is>(std::forward<Tuple>(tuple2)))...);
}
template <class F, class Tuple, std::size_t... Is>
- constexpr decltype(auto)
+ constexpr auto
transform_named_impl(F && func, Tuple && tuple,
- std::index_sequence<Is...> && /*unused*/) {
+ std::index_sequence<Is...> && /*unused*/)
+ -> decltype(auto) {
return make_named_tuple_no_decay(
typename std::decay_t<Tuple>::Names_t{},
std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(tuple)))...);
}
- } // namespace details
+ template <class Tuple, std::size_t... Is>
+ auto flatten(Tuple && tuples, std::index_sequence<Is...> /*unused*/)
+ -> decltype(auto) {
+ return std::tuple_cat(std::get<Is>(tuples)...);
+ }
+
+ template <class Tuple, class... Vals, std::size_t... Is>
+ auto append_impl(std::index_sequence<Is...> && /*unused*/, Tuple && tuple,
+ Vals &&... other_vals) -> decltype(auto) {
+ return make_tuple_no_decay(
+ FWD(std::get<Is>(std::forward<Tuple>(tuple)))...,
+ std::forward<Vals>(other_vals)...);
+ }
+
+ template <class Tuple, class... Vals, std::size_t... Is>
+ auto append_named_impl(std::index_sequence<Is...> && /*unused*/,
+ Tuple && tuple, Vals &&... other_vals)
+ -> decltype(auto) {
+ return make_named_tuple_no_decay(
+ std::tuple<tuple_name_tag_t<Is, Tuple>...,
+ typename std::decay_t<Vals>::_tag...>(),
+ FWD(std::get<Is>(std::forward<Tuple>(tuple)))...,
+ FWD(other_vals._value)...);
+ }
+
+ template <std::size_t nth, class Tuple, std::size_t... Is_before,
+ std::size_t... Is_after>
+ auto remove_impl(std::index_sequence<Is_before...> && /*unused*/,
+ std::index_sequence<Is_after...> && /*unused*/,
+ Tuple && tuple) -> decltype(auto) {
+ return make_tuple_no_decay(
+ FWD(std::get<Is_before>(std::forward<Tuple>(tuple)))...,
+ FWD(std::get<Is_after + nth + 1>(std::forward<Tuple>(tuple)))...);
+ }
+
+ template <std::size_t nth, class Tuple, std::size_t... Is_before,
+ std::size_t... Is_after>
+ auto remove_named_impl(std::index_sequence<Is_before...> && /*unused*/,
+ std::index_sequence<Is_after...> && /*unused*/,
+ Tuple && tuple) -> decltype(auto) {
+ return make_named_tuple_no_decay(
+ std::tuple<tuple::tuple_name_tag_t<Is_before, std::decay_t<Tuple>>...,
+ tuple::tuple_name_tag_t<Is_after + nth + 1,
+ std::decay_t<Tuple>>...>{},
+ std::get<Is_before>(std::forward<Tuple>(tuple))...,
+ std::get<Is_after + nth + 1>(std::forward<Tuple>(tuple))...);
+ }
+
+ template <std::size_t nth, class Tuple, class Value,
+ std::size_t... Is_before, std::size_t... Is_after>
+ auto replace_impl(std::index_sequence<Is_before...> && /*unused*/,
+ std::index_sequence<Is_after...> && /*unused*/,
+ Tuple && tuple, Value && value) -> decltype(auto) {
+ return make_tuple_no_decay(
+ std::get<Is_before>(std::forward<Tuple>(tuple))...,
+ std::forward<Value>(value),
+ std::get<Is_after + nth + 1>(std::forward<Tuple>(tuple))...);
+ }
+
+ template <std::size_t nth, typename Tag, class Tuple, class Value,
+ std::size_t... Is_before, std::size_t... Is_after>
+ auto replace_named_impl(std::index_sequence<Is_before...> && /*unused*/,
+ std::index_sequence<Is_after...> && /*unused*/,
+ Tuple && tuple, Value && value) -> decltype(auto) {
+ using tuple_type = std::decay_t<Tuple>;
+ return make_named_tuple_no_decay(
+ std::tuple<
+ tuple::tuple_name_tag_t<Is_before, tuple_type>..., Tag,
+ tuple::tuple_name_tag_t<Is_after + nth + 1, tuple_type>...>{},
+ std::get<Is_before>(std::forward<Tuple>(tuple))...,
+ std::forward<Value>(value),
+ std::get<Is_after + nth + 1>(std::forward<Tuple>(tuple))...);
+ }
+ } // namespace AKA_ITERATOR_EXPORT_NAMESPACE
/* ------------------------------------------------------------------------
*/
template <class Tuple,
- std::enable_if_t<not is_named_tuple<std::decay_t<Tuple>>::value> * =
- nullptr>
+ std::enable_if_t<is_tuple<std::decay_t<Tuple>>::value> * = nullptr>
constexpr auto are_not_equal(Tuple && a, Tuple && b) -> bool {
return details::Foreach<std::tuple_size<std::decay_t<Tuple>>::value>::
not_equal(std::forward<Tuple>(a), std::forward<Tuple>(b));
}
template <
class Tuple,
std::enable_if_t<is_named_tuple<std::decay_t<Tuple>>::value> * = nullptr>
constexpr auto are_not_equal(Tuple && a, Tuple && b) -> bool {
return details::Foreach<
std::tuple_size<typename std::decay_t<Tuple>::parent>::value>::
not_equal(std::forward<Tuple>(a), std::forward<Tuple>(b));
}
template <class Tuple, class V>
constexpr decltype(auto) find(Tuple && tuple, V && value) {
return details::Foreach<std::tuple_size<std::decay_t<Tuple>>::value>::find(
std::forward<Tuple>(tuple), std::forward<V>(value));
}
template <class F, class Tuple,
- std::enable_if_t<not is_named_tuple<std::decay_t<Tuple>>::value> * =
- nullptr>
+ std::enable_if_t<is_tuple<std::decay_t<Tuple>>::value> * = nullptr>
constexpr void foreach (F && func, Tuple && tuple) {
return details::foreach_impl(
std::forward<F>(func), std::forward<Tuple>(tuple),
std::make_index_sequence<
std::tuple_size<std::decay_t<Tuple>>::value>{});
}
template <
class F, class Tuple,
std::enable_if_t<is_named_tuple<std::decay_t<Tuple>>::value> * = nullptr>
constexpr void foreach (F && func, Tuple && tuple) {
return details::foreach_impl(
std::forward<F>(func), std::forward<Tuple>(tuple),
std::make_index_sequence<
std::tuple_size<typename std::decay_t<Tuple>::parent>::value>{});
}
+ /* ------------------------------------------------------------------------ */
template <class F, class Tuple,
- std::enable_if_t<not is_named_tuple<std::decay_t<Tuple>>::value> * =
- nullptr>
- constexpr decltype(auto) transform(F && func, Tuple && tuple) {
+ std::enable_if_t<is_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ constexpr auto transform(F && func, Tuple && tuple) -> decltype(auto) {
return details::transform_impl(
std::forward<F>(func), std::forward<Tuple>(tuple),
std::make_index_sequence<
std::tuple_size<std::decay_t<Tuple>>::value>{});
}
template <class F, class Tuple,
- std::enable_if_t<not is_named_tuple<std::decay_t<Tuple>>::value> * =
- nullptr>
- constexpr decltype(auto) transform(F && func, Tuple && tuple1,
- Tuple && tuple2) {
+ std::enable_if_t<is_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ constexpr auto transform(F && func, Tuple && tuple1, Tuple && tuple2)
+ -> decltype(auto) {
return details::transform_impl(
std::forward<F>(func), std::forward<Tuple>(tuple1),
std::forward<Tuple>(tuple2),
std::make_index_sequence<
std::tuple_size<std::decay_t<Tuple>>::value>{});
}
template <
class F, class Tuple,
std::enable_if_t<is_named_tuple<std::decay_t<Tuple>>::value> * = nullptr>
- constexpr decltype(auto) transform(F && func, Tuple && tuple) {
+ constexpr auto transform(F && func, Tuple && tuple) -> decltype(auto) {
return details::transform_named_impl(
std::forward<F>(func), std::forward<Tuple>(tuple),
std::make_index_sequence<
std::tuple_size<typename std::decay_t<Tuple>::parent>::value>{});
}
- namespace details {
- template <class Tuple, std::size_t... Is>
- constexpr decltype(auto) flatten(Tuple && tuples,
- std::index_sequence<Is...> /*unused*/) {
- return std::tuple_cat(std::get<Is>(tuples)...);
- }
- } // namespace details
-
- template <class Tuple> constexpr decltype(auto) flatten(Tuple && tuples) {
+ /* ------------------------------------------------------------------------ */
+ template <class Tuple> auto flatten(Tuple && tuples) -> decltype(auto) {
return details::flatten(std::forward<Tuple>(tuples),
std::make_index_sequence<
std::tuple_size<std::decay_t<Tuple>>::value>());
}
namespace details {
template <size_t n, class Tuple>
- decltype(auto) dynamic_get_impl(size_t i, Tuple && tuple) {
+ auto dynamic_get_impl(size_t i, Tuple && tuple) -> decltype(auto) {
constexpr auto size = std::tuple_size<std::decay_t<Tuple>>::value;
if (i == n) {
return std::get<n>(tuple);
- } else if (n == size - 1) {
+ }
+
+ if (n == size - 1) {
throw std::out_of_range("Tuple element out of range.");
- } else {
- return dynamic_get_impl<(n < size - 1 ? n + 1 : 0)>(i, tuple);
}
+
+ return dynamic_get_impl<(n < size - 1 ? n + 1 : 0)>(i, tuple);
}
} // namespace details
+ /* ------------------------------------------------------------------------ */
+ template <typename... Ts> struct cat {
+ using type = decltype(std::tuple_cat(std::declval<Ts>()...));
+ };
+
+ template <typename... T> using cat_t = typename cat<T...>::type;
+
+ /* ------------------------------------------------------------------------ */
+ template <template <typename> class Pred, typename... Ts> struct filter {};
+
+ template <template <typename> class Pred, typename T>
+ struct filter<Pred, std::tuple<T>> {
+ using type =
+ std::conditional_t<Pred<T>::value, std::tuple<T>, std::tuple<>>;
+ };
+
+ template <template <typename> class Pred, typename T, typename... Ts>
+ struct filter<Pred, std::tuple<T, Ts...>> {
+ using type = cat_t<typename filter<Pred, std::tuple<T>>::type,
+ typename filter<Pred, std::tuple<Ts...>>::type>;
+ };
+
+ template <template <typename> class Pred, typename... Ts>
+ using filter_t = typename filter<Pred, Ts...>::type;
+
+ /* ------------------------------------------------------------------------ */
template <class Tuple>
- constexpr decltype(auto) dynamic_get(std::size_t i, Tuple && tuple) {
+ constexpr auto dynamic_get(std::size_t i, Tuple && tuple) -> decltype(auto) {
return details::dynamic_get_impl<0>(i, std::forward<Tuple>(tuple));
}
+
+ /* ------------------------------------------------------------------------ */
+ template <class Tuple, class... Vals,
+ std::enable_if_t<is_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ auto append(Tuple && tuple, Vals &&... vals) -> decltype(auto) {
+ return details::append_impl(
+ std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{},
+ FWD(tuple), std::forward<Vals>(vals)...);
+ }
+
+ template <
+ class Tuple, class... Vals,
+ std::enable_if_t<is_named_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ auto append(Tuple && tuple, Vals &&... vals) -> decltype(auto) {
+ return details::append_named_impl(
+ std::make_index_sequence<
+ std::tuple_size<typename std::decay_t<Tuple>::parent>::value>{},
+ FWD(tuple), std::forward<Vals>(vals)...);
+ }
+
+ /* ------------------------------------------------------------------------ */
+ template <std::size_t nth, class Tuple,
+ std::enable_if_t<is_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ auto remove(Tuple && tuple) -> decltype(auto) {
+ static_assert(nth < std::tuple_size<Tuple>(),
+ "You are trying to remove a non existing entry");
+ return details::remove_impl<nth>(
+ std::make_index_sequence<nth>{},
+ std::make_index_sequence<std::tuple_size<Tuple>::value - nth - 1>{},
+ std::forward<Tuple>(tuple));
+ }
+
+ template <
+ typename Tag, class Tuple,
+ std::enable_if_t<is_named_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ auto remove(Tuple && tuple) -> decltype(auto) {
+ static_assert(tuple.has(Tag{}),
+ "You are trying to remove a non existing entry");
+ constexpr auto nth = tuple.get_element_index(Tag{});
+ return details::remove_named_impl<nth>(
+ std::make_index_sequence<nth>{},
+ std::make_index_sequence<
+ std::tuple_size<typename std::decay_t<Tuple>::parent>::value - nth -
+ 1>{},
+ std::forward<Tuple>(tuple));
+ }
+
+ template <std::size_t nth, class Tuple, class Value,
+ std::enable_if_t<is_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ auto replace(Tuple && tuple, Value && value) -> decltype(auto) {
+ static_assert(nth < std::tuple_size<Tuple>(),
+ "You are trying to replace a non existing entry");
+ return details::replace_impl<nth>(
+ std::make_index_sequence<nth>{},
+ std::make_index_sequence<std::tuple_size<Tuple>::value - nth - 1>{},
+ std::forward<Tuple>(tuple), std::forward<Value>(value));
+ }
+
+ template <typename Tag, class Tuple, class Value,
+ std::enable_if_t<is_named_tuple<std::decay_t<Tuple>>::value and
+ not is_named_tag_v<Value>> * = nullptr>
+ auto replace(Tuple && tuple, Value && value) -> decltype(auto) {
+ static_assert(tuple::has<Tag, Tuple>(),
+ "You are trying to replace a non existing entry");
+ constexpr std::size_t nth =
+ std::decay_t<Tuple>::template get_element_index<Tag>();
+ return details::replace_named_impl<nth, typename Tag::_tag>(
+ std::make_index_sequence<nth>{},
+ std::make_index_sequence<
+ std::tuple_size<typename std::decay_t<Tuple>::parent>::value - nth -
+ 1>{},
+ std::forward<Tuple>(tuple), std::forward<Value>(value));
+ }
+
+ template <class Tuple, class Value,
+ std::enable_if_t<is_named_tuple_v<std::decay_t<Tuple>> and
+ is_named_tag_v<Value>> * = nullptr>
+ auto replace(Tuple && tuple, Value && value) -> decltype(auto) {
+ using Tag = decltype(make_named_tag<typename std::decay_t<Value>::_tag>());
+ return replace<Tag>(std::forward<Tuple>(tuple),
+ std::forward<decltype(value._value)>(value._value));
+ }
+
} // namespace tuple
} // namespace AKANTU_ITERATORS_NAMESPACE
-/* -------------------------------------------------------------------------- */
-#include <iterator>
-/* -------------------------------------------------------------------------- */
+#undef FWD
-namespace std {
-template <typename tag, typename type>
-struct iterator_traits<
- ::AKANTU_ITERATORS_NAMESPACE::tuple::named_tag<tag, type>> {
- using iterator_category = typename type::iterator_category;
- using value_type = typename type::value_type;
- using difference_type = typename type::difference_type;
- using pointer = typename type::pointer;
- using reference = typename type::reference;
-};
-} // namespace std
#endif /* AKANTU_AKA_TUPLE_TOOLS_HH */
diff --git a/third-party/akantu_iterators/include/iterators/aka_arange_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_arange_iterator.hh
index a9a521741..6e3cd1872 100644
--- a/third-party/akantu_iterators/include/iterators/aka_arange_iterator.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_arange_iterator.hh
@@ -1,176 +1,178 @@
/**
* @file aka_arange_iterator.hh
*
* @author Nicolas Richart
*
* @date creation jeu déc 12 2019
*
* @brief implementation of arange
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "aka_iterator_tools.hh"
+/* -------------------------------------------------------------------------- */
#include <cstddef>
#include <iterator>
#include <utility>
/* -------------------------------------------------------------------------- */
#ifndef AKA_ARANGE_ITERATOR_HH
#define AKA_ARANGE_ITERATOR_HH
-#ifndef AKANTU_ITERATORS_NAMESPACE
-#define AKANTU_ITERATORS_NAMESPACE akantu
-#endif
-
namespace AKANTU_ITERATORS_NAMESPACE {
-namespace containers {
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
template <class Iterator> class Range {
public:
+ using size_type =
+ std::size_t; // typename
+ // std::iterator_traits<Iterator>::difference_type;
using iterator = Iterator;
// ugly trick
using const_iterator = Iterator;
explicit Range(Iterator && it1, Iterator && it2)
: iterators(std::forward<Iterator>(it1), std::forward<Iterator>(it2)) {}
decltype(auto) begin() const { return std::get<0>(iterators); }
decltype(auto) begin() { return std::get<0>(iterators); }
decltype(auto) end() const { return std::get<1>(iterators); }
decltype(auto) end() { return std::get<1>(iterators); }
private:
std::tuple<Iterator, Iterator> iterators;
};
-} // namespace containers
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
template <class Iterator>
decltype(auto) range(Iterator && it1, Iterator && it2) {
return containers::Range<Iterator>(std::forward<Iterator>(it1),
std::forward<Iterator>(it2));
}
/* -------------------------------------------------------------------------- */
/* Arange */
/* -------------------------------------------------------------------------- */
-namespace iterators {
+namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
template <class T> class ArangeIterator {
public:
using value_type = T;
using pointer = T *;
using reference = T &;
using difference_type = size_t;
using iterator_category = std::forward_iterator_tag;
constexpr ArangeIterator(T value, T step) : value(value), step(step) {}
constexpr ArangeIterator(const ArangeIterator &) = default;
- constexpr ArangeIterator & operator++() {
+ constexpr auto operator++() -> ArangeIterator & {
value += step;
return *this;
}
- constexpr T operator*() const { return value; }
+ constexpr auto operator*() const -> T { return value; }
- constexpr bool operator==(const ArangeIterator & other) const {
+ constexpr auto operator==(const ArangeIterator & other) const -> bool {
return (value == other.value) and (step == other.step);
}
- constexpr bool operator!=(const ArangeIterator & other) const {
+ constexpr auto operator!=(const ArangeIterator & other) const -> bool {
return not operator==(other);
}
private:
T value{0};
const T step{1};
};
-} // namespace iterators
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
-namespace containers {
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
template <class T> class ArangeContainer {
public:
using iterator = iterators::ArangeIterator<T>;
using const_iterator = iterators::ArangeIterator<T>;
+ using size_type = T;
constexpr ArangeContainer(T start, T stop, T step = 1)
: start(start), stop((stop - start) % step == 0
? stop
: start + (1 + (stop - start) / step) * step),
step(step) {}
explicit constexpr ArangeContainer(T stop) : ArangeContainer(0, stop, 1) {}
- constexpr T operator[](std::size_t i) {
+ constexpr auto operator[](std::size_t i) -> T {
T val = start + i * step;
assert(val < stop && "i is out of range");
return val;
}
- constexpr T size() { return (stop - start) / step; }
+ constexpr auto size() -> T { return (stop - start) / step; }
- constexpr iterator begin() { return iterator(start, step); }
- constexpr iterator end() { return iterator(stop, step); }
+ constexpr auto begin() -> iterator { return iterator(start, step); }
+ constexpr auto end() -> iterator { return iterator(stop, step); }
private:
const T start{0}, stop{0}, step{1};
};
-} // namespace containers
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
template <class T,
typename = std::enable_if_t<std::is_integral<std::decay_t<T>>::value>>
inline decltype(auto) arange(const T & stop) {
return containers::ArangeContainer<T>(stop);
}
template <class T1, class T2,
typename = std::enable_if_t<
std::is_integral<std::common_type_t<T1, T2>>::value>>
inline constexpr decltype(auto) arange(const T1 & start, const T2 & stop) {
return containers::ArangeContainer<std::common_type_t<T1, T2>>(start, stop);
}
template <class T1, class T2, class T3,
typename = std::enable_if_t<
std::is_integral<std::common_type_t<T1, T2, T3>>::value>>
inline constexpr decltype(auto) arange(const T1 & start, const T2 & stop,
const T3 & step) {
return containers::ArangeContainer<std::common_type_t<T1, T2, T3>>(
start, stop, step);
}
} // namespace AKANTU_ITERATORS_NAMESPACE
namespace std {
template <class T>
struct iterator_traits<
::AKANTU_ITERATORS_NAMESPACE::iterators::ArangeIterator<T>> {
private:
using iterator_type =
typename ::AKANTU_ITERATORS_NAMESPACE::iterators::ArangeIterator<T>;
public:
using iterator_category = typename iterator_type::iterator_category;
using value_type = typename iterator_type::value_type;
using difference_type = typename iterator_type::difference_type;
using pointer = typename iterator_type::pointer;
using reference = typename iterator_type::reference;
};
} // namespace std
#endif /* AKA_ARANGE_ITERATOR_HH */
diff --git a/third-party/akantu_iterators/include/iterators/aka_concatenate_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_concatenate_iterator.hh
index a7948c5a9..5cae42a1a 100644
--- a/third-party/akantu_iterators/include/iterators/aka_concatenate_iterator.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_concatenate_iterator.hh
@@ -1,205 +1,204 @@
/**
* @file aka_concatenate_iterator.hh
*
* @author Nicolas Richart
*
* @date creation jeu déc 12 2019
*
* @brief implementation of arange
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_compatibilty_with_cpp_standard.hh"
#include "aka_iterator_tools.hh"
#include "aka_tuple_tools.hh"
/* -------------------------------------------------------------------------- */
#include <iterator>
#include <utility>
/* -------------------------------------------------------------------------- */
#ifndef AKA_CONCATENATE_ITERATOR_H
#define AKA_CONCATENATE_ITERATOR_H
-#ifndef AKANTU_ITERATORS_NAMESPACE
-#define AKANTU_ITERATORS_NAMESPACE akantu
-#endif
-
namespace AKANTU_ITERATORS_NAMESPACE {
-namespace iterators {
+namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
/* ------------------------------------------------------------------------ */
template <class... Iterators>
class ConcatIterator
: public details::CopyAssignmentEnabler<
aka::conjunction<std::is_copy_assignable<Iterators>...,
std::is_copy_constructible<Iterators>...>::value>,
public details::MoveAssignmentEnabler<
aka::conjunction<std::is_move_assignable<Iterators>...,
std::is_move_constructible<Iterators>...>::value> {
private:
using tuple_t = std::tuple<Iterators...>;
public:
using value_type =
std::tuple<typename std::iterator_traits<Iterators>::value_type...>;
using difference_type = std::common_type_t<
typename std::iterator_traits<Iterators>::difference_type...>;
using pointer =
std::tuple<typename std::iterator_traits<Iterators>::pointer...>;
using reference =
std::tuple<typename std::iterator_traits<Iterators>::reference...>;
using iterator_category = std::input_iterator_tag;
public:
explicit ConcatIterator(tuple_t iterators, tuple_t end_iterators)
: iterators(std::move(iterators)),
end_iterators(std::move(end_iterators)) {}
/* ---------------------------------------------------------------------- */
// input iterator ++it
ConcatIterator & operator++() {
auto && ends =
tuple::transform([](auto && a, auto && b) { return a == b; },
iterators, end_iterators);
auto && pos = tuple::find(ends, false);
++(tuple::dynamic_get(pos, iterators));
return *this;
}
// input iterator it++
ConcatIterator operator++(int) {
auto cpy = *this;
this->operator++();
return cpy;
}
// input iterator it != other_it
bool operator!=(const ConcatIterator & other) const {
return tuple::are_not_equal(iterators, other.iterators);
}
// input iterator dereference *it
decltype(auto) operator*() {
auto && ends =
tuple::transform([](auto && a, auto && b) { return a == b; },
iterators, end_iterators);
auto && pos = tuple::find(ends, false);
return *(tuple::dynamic_get(pos, iterators));
}
template <
class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_, std::forward_iterator_tag>::value> * = nullptr>
bool operator==(const ConcatIterator & other) const {
return not tuple::are_not_equal(iterators, other.iterators);
}
private:
tuple_t iterators;
tuple_t end_iterators;
};
-} // namespace iterators
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
/* -------------------------------------------------------------------------- */
template <class... Iterators>
decltype(auto)
concat_iterator(std::tuple<Iterators...> && iterators_tuple,
std::tuple<Iterators...> && end_iterators_tuple) {
auto concat = iterators::ConcatIterator<Iterators...>(
std::forward<decltype(iterators_tuple)>(iterators_tuple),
std::forward<decltype(end_iterators_tuple)>(end_iterators_tuple));
return concat;
}
/* -------------------------------------------------------------------------- */
-namespace containers {
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
template <class... Containers> class ConcatContainer {
using containers_t = std::tuple<Containers...>;
public:
+ using size_type = std::common_type_t<aka::size_type_t<Containers>...>;
+
explicit ConcatContainer(Containers &&... containers)
: containers(std::forward<Containers>(containers)...) {}
- decltype(auto) begin() const {
+ auto begin() const -> decltype(auto) {
return concat_iterator(
tuple::transform([](auto && c) { return c.begin(); },
std::forward<containers_t>(containers)),
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)));
}
- decltype(auto) end() const {
+ auto end() const -> decltype(auto) {
return concat_iterator(
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)),
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)));
}
- decltype(auto) begin() {
- return concat_iterator(
+ auto begin() -> decltype(auto) {
+ return concat_iterator(
tuple::transform([](auto && c) { return c.begin(); },
std::forward<containers_t>(containers)),
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)));
}
- decltype(auto) end() {
+ auto end() -> decltype(auto) {
return concat_iterator(
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)),
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)));
}
private:
containers_t containers;
};
/* ------------------------------------------------------------------------ */
- template <class... Containers> decltype(auto) concat(Containers &&... conts) {
+ template <class... Containers>
+ auto concat(Containers &&... conts) -> decltype(auto) {
return containers::ConcatContainer<Containers...>(
std::forward<Containers>(conts)...);
}
-} // namespace containers
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
} // namespace AKANTU_ITERATORS_NAMESPACE
namespace std {
template <typename... Its>
struct iterator_traits<
::AKANTU_ITERATORS_NAMESPACE::iterators::ConcatIterator<Its...>> {
private:
using iterator_type =
typename ::AKANTU_ITERATORS_NAMESPACE::iterators::ConcatIterator<Its...>;
public:
using iterator_category = typename iterator_type::iterator_category;
using value_type = typename iterator_type::value_type;
using difference_type = typename iterator_type::difference_type;
using pointer = typename iterator_type::pointer;
using reference = typename iterator_type::reference;
};
} // namespace std
#endif // __AKA_CONCATENATE_ITERATOR_H_
diff --git a/third-party/akantu_iterators/include/iterators/aka_enumerate_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_enumerate_iterator.hh
index 35c8b0bf6..bb3e4af74 100644
--- a/third-party/akantu_iterators/include/iterators/aka_enumerate_iterator.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_enumerate_iterator.hh
@@ -1,154 +1,226 @@
/**
* @file aka_enumerate_iterator.hh
*
* @author Nicolas Richart
*
* @date creation jeu déc 12 2019
*
* @brief implementation of enumerate.
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
+#include "iterators/aka_iterator_tools.hh"
#include "iterators/aka_zip_iterator.hh"
/* -------------------------------------------------------------------------- */
#include <iterator>
#include <utility>
/* -------------------------------------------------------------------------- */
#ifndef AKA_ENUMERATE_ITERATOR_HH
#define AKA_ENUMERATE_ITERATOR_HH
-#ifndef AKANTU_ITERATORS_NAMESPACE
-#define AKANTU_ITERATORS_NAMESPACE akantu
-#endif
-
namespace AKANTU_ITERATORS_NAMESPACE {
/* -------------------------------------------------------------------------- */
-namespace iterators {
- template <class Iterator> class EnumerateIterator {
- public:
- using value_type =
- std::tuple<std::size_t,
- typename std::iterator_traits<Iterator>::value_type>;
- using difference_type = std::size_t;
- using pointer =
- std::tuple<std::size_t,
- typename std::iterator_traits<Iterator>::pointer>;
- using reference =
- std::tuple<std::size_t,
- typename std::iterator_traits<Iterator>::reference>;
- using iterator_category = std::input_iterator_tag;
+namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
+ template <class Iterator, class size_type_>
+ class EnumerateIterator
+ : public details::CopyAssignmentEnabler<
+ aka::conjunction<std::is_copy_assignable<Iterator>,
+ std::is_copy_constructible<Iterator>>::value>,
+ public details::MoveAssignmentEnabler<
+ aka::conjunction<std::is_move_assignable<Iterator>,
+ std::is_move_constructible<Iterator>>::value> {
+
+ private:
+ using it_traits = typename std::iterator_traits<Iterator>;
public:
- explicit EnumerateIterator(Iterator && iterator) : iterator(iterator) {}
+ using value_type = std::tuple<size_type_, typename it_traits::value_type>;
+ using difference_type = size_type_;
+ using pointer = std::tuple<size_type_, typename it_traits::pointer>;
+ using reference = std::tuple<size_type_, typename it_traits::reference>;
+ using iterator_category = typename it_traits::iterator_category;
+
+ explicit EnumerateIterator(Iterator iterator)
+ : iterator(std::move(iterator)) {}
// input iterator ++it
- EnumerateIterator & operator++() {
+ auto operator++() -> EnumerateIterator & {
++iterator;
++index;
return *this;
}
// input iterator it++
- EnumerateIterator operator++(int) {
+ auto operator++(int) -> EnumerateIterator {
auto cpy = *this;
this->operator++();
return cpy;
}
// input iterator it != other_it
- bool operator!=(const EnumerateIterator & other) const {
+ auto operator!=(const EnumerateIterator & other) const -> bool {
return iterator != other.iterator;
}
// input iterator dereference *it
- decltype(auto) operator*() {
+ auto operator*() -> decltype(auto) {
return std::tuple_cat(std::make_tuple(index), *iterator);
}
- bool operator==(const EnumerateIterator & other) const {
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::bidirectional_iterator_tag>::value> * = nullptr>
+ auto operator--() -> EnumerateIterator & {
+ --iterator;
+ --index;
+ return *this;
+ }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::bidirectional_iterator_tag>::value> * = nullptr>
+ auto operator--(int) -> EnumerateIterator {
+ auto cpy = *this;
+ this->operator--();
+ return cpy;
+ }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator-(const EnumerateIterator & other) const -> difference_type {
+ return iterator - other.iterator;
+ }
+
+ // random iterator it[idx]
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator[](size_type_ idx) -> decltype(auto) {
+ return std::tuple_cat(index + idx, iterator[idx]);
+ }
+
+ // random iterator it + n
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator+(size_type_ n) const -> decltype(auto) {
+ auto it = EnumerateIterator(iterator + n);
+ it.index = this->index + n;
+ return it;
+ }
+
+ // random iterator it - n
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator-(size_type_ n) const -> decltype(auto) {
+ auto it = EnumerateIterator(iterator - n);
+ it.index = this->index - n;
+ return it;
+ }
+
+ template <
+ class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_, std::forward_iterator_tag>::value> * = nullptr>
+ auto operator==(const EnumerateIterator & other) const -> bool {
return not this->operator!=(other);
}
private:
Iterator iterator;
- size_t index{0};
+ size_type_ index{0};
};
- template <class Iterator>
- inline constexpr decltype(auto) enumerate(Iterator && iterator) {
- return EnumerateIterator<Iterator>(std::forward<Iterator>(iterator));
+ template <class Iterator, class size_type_ = std::size_t>
+ inline constexpr auto enumerate(Iterator && iterator, size_type_ /*size*/)
+ -> decltype(auto) {
+ return EnumerateIterator<Iterator, size_type_>(
+ std::forward<Iterator>(iterator));
}
-} // namespace iterators
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
-namespace containers {
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
template <class... Containers> class EnumerateContainer {
+ using ZipContainer_t = ZipContainer<Containers...>;
+ using size_type = typename ZipContainer_t::size_type;
+
public:
explicit EnumerateContainer(Containers &&... containers)
: zip_container(std::forward<Containers>(containers)...) {}
- decltype(auto) begin() {
- return iterators::enumerate(zip_container.begin());
+ auto begin() -> decltype(auto) {
+ return iterators::enumerate(zip_container.begin(), size_type{});
}
- decltype(auto) begin() const {
- return iterators::enumerate(zip_container.begin());
+ auto begin() const -> decltype(auto) {
+ return iterators::enumerate(zip_container.begin(), size_type{});
}
- decltype(auto) end() { return iterators::enumerate(zip_container.end()); }
+ auto end() -> decltype(auto) {
+ return iterators::enumerate(zip_container.end(), size_type{});
+ }
- decltype(auto) end() const {
- return iterators::enumerate(zip_container.end());
+ auto end() const -> decltype(auto) {
+ return iterators::enumerate(zip_container.end(), size_type{});
}
private:
- ZipContainer<Containers...> zip_container;
+ ZipContainer_t zip_container;
};
-} // namespace containers
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
template <class... Container>
-inline constexpr decltype(auto) enumerate(Container &&... container) {
+inline constexpr auto enumerate(Container &&... container) -> decltype(auto) {
return containers::EnumerateContainer<Container...>(
std::forward<Container>(container)...);
}
} // namespace AKANTU_ITERATORS_NAMESPACE
namespace std {
-template <class Iterator>
-struct iterator_traits<
- ::AKANTU_ITERATORS_NAMESPACE::iterators::EnumerateIterator<Iterator>> {
+template <class Iterator, class size_type>
+struct iterator_traits<::AKANTU_ITERATORS_NAMESPACE::iterators::
+ EnumerateIterator<Iterator, size_type>> {
private:
using iterator_type =
typename ::AKANTU_ITERATORS_NAMESPACE::iterators::EnumerateIterator<
- Iterator>;
+ Iterator, size_type>;
public:
using iterator_category = typename iterator_type::iterator_category;
using value_type = typename iterator_type::value_type;
using difference_type = typename iterator_type::difference_type;
using pointer = typename iterator_type::pointer;
using reference = typename iterator_type::reference;
};
} // namespace std
#endif /* AKA_ENUMERATE_ITERATOR_HH */
diff --git a/third-party/akantu_iterators/include/iterators/aka_filter_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_filter_iterator.hh
index 11885da1a..c657ecf68 100644
--- a/third-party/akantu_iterators/include/iterators/aka_filter_iterator.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_filter_iterator.hh
@@ -1,157 +1,346 @@
/**
* @file aka_filter_iterator.hh
*
* @author Nicolas Richart
*
* @date creation jeu déc 12 2019
*
* @brief A Documented file.
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include <iterator>
#include <utility>
/* -------------------------------------------------------------------------- */
-#ifndef AKA_FILTER_ITERATOR_H
-#define AKA_FILTER_ITERATOR_H
+#ifndef AKA_FILTER_ITERATOR_HH
+#define AKA_FILTER_ITERATOR_HH
#ifndef AKANTU_ITERATORS_NAMESPACE
#define AKANTU_ITERATORS_NAMESPACE akantu
#endif
namespace AKANTU_ITERATORS_NAMESPACE {
/* -------------------------------------------------------------------------- */
-namespace iterators {
+namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
template <class filter_iterator_t, class container_iterator_t>
- class FilterIterator {
+ class FilterIterator
+ : public details::CopyAssignmentEnabler<aka::conjunction<
+ std::is_copy_assignable<filter_iterator_t>,
+ std::is_copy_constructible<filter_iterator_t>,
+ std::is_copy_assignable<container_iterator_t>,
+ std::is_copy_constructible<container_iterator_t>>::value>,
+ public details::MoveAssignmentEnabler<aka::conjunction<
+ std::is_move_assignable<filter_iterator_t>,
+ std::is_move_constructible<filter_iterator_t>,
+ std::is_move_assignable<container_iterator_t>,
+ std::is_move_constructible<container_iterator_t>>::value> {
public:
- using value_type =
- decltype(std::declval<container_iterator_t>().operator[](0));
- using difference_type = typename filter_iterator_t::difference_type;
+ using value_type = typename std::decay_t<container_iterator_t>::value_type;
+ using difference_type =
+ typename std::decay_t<filter_iterator_t>::difference_type;
using pointer = std::decay_t<value_type> *;
- using reference = value_type &;
- using iterator_category = typename filter_iterator_t::iterator_category;
+ using reference = typename std::decay_t<container_iterator_t>::reference;
+ using iterator_category =
+ typename std::decay_t<filter_iterator_t>::iterator_category;
FilterIterator(filter_iterator_t filter_it,
- container_iterator_t container_begin)
- : filter_it(std::move(filter_it)),
- container_begin(std::move(container_begin)) {}
+ const container_iterator_t & container_begin)
+ : filter_it(std::move(filter_it)), container_begin(container_begin),
+ container_it(container_begin) {}
- FilterIterator(const FilterIterator &) = default;
-
- FilterIterator & operator++() {
+ auto operator++() -> FilterIterator & {
++filter_it;
return *this;
}
- decltype(auto) operator*() {
- auto container_it = this->container_begin + *this->filter_it;
+ auto operator++(int) -> FilterIterator {
+ auto cpy = *this;
+ this->operator++();
+ return cpy;
+ }
+
+ auto operator*() -> reference {
+ container_it = this->container_begin + *this->filter_it;
return *container_it;
}
- decltype(auto) operator*() const {
- auto container_it = this->container_begin + *this->filter_it;
+ auto operator!=(const FilterIterator & other) const -> bool {
+ return (filter_it != other.filter_it) or
+ (container_begin != other.container_begin);
+ }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::bidirectional_iterator_tag>::value> * = nullptr>
+ auto operator--() -> FilterIterator & {
+ --filter_it;
+ return *this;
+ }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::bidirectional_iterator_tag>::value> * = nullptr>
+ auto operator--(int) -> FilterIterator {
+ auto cpy = *this;
+ this->operator--();
+ return cpy;
+ }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator-(const FilterIterator & other) -> difference_type {
+ return filter_it - other.index;
+ }
+
+ // random iterator it[idx]
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator[](difference_type idx) -> reference {
+ container_it = this->container_begin + *(this->filter_it + idx);
return *container_it;
}
- bool operator==(const FilterIterator & other) const {
- return (filter_it == other.filter_it) and
- (container_begin == other.container_begin);
+ // random iterator it + n
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator+(difference_type n) -> FilterIterator {
+ auto it = FilterIterator(filter_it + n, container_begin);
+ return it;
}
- bool operator!=(const FilterIterator & other) const {
- return filter_it != other.filter_it;
+ // random iterator it - n
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator-(difference_type n) -> FilterIterator {
+ auto it = FilterIterator(filter_it - n, container_begin);
+ return it;
+ }
+
+ template <
+ class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_, std::forward_iterator_tag>::value> * = nullptr>
+ auto operator==(const FilterIterator & other) const -> bool {
+ return (filter_it == other.filter_it) and
+ (container_begin == other.container_begin);
}
private:
filter_iterator_t filter_it;
container_iterator_t container_begin;
+ container_iterator_t container_it;
};
template <class filter_iterator_t, class container_iterator_t>
- decltype(auto) make_filter_iterator(filter_iterator_t && filter_it,
- container_iterator_t && container_begin) {
+ auto make_filter_iterator(filter_iterator_t && filter_it,
+ container_iterator_t && container_begin)
+ -> decltype(auto) {
return FilterIterator<filter_iterator_t, container_iterator_t>(
std::forward<filter_iterator_t>(filter_it),
std::forward<container_iterator_t>(container_begin));
}
-} // namespace iterators
-namespace containers {
+ template <class container_iterator_t, class Predicate>
+ class FilterIfIterator
+ : public details::CopyAssignmentEnabler<aka::conjunction<
+ std::is_copy_assignable<Predicate>,
+ std::is_copy_constructible<Predicate>,
+ std::is_copy_assignable<container_iterator_t>,
+ std::is_copy_constructible<container_iterator_t>>::value>,
+ public details::MoveAssignmentEnabler<aka::conjunction<
+ std::is_move_assignable<Predicate>,
+ std::is_move_constructible<Predicate>,
+ std::is_move_assignable<container_iterator_t>,
+ std::is_move_constructible<container_iterator_t>>::value> {
+ public:
+ using value_type = typename std::decay_t<container_iterator_t>::value_type;
+ using difference_type =
+ typename std::decay_t<container_iterator_t>::difference_type;
+ using pointer = std::decay_t<value_type> *;
+ using reference = typename std::decay_t<container_iterator_t>::reference;
+ using iterator_category = std::common_type_t<
+ std::forward_iterator_tag,
+ typename std::decay_t<container_iterator_t>::iterator_category>;
+
+ FilterIfIterator(const container_iterator_t & container_begin,
+ const container_iterator_t & container_end,
+ Predicate & predicate)
+ : container_it(container_begin), container_end(container_end),
+ predicate(predicate) {}
+
+ auto operator++() -> FilterIfIterator & {
+ do {
+ ++container_it;
+ } while (container_it != container_end and not predicate(*container_it));
+ return *this;
+ }
+
+ auto operator++(int) -> FilterIfIterator {
+ auto cpy = *this;
+ this->operator++();
+ return cpy;
+ }
+
+ auto operator*() -> decltype(auto) { return (*container_it); }
+
+ auto operator!=(const FilterIfIterator & other) const -> bool {
+ return (container_it != other.container_it);
+ }
+
+ template <
+ class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_, std::forward_iterator_tag>::value> * = nullptr>
+ auto operator==(const FilterIfIterator & other) const -> bool {
+ return (container_it == other.container_it);
+ }
+
+ private:
+ container_iterator_t container_it, container_end;
+ Predicate predicate;
+ };
+
+ template <class container_iterator_t, class Predicate>
+ auto make_filter_if_iterator(container_iterator_t && container_begin,
+ container_iterator_t && container_end,
+ Predicate && predicate) -> decltype(auto) {
+ return FilterIfIterator<container_iterator_t, Predicate>(
+ std::forward<container_iterator_t>(container_begin),
+ std::forward<container_iterator_t>(container_end),
+ std::forward<Predicate>(predicate));
+ }
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
+
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
template <class filter_t, class Container> class FilterAdaptor {
public:
+ using size_type = typename std::decay_t<Container>::size_type;
+
FilterAdaptor(filter_t && filter, Container && container)
: filter(std::forward<filter_t>(filter)),
container(std::forward<Container>(container)) {
static_assert(
std::is_same<typename decltype(container.begin())::iterator_category,
std::random_access_iterator_tag>::value,
"Containers must all have random iterators");
}
- decltype(auto) begin() const {
+ auto begin() const -> decltype(auto) {
return iterators::make_filter_iterator(filter.begin(), container.begin());
}
- decltype(auto) begin() {
+
+ auto begin() -> decltype(auto) {
return iterators::make_filter_iterator(filter.begin(), container.begin());
}
- decltype(auto) end() const {
+ auto end() const -> decltype(auto) {
return iterators::make_filter_iterator(filter.end(), container.begin());
}
- decltype(auto) end() {
+
+ auto end() -> decltype(auto) {
return iterators::make_filter_iterator(filter.end(), container.begin());
}
private:
filter_t filter;
Container container;
};
-} // namespace containers
+
+ template <class Container, class Predicate> class FilterIfAdaptor {
+ public:
+ using size_type = typename std::decay_t<Container>::size_type;
+
+ FilterIfAdaptor(Container && container, Predicate && predicate)
+ : container(std::forward<Container>(container)),
+ predicate(std::forward<Predicate>(predicate)) {}
+
+ auto begin() const -> decltype(auto) {
+ return iterators::make_filter_if_iterator(container.begin(),
+ container.end(), predicate);
+ }
+
+ auto end() const -> decltype(auto) {
+ return iterators::make_filter_if_iterator(container.end(),
+ container.end(), predicate);
+ }
+
+ auto begin() -> decltype(auto) {
+ return iterators::make_filter_if_iterator(container.begin(),
+ container.end(), predicate);
+ }
+
+ auto end() -> decltype(auto) {
+ return iterators::make_filter_if_iterator(container.end(),
+ container.end(), predicate);
+ }
+
+ private:
+ Container container;
+ Predicate predicate;
+ };
+
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
template <class filter_t, class Container>
-decltype(auto) filter(filter_t && filter, Container && container) {
+auto filter(filter_t && filter, Container && container) -> decltype(auto) {
return containers::FilterAdaptor<filter_t, Container>(
std::forward<filter_t>(filter), std::forward<Container>(container));
}
+template <class Container, class Predicate>
+auto filter_if(Container && container, Predicate && predicate)
+ -> decltype(auto) {
+ return containers::FilterIfAdaptor<Container, Predicate>(
+ std::forward<Container>(container), std::forward<Predicate>(predicate));
+}
+
} // namespace AKANTU_ITERATORS_NAMESPACE
namespace std {
template <class filter_iterator_t, class container_iterator_t>
struct iterator_traits<::AKANTU_ITERATORS_NAMESPACE::iterators::FilterIterator<
filter_iterator_t, container_iterator_t>> {
private:
using iterator_type =
typename ::AKANTU_ITERATORS_NAMESPACE::iterators::FilterIterator<
filter_iterator_t, container_iterator_t>;
public:
using iterator_category = typename iterator_type::iterator_category;
using value_type = typename iterator_type::value_type;
using difference_type = typename iterator_type::difference_type;
using pointer = typename iterator_type::pointer;
using reference = typename iterator_type::reference;
};
} // namespace std
-#endif // AKA_FILTER_ITERATOR_H
+#endif // AKA_FILTER_ITERATOR_HH
diff --git a/third-party/akantu_iterators/include/iterators/aka_iterator_tools.hh b/third-party/akantu_iterators/include/iterators/aka_iterator_tools.hh
index aec788231..f025f3054 100644
--- a/third-party/akantu_iterators/include/iterators/aka_iterator_tools.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_iterator_tools.hh
@@ -1,69 +1,71 @@
/**
* @file aka_iterator_tools.hh
*
* @author Nicolas Richart
*
* @date creation jeu déc 12 2019
*
* @brief A Documented file.
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef AKA_ITERATOR_TOOLS_H
#define AKA_ITERATOR_TOOLS_H
#ifndef AKANTU_ITERATORS_NAMESPACE
#define AKANTU_ITERATORS_NAMESPACE akantu
#endif
+#define AKA_ITERATOR_EXPORT_NAMESPACE __attribute__((visibility("hidden")))
+
namespace AKANTU_ITERATORS_NAMESPACE {
/* -------------------------------------------------------------------------- */
namespace iterators {
- namespace details {
+ namespace details AKA_ITERATOR_EXPORT_NAMESPACE {
template <bool enable> struct CopyAssignmentEnabler {};
template <> struct CopyAssignmentEnabler<false> {
CopyAssignmentEnabler() = default;
CopyAssignmentEnabler(const CopyAssignmentEnabler &) = default;
CopyAssignmentEnabler(CopyAssignmentEnabler &&) = default;
auto operator=(const CopyAssignmentEnabler &)
-> CopyAssignmentEnabler & = delete;
auto operator=(CopyAssignmentEnabler &&)
-> CopyAssignmentEnabler & = default;
};
template <bool enable> struct MoveAssignmentEnabler {};
template <> struct MoveAssignmentEnabler<false> {
MoveAssignmentEnabler() = default;
MoveAssignmentEnabler(const MoveAssignmentEnabler &) = default;
MoveAssignmentEnabler(MoveAssignmentEnabler &&) = default;
auto operator=(const MoveAssignmentEnabler &)
-> MoveAssignmentEnabler & = delete;
auto operator=(MoveAssignmentEnabler &&)
-> MoveAssignmentEnabler & = default;
};
- } // namespace details
+ } // namespace AKA_ITERATOR_EXPORT_NAMESPACE
} // namespace iterators
} // namespace AKANTU_ITERATORS_NAMESPACE
#endif // AKA_ITERATOR_TOOLS_H
diff --git a/third-party/akantu_iterators/include/iterators/aka_repeat_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_repeat_iterator.hh
new file mode 100644
index 000000000..76b856c8a
--- /dev/null
+++ b/third-party/akantu_iterators/include/iterators/aka_repeat_iterator.hh
@@ -0,0 +1,220 @@
+/**
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * akantu-iterators is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * akantu-iterators is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "iterators/aka_iterator_tools.hh"
+/* -------------------------------------------------------------------------- */
+#include <cmath>
+#include <utility>
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_AKA_REPEAT_ITERATOR_HH
+#define AKANTU_AKA_REPEAT_ITERATOR_HH
+namespace AKANTU_ITERATORS_NAMESPACE {
+
+namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
+
+ template <class Iterator, typename N>
+ class RepeatNIterator
+ : public details::CopyAssignmentEnabler<
+ aka::conjunction<std::is_copy_assignable<Iterator>,
+ std::is_copy_constructible<Iterator>>::value>,
+ public details::MoveAssignmentEnabler<
+ aka::conjunction<std::is_move_assignable<Iterator>,
+ std::is_move_constructible<Iterator>>::value> {
+
+ private:
+ using it_traits = typename std::iterator_traits<Iterator>;
+
+ public:
+ using value_type = typename it_traits::value_type;
+ using difference_type = typename it_traits::difference_type;
+ using pointer = typename it_traits::pointer;
+ using reference = typename it_traits::reference;
+ using iterator_category = typename it_traits::iterator_category;
+
+ explicit RepeatNIterator(Iterator iterator, N n)
+ : iterator(std::move(iterator)), n(std::move(n)) {}
+
+ // input iterator ++it
+ auto operator++() -> RepeatNIterator & {
+ ++i;
+ if (i == n) {
+ ++iterator;
+ i = 0;
+ }
+ return *this;
+ }
+
+ // input iterator it++
+ auto operator++(int) -> RepeatNIterator {
+ auto cpy = *this;
+ this->operator++();
+ return cpy;
+ }
+
+ // input iterator it != other_it
+ auto operator!=(const RepeatNIterator & other) const -> bool {
+ return iterator != other.iterator or i != other.i;
+ }
+
+ // input iterator dereference *it
+ auto operator*() -> decltype(auto) { return *iterator; }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::bidirectional_iterator_tag>::value> * = nullptr>
+ auto operator--() -> RepeatNIterator & {
+ if (i == 0) {
+ --iterator;
+ i = n - 1;
+ } else {
+ --i;
+ }
+ return *this;
+ }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::bidirectional_iterator_tag>::value> * = nullptr>
+ auto operator--(int) -> RepeatNIterator {
+ auto cpy = *this;
+ this->operator--();
+ return cpy;
+ }
+
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator-(const RepeatNIterator & other) const -> difference_type {
+ return (iterator - other.iterator) + (i - other.i);
+ }
+
+ // random iterator it[idx]
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator[](const N & idx) -> decltype(auto) {
+ return iterator[(i + idx) / n];
+ }
+
+ // random iterator it + n
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator+(const N & n_) const -> decltype(auto) {
+ auto it = RepeatNIterator(iterator + n_ / n, n);
+ it.i = (i + n_) % n;
+ return it;
+ }
+
+ // random iterator it - n
+ template <class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_,
+ std::random_access_iterator_tag>::value> * = nullptr>
+ auto operator-(const N & n_) const -> decltype(auto) {
+ auto it = RepeatNIterator(iterator + N(std::floor(double(-n_) / n)), n);
+ it.i = (i + n - n_) % n;
+ return it;
+ }
+
+ template <
+ class iterator_category_ = iterator_category,
+ std::enable_if_t<aka::is_iterator_category_at_least<
+ iterator_category_, std::forward_iterator_tag>::value> * = nullptr>
+ auto operator==(const RepeatNIterator & other) const -> bool {
+ return not this->operator!=(other);
+ }
+
+ private:
+ Iterator iterator;
+ const N n;
+ N i{0};
+ };
+
+ template <class Iterator, typename N>
+ inline constexpr auto repeat_n(Iterator && iterator, N n) -> decltype(auto) {
+ return RepeatNIterator<Iterator, N>(std::forward<Iterator>(iterator),
+ std::move(n));
+ }
+
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
+
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
+ template <class Container, typename N> class RepeatNContainer {
+ public:
+ using size_type = typename std::decay_t<Container>::size_type;
+
+ explicit RepeatNContainer(Container && container, N n)
+ : container(std::forward<Container>(container)), n(std::move(n)) {}
+ auto begin() -> decltype(auto) {
+ return iterators::repeat_n(container.begin(), n);
+ }
+
+ auto begin() const -> decltype(auto) {
+ return iterators::repeat_n(container.begin(), n);
+ }
+
+ auto end() -> decltype(auto) {
+ return iterators::repeat_n(container.end(), n);
+ }
+
+ auto end() const -> decltype(auto) {
+ return iterators::repeat_n(container.end(), n);
+ }
+
+ private:
+ Container container;
+ N n;
+ };
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
+
+template <class Container, typename N>
+inline constexpr auto repeat_n(Container && container, N n) -> decltype(auto) {
+ return containers::RepeatNContainer<Container, N>(
+ std::forward<Container>(container), std::move(n));
+}
+
+} // namespace AKANTU_ITERATORS_NAMESPACE
+
+namespace std {
+template <class Iterator, typename N>
+struct iterator_traits<
+ ::AKANTU_ITERATORS_NAMESPACE::iterators::RepeatNIterator<Iterator, N>> {
+private:
+ using iterator_type =
+ typename ::AKANTU_ITERATORS_NAMESPACE::iterators::RepeatNIterator<
+ Iterator, N>;
+
+public:
+ using iterator_category = typename iterator_type::iterator_category;
+ using value_type = typename iterator_type::value_type;
+ using difference_type = typename iterator_type::difference_type;
+ using pointer = typename iterator_type::pointer;
+ using reference = typename iterator_type::reference;
+};
+
+} // namespace std
+
+#endif /* AKANTU_AKA_REPEAT_ITERATOR_HH */
diff --git a/third-party/akantu_iterators/include/iterators/aka_transform_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_transform_iterator.hh
index e7d2e5bc6..26a646cd0 100644
--- a/third-party/akantu_iterators/include/iterators/aka_transform_iterator.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_transform_iterator.hh
@@ -1,155 +1,175 @@
/**
* @file aka_transform_iterator.hh
*
* @author Nicolas Richart
*
* @date creation jeu déc 12 2019
*
* @brief transform adaptors
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
-#include "aka_compatibilty_with_cpp_standard.hh"
+#include "aka_iterator_tools.hh"
/* -------------------------------------------------------------------------- */
#include <utility>
/* -------------------------------------------------------------------------- */
#ifndef AKA_TRANSFORM_ITERATOR_H
#define AKA_TRANSFORM_ITERATOR_H
-#ifndef AKANTU_ITERATORS_NAMESPACE
-#define AKANTU_ITERATORS_NAMESPACE akantu
-#endif
-
namespace AKANTU_ITERATORS_NAMESPACE {
-namespace iterators {
+namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
template <class iterator_t, class operator_t>
class transform_adaptor_iterator {
public:
using value_type = decltype(std::declval<operator_t>()(
std::declval<typename iterator_t::value_type>()));
using difference_type = typename iterator_t::difference_type;
using pointer = std::decay_t<value_type> *;
using reference = value_type &;
using iterator_category = typename iterator_t::iterator_category;
- transform_adaptor_iterator(iterator_t it, operator_t op)
+ constexpr transform_adaptor_iterator(iterator_t it, operator_t op)
: it(std::move(it)), op(op) {}
- transform_adaptor_iterator(const transform_adaptor_iterator &) = default;
+ constexpr transform_adaptor_iterator(const transform_adaptor_iterator &) =
+ default;
- transform_adaptor_iterator & operator++() {
+ constexpr transform_adaptor_iterator & operator++() {
++it;
return *this;
}
- decltype(auto) operator*() { return op(std::forward<decltype(*it)>(*it)); }
+ constexpr decltype(auto) operator*() {
+ return op(std::forward<decltype(*it)>(*it));
+ }
- bool operator==(const transform_adaptor_iterator & other) const {
+ constexpr bool operator==(const transform_adaptor_iterator & other) const {
return (it == other.it);
}
- bool operator!=(const transform_adaptor_iterator & other) const {
+ constexpr bool operator!=(const transform_adaptor_iterator & other) const {
return not operator==(other);
}
template <class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_,
std::random_access_iterator_tag>::value> * = nullptr>
- difference_type operator-(const transform_adaptor_iterator & other) {
+ constexpr difference_type
+ operator-(const transform_adaptor_iterator & other) {
return other - *this;
}
private:
iterator_t it;
operator_t op;
};
template <class iterator_t, class operator_t>
- decltype(auto) make_transform_adaptor_iterator(iterator_t it, operator_t op) {
+ constexpr auto make_transform_adaptor_iterator(iterator_t it, operator_t op)
+ -> decltype(auto) {
return transform_adaptor_iterator<iterator_t, operator_t>(
it, std::forward<operator_t>(op));
}
-} // namespace iterators
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
-namespace containers {
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
template <class container_t, class operator_t>
class TransformIteratorAdaptor {
public:
// using const_iterator = typename
// std::decay_t<container_t>::const_iterator; using iterator = typename
// std::decay_t<container_t>::iterator;
+ using size_type = typename std::decay_t<container_t>::size_type;
- TransformIteratorAdaptor(container_t && cont, operator_t op)
+ constexpr TransformIteratorAdaptor(container_t && cont, operator_t op)
: cont(std::forward<container_t>(cont)),
op(std::forward<operator_t>(op)) {}
- decltype(auto) begin() const {
+ constexpr auto begin() const -> decltype(auto) {
return iterators::make_transform_adaptor_iterator(cont.begin(), op);
}
- decltype(auto) begin() {
+ constexpr auto begin() -> decltype(auto) {
return iterators::make_transform_adaptor_iterator(cont.begin(), op);
}
- decltype(auto) end() const {
+ constexpr auto end() const -> decltype(auto) {
return iterators::make_transform_adaptor_iterator(cont.end(), op);
}
- decltype(auto) end() {
+ constexpr auto end() -> decltype(auto) {
return iterators::make_transform_adaptor_iterator(cont.end(), op);
}
private:
container_t cont;
operator_t op;
};
-} // namespace containers
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
template <class container_t, class operator_t>
-decltype(auto) make_transform_adaptor(container_t && cont, operator_t && op) {
+constexpr auto make_transform_adaptor(container_t && cont, operator_t && op)
+ -> decltype(auto) {
return containers::TransformIteratorAdaptor<container_t, operator_t>(
std::forward<container_t>(cont), std::forward<operator_t>(op));
}
template <class container_t>
-decltype(auto) make_keys_adaptor(container_t && cont) {
+constexpr auto make_keys_adaptor(container_t && cont) -> decltype(auto) {
return make_transform_adaptor(
std::forward<container_t>(cont),
[](auto && pair) -> const auto & { return pair.first; });
}
template <class container_t>
-decltype(auto) make_values_adaptor(container_t && cont) {
+constexpr auto make_values_adaptor(container_t && cont) -> decltype(auto) {
return make_transform_adaptor(
std::forward<container_t>(cont),
[](auto && pair) -> auto & { return pair.second; });
}
template <class container_t>
-decltype(auto) make_dereference_adaptor(container_t && cont) {
+constexpr auto make_dereference_adaptor(container_t && cont) -> decltype(auto) {
return make_transform_adaptor(
std::forward<container_t>(cont),
[](auto && value) -> decltype(*value) { return *value; });
}
+namespace details {
+ template <typename T> struct BroadcastHelper {
+ BroadcastHelper(T && t) : t(std::forward<T>(t)) {}
+ constexpr auto operator()() -> std::remove_reference_t<T> & { return t; }
+ T t;
+ };
+} // namespace details
+
+template <typename Type, typename Size>
+constexpr auto broadcast(Type && data, Size size) -> decltype(auto) {
+ auto && accessor = details::BroadcastHelper<Type>(std::forward<Type>(data));
+ return make_transform_adaptor(
+ arange(size), [accessor](auto && /*value*/) constexpr mutable
+ ->std::remove_reference_t<Type> &
+ { return accessor(); });
+}
+
} // namespace AKANTU_ITERATORS_NAMESPACE
#endif // AKA_TRANSFORM_ITERATOR_H
diff --git a/third-party/akantu_iterators/include/iterators/aka_zip_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_zip_iterator.hh
index 30c338996..419c9ba97 100644
--- a/third-party/akantu_iterators/include/iterators/aka_zip_iterator.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_zip_iterator.hh
@@ -1,282 +1,398 @@
/**
* @file aka_zip_iterator.hh
*
* @author Nicolas Richart
*
* @date creation jeu déc 12 2019
*
* @brief A Documented file.
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_compatibilty_with_cpp_standard.hh"
#include "aka_iterator_tools.hh"
#include "aka_tuple_tools.hh"
/* -------------------------------------------------------------------------- */
#include <iterator>
#include <utility>
/* -------------------------------------------------------------------------- */
#ifndef AKA_ZIP_ITERATOR_HH
#define AKA_ZIP_ITERATOR_HH
#ifndef AKANTU_ITERATORS_NAMESPACE
#define AKANTU_ITERATORS_NAMESPACE akantu
#endif
+#define FWD(x) std::forward<decltype(x)>(x)
+
namespace AKANTU_ITERATORS_NAMESPACE {
/* -------------------------------------------------------------------------- */
-namespace iterators {
+namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
/* ------------------------------------------------------------------------ */
template <template <class...> class Tuple, class... Iterators>
class ZipIterator_
: public details::CopyAssignmentEnabler<
aka::conjunction<std::is_copy_assignable<Iterators>...,
std::is_copy_constructible<Iterators>...>::value>,
public details::MoveAssignmentEnabler<
aka::conjunction<std::is_move_assignable<Iterators>...,
std::is_move_constructible<Iterators>...>::value> {
private:
using tuple_t = Tuple<Iterators...>;
public:
using value_type =
Tuple<typename std::iterator_traits<Iterators>::value_type...>;
using difference_type = std::common_type_t<
typename std::iterator_traits<Iterators>::difference_type...>;
using pointer = Tuple<typename std::iterator_traits<Iterators>::pointer...>;
using reference =
Tuple<typename std::iterator_traits<Iterators>::reference...>;
using iterator_category = // std::input_iterator_tag;
std::common_type_t<
typename std::iterator_traits<Iterators>::iterator_category...>;
- // using nb_iterators = sizeof...(Iterators);
-
- public:
explicit ZipIterator_(tuple_t iterators)
: iterators(std::move(iterators)) {}
/* ---------------------------------------------------------------------- */
template <class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_,
std::bidirectional_iterator_tag>::value> * = nullptr>
- ZipIterator_ & operator--() {
+ auto operator--() -> ZipIterator_ & {
tuple::foreach ([](auto && it) { --it; }, iterators);
return *this;
}
template <class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_,
std::bidirectional_iterator_tag>::value> * = nullptr>
- ZipIterator_ operator--(int) {
+ auto operator--(int) -> ZipIterator_ {
auto cpy = *this;
this->operator--();
return cpy;
}
// input iterator ++it
- ZipIterator_ & operator++() {
+ auto operator++() -> ZipIterator_ & {
tuple::foreach ([](auto && it) { ++it; }, iterators);
return *this;
}
// input iterator it++
- ZipIterator_ operator++(int) {
+ auto operator++(int) -> ZipIterator_ {
auto cpy = *this;
this->operator++();
return cpy;
}
// input iterator it != other_it
- bool operator!=(const ZipIterator_ & other) const {
+ auto operator!=(const ZipIterator_ & other) const -> bool {
// return tuple::are_not_equal(iterators, other.iterators);
return std::get<0>(iterators) !=
std::get<0>(other.iterators); // helps the compiler to optimize
}
// input iterator dereference *it
- decltype(auto) operator*() {
+ auto operator*() -> decltype(auto) {
return tuple::transform([](auto && it) -> decltype(auto) { return *it; },
iterators);
}
template <class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_,
std::random_access_iterator_tag>::value> * = nullptr>
- difference_type operator-(const ZipIterator_ & other) {
+ auto operator-(const ZipIterator_ & other) const -> difference_type {
return std::get<0>(this->iterators) - std::get<0>(other.iterators);
}
// random iterator it[idx]
template <class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_,
std::random_access_iterator_tag>::value> * = nullptr>
- decltype(auto) operator[](std::size_t idx) {
+ auto operator[](std::size_t idx) -> decltype(auto) {
return tuple::transform(
[idx](auto && it) -> decltype(auto) { return it[idx]; }, iterators);
}
// random iterator it + n
template <class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_,
std::random_access_iterator_tag>::value> * = nullptr>
- decltype(auto) operator+(std::size_t n) {
+ auto operator+(std::size_t n) const -> decltype(auto) {
return ZipIterator_(std::forward<tuple_t>(tuple::transform(
[n](auto && it) -> decltype(auto) { return it + n; }, iterators)));
}
// random iterator it - n
template <class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_,
std::random_access_iterator_tag>::value> * = nullptr>
- decltype(auto) operator-(std::size_t n) {
+ auto operator-(std::size_t n) const -> decltype(auto) {
return ZipIterator_(std::forward<tuple_t>(tuple::transform(
[n](auto && it) -> decltype(auto) { return it - n; }, iterators)));
}
template <
class iterator_category_ = iterator_category,
std::enable_if_t<aka::is_iterator_category_at_least<
iterator_category_, std::forward_iterator_tag>::value> * = nullptr>
- bool operator==(const ZipIterator_ & other) const {
+ auto operator==(const ZipIterator_ & other) const -> bool {
return not tuple::are_not_equal(iterators, other.iterators);
}
private:
tuple_t iterators;
};
template <class... Iterators>
using ZipIterator = ZipIterator_<std::tuple, Iterators...>;
template <class... Iterators>
using NamedZipIterator = ZipIterator_<tuple::named_tuple, Iterators...>;
-} // namespace iterators
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
/* -------------------------------------------------------------------------- */
template <class... Iterators>
-decltype(auto) zip_iterator(std::tuple<Iterators...> && iterators_tuple) {
- auto zip = iterators::ZipIterator<Iterators...>(
- std::forward<decltype(iterators_tuple)>(iterators_tuple));
+auto zip_iterator(std::tuple<Iterators...> && iterators_tuple)
+ -> decltype(auto) {
+ auto zip = iterators::ZipIterator<Iterators...>(FWD(iterators_tuple));
return zip;
}
template <class... Iterators>
-decltype(auto)
-zip_iterator(tuple::named_tuple<Iterators...> && iterators_tuple) {
- auto zip = iterators::NamedZipIterator<Iterators...>(
- std::forward<decltype(iterators_tuple)>(iterators_tuple));
+auto zip_iterator(tuple::named_tuple<Iterators...> && iterators_tuple)
+ -> decltype(auto) {
+ auto zip = iterators::NamedZipIterator<Iterators...>(FWD(iterators_tuple));
return zip;
}
/* -------------------------------------------------------------------------- */
-namespace containers {
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
template <template <class...> class Tuple, class... Containers>
class ZipContainer_ {
+ public:
using containers_t = Tuple<Containers...>;
+ using size_type = std::common_type_t<aka::size_type_t<Containers>...>;
- public:
explicit ZipContainer_(Containers &&... containers)
: containers(std::forward<Containers>(containers)...) {}
- decltype(auto) begin() const {
+ auto begin() const -> decltype(auto) {
return zip_iterator(
tuple::transform([](auto && c) { return c.begin(); },
std::forward<containers_t>(containers)));
}
- decltype(auto) end() const {
+ auto end() const -> decltype(auto) {
return zip_iterator(
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)));
}
- decltype(auto) begin() {
+ auto begin() -> decltype(auto) {
return zip_iterator(
tuple::transform([](auto && c) { return c.begin(); },
std::forward<containers_t>(containers)));
}
- decltype(auto) end() {
+ auto end() -> decltype(auto) {
return zip_iterator(
tuple::transform([](auto && c) { return c.end(); },
std::forward<containers_t>(containers)));
}
+ template <class... OtherContainers>
+ static inline auto append(ZipContainer_ && zip_container,
+ OtherContainers &&... cont);
+
+ template <typename Tag, class OtherContainers>
+ static inline auto replace(ZipContainer_ && zip_container,
+ OtherContainers && cont);
+
+ template <typename Tag>
+ static inline auto remove(ZipContainer_ && zip_container);
+
private:
+ template <template <class...> class OtherTuple, class... OtherContainers>
+ friend class ZipContainer_;
+
containers_t containers;
};
template <class... Containers>
using ZipContainer = ZipContainer_<std::tuple, Containers...>;
template <class... Containers>
using NamedZipContainer = ZipContainer_<tuple::named_tuple, Containers...>;
-} // namespace containers
+
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
/* -------------------------------------------------------------------------- */
-template <class... Containers> decltype(auto) zip(Containers &&... conts) {
+template <class... Containers,
+ std::enable_if_t<not aka::conjunction<tuple::is_named_tag<
+ std::decay_t<Containers>>...>::value> * = nullptr>
+constexpr auto zip(Containers &&... conts)
+ -> containers::ZipContainer<Containers...> {
return containers::ZipContainer<Containers...>(
std::forward<Containers>(conts)...);
}
-template <class... NamedContainers>
-decltype(auto) named_zip(NamedContainers &&... conts) {
- return containers::NamedZipContainer<NamedContainers...>(
- std::forward<NamedContainers>(conts)...);
+template <class... Containers,
+ std::enable_if_t<aka::conjunction<tuple::is_named_tag<
+ std::decay_t<Containers>>...>::value> * = nullptr>
+constexpr auto zip(Containers &&... conts)
+ -> containers::NamedZipContainer<Containers...> {
+ return containers::NamedZipContainer<Containers...>(
+ std::forward<Containers>(conts)...);
}
/* -------------------------------------------------------------------------- */
-template <class... zip_container_t>
-decltype(auto) make_zip_cat(zip_container_t &&... cont) {
+template <class... ZipContainer> inline auto zip_cat(ZipContainer &&... cont) {
return make_transform_adaptor(
- zip(std::forward<zip_container_t>(cont)...),
+ zip(std::forward<ZipContainer>(cont)...),
[](auto && value) { return tuple::flatten(value); });
}
+template <class ZipContainer, class... OtherContainers,
+ std::enable_if_t<std::is_rvalue_reference<ZipContainer &&>::value> * =
+ nullptr>
+constexpr inline auto zip_append(ZipContainer && zip_container,
+ OtherContainers &&... cont) {
+ return std::decay_t<ZipContainer>::append(FWD(zip_container), FWD(cont)...);
+}
+
+template <typename Tag, class ZipContainer, class OtherContainer,
+ std::enable_if_t<std::is_rvalue_reference<ZipContainer &&>::value> * =
+ nullptr>
+constexpr inline auto zip_replace(ZipContainer && zip_container,
+ OtherContainer && cont) {
+ return std::decay_t<ZipContainer>::template replace<Tag>(FWD(zip_container),
+ FWD(cont));
+}
+
+template <class ZipContainer, class OtherContainer,
+ std::enable_if_t<std::is_rvalue_reference_v<ZipContainer &&> and
+ tuple::is_named_tag_v<OtherContainer>> * = nullptr>
+constexpr inline auto zip_replace(ZipContainer && zip_container,
+ OtherContainer && cont) {
+ using Tag = decltype(tuple::make_named_tag<
+ typename std::decay_t<OtherContainer>::_tag>());
+ return std::decay_t<ZipContainer>::template replace<Tag>(FWD(zip_container),
+ FWD(cont._value));
+}
+
+template <typename Tag, class ZipContainer,
+ std::enable_if_t<std::is_rvalue_reference<ZipContainer &&>::value> * =
+ nullptr>
+constexpr inline auto zip_remove(ZipContainer && zip_container) {
+ return std::decay_t<ZipContainer>::template remove<Tag>(FWD(zip_container));
+}
+
+/* -------------------------------------------------------------------------- */
+namespace details AKA_ITERATOR_EXPORT_NAMESPACE {
+ template <class Tuple, std::size_t... Is,
+ std::enable_if_t<not tuple::is_named_tuple<
+ std::decay_t<Tuple>>::value> * = nullptr>
+ constexpr inline auto
+ make_zip_from_tuple_impl(std::index_sequence<Is...> && /*unused*/,
+ Tuple && tuple) {
+ return zip(FWD(std::get<Is>(FWD(tuple)))...);
+ }
+
+ template <class Tuple, std::size_t... Is,
+ std::enable_if_t<
+ tuple::is_named_tuple<std::decay_t<Tuple>>::value> * = nullptr>
+ constexpr inline auto
+ make_zip_from_tuple_impl(std::index_sequence<Is...> && /*unused*/,
+ Tuple && tuple) {
+ using namespace tuple;
+ return zip(make_named_tag<tuple_name_tag_t<Is, std::decay_t<Tuple>>>() =
+ FWD(std::get<Is>(FWD(tuple)))...);
+ }
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
+
+template <class Tuple>
+constexpr inline auto make_zip_from_tuple(Tuple && tuple) {
+ return details::make_zip_from_tuple_impl(
+ std::make_index_sequence<
+ std::tuple_size<typename std::decay_t<Tuple>>::value>{},
+ std::forward<Tuple>(tuple));
+}
+
+namespace containers AKA_ITERATOR_EXPORT_NAMESPACE {
+ template <template <class...> class Tuple, class... Containers>
+ template <class... OtherContainers>
+ inline auto
+ ZipContainer_<Tuple, Containers...>::append(ZipContainer_ && zip_container,
+ OtherContainers &&... cont) {
+ return make_zip_from_tuple(
+ tuple::append(FWD(zip_container.containers), FWD(cont)...));
+ }
+
+ template <template <class...> class Tuple, class... Containers>
+ template <typename Tag, class OtherContainer>
+ inline auto
+ ZipContainer_<Tuple, Containers...>::replace(ZipContainer_ && zip_container,
+ OtherContainer && cont) {
+ return make_zip_from_tuple(
+ tuple::replace<Tag>(FWD(zip_container.containers), FWD(cont)));
+ }
+
+ template <template <class...> class Tuple, class... Containers>
+ template <typename Tag>
+ inline auto
+ ZipContainer_<Tuple, Containers...>::remove(ZipContainer_ && zip_container) {
+ return make_zip_from_tuple(
+ tuple::remove<Tag>(FWD(zip_container.containers)));
+ }
+} // namespace AKA_ITERATOR_EXPORT_NAMESPACE
+
} // namespace AKANTU_ITERATORS_NAMESPACE
+#undef FWD
+
namespace std {
template <template <class...> class Tuple, typename... Its>
struct iterator_traits<
::AKANTU_ITERATORS_NAMESPACE::iterators::ZipIterator_<Tuple, Its...>> {
private:
using iterator_type =
typename ::AKANTU_ITERATORS_NAMESPACE::iterators::ZipIterator_<Tuple,
Its...>;
public:
using iterator_category = typename iterator_type::iterator_category;
using value_type = typename iterator_type::value_type;
using difference_type = typename iterator_type::difference_type;
using pointer = typename iterator_type::pointer;
using reference = typename iterator_type::reference;
};
} // namespace std
#endif /* AKA_ZIP_ITERATOR_HH */
diff --git a/third-party/akantu_iterators/test/test_iterators.cc b/third-party/akantu_iterators/test/test_iterators.cc
index 8ac313879..dcbeab184 100644
--- a/third-party/akantu_iterators/test/test_iterators.cc
+++ b/third-party/akantu_iterators/test/test_iterators.cc
@@ -1,402 +1,630 @@
/**
* @file test_zip_iterator.cc
*
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Fri Jul 21 2017
* @date last modification: Fri Dec 08 2017
*
* @brief test the zip container and iterator
*
*
* Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_iterators.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <vector>
/* -------------------------------------------------------------------------- */
using namespace aka;
/* -------------------------------------------------------------------------- */
// Non Trivial class that counts moves and copies
template <class T> class A {
public:
A() = default;
A(T a) : a(a){};
A(const A & other)
: a(other.a), copy_counter(other.copy_counter + 1),
move_counter(other.move_counter) {}
- A & operator=(const A & other) {
+ auto operator=(const A & other) -> A & {
if (this != &other) {
a = other.a;
copy_counter = other.copy_counter + 1;
}
return *this;
}
A(A && other)
+ noexcept
: a(std::move(other.a)), copy_counter(std::move(other.copy_counter)),
move_counter(std::move(other.move_counter) + 1) {}
- A & operator=(A && other) {
+ auto operator=(A && other) noexcept -> A & {
if (this != &other) {
a = std::move(other.a);
copy_counter = std::move(other.copy_counter);
move_counter = std::move(other.move_counter) + 1;
}
return *this;
}
- A & operator*=(const T & b) {
+ auto operator*=(const T & b) -> A & {
a *= b;
return *this;
}
T a{};
size_t copy_counter{0};
size_t move_counter{0};
};
template <typename T> struct C {
+ using size_type = std::size_t;
struct iterator {
using reference = A<T>;
using difference_type = void;
using iterator_category = std::input_iterator_tag;
using value_type = A<T>;
using pointer = A<T> *;
iterator(T pos) : pos(std::move(pos)) {}
- A<T> operator*() { return A<int>(pos); }
- bool operator!=(const iterator & other) const { return pos != other.pos; }
- bool operator==(const iterator & other) const { return pos == other.pos; }
- iterator & operator++() {
+ auto operator*() -> A<T> { return A<int>(pos); }
+ auto operator!=(const iterator & other) const -> bool {
+ return pos != other.pos;
+ }
+ auto operator==(const iterator & other) const -> bool {
+ return pos == other.pos;
+ }
+ auto operator++() -> iterator & {
++pos;
return *this;
}
T pos;
};
C(T begin_, T end_) : begin_(std::move(begin_)), end_(std::move(end_)) {}
- iterator begin() { return iterator(begin_); }
- iterator end() { return iterator(end_); }
+ auto begin() -> iterator { return iterator(begin_); }
+ auto end() -> iterator { return iterator(end_); }
T begin_, end_;
};
class TestZipFixutre : public ::testing::Test {
protected:
void SetUp() override {
a.reserve(size);
b.reserve(size);
for (size_t i = 0; i < size; ++i) {
a.emplace_back(i);
b.emplace_back(i + size);
}
}
template <typename A, typename B>
void check(A && a, B && b, size_t pos, size_t nb_copy, size_t nb_move) {
EXPECT_EQ(pos, a.a);
EXPECT_EQ(nb_copy, a.copy_counter);
EXPECT_EQ(nb_move, a.move_counter);
EXPECT_FLOAT_EQ(pos + this->size, b.a);
EXPECT_EQ(nb_copy, b.copy_counter);
EXPECT_EQ(nb_move, b.move_counter);
}
-protected:
- size_t size{20};
+public:
+ std::size_t size{20};
std::vector<A<int>> a{};
std::vector<A<float>> b{};
};
TEST_F(TestZipFixutre, SimpleTest) {
size_t i = 0;
for (auto && pair : zip(this->a, this->b)) {
this->check(std::get<0>(pair), std::get<1>(pair), i, 0, 0);
++i;
}
}
TEST_F(TestZipFixutre, ConstTest) {
size_t i = 0;
const auto & ca = this->a;
const auto & cb = this->b;
for (auto && pair : zip(ca, cb)) {
this->check(std::get<0>(pair), std::get<1>(pair), i, 0, 0);
EXPECT_EQ(true,
std::is_const<
std::remove_reference_t<decltype(std::get<0>(pair))>>::value);
EXPECT_EQ(true,
std::is_const<
std::remove_reference_t<decltype(std::get<1>(pair))>>::value);
++i;
}
}
TEST_F(TestZipFixutre, MixteTest) {
size_t i = 0;
const auto & cb = this->b;
for (auto && pair : zip(a, cb)) {
this->check(std::get<0>(pair), std::get<1>(pair), i, 0, 0);
EXPECT_EQ(false,
std::is_const<
std::remove_reference_t<decltype(std::get<0>(pair))>>::value);
EXPECT_EQ(true,
std::is_const<
std::remove_reference_t<decltype(std::get<1>(pair))>>::value);
++i;
}
}
TEST_F(TestZipFixutre, MoveTest) {
size_t i = 0;
for (auto && pair :
zip(C<int>(0, this->size), C<int>(this->size, 2 * this->size))) {
this->check(std::get<0>(pair), std::get<1>(pair), i, 0, 1);
++i;
}
}
TEST_F(TestZipFixutre, Bidirectional) {
auto _zip = zip(a, b);
auto begin = _zip.begin();
auto it = begin;
++it;
EXPECT_EQ(begin, --it);
it = begin;
EXPECT_EQ(begin, it++);
EXPECT_EQ(begin, --it);
auto it2 = it = begin;
++it;
++it2;
EXPECT_EQ(it2, it--);
EXPECT_EQ(begin, it);
}
TEST_F(TestZipFixutre, RandomAccess) {
auto _zip = zip(a, b);
auto begin = _zip.begin();
auto end = _zip.end();
auto && val5 = begin[5];
this->check(std::get<0>(val5), std::get<1>(val5), 5, 0, 0);
auto && val13 = begin[13];
this->check(std::get<0>(val13), std::get<1>(val13), 13, 0, 0);
EXPECT_EQ(end - begin, a.size());
auto it = ++begin;
EXPECT_EQ(begin + 1, ++it);
EXPECT_EQ(begin, it - 1);
}
TEST_F(TestZipFixutre, Cat) {
size_t i = 0;
- for (auto && data : make_zip_cat(zip(a, b), zip(a, b))) {
+ for (auto && data : zip_cat(zip(a, b), zip(a, b))) {
this->check(std::get<0>(data), std::get<1>(data), i, 0, 0);
this->check(std::get<2>(data), std::get<3>(data), i, 0, 0);
++i;
}
}
+TEST_F(TestZipFixutre, AppendSimple) {
+ size_t i = 0;
+
+ auto zip_ = zip_append(zip(a, arange(size)), b);
+
+ for (auto && data : zip_) {
+ this->check(std::get<0>(data), std::get<2>(data), i, 0, 0);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, AppendTemporaries) {
+ size_t i = 0;
+
+ auto zip_ = zip_append(zip_append(zip(a, arange(size)), b), arange(size));
+
+ for (auto && data : zip_) {
+ this->check(std::get<0>(data), std::get<2>(data), i, 0, 0);
+ EXPECT_EQ(std::get<3>(data), i);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, Replace) {
+ size_t i = 0;
+ for (auto && data :
+ zip_replace<1>(zip_replace<1>(zip(a, a), arange(size)), b)) {
+ this->check(std::get<0>(data), std::get<1>(data), i, 0, 0);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, Remove) {
+ size_t i = 0;
+ for (auto && data :
+ zip_remove<1>(zip_remove<1>(zip(a, a, arange(size), b)))) {
+ this->check(std::get<0>(data), std::get<1>(data), i, 0, 0);
+ ++i;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+TEST_F(TestZipFixutre, SimpleNamedTest) {
+ size_t i = 0;
+ for (auto && pair : zip("a"_n = this->a, "b"_n = this->b)) {
+ this->check(tuple::get<"a"_h>(pair), tuple::get<"b"_h>(pair), i, 0, 0);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, NamedConstTest) {
+ size_t i = 0;
+ const auto & ca = this->a;
+ const auto & cb = this->b;
+ for (auto && pair : zip("a"_n = ca, "b"_n = cb)) {
+ this->check(tuple::get<"a"_h>(pair), tuple::get<"b"_h>(pair), i, 0, 0);
+ EXPECT_EQ(
+ true,
+ std::is_const<
+ std::remove_reference_t<decltype(tuple::get<"a"_h>(pair))>>::value);
+ EXPECT_EQ(
+ true,
+ std::is_const<
+ std::remove_reference_t<decltype(tuple::get<"b"_h>(pair))>>::value);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, NamedMixteTest) {
+ size_t i = 0;
+ const auto & cb = this->b;
+ for (auto && pair : zip("a"_n = a, "b"_n = cb)) {
+ this->check(std::get<0>(pair), std::get<1>(pair), i, 0, 0);
+ EXPECT_EQ(
+ false,
+ std::is_const<
+ std::remove_reference_t<decltype(tuple::get<"a"_h>(pair))>>::value);
+ EXPECT_EQ(
+ true,
+ std::is_const<
+ std::remove_reference_t<decltype(tuple::get<"b"_h>(pair))>>::value);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, MoveNamedTest) {
+ size_t i = 0;
+ for (auto && pair : zip("a"_n = C<int>(0, this->size),
+ "b"_n = C<int>(this->size, 2 * this->size))) {
+ this->check(tuple::get<"a"_h>(pair), tuple::get<"b"_h>(pair), i, 0, 1);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, BidirectionalNamed) {
+ auto _zip = zip("a"_n = a, "b"_n = b);
+ auto begin = _zip.begin();
+
+ auto it = begin;
+ ++it;
+ EXPECT_EQ(begin, --it);
+
+ it = begin;
+ EXPECT_EQ(begin, it++);
+ EXPECT_EQ(begin, --it);
+
+ auto it2 = it = begin;
+ ++it;
+ ++it2;
+ EXPECT_EQ(it2, it--);
+ EXPECT_EQ(begin, it);
+}
+
+TEST_F(TestZipFixutre, RandomAccessNamed) {
+ auto _zip = zip("a"_n = a, "b"_n = b);
+ auto begin = _zip.begin();
+ auto end = _zip.end();
+
+ auto && val5 = begin[5];
+ this->check(tuple::get<"a"_h>(val5), tuple::get<"b"_h>(val5), 5, 0, 0);
+
+ auto && val13 = begin[13];
+ this->check(tuple::get<"a"_h>(val13), tuple::get<"b"_h>(val13), 13, 0, 0);
+
+ EXPECT_EQ(end - begin, a.size());
+ auto it = ++begin;
+ EXPECT_EQ(begin + 1, ++it);
+ EXPECT_EQ(begin, it - 1);
+}
+
+// TEST_F(TestZipFixutre, NamedCat) {
+// size_t i = 0;
+// for (auto && data :
+// zip_cat(zip("a"_n = a, "b"_n = b),
+// zip("c"_n = a, "d"_n = b))) {
+// this->check(std::get<0>(data), std::get<1>(data), i, 0, 0);
+// this->check(std::get<2>(data), std::get<3>(data), i, 0, 0);
+// ++i;
+// }
+// }
+
+TEST_F(TestZipFixutre, NamedAppend) {
+ size_t i = 0;
+
+ auto func = [&]() { return zip("a"_n = a, "temporary"_n = arange(size)); };
+
+ auto && _zip = zip_append(zip_append(func(), "b"_n = b), "c"_n = arange(size),
+ "d"_n = b);
+ for (auto && data : _zip) {
+ this->check(tuple::get<"a"_h>(data), tuple::get<"b"_h>(data), i, 0, 0);
+ EXPECT_EQ(tuple::get<"c"_h>(data), i);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, NamedReplace) {
+ size_t i = 0;
+ for (auto && data : zip_replace<"b"_h>(
+ zip_replace<"b"_h>(zip("a"_n = a, "b"_n = a, "c"_n = b),
+ arange(size)),
+ b)) {
+ this->check(tuple::get<"a"_h>(data), tuple::get<"b"_h>(data), i, 0, 0);
+ this->check(tuple::get<"a"_h>(data), tuple::get<"c"_h>(data), i, 0, 0);
+ ++i;
+ }
+}
+
+TEST_F(TestZipFixutre, NamedRemove) {
+ size_t i = 0;
+ for (auto && data :
+ zip_remove<"a2"_h>(zip("a"_n = a, "a2"_n = arange(size), "b"_n = b))) {
+ EXPECT_EQ(data.has<"a2"_h>(), false);
+ this->check(data["a"_n], data["b"_n], i, 0, 0);
+ ++i;
+ }
+}
+
TEST(TestNamedZipFixutre, Simple) {
std::vector<int> a{0, 10, 20, 30, 40};
std::vector<int> b{0, 1, 2, 3, 4};
using namespace tuple;
- for (auto && data : named_zip(get<"a"_h>() = a, get<"b"_h>() = b)) {
- auto & a = tuple::get<"a"_h>(data);
- auto & b = tuple::get<"b"_h>(data);
+ for (auto && data : zip(get<"a"_h>() = a, get<"b"_h>() = b)) {
+ auto & a = data["a"_n];
+ auto & b = data["b"_n];
b *= 10;
EXPECT_EQ(b, a);
}
- for (auto && data : named_zip(get<"a"_h>() = a, get<"b"_h>() = b)) {
- auto & a = tuple::get<"a"_h>(data);
- auto & b = tuple::get<"b"_h>(data);
+ for (auto && data : zip(get<"a"_h>() = a, get<"b"_h>() = b)) {
+ auto & a = data["a"_n];
+ auto & b = data["b"_n];
EXPECT_EQ(b, a);
}
}
/* -------------------------------------------------------------------------- */
TEST(TestArangeIterator, Stop) {
size_t ref_i = 0;
for (auto i : arange(10)) {
EXPECT_EQ(ref_i, i);
++ref_i;
}
}
TEST(TestArangeIterator, StartStop) {
size_t ref_i = 1;
for (auto i : arange(1, 10)) {
EXPECT_EQ(ref_i, i);
++ref_i;
}
}
TEST(TestArangeIterator, StartStopStep) {
size_t ref_i = 1;
for (auto i : arange(1, 22, 2)) {
EXPECT_EQ(ref_i, i);
ref_i += 2;
}
}
TEST(TestArangeIterator, StartStopStepZipped) {
int ref_i1 = -1, ref_i2 = 1;
for (auto && i : zip(arange(-1, -10, -1), arange(1, 18, 2))) {
EXPECT_EQ(ref_i1, std::get<0>(i));
EXPECT_EQ(ref_i2, std::get<1>(i));
ref_i1 += -1;
ref_i2 += 2;
}
}
/* -------------------------------------------------------------------------- */
TEST(TestEnumerateIterator, SimpleTest) {
std::vector<int> a{0, 10, 20, 30, 40};
std::vector<int> b{0, 2, 4, 6, 8};
for (auto && data : enumerate(a, b)) {
EXPECT_EQ(std::get<0>(data) * 10, std::get<1>(data));
EXPECT_EQ(std::get<0>(data) * 2, std::get<2>(data));
}
}
/* -------------------------------------------------------------------------- */
TEST(TestTransformAdaptor, Keys) {
std::map<std::string, int> map{
{"1", 1}, {"2", 2}, {"3", 3}, {"3", 3}, {"4", 4}};
char counter = '1';
for (auto && key : make_keys_adaptor(map)) {
EXPECT_EQ(counter, key[0]);
++counter;
}
}
TEST(TestTransformAdaptor, Values) {
std::map<std::string, int> map{
{"1", 1}, {"2", 2}, {"3", 3}, {"3", 3}, {"4", 4}};
int counter = 1;
for (auto && value : make_values_adaptor(map)) {
EXPECT_EQ(counter, value);
++counter;
}
}
static int plus1(int value) { return value + 1; }
struct Plus {
Plus(int a) : a(a) {}
int operator()(int b) { return a + b; }
private:
int a{0};
};
TEST(TestTransformAdaptor, Lambda) {
auto && container = arange(10);
for (auto && data :
zip(container, make_transform_adaptor(container, [](auto && value) {
return value + 1;
}))) {
EXPECT_EQ(std::get<0>(data) + 1, std::get<1>(data));
}
}
TEST(TestTransformAdaptor, LambdaLambda) {
std::map<std::string, int> map{
{"1", 1}, {"2", 2}, {"3", 3}, {"3", 3}, {"4", 4}};
int counter = 1;
for (auto && data : make_transform_adaptor(
make_values_adaptor(map), [](auto && value) { return value + 1; })) {
EXPECT_EQ(counter + 1, data);
++counter;
}
auto && container = arange(10);
for (auto && data :
zip(container, make_transform_adaptor(container, [](auto && value) {
return value + 1;
}))) {
EXPECT_EQ(std::get<0>(data) + 1, std::get<1>(data));
}
}
TEST(TestTransformAdaptor, Function) {
auto && container = arange(10);
for (auto && data :
zip(container, make_transform_adaptor(container, plus1))) {
EXPECT_EQ(std::get<0>(data) + 1, std::get<1>(data));
}
}
TEST(TestTransformAdaptor, Functor) {
auto && container = arange(10);
for (auto && data :
zip(container, make_transform_adaptor(container, Plus(1)))) {
EXPECT_EQ(std::get<0>(data) + 1, std::get<1>(data));
}
}
/* -------------------------------------------------------------------------- */
TEST(TestFilteredIterator, Simple) {
std::vector<int> values{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::vector<int> filter_{1, 3, 4, 10, 8, 6};
for (auto && data : zip(filter_, filter(filter_, values))) {
EXPECT_EQ(std::get<0>(data), std::get<1>(data));
}
}
/* -------------------------------------------------------------------------- */
TEST(TestFilteredIterator, Temporary) {
std::vector<int> filter_{1, 3, 4, 10, 8, 6};
for (auto && data :
zip(filter_, filter(filter_, std::vector<int>{0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10}))) {
EXPECT_EQ(std::get<0>(data), std::get<1>(data));
}
}
+/* -------------------------------------------------------------------------- */
+TEST(TestFilteredIfIterator, Simple) {
+ std::vector<int> values{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ for (auto && data : filter_if(values, [](auto && a) { return a % 2 == 0; })) {
+ std::cout << data << std::endl;
+ EXPECT_EQ(data % 2, 0);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+TEST(TestFilteredIfIterator, Temporary) {
+ for (auto && data :
+ filter_if(arange(10), [](auto && a) { return a % 2 == 0; })) {
+ EXPECT_EQ(data % 2, 0);
+ }
+}
+
/* -------------------------------------------------------------------------- */
TEST(TestConcatenateIterator, SimpleTest) {
for (auto && data : zip(arange(0, 13), concat(arange(0, 5), arange(5, 10),
arange(10, 13)))) {
EXPECT_EQ(std::get<0>(data), std::get<1>(data));
}
}
+
+/* -------------------------------------------------------------------------- */
+TEST(TestRepeatNIterator, SimpleTest) {
+ std::vector<int> ref{0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4};
+ for (auto && data : zip(repeat_n(arange(0, 5), 3), ref)) {
+ EXPECT_EQ(std::get<0>(data), std::get<1>(data));
+ }
+}
+
+TEST(TestRepeatNIterator, IncTest) {
+ std::vector<int> ref{0, 1, 2, 3, 4};
+ auto r = repeat_n(ref, 3);
+
+ auto it = r.begin();
+ EXPECT_EQ(*it, 0);
+ EXPECT_EQ(it[3], 1);
+ EXPECT_EQ(it[4], 1);
+ EXPECT_EQ(it[5], 1);
+
+ auto it1 = it + 1;
+ EXPECT_EQ(it1[3], 1);
+ EXPECT_EQ(it1[4], 1);
+ EXPECT_EQ(it1[5], 2);
+
+ auto end = r.end();
+ EXPECT_EQ(*(it + 5), 1);
+ EXPECT_EQ(*(end - 1), 4);
+}
diff --git a/third-party/akantu_iterators/test/test_tuples.cc b/third-party/akantu_iterators/test/test_tuples.cc
index 48ed045c2..3f6979a6d 100644
--- a/third-party/akantu_iterators/test/test_tuples.cc
+++ b/third-party/akantu_iterators/test/test_tuples.cc
@@ -1,71 +1,137 @@
/**
* @file test_tuples.cc
*
* @author Nicolas Richart
*
* @date creation mar déc 10 2019
*
* @brief A Documented file.
*
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* akantu-iterators is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* akantu-iterators is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with akantu-iterators. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "aka_tuple_tools.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
/* -------------------------------------------------------------------------- */
using namespace aka;
using namespace aka::tuple;
+TEST(NamedTuples, WithHash) {
+ const auto a = std::vector<int>{1, 10, 3};
+ const auto tuple = make_named_tuple(
+ get<"nom"_h>() = std::string("Roger"), get<"age"_h>() = 47,
+ get<"taille"_h>() = 1.92, get<"liste"_h>() = std::vector<int>({1, 2, 3}),
+ get<"ref"_h>() = a);
+
+ EXPECT_EQ(47, tuple.get(get<"age"_h>()));
+ EXPECT_EQ("Roger", tuple.get(get<"nom"_h>()));
+ EXPECT_EQ(1.92, tuple::get<"taille"_h>(tuple));
+ EXPECT_EQ(a.data(), tuple::get<"ref"_h>(tuple).data());
+
+ EXPECT_EQ(47, std::get<1>(tuple));
+}
+
+TEST(NamedTuples, StdGet) {
+ const auto tuple = make_named_tuple(get<"a"_h>() = 1, get<"b"_h>() = 2);
+
+ EXPECT_EQ(1, std::get<0>(tuple));
+ EXPECT_EQ(2, std::get<1>(tuple));
+}
+
+TEST(NamedTuples, Transform) {
+ const auto tuple = make_named_tuple(get<"a"_h>() = 1, get<"b"_h>() = 2);
+
+ auto new_tuple = tuple::transform([](auto && a) { return 2 * a; }, tuple);
+
+ EXPECT_EQ(2, tuple::get<"a"_h>(new_tuple));
+ EXPECT_EQ(4, tuple::get<"b"_h>(new_tuple));
+}
+
+TEST(NamedTuples, Append) {
+ const auto tuple = tuple::append(
+ make_named_tuple(get<"a"_h>() = 1, get<"b"_h>() = 2), get<"c"_h>() = 3);
+
+ EXPECT_EQ(1, tuple::get<"a"_h>(tuple));
+ EXPECT_EQ(2, tuple::get<"b"_h>(tuple));
+ EXPECT_EQ(3, tuple::get<"c"_h>(tuple));
+}
+
+TEST(NamedTuples, Replace) {
+ const auto tuple = make_named_tuple(get<"a"_h>() = 1, get<"b"_h>() = 2);
+
+ const auto new_tuple = tuple::replace<"a"_h>(tuple, 4);
+
+ EXPECT_EQ(4, tuple::get<"a"_h>(new_tuple));
+ EXPECT_EQ(2, tuple::get<"b"_h>(new_tuple));
+}
+
+TEST(NamedTuples, Has) {
+ const auto tuple =
+ tuple::append(make_named_tuple(get<"a"_h>() = 1, get<"b"_h>() = 2));
+
+ auto has_a = tuple::has_t<"a"_h, decltype(tuple)>();
+ auto has_b = tuple::has_t<"b"_h, decltype(tuple)>();
+ auto has_c = tuple::has_t<"c"_h, decltype(tuple)>();
+
+ static_assert(has_a, "Test of static assert on has_t");
+
+ EXPECT_EQ(true, has_a);
+ EXPECT_EQ(true, has_b);
+ EXPECT_EQ(false, has_c);
+}
+
+#if defined(__INTEL_COMPILER)
+// intel warnings here
+#elif defined(__clang__)
+// clang warnings here
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
+#elif (defined(__GNUC__) || defined(__GNUG__))
+// gcc warnings here
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
TEST(NamedTuples, GNUExtension) {
const auto a = std::vector<int>{1, 10, 3};
const auto test = make_named_tuple(
"nom"_n = std::string("Roger"), "age"_n = 47, "taille"_n = 1.92,
"liste"_n = std::vector<int>({1, 2, 3}), "ref"_n = a);
auto nom = test.get("nom"_n);
EXPECT_EQ(47, test.get("age"_n));
EXPECT_EQ("Roger", nom);
EXPECT_EQ(1.92, test.get("taille"_n));
EXPECT_EQ(a.data(), test.get("ref"_n).data());
EXPECT_EQ(47, std::get<1>(test));
}
-TEST(NamedTuples, WithHash) {
- const auto a = std::vector<int>{1, 10, 3};
- const auto tuple = make_named_tuple(
- get<"nom"_h>() = std::string("Roger"), get<"age"_h>() = 47, get<"taille"_h>() = 1.92,
- get<"liste"_h>() = std::vector<int>({1, 2, 3}), get<"ref"_h>() = a);
-
- EXPECT_EQ(47, tuple::get<"age"_h>(tuple));
- EXPECT_EQ("Roger", tuple::get<"nom"_h>(tuple));
- EXPECT_EQ(1.92, tuple::get<"taille"_h>(tuple));
- EXPECT_EQ(a.data(), tuple::get<"ref"_h>(tuple).data());
-
- EXPECT_EQ(47, std::get<1>(tuple));
-}
-
-TEST(NamedTuples, Mix) {
- const auto tuple = make_named_tuple(
- get<"nom"_h>() = std::string("Roger"), get<"age"_h>() = 47);
+TEST(NamedTuples, MixGNUExtensionHash) {
+ const auto tuple =
+ make_named_tuple("nom"_n = std::string("Roger"), get<"age"_h>() = 47);
EXPECT_EQ(47, tuple.get("age"_n));
}
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif (defined(__GNUC__) || defined(__GNUG__))
+#pragma GCC diagnostic pop
+#endif
diff --git a/third-party/cmake/eigen3.cmake b/third-party/cmake/eigen3.cmake
new file mode 100644
index 000000000..9a5fe055c
--- /dev/null
+++ b/third-party/cmake/eigen3.cmake
@@ -0,0 +1,32 @@
+set(_working_dir ${PROJECT_BINARY_DIR}/third-party/src/eigen3-download)
+configure_file(${PROJECT_SOURCE_DIR}/third-party/eigen3.cmake.in ${_working_dir}/CMakeLists.txt)
+
+if(NOT EXISTS ${PROJECT_SOURCE_DIR}/third-party/eigen3/CMakeLists.txt)
+ message(STATUS "Downloading eigen3")
+ execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+ RESULT_VARIABLE result WORKING_DIRECTORY ${_working_dir}
+ OUTPUT_FILE ${_working_dir}/configure-out.log
+ ERROR_FILE ${_working_dir}/configure-error.log)
+
+ execute_process(COMMAND "${CMAKE_COMMAND}" --build .
+ WORKING_DIRECTORY ${_working_dir}
+ OUTPUT_FILE ${_working_dir}/build-out.log
+ ERROR_FILE ${_working_dir}/build-error.log)
+endif()
+
+set(CMAKE_BUILD_TYPE Release)
+set(BUILD_TESTING OFF CACHE BOOL "Eigen Tests" FORCE)
+add_subdirectory(${PROJECT_SOURCE_DIR}/third-party/eigen3)
+
+set_property(TARGET eigen APPEND
+ PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/third-party/eigen3>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
+
+set(Eigen3_FOUND TRUE CACHE INTERNAL "" FORCE)
+set(EIGEN3_LIBRARIES eigen CACHE INTERNAL "")
+
+mark_as_advanced(BUILD_TESTING)
+mask_package_options(EIGEN3)
+mask_package_options(EIGEN)
diff --git a/third-party/cmake/pybind11.cmake b/third-party/cmake/pybind11.cmake
index 06d931535..2ab700dcb 100644
--- a/third-party/cmake/pybind11.cmake
+++ b/third-party/cmake/pybind11.cmake
@@ -1,31 +1,40 @@
set(_working_dir ${PROJECT_BINARY_DIR}/third-party/src/pybind11-download)
configure_file(${PROJECT_SOURCE_DIR}/third-party/pybind11.cmake.in ${_working_dir}/CMakeLists.txt)
if(NOT EXISTS ${PROJECT_SOURCE_DIR}/third-party/pybind11/CMakeLists.txt)
message(STATUS "Downloading pybind11")
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result WORKING_DIRECTORY ${_working_dir}
OUTPUT_FILE ${_working_dir}/configure-out.log
ERROR_FILE ${_working_dir}/configure-error.log)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY ${_working_dir}
OUTPUT_FILE ${_working_dir}/build-out.log
ERROR_FILE ${_working_dir}/build-error.log)
endif()
set(PYBIND11_PYTHON_VERSION ${AKANTU_PREFERRED_PYTHON_VERSION})
add_subdirectory(${PROJECT_SOURCE_DIR}/third-party/pybind11)
set_property(TARGET pybind11 APPEND
PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
$<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ target_compile_options(pybind11 INTERFACE -fsized-deallocation)
+endif()
+
set(pybind11_FOUND TRUE CACHE INTERNAL "" FORCE)
set(PYBIND11_INCLUDE_DIR "${PYBIND11_INCLUDE_DIR};${PYTHON_INCLUDE_DIRS}" CACHE INTERNAL "")
set(PYBIND11_LIBRARIES "${PYTHON_LIBRARIES}" CACHE INTERNAL "")
mask_package_options(PYBIND11)
mark_as_advanced(USE_PYTHON_INCLUDE_DIR)
+
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args(pybind11
+ REQUIRED_VARS PYBIND11_LIBRARIES PYBIND11_INCLUDE_DIR
+ VERSION_VAR PYBIND11_VERSION)
diff --git a/third-party/eigen3.cmake.in b/third-party/eigen3.cmake.in
new file mode 100644
index 000000000..5e3e8f7ee
--- /dev/null
+++ b/third-party/eigen3.cmake.in
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(eigen3-download NONE)
+
+include(ExternalProject)
+
+ExternalProject_Add(eigen3
+ SOURCE_DIR ${PROJECT_SOURCE_DIR}/third-party/eigen3
+ BINARY_DIR ${PROJECT_BINARY_DIR}/third-party/eigen3
+ GIT_REPOSITORY ${EIGEN3_GIT}
+ GIT_TAG ${EIGEN3_VERSION}
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+ PATCH_COMMAND
+ )
diff --git a/third-party/iohelper/src/CMakeLists.txt b/third-party/iohelper/src/CMakeLists.txt
index bbf164a4b..98881702d 100644
--- a/third-party/iohelper/src/CMakeLists.txt
+++ b/third-party/iohelper/src/CMakeLists.txt
@@ -1,114 +1,114 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
#
# @date creation: Thu Nov 24 2011
# @date last modification: Wed Nov 13 2013
#
# @brief main iohelper configuration
#
# @section LICENSE
#
# Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# IOHelper is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# IOHelper is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with IOHelper. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
#===============================================================================
# List of source files
#===============================================================================
set(IOHELPER_COMMON_SRC
dumper_lammps.cc
dumper.cc
dumper_paraview.cc
dumper_text.cc
paraview_helper.cc
# src/reader_restart.cpp
)
set(IOHELPER_COMMON_HEADERS
field_inline_impl.hh
dumper_restart.hh
field_interface.hh
visitor.hh
field.hh
variable_inline_impl.hh
variable_interface.hh
variable.hh
container_array.hh
dumper_paraview.hh
dumper_text.hh
paraview_helper.tcc
iohelper_common.hh
io_helper.hh
dumper.hh
file_manager.hh
paraview_helper.hh
dumper_C_wrapper.h
base64.hh
dumper_lammps.hh
base64_reader.hh
)
#===============================================================================
# Library creation rule
#===============================================================================
add_library(iohelper ${IOHELPER_COMMON_SRC})
# link library with other libraries
target_link_libraries(iohelper ${IOHELPER_EXTERNAL_LIBS})
target_include_directories(iohelper
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include/iohelper>
PUBLIC ${ZLIB_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS}
)
set_target_properties(iohelper PROPERTIES PUBLIC_HEADER "${IOHELPER_COMMON_HEADERS}")
-set_property(TARGET iohelper PROPERTY CXX_STANDARD 11)
+set_property(TARGET iohelper PROPERTY CXX_STANDARD 14)
export(TARGETS iohelper
FILE "${CMAKE_BINARY_DIR}/IOHelperLibraryDepends.cmake")
export(PACKAGE IOHelper)
#===============================================================================
# Install rules
#===============================================================================
# Tweak for when IOHelper is a subproject
if(NOT IOHELPER_TARGETS_EXPORT)
set(IOHELPER_TARGETS_EXPORT IOHelperLibraryDepends)
endif()
include(GNUInstallDirs)
install(TARGETS iohelper
EXPORT ${IOHELPER_TARGETS_EXPORT}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/iohelper COMPONENT dev
)
# Install the export set for use with the install-tree
if("${IOHELPER_TARGETS_EXPORT}" STREQUAL "IOHelperLibraryDepends")
install(EXPORT IOHelperLibraryDepends DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/IOHelper
COMPONENT dev)
endif()
set(IOHELPER_INCLUDE_DIRS ${IOHelper_SOURCE_DIR}/src CACHE INTERNAL "Internal include directorie to link with IOHelper as a subproject")
diff --git a/third-party/iohelper/src/dumper_lammps.hh b/third-party/iohelper/src/dumper_lammps.hh
index 21a97f08f..0ebc5d4f4 100644
--- a/third-party/iohelper/src/dumper_lammps.hh
+++ b/third-party/iohelper/src/dumper_lammps.hh
@@ -1,143 +1,155 @@
/**
* @file dumper_lammps.hh
*
* @author Till Junge <till.junge@epfl.ch>
*
* @date creation: Thu Nov 25 2010
* @date last modification: Tue Jun 04 2013
*
* @brief header for lammps dumper
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* IOHelper is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* IOHelper is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with IOHelper. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef IOHELPER_DUMPER_LAMMPS_H_
#define IOHELPER_DUMPER_LAMMPS_H_
/* -------------------------------------------------------------------------- */
#include "dumper.hh"
+/* -------------------------------------------------------------------------- */
#include <fstream>
+#include <type_traits>
/* -------------------------------------------------------------------------- */
-
namespace iohelper {
-enum LammpsAtomStyle {atomic, bond}; //please extend ad libidum
+enum LammpsAtomStyle { atomic, bond }; // please extend ad libidum
-template<LammpsAtomStyle style>
-class DumperLammps: public Dumper, public Visitor {
+template <LammpsAtomStyle style>
+class DumperLammps : public Dumper, public Visitor {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
DumperLammps(Real * bounds = nullptr, const std::string & prefix = "./");
~DumperLammps() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
//! dump to file
void dump(const std::string & current_name = std::string(),
UInt count = UInt(-1)) override;
void dumpHead(Real * bounds = nullptr);
template<typename T>
void visitField(T & visited);
void dumpFinalize();
//! set mode for file creation : TEXT, BASE64, COMPRESSED
void setMode(int mode) override { Dumper::setMode(mode); }
void dumpAdd(int grain_id = 1);
- void setEmbeddedValue(const std::string & /*name*/, int /*value*/
-){}
+ void setEmbeddedValue(const std::string & /*name*/, int /*value*/) {}
+
+protected:
+ template <typename Cont, std::enable_if_t<is_vector<Cont>::value> * = nullptr>
+ void writeData(const Cont & cont, UInt dim);
+
+ template <typename Cont, std::enable_if_t<is_matrix<Cont>::value> * = nullptr>
+ void writeData(const Cont & cont, UInt dim);
/* ------------------------------------------------------------------------ */
- /* Accessors */
+ /* Accessors */
/* ------------------------------------------------------------------------ */
public:
-
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
- //position of where the number of atoms is printed;
+ // position of where the number of atoms is printed;
std::streampos nb_atom_position;
- //current number of atoms printed to the file
+ // current number of atoms printed to the file
unsigned long int curr_nb_atom;
std::fstream lammps_dump_file;
Real * bounds;
//! flag to produce zipped files
bool flag_compressed;
//! current values
int grain_id;
};
/* -------------------------------------------------------------------------- */
-template<>
-template <typename T>
-void DumperLammps<bond>::visitField(T & visited) {
+template <LammpsAtomStyle style>
+template <typename Cont, std::enable_if_t<is_vector<Cont>::value> *>
+void DumperLammps<style>::writeData(const Cont & cont, UInt dim) {
+ for (UInt i = 0; i < dim; ++i) {
+ this->lammps_dump_file << cont[i] << " ";
+ }
+}
- typename T::iterator it = visited.begin();
- typename T::iterator end = visited.end();
+/* -------------------------------------------------------------------------- */
+template <LammpsAtomStyle style>
+template <typename Cont, std::enable_if_t<is_matrix<Cont>::value> *>
+void DumperLammps<style>::writeData(const Cont & cont, UInt /*dim*/) {
+ for (decltype(cont.rows()) i = 0; i < cont.rows(); ++i) {
+ for (decltype(cont.cols()) j = 0; j < cont.cols(); ++j) {
+ this->lammps_dump_file << cont(i, j) << " ";
+ }
+ }
+}
- UInt dim = visited.getDim();
+/* -------------------------------------------------------------------------- */
+template <>
+template <typename T>
+void DumperLammps<bond>::visitField(T & visited) {
+ auto dim = visited.getDim();
- for (; it != end ; ++it) {
+ for (auto && cont : visited) {
this->lammps_dump_file << this->curr_nb_atom + 1 << " "
<< this->grain_id + 2 << " 1 ";
- for (UInt i = 0 ; i < dim ; ++i) {
- this->lammps_dump_file << (*it)[i] << " ";
- }
- this->lammps_dump_file << std::endl;
+ writeData(cont, dim);
+ this->lammps_dump_file << "\n";
++this->curr_nb_atom;
}
}
/* -------------------------------------------------------------------------- */
-template<>
+template <>
template <typename T>
void DumperLammps<atomic>::visitField(T & visited) {
-
- typename T::iterator it = visited.begin();
- typename T::iterator end = visited.end();
-
UInt dim = visited.getDim();
- for (; it != end ; ++it) {
+ for (auto && cont : visited) {
this->lammps_dump_file << this->curr_nb_atom + 1 << " 1 ";
- for (UInt i = 0 ; i < dim ; ++i) {
- this->lammps_dump_file << (*it)[i] << " ";
- }
- this->lammps_dump_file << std::endl;
+ this->writeData(cont, dim);
+ this->lammps_dump_file << "\n";
++this->curr_nb_atom;
}
}
/* -------------------------------------------------------------------------- */
-}
+} // namespace iohelper
/* -------------------------------------------------------------------------- */
#include "field_inline_impl.hh"
/* -------------------------------------------------------------------------- */
-
-
#endif /* IOHELPER_DUMPER_LAMMPS_H_ */
diff --git a/third-party/iohelper/src/dumper_text.hh b/third-party/iohelper/src/dumper_text.hh
index 486164e18..dac78cc7d 100644
--- a/third-party/iohelper/src/dumper_text.hh
+++ b/third-party/iohelper/src/dumper_text.hh
@@ -1,198 +1,219 @@
/**
* @file dumper_text.hh
*
* @author David Simon Kammer <david.kammer@epfl.ch>
*
* @date creation: Tue May 14 2013
* @date last modification: Tue Sep 02 2014
*
* @brief header for dumper text
*
*
* Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
- * IOHelper is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
+ * IOHelper is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
*
- * IOHelper is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
+ * IOHelper is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with IOHelper. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef IOHELPER_DUMPER_TEXT_H_
#define IOHELPER_DUMPER_TEXT_H_
/* -------------------------------------------------------------------------- */
-#include <map>
-#include <string>
#include "dumper.hh"
#include "file_manager.hh"
/* -------------------------------------------------------------------------- */
+#include <map>
+#include <string>
+/* -------------------------------------------------------------------------- */
namespace iohelper {
/** Class DumperText
* Implementation of a dumper to text file
*/
class DumperText : public Dumper, public Visitor {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
-
+
public:
-
- DumperText(TextDumpMode md = _tdm_space,
- const std::string & prefix = "./",
- bool file_per_time_step = false);
+ DumperText(TextDumpMode md = _tdm_space, const std::string & prefix = "./",
+ bool file_per_time_step = false);
~DumperText() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
void dump(const std::string & name, UInt count) override;
- void setEmbeddedValue(const std::string & /*name*/,
- int /*value*/) {};
+ void setEmbeddedValue(const std::string & /*name*/, int /*value*/){};
void dumpDescription(char descr_sep = ' ') override;
virtual void dumpFieldDescription(char descr_sep = ' ');
virtual void dumpTimeDescription(char descr_sep = ' ');
-
+
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
void setDataSubDirectory(const std::string & name);
std::string getDataSubDirectory();
void setDataFileExtensions(const std::string & ext);
void setDumpMode(const TextDumpMode & mode);
void setPrecision(UInt prec) { this->precision = prec; };
-
+
//! visitor system
template <typename T> void visitField(T & visited);
template <typename T> void visitVariable(T & visited);
-
+
+protected:
+ template <typename Cont, std::enable_if_t<is_vector<Cont>::value> * = nullptr>
+ void writeData(File & file, const Cont & cont, UInt dim);
+
+ template <typename Cont, std::enable_if_t<is_matrix<Cont>::value> * = nullptr>
+ void writeData(File & file, const Cont & cont, UInt dim);
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
-
using FileMap = std::map<std::string, File *>;
/**
* another base name so that you will never understand how iohelper
* does what it does (now useless so it is commented but not removed
* for historical reasons)
*/
// std::string yet_another_base_name;
/// name of simulation, time and field description options
std::string sim_name;
std::string time_name;
std::string field_name;
char description_sep;
/// this is a separator !!
TextDumpMode dump_mode;
char separator;
char comment;
UInt precision;
bool file_per_time_step;
bool is_first_dump;
FileMap file_map;
};
/* -------------------------------------------------------------------------- */
-template <typename T>
-void DumperText::visitField(T & visited) {
+template <typename Cont, std::enable_if_t<is_vector<Cont>::value> *>
+void DumperText::writeData(File & file, const Cont & cont, UInt dim) {
+ for (UInt i = 0; i < dim; ++i) {
+ if (i != 0)
+ file << this->separator;
+ file << cont[i];
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename Cont, std::enable_if_t<is_matrix<Cont>::value> *>
+void DumperText::writeData(File & file, const Cont & cont, UInt /*dim*/) {
+ for (decltype(cont.rows()) i = 0; i < cont.rows(); ++i) {
+ for (decltype(cont.cols()) j = 0; j < cont.cols(); ++j) {
+ if (i != 0 and j != 0)
+ file << this->separator;
+ file << cont(i, j);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T> void DumperText::visitField(T & visited) {
File file;
-
+
if (this->file_per_time_step || this->is_first_dump) {
- file.open(this->getAbsoluteFilePath(this->getBaseName() + "_" + visited.getName(),
- "data_fields"),
- std::fstream::out);
- }
- else {
- file.open(this->getAbsoluteFilePath(this->getBaseName() + "_" + visited.getName(),
- "data_fields"),
- std::fstream::out | std::fstream::app);
+ file.open(this->getAbsoluteFilePath(
+ this->getBaseName() + "_" + visited.getName(), "data_fields"),
+ std::fstream::out);
+ } else {
+ file.open(this->getAbsoluteFilePath(
+ this->getBaseName() + "_" + visited.getName(), "data_fields"),
+ std::fstream::out | std::fstream::app);
}
file << std::scientific << std::setprecision(this->precision);
typename T::iterator it = visited.begin();
typename T::iterator end = visited.end();
-
+
UInt dim = visited.getDim();
-
+
for (; it != end; ++it) {
- for (UInt i=0; i<dim; ++i) {
+ for (UInt i = 0; i < dim; ++i) {
if (i != 0) {
file << this->separator;
}
- file << (*it)[i];
+ file << (*it)(i);
}
file << std::endl;
}
- file << std::endl;
+ file << std::endl;
file.close();
}
/* -------------------------------------------------------------------------- */
-template <typename T>
-void DumperText::visitVariable(T & visited) {
+template <typename T> void DumperText::visitVariable(T & visited) {
// only root rank dumps variables
if (this->my_rank != this->root_rank) {
return;
}
const std::string & name = visited.getName();
auto it = this->file_map.find(name);
auto end = this->file_map.end();
File * file;
if (it == end) {
auto * new_file = new File;
new_file->open(this->getAbsoluteFilePath(this->getBaseName() + "_" + name,
- "data_variables"),
- std::fstream::out);
+ "data_variables"),
+ std::fstream::out);
this->file_map[name] = new_file;
file = new_file;
(*file) << std::scientific << std::setprecision(this->precision);
- }
- else {
+ } else {
file = it->second;
}
UInt dim = visited.getDim();
-
+
// File file = it->second;
- for (UInt i=0; i<dim; ++i) {
+ for (UInt i = 0; i < dim; ++i) {
if (i != 0) {
(*file) << this->separator;
}
(*file) << (*visited)[i];
}
(*file) << std::endl;
-
}
/* -------------------------------------------------------------------------- */
-}
+} // namespace iohelper
#endif /* IOHELPER_DUMPER_TEXT_H_ */
diff --git a/third-party/iohelper/src/field.hh b/third-party/iohelper/src/field.hh
index a554441b3..a9b88fa36 100644
--- a/third-party/iohelper/src/field.hh
+++ b/third-party/iohelper/src/field.hh
@@ -1,136 +1,122 @@
/**
* @file field.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Till Junge <till.junge@epfl.ch>
*
* @date creation: Thu Mar 11 2010
* @date last modification: Tue Feb 05 2013
*
* @brief description of field
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* IOHelper is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* IOHelper is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with IOHelper. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef IOHELPER_FIELD_HH_
#define IOHELPER_FIELD_HH_
/* -------------------------------------------------------------------------- */
#include "field_interface.hh"
// #include "paraview_helper.hh"
// #include "dumper_lammps.hh"
/* -------------------------------------------------------------------------- */
namespace iohelper {
template <class Cont>
class Field : public FieldInterface {
/* ------------------------------------------------------------------------ */
/* Typedefs */
/* ------------------------------------------------------------------------ */
public:
using iterator = typename Cont::iterator;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
Field(Cont & c, const std::string & name) : my_field(c), name(name){};
~Field() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
-
//! return true if the data is a constant size per element
inline bool isHomogeneous() override;
//! return the size per element (valid only if isHomogeneous is true)
inline UInt getDim() override;
//! return the number of stored items (elements, nodes, etc...)
inline UInt size() override;
//! return the description name of the container
inline std::string getName() override;
//! accept to be visited by a visitor
void accept(Visitor & v) override;
//! begin method
iterator begin(){return my_field.begin();}
//! end method
iterator end(){return my_field.end();}
-
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
-
- inline DataType getDataType() override { return my_field.getDataType(); }
-
public:
-
+ inline DataType getDataType() override { return my_field.getDataType(); }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
-
Cont & my_field;
std::string name;
};
/* -------------------------------------------------------------------------- */
template <class Cont>
bool Field<Cont>::isHomogeneous(){
return my_field.isHomogeneous();
}
/* -------------------------------------------------------------------------- */
-
-template <class Cont>
-UInt Field<Cont>::getDim(){
- return my_field.getDim();
-}
+template <class Cont> UInt Field<Cont>::getDim() { return my_field.getDim(); }
/* -------------------------------------------------------------------------- */
-
-template <class Cont>
-std::string Field<Cont>::getName(){
- return name;
-}
+template <class Cont> std::string Field<Cont>::getName() { return name; }
/* -------------------------------------------------------------------------- */
template <class Cont>
UInt Field<Cont>::size(){
return my_field.size();
}
/* -------------------------------------------------------------------------- */
}
#endif /* IOHELPER_FIELD_HH_ */
diff --git a/third-party/iohelper/src/iohelper_common.hh b/third-party/iohelper/src/iohelper_common.hh
index a1c698b3b..4c8d117c7 100644
--- a/third-party/iohelper/src/iohelper_common.hh
+++ b/third-party/iohelper/src/iohelper_common.hh
@@ -1,284 +1,294 @@
/**
* @file iohelper_common.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author David Simon Kammer <david.kammer@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Mar 11 2010
* @date last modification: Thu Oct 10 2013
*
* @brief header for common types
*
*
* Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* IOHelper is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* IOHelper is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with IOHelper. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef IOHELPER_COMMON_H_
#define IOHELPER_COMMON_H_
/* -------------------------------------------------------------------------- */
#define USING_ZLIB
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <string>
/* -------------------------------------------------------------------------- */
namespace iohelper {
using UInt = unsigned int;
using Int = int;
using Real = double;
/* -------------------------------------------------------------------------- */
enum DataType { _bool, _uint, _int, _float, _double, _int64, _uint64, _uint8 };
enum IndexingMode { C_MODE = 0, FORTRAN_MODE = 1 };
/* -------------------------------------------------------------------------- */
#if __cplusplus <= 199711L
enum ElemType {
#else
enum ElemType : unsigned int {
#endif
TRIANGLE1,
TRIANGLE2,
TETRA1,
TETRA2,
POINT_SET,
LINE1,
LINE2,
QUAD1,
QUAD2,
HEX1,
HEX2,
BEAM2,
BEAM3,
PRISM1,
PRISM2,
COH1D2,
COH2D4,
COH2D6,
COH3D6,
COH3D12,
COH3D8,
MAX_ELEM_TYPE
};
/* -------------------------------------------------------------------------- */
enum FileStorageMode { TEXT = 0, BASE64 = 1, COMPRESSED = 2 };
enum TextDumpMode { _tdm_space, _tdm_csv };
/* -------------------------------------------------------------------------- */
static UInt nb_node_per_elem[MAX_ELEM_TYPE] __attribute__((unused)) = {
3, // TRIANGLE1
6, // TRIANGLE2
4, // TETRA1
10, // TETRA2
1, // POINT_SET
2, // LINE1
3, // LINE2
4, // QUAD1
8, // QUAD2
8, // HEX1
20, // HEX2
2, // BEAM2
2, // BEAM3
6, // PRISM1
15, // PRISM2
2, // COH1D2
4, // COH2D4
6, // COH2D6
6, // COH3D6
12, // COH3D12
8, // COH3D8
};
/* -------------------------------------------------------------------------- */
static UInt nb_quad_points[MAX_ELEM_TYPE] __attribute__((unused)) = {
1, // TRIANGLE1
3, // TRIANGLE2
1, // TETRA1
4, // TETRA2
0, // POINT_SET
1, // LINE1
2, // LINE2
4, // QUAD1
9, // QUAD2
8, // HEX1
27, // HEX2
2, // BEAM2
3, // BEAM3
6, // PRISM1
8, // PRISM2
1, // COH1D2
1, // COH2D4
2, // COH2D6
1, // COH3D6
3, // COH3D12
1, // COH3D8
};
/* -------------------------------------------------------------------------- */
template <typename T> class IOHelperVector {
public:
+ using value_type = T;
+
virtual ~IOHelperVector() = default;
inline IOHelperVector(T * ptr, UInt size) {
this->ptr = ptr;
this->_size = size;
};
inline UInt size() const { return _size; };
inline const T & operator[](UInt i) const { return ptr[i]; };
+ inline const T & operator()(UInt i) const { return ptr[i]; };
inline const T * getPtr() const { return ptr; };
private:
T * ptr;
UInt _size;
};
/* -------------------------------------------------------------------------- */
/* Iterator interface */
/* -------------------------------------------------------------------------- */
template <typename T, class daughter, class ret_cont = IOHelperVector<T>>
class iterator {
public:
using type = ret_cont;
virtual ~iterator() = default;
virtual bool operator!=(const daughter & it) const = 0;
virtual daughter & operator++() = 0;
virtual ret_cont operator*() = 0;
//! This function is only for the element iterators
virtual ElemType element_type() { return MAX_ELEM_TYPE; }
};
+template <typename T> struct is_vector : public std::false_type {};
+
+template <typename T>
+struct is_vector<IOHelperVector<T>> : public std::true_type {};
+
+template <typename T> struct is_matrix : public std::false_type {};
+
/* -------------------------------------------------------------------------- */
class IOHelperException : public std::exception {
public:
enum ErrorType {
_et_non_homogeneous_data,
_et_unknown_visitor_stage,
_et_file_error,
_et_missing_field,
_et_data_type,
_et_options_error
};
public:
IOHelperException(const std::string & message,
const ErrorType type) noexcept {
this->message = message;
this->type = type;
};
~IOHelperException() noexcept override = default;
const char * what() const noexcept override { return message.c_str(); };
private:
std::string message;
ErrorType type;
};
/* -------------------------------------------------------------------------- */
#define IOHELPER_THROW(x, type) \
{ \
std::stringstream ioh_throw_sstr; \
ioh_throw_sstr << __FILE__ << ":" << __LINE__ << ":" \
<< __PRETTY_FUNCTION__ << ": " << x; /* NOLINT */ \
std::string ioh_message(ioh_throw_sstr.str()); \
throw ::iohelper::IOHelperException(ioh_message, \
::iohelper::IOHelperException::type); \
}
/* -------------------------------------------------------------------------- */
template <typename T> DataType getDataType();
#define DEFINE_GET_DATA_TYPE(type, data_type) \
template <> inline DataType getDataType<type>() { return data_type; }
DEFINE_GET_DATA_TYPE(bool, _bool)
DEFINE_GET_DATA_TYPE(ElemType, _int)
DEFINE_GET_DATA_TYPE(int, _int)
DEFINE_GET_DATA_TYPE(unsigned int, _uint)
DEFINE_GET_DATA_TYPE(float, _float)
DEFINE_GET_DATA_TYPE(double, _double)
DEFINE_GET_DATA_TYPE(long int, _int64)
DEFINE_GET_DATA_TYPE(unsigned long int, _uint64)
DEFINE_GET_DATA_TYPE(std::uint8_t, _uint8)
#undef DEFINE_GET_DATA_TYPE
inline std::ostream & operator<<(std::ostream & stream, DataType type) {
switch (type) {
case _bool:
stream << "bool";
break;
case _uint:
stream << "uint32";
break;
case _int:
stream << "int32";
break;
case _float:
stream << "float32";
break;
case _double:
stream << "float64";
break;
case _uint64:
stream << "uint64";
break;
case _int64:
stream << "int64";
break;
case _uint8:
stream << "uint8";
break;
}
return stream;
}
inline std::ostream & operator<<(std::ostream & stream, TextDumpMode mode) {
switch (mode) {
case _tdm_space:
stream << "space";
break;
case _tdm_csv:
stream << "csv";
break;
}
return stream;
}
} // namespace iohelper
#endif /* IOHELPER_COMMON_H_ */
diff --git a/third-party/iohelper/src/paraview_helper.hh b/third-party/iohelper/src/paraview_helper.hh
index c5aafa053..1910cad10 100644
--- a/third-party/iohelper/src/paraview_helper.hh
+++ b/third-party/iohelper/src/paraview_helper.hh
@@ -1,258 +1,258 @@
/**
* @file paraview_helper.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date creation: Thu Mar 11 2010
* @date last modification: Wed Jun 05 2013
*
* @brief paraview helper header
*
*
* Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* IOHelper is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* IOHelper is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with IOHelper. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef IOHELPER_PARAVIEW_HELPER_H_
#define IOHELPER_PARAVIEW_HELPER_H_
/* -------------------------------------------------------------------------- */
#include "base64.hh"
+#include "field_interface.hh"
+#include "visitor.hh"
+/* -------------------------------------------------------------------------- */
#include <iomanip>
#include <map>
-#include "visitor.hh"
-#include "field_interface.hh"
+#include <type_traits>
/* -------------------------------------------------------------------------- */
namespace iohelper {
// Taken from vtkCellType.h
enum VTKCellType {
// Linear cells
VTK_EMPTY_CELL = 0,
VTK_VERTEX = 1,
VTK_POLY_VERTEX = 2,
VTK_LINE = 3,
VTK_POLY_LINE = 4,
VTK_TRIANGLE = 5,
VTK_TRIANGLE_STRIP = 6,
VTK_POLYGON = 7,
VTK_PIXEL = 8,
VTK_QUAD = 9,
VTK_TETRA = 10,
VTK_VOXEL = 11,
VTK_HEXAHEDRON = 12,
VTK_WEDGE = 13,
VTK_PYRAMID = 14,
VTK_PENTAGONAL_PRISM = 15,
VTK_HEXAGONAL_PRISM = 16,
// Quadratic, isoparametric cells
VTK_QUADRATIC_EDGE = 21,
VTK_QUADRATIC_TRIANGLE = 22,
VTK_QUADRATIC_QUAD = 23,
VTK_QUADRATIC_POLYGON = 36,
VTK_QUADRATIC_TETRA = 24,
VTK_QUADRATIC_HEXAHEDRON = 25,
VTK_QUADRATIC_WEDGE = 26,
VTK_QUADRATIC_PYRAMID = 27,
VTK_BIQUADRATIC_QUAD = 28,
VTK_TRIQUADRATIC_HEXAHEDRON = 29,
VTK_QUADRATIC_LINEAR_QUAD = 30,
VTK_QUADRATIC_LINEAR_WEDGE = 31,
VTK_BIQUADRATIC_QUADRATIC_WEDGE = 32,
VTK_BIQUADRATIC_QUADRATIC_HEXAHEDRON = 33,
VTK_BIQUADRATIC_TRIANGLE = 34,
// Polyhedron cell (consisting of polygonal faces)
VTK_POLYHEDRON = 42,
// Higher order cells in parametric form
VTK_PARAMETRIC_CURVE = 51,
VTK_PARAMETRIC_SURFACE = 52,
VTK_PARAMETRIC_TRI_SURFACE = 53,
VTK_PARAMETRIC_QUAD_SURFACE = 54,
VTK_PARAMETRIC_TETRA_REGION = 55,
VTK_PARAMETRIC_HEX_REGION = 56,
// Higher order cells
VTK_HIGHER_ORDER_EDGE = 60,
VTK_HIGHER_ORDER_TRIANGLE = 61,
VTK_HIGHER_ORDER_QUAD = 62,
VTK_HIGHER_ORDER_POLYGON = 63,
VTK_HIGHER_ORDER_TETRAHEDRON = 64,
VTK_HIGHER_ORDER_WEDGE = 65,
VTK_HIGHER_ORDER_PYRAMID = 66,
VTK_HIGHER_ORDER_HEXAHEDRON = 67,
VTK_NUMBER_OF_CELL_TYPES
};
-
inline std::ostream & operator <<(std::ostream & stream, const VTKCellType & type) {
stream << UInt(type);
return stream;
}
-
class ParaviewHelper : public Visitor {
/* ------------------------------------------------------------------------ */
/* Typedefs */
/* ------------------------------------------------------------------------ */
- enum Stage{
+ enum Stage {
_s_writePosition,
_s_writeFieldProperty,
_s_writeField,
_s_writeConnectivity,
_s_writeElemType,
_s_buildOffsets
};
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
- public:
-
+public:
ParaviewHelper(File & f, UInt mode);
~ParaviewHelper() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
-
//! write the PVTU file
template <typename T>
void writePVTU(T & per_node_data, T & per_elem_data,
- const std::vector<std::string> & vtus);
+ const std::vector<std::string> & vtus);
//! write the PVD file for time description
static void writeTimePVD(const std::string & filename,
- const std::vector< std::pair<Real, std::string> > & pvtus);
+ const std::vector<std::pair<Real, std::string>> & pvtus);
//! write the header of a vtu file
- void writeHeader(int nb_nodes,int nb_elems);
+ void writeHeader(int nb_nodes, int nb_elems);
//! write a field
template <typename T> void writeField(T & data);
//! write a connectivity field
- template <typename T> void writeConnectivity(T & data);
+ template <typename T> void writeConnectivity(T & data);
//! write an element type field
template <typename T> void writeElemType(T & data);
//! write the field properties
template <typename T> void writeFieldProperty(T & data);
//! write the connectivities offset
template <typename T> void writeOffsets(T & data);
-
template <typename T>
void pushDataFields(T & per_node_data, T & per_elem_data);
//! push the position field to the paraview file
void pushPosition(FieldInterface & f);
//! push a field to the paraview file
void pushField(FieldInterface & f);
//! build the offset from connectivities
void buildOffsets(FieldInterface & f);
//! push a connectivity field
void pushConnectivity(FieldInterface & f);
//! push a element type field
void pushElemType(FieldInterface & f);
//! get the formated vtu name
// static std::string getVTUName(const std::string & basename, UInt proc);
//! push a small array of values
- template <template<typename T> class Cont, typename T>
- void pushData(const Cont<T> & n);
+ template <class Cont>
+ void pushData(const Cont & n);
+
+ //! push a small array of values of homogeneous values with padding to size
+ //! dim
+ template <class Cont, std::enable_if_t<is_vector<Cont>::value> * = nullptr>
+ inline void pushData(const Cont & n, UInt dim);
- //! push a small array of values of homogeneous values with padding to size dim
- template <template<typename T> class Cont, typename T>
- inline void pushData(const Cont<T> & n, UInt dim);
+ template <class Cont, std::enable_if_t<is_matrix<Cont>::value> * = nullptr>
+ inline void pushData(const Cont & n, UInt dim);
//! pushing datum
template <typename T> void pushDatum(const T & n, UInt size = 3);
//! visitor system
template <typename T> void visitField(T & visited);
-private:
+private:
void setMode(int mode);
static std::string dataTypeToStr(DataType data_type);
/* ------------------------------------------------------------------------ */
/* Methods for writing control sequences in the paraview files */
/* ------------------------------------------------------------------------ */
public:
void startDofList(int dimension);
void endDofList();
void startCells();
void endCells();
void startCellsConnectivityList();
void endCellsConnectivityList();
void startCellsoffsetsList();
void endCellsoffsetsList();
void startCellstypesList();
void endCellstypesList();
void startPointDataList();
void endPointDataList();
void startCellDataList();
void endCellDataList();
void startData(const std::string & name, int nb_components, const std::string & type);
void PDataArray(const std::string & name, int nb_components, const std::string & type);
void endData();
void write_conclusion();
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
-
Base64Writer b64;
int bflag;
File & file;
long header_offset;
unsigned int compteur;
Stage current_stage;
bool position_flag;
//! mapping between iohelper elements and paraview elements
std::map<ElemType, VTKCellType> paraview_code_type;
//! mapping of the connectivities between iohelper and paraview
std::map<ElemType, UInt *> write_reorder;
};
/* -------------------------------------------------------------------------- */
#include "paraview_helper.tcc"
/* -------------------------------------------------------------------------- */
}
#endif /* IOHELPER_PARAVIEW_HELPER_H_ */
diff --git a/third-party/iohelper/src/paraview_helper.tcc b/third-party/iohelper/src/paraview_helper.tcc
index b3901f4bc..76a1b11d9 100644
--- a/third-party/iohelper/src/paraview_helper.tcc
+++ b/third-party/iohelper/src/paraview_helper.tcc
@@ -1,326 +1,351 @@
#include <cassert>
#if defined(__INTEL_COMPILER)
-#pragma warning ( push )
+#pragma warning(push)
/// remark #981: operands are evaluated in unspecified order
-#pragma warning ( disable : 981 )
-#endif //defined(__INTEL_COMPILER)
-
+#pragma warning(disable : 981)
+#endif // defined(__INTEL_COMPILER)
inline std::string ParaviewHelper::dataTypeToStr(DataType data_type) {
std::string str;
- switch(data_type) {
- case _bool : str = "UInt8" ; break;
- case _uint : str = "UInt32" ; break;
- case _int : str = "Int32" ; break;
- case _float : str = "Float32"; break;
- case _double : str = "Float64"; break;
- case _uint64 : str = "UInt64" ; break;
- case _int64 : str = "Int64" ; break;
- case _uint8 : str = "UInt8" ; break;
+ switch (data_type) {
+ case _bool:
+ str = "UInt8";
+ break;
+ case _uint:
+ str = "UInt32";
+ break;
+ case _int:
+ str = "Int32";
+ break;
+ case _float:
+ str = "Float32";
+ break;
+ case _double:
+ str = "Float64";
+ break;
+ case _uint64:
+ str = "UInt64";
+ break;
+ case _int64:
+ str = "Int64";
+ break;
+ case _uint8:
+ str = "UInt8";
+ break;
}
return str;
}
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline void ParaviewHelper::visitField(T & visited){
+template <typename T> inline void ParaviewHelper::visitField(T & visited) {
this->position_flag = false;
- switch (current_stage){
- case _s_writeFieldProperty: writeFieldProperty(visited); break;
- case _s_writePosition: this->position_flag = true; /* FALLTHRU */
- // [[fallthrough]] un-comment when compiler gets it
- case _s_writeField: writeField(visited); break;
- case _s_writeConnectivity: writeConnectivity(visited); break;
- case _s_writeElemType: writeElemType(visited); break;
- case _s_buildOffsets: writeOffsets(visited); break;
+ switch (current_stage) {
+ case _s_writeFieldProperty:
+ writeFieldProperty(visited);
+ break;
+ case _s_writePosition:
+ this->position_flag = true;
+ [[fallthrough]]; /* FALLTHRU */
+ case _s_writeField:
+ writeField(visited);
+ break;
+ case _s_writeConnectivity:
+ writeConnectivity(visited);
+ break;
+ case _s_writeElemType:
+ writeElemType(visited);
+ break;
+ case _s_buildOffsets:
+ writeOffsets(visited);
+ break;
default:
std::stringstream sstr;
- sstr << "the stage " << current_stage << " is not a known paraviewhelper stage";
- IOHELPER_THROW(sstr.str(),
- IOHelperException::_et_unknown_visitor_stage);
+ sstr << "the stage " << current_stage
+ << " is not a known paraview helper stage";
+ IOHELPER_THROW(sstr.str(), IOHelperException::_et_unknown_visitor_stage);
}
}
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline void ParaviewHelper::writeFieldProperty(T & data){
+template <typename T> inline void ParaviewHelper::writeFieldProperty(T & data) {
if (not static_cast<bool>(data.isHomogeneous()))
- IOHELPER_THROW(std::string("try to write field property of a non homogeneous field"),
- IOHelperException::_et_non_homogeneous_data);
+ IOHELPER_THROW(
+ std::string("try to write field property of a non homogeneous field"),
+ IOHelperException::_et_non_homogeneous_data);
UInt dim = data.getDim();
std::string name = data.getName();
PDataArray(name, dim, dataTypeToStr(data.getDataType()));
}
-
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline void ParaviewHelper::writeField(T & data){
+template <typename T> inline void ParaviewHelper::writeField(T & data) {
typename T::iterator it = data.begin();
typename T::iterator end = data.end();
compteur = 0;
UInt dim;
- if(data.isHomogeneous()) {
+ if (data.isHomogeneous()) {
dim = data.getDim();
if (position_flag) {
dim = 3;
}
for (; it != end; ++it) {
pushData((*it), dim);
}
- }
- else {
+ } else {
for (; it != end; ++it) {
pushData((*it));
}
}
}
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline void ParaviewHelper::writeConnectivity(T & data) {
+template <typename T> inline void ParaviewHelper::writeConnectivity(T & data) {
typename T::iterator it = data.begin();
typename T::iterator end = data.end();
for (; it != end; ++it) {
auto type = (ElemType)it.element_type();
- //typename T::iterator::type & n = *it;
+ // typename T::iterator::type & n = *it;
UInt dim = (*it).size();
assert(nb_node_per_elem[type] == dim);
UInt * reorder = this->write_reorder[type];
for (UInt i = 0; i < dim; ++i) {
- this->pushDatum((*it)[reorder[i]], dim);
+ this->pushDatum((*it)(reorder[i]), dim);
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline void ParaviewHelper::writeElemType(T & data){
+template <typename T> inline void ParaviewHelper::writeElemType(T & data) {
typename T::iterator it = data.begin();
typename T::iterator end = data.end();
for (; it != end; ++it) {
auto type = (ElemType)it.element_type();
this->pushDatum(this->paraview_code_type[type], 1);
}
}
-
/* -------------------------------------------------------------------------- */
-template <typename T>
-inline void ParaviewHelper::writeOffsets(T & data){
+template <typename T> inline void ParaviewHelper::writeOffsets(T & data) {
typename T::iterator it = data.begin();
typename T::iterator end = data.end();
-
UInt count = 0;
for (; it != end; ++it) {
count += (*it).size();
pushDatum(count);
}
}
/* -------------------------------------------------------------------------- */
-template <template<typename T> class Cont, typename T>
-inline void ParaviewHelper::pushData(const Cont<T> & n, UInt dim){
- for (UInt i = 0; i < n.size(); ++i) {
+template <typename Cont, std::enable_if_t<is_vector<Cont>::value> *>
+inline void ParaviewHelper::pushData(const Cont & n, UInt dim) {
+ using T = typename Cont::value_type;
+ for (decltype(n.size()) i = 0; i < n.size(); ++i) {
pushDatum<T>(n[i], dim);
}
- for (UInt i = n.size(); i < dim; ++i) { T t = T(); this->pushDatum<T>(t, dim); }
+ for (decltype(dim) i = n.size(); i < dim; ++i) {
+ T t = T();
+ this->pushDatum<T>(t, dim);
+ }
}
-/* -------------------------------------------------------------------------- */
-template <template<typename T> class Cont, typename T>
-inline void ParaviewHelper::pushData(const Cont<T> & n) {
- for (UInt i = 0; i < n.size(); ++i) {
- pushDatum<T>(n[i], n.size());
+template <typename Cont, std::enable_if_t<is_matrix<Cont>::value> *>
+inline void ParaviewHelper::pushData(const Cont & n, UInt dim) {
+ using T = typename Cont::value_type;
+ using Idx = decltype(n.rows());
+ for (Idx i = 0; i < Idx(dim); ++i) {
+ for (Idx j = 0; j < Idx(dim); ++j) {
+ if (i >= n.rows() or j >= n.cols()) {
+ pushDatum<T>(T(), dim);
+ } else {
+ pushDatum<T>(n(i, j), dim);
+ }
+ }
}
}
-
/* -------------------------------------------------------------------------- */
-inline void ParaviewHelper::setMode(int mode){
- bflag = BASE64 & mode;
+template <typename Cont> inline void ParaviewHelper::pushData(const Cont & n) {
+ pushData(n, n.size());
}
+/* -------------------------------------------------------------------------- */
+inline void ParaviewHelper::setMode(int mode) { bflag = BASE64 & mode; }
+
/* -------------------------------------------------------------------------- */
template <typename T>
inline void ParaviewHelper::writePVTU(T & per_node_data, T & per_elem_data,
- const std::vector<std::string> & vtus){
+ const std::vector<std::string> & vtus) {
current_stage = _s_writeFieldProperty;
file << "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" " << std::endl;
file << "byte_order=\"LittleEndian\">" << std::endl;
file << " <PUnstructuredGrid GhostLevel=\"0\">" << std::endl;
file << " <PPoints>" << std::endl;
file << " <PDataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"";
if (bflag == BASE64) {
file << "binary";
} else {
file << "ascii";
}
file << "\" />" << std::endl;
file << " </PPoints>" << std::endl;
file << " <PPointData>" << std::endl;
auto itNodeField = per_node_data.begin();
auto endNodeField = per_node_data.end();
for (; itNodeField != endNodeField; ++itNodeField) {
if ((*itNodeField).first != "positions") {
(*itNodeField).second->accept(*this);
}
}
file << " </PPointData>" << std::endl;
file << " <PCellData>" << std::endl;
auto itElemField = per_elem_data.begin();
auto endElemField = per_elem_data.end();
- for (; itElemField != endElemField ; ++itElemField) {
+ for (; itElemField != endElemField; ++itElemField) {
std::string name = (*itElemField).first;
if (name == "connectivities" || name == "element_type") {
continue;
}
(*itElemField).second->accept(*this);
}
file << " </PCellData>" << std::endl;
for (UInt l = 0; l < vtus.size(); ++l) {
file << " <Piece Source=\"" << vtus[l] << "\" />" << std::endl;
}
file << " </PUnstructuredGrid>" << std::endl;
file << "</VTKFile>" << std::endl;
file.close();
}
/* -------------------------------------------------------------------------- */
template <typename T>
-void ParaviewHelper::pushDataFields(T & per_node_data, T & per_elem_data){
+void ParaviewHelper::pushDataFields(T & per_node_data, T & per_elem_data) {
startPointDataList();
{
auto itNodeField = per_node_data.begin();
auto endNodeField = per_node_data.end();
for (; itNodeField != endNodeField; ++itNodeField) {
std::string name = (*itNodeField).first;
if (name == "positions") {
continue;
}
FieldInterface & f = *(*itNodeField).second;
startData(f.getName(), f.getDim(), dataTypeToStr(f.getDataType()));
pushField(f);
endData();
- }
+ }
}
endPointDataList();
startCellDataList();
{
- auto itElemField = per_elem_data.begin();
- auto endElemField = per_elem_data.end();
- for (; itElemField != endElemField; ++itElemField) {
- std::string name = (*itElemField).first;
+ for (auto elem_field : per_elem_data) {
+ std::string name = elem_field.first;
if (name == "connectivities" || name == "element_type") {
continue;
}
- FieldInterface & f = *(*itElemField).second;
+ FieldInterface & f = *(elem_field.second);
startData(f.getName(), f.getDim(), dataTypeToStr(f.getDataType()));
pushField(f);
endData();
- }
+ }
}
endCellDataList();
}
/* -------------------------------------------------------------------------- */
template <typename T>
-inline void ParaviewHelper::pushDatum(const T & n,
- __attribute__((unused)) UInt size){
+inline void ParaviewHelper::pushDatum(const T & n, UInt /*size*/) {
if (bflag == BASE64) {
b64.push<T>(n);
} else {
if (compteur == 0) {
file << " ";
}
++compteur;
file << n << " ";
}
}
/* -------------------------------------------------------------------------- */
template <>
-inline void ParaviewHelper::pushDatum<double>(const double & n,
- UInt size){
+inline void ParaviewHelper::pushDatum<double>(const double & n, UInt size) {
if (bflag == BASE64) {
b64.push<double>(n);
} else {
if (compteur % size == 0) {
file << " ";
}
file << std::setw(22);
file << std::setprecision(15);
file << std::scientific;
file << n;
file << " ";
++compteur;
if (compteur % size == 0) {
file << std::endl;
}
}
}
/* -------------------------------------------------------------------------- */
template <>
-inline void ParaviewHelper::pushDatum<ElemType>(const ElemType & n,
- __attribute__((unused)) UInt size){
- UInt n_ = this->paraview_code_type[n];
- pushDatum<UInt>(n_);
+inline void ParaviewHelper::pushDatum<ElemType>(const ElemType & type,
+ UInt /*size*/) {
+ UInt n = this->paraview_code_type[type];
+ pushDatum<UInt>(n);
}
/* -------------------------------------------------------------------------- */
-inline void ParaviewHelper::pushPosition(FieldInterface & f){
+inline void ParaviewHelper::pushPosition(FieldInterface & f) {
current_stage = _s_writePosition;
f.accept(*this);
}
/* -------------------------------------------------------------------------- */
-inline void ParaviewHelper::pushField(FieldInterface & f){
+inline void ParaviewHelper::pushField(FieldInterface & f) {
current_stage = _s_writeField;
f.accept(*this);
}
/* -------------------------------------------------------------------------- */
inline void ParaviewHelper::pushConnectivity(FieldInterface & f) {
current_stage = _s_writeConnectivity;
f.accept(*this);
}
/* -------------------------------------------------------------------------- */
inline void ParaviewHelper::pushElemType(FieldInterface & f) {
current_stage = _s_writeElemType;
f.accept(*this);
}
-
/* -------------------------------------------------------------------------- */
-inline void ParaviewHelper::buildOffsets(FieldInterface & f){
+inline void ParaviewHelper::buildOffsets(FieldInterface & f) {
current_stage = _s_buildOffsets;
f.accept(*this);
}
/* -------------------------------------------------------------------------- */
#if defined(__INTEL_COMPILER)
-#pragma warning ( pop )
-#endif //defined(__INTEL_COMPILER)
+#pragma warning(pop)
+#endif // defined(__INTEL_COMPILER)

Event Timeline